@pol-studios/powersync 1.0.30 → 1.0.33
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/dist/{CacheSettingsManager-uz-kbnRH.d.ts → CacheSettingsManager-0H_7thHW.d.ts} +21 -3
- package/dist/attachments/index.d.ts +30 -30
- package/dist/attachments/index.js +13 -4
- package/dist/{background-sync-CVR3PkFi.d.ts → background-sync-BujnI3IR.d.ts} +1 -1
- package/dist/{chunk-RE5HWLCB.js → chunk-2RDWLXJW.js} +322 -103
- package/dist/chunk-2RDWLXJW.js.map +1 -0
- package/dist/{chunk-P4HZA6ZT.js → chunk-4665ZSE5.js} +2 -2
- package/dist/chunk-4665ZSE5.js.map +1 -0
- package/dist/{chunk-XOY2CJ67.js → chunk-4F5B5CZ7.js} +3 -3
- package/dist/chunk-5WRI5ZAA.js +31 -0
- package/dist/{chunk-BC2SRII2.js → chunk-65A3SYJZ.js} +14 -1
- package/dist/chunk-65A3SYJZ.js.map +1 -0
- package/dist/chunk-6SZ64KCZ.js +755 -0
- package/dist/chunk-6SZ64KCZ.js.map +1 -0
- package/dist/{chunk-C2ACBYBZ.js → chunk-74TBHWJ4.js} +10 -96
- package/dist/{chunk-C2ACBYBZ.js.map → chunk-74TBHWJ4.js.map} +1 -1
- package/dist/chunk-ANXWYQEJ.js +1 -0
- package/dist/chunk-ANXWYQEJ.js.map +1 -0
- package/dist/{chunk-CAB26E6F.js → chunk-C4J4MLER.js} +29 -24
- package/dist/chunk-C4J4MLER.js.map +1 -0
- package/dist/{chunk-C5ODS3XH.js → chunk-EOW7JK7Q.js} +9 -16
- package/dist/chunk-EOW7JK7Q.js.map +1 -0
- package/dist/chunk-HRAVPIAZ.js +220 -0
- package/dist/chunk-HRAVPIAZ.js.map +1 -0
- package/dist/{chunk-XAEII4ZX.js → chunk-NUGQOTEM.js} +32 -4
- package/dist/chunk-NUGQOTEM.js.map +1 -0
- package/dist/chunk-OGUFUZSY.js +5415 -0
- package/dist/chunk-OGUFUZSY.js.map +1 -0
- package/dist/{chunk-JCGOZVWL.js → chunk-P4D6BQ4X.js} +115 -576
- package/dist/chunk-P4D6BQ4X.js.map +1 -0
- package/dist/{chunk-CACKC6XG.js → chunk-PGEDE6IM.js} +136 -89
- package/dist/chunk-PGEDE6IM.js.map +1 -0
- package/dist/{chunk-A4IBBWGO.js → chunk-RALHHPTU.js} +1 -1
- package/dist/chunk-RIDSPLE5.js +42 -0
- package/dist/chunk-RIDSPLE5.js.map +1 -0
- package/dist/{chunk-Z6VOBGTU.js → chunk-UOMHWUHV.js} +2 -12
- package/dist/chunk-UOMHWUHV.js.map +1 -0
- package/dist/{chunk-QREWE3NR.js → chunk-YONQYTVH.js} +2 -2
- package/dist/chunk-ZAN22NGL.js +13 -0
- package/dist/chunk-ZAN22NGL.js.map +1 -0
- package/dist/config/index.d.ts +200 -0
- package/dist/config/index.js +23 -0
- package/dist/config/index.js.map +1 -0
- package/dist/connector/index.d.ts +23 -5
- package/dist/connector/index.js +4 -1
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +1 -0
- package/dist/error/index.js +1 -0
- package/dist/generator/index.js +2 -0
- package/dist/generator/index.js.map +1 -1
- package/dist/index.d.ts +19 -16
- package/dist/index.js +68 -36
- package/dist/index.native.d.ts +18 -14
- package/dist/index.native.js +73 -34
- package/dist/index.web.d.ts +17 -14
- package/dist/index.web.js +68 -36
- package/dist/maintenance/index.d.ts +2 -2
- package/dist/maintenance/index.js +3 -2
- package/dist/platform/index.d.ts +1 -1
- package/dist/platform/index.js +2 -0
- package/dist/platform/index.js.map +1 -1
- package/dist/platform/index.native.d.ts +1 -1
- package/dist/platform/index.native.js +1 -0
- package/dist/platform/index.web.d.ts +1 -1
- package/dist/platform/index.web.js +1 -0
- package/dist/pol-attachment-queue-DqBvLAEY.d.ts +255 -0
- package/dist/provider/index.d.ts +149 -114
- package/dist/provider/index.js +9 -14
- package/dist/provider/index.native.d.ts +108 -0
- package/dist/provider/index.native.js +121 -0
- package/dist/provider/index.native.js.map +1 -0
- package/dist/provider/index.web.d.ts +16 -0
- package/dist/provider/index.web.js +112 -0
- package/dist/provider/index.web.js.map +1 -0
- package/dist/react/index.d.ts +16 -65
- package/dist/react/index.js +2 -9
- package/dist/storage/index.d.ts +5 -4
- package/dist/storage/index.js +12 -9
- package/dist/storage/index.native.d.ts +5 -4
- package/dist/storage/index.native.js +8 -5
- package/dist/storage/index.web.d.ts +5 -4
- package/dist/storage/index.web.js +11 -8
- package/dist/storage/upload/index.d.ts +4 -3
- package/dist/storage/upload/index.js +4 -2
- package/dist/storage/upload/index.native.d.ts +4 -3
- package/dist/storage/upload/index.native.js +4 -2
- package/dist/storage/upload/index.web.d.ts +2 -1
- package/dist/storage/upload/index.web.js +4 -2
- package/dist/{supabase-connector-C4YpH_l3.d.ts → supabase-connector-HMxBA9Kg.d.ts} +2 -2
- package/dist/sync/index.d.ts +155 -20
- package/dist/sync/index.js +13 -3
- package/dist/{types-CyvBaAl8.d.ts → types-6QHGELuY.d.ts} +4 -1
- package/dist/{types-Dv1uf0LZ.d.ts → types-B9MptP7E.d.ts} +7 -10
- package/dist/types-BhAEsJj-.d.ts +330 -0
- package/dist/{types-D0WcHrq6.d.ts → types-CGMibJKD.d.ts} +8 -0
- package/dist/{types-CpM2_LhU.d.ts → types-DqJnP50o.d.ts} +6 -1
- package/dist/{pol-attachment-queue-BE2HU3Us.d.ts → types-JCEhw2Lf.d.ts} +139 -346
- package/package.json +18 -4
- package/dist/chunk-654ERHA7.js +0 -1
- package/dist/chunk-BC2SRII2.js.map +0 -1
- package/dist/chunk-C5ODS3XH.js.map +0 -1
- package/dist/chunk-CAB26E6F.js.map +0 -1
- package/dist/chunk-CACKC6XG.js.map +0 -1
- package/dist/chunk-FNYQFILT.js +0 -44
- package/dist/chunk-FNYQFILT.js.map +0 -1
- package/dist/chunk-JCGOZVWL.js.map +0 -1
- package/dist/chunk-P4HZA6ZT.js.map +0 -1
- package/dist/chunk-RBPWEOIV.js +0 -358
- package/dist/chunk-RBPWEOIV.js.map +0 -1
- package/dist/chunk-RE5HWLCB.js.map +0 -1
- package/dist/chunk-XAEII4ZX.js.map +0 -1
- package/dist/chunk-Z6VOBGTU.js.map +0 -1
- /package/dist/{chunk-XOY2CJ67.js.map → chunk-4F5B5CZ7.js.map} +0 -0
- /package/dist/{chunk-654ERHA7.js.map → chunk-5WRI5ZAA.js.map} +0 -0
- /package/dist/{chunk-A4IBBWGO.js.map → chunk-RALHHPTU.js.map} +0 -0
- /package/dist/{chunk-QREWE3NR.js.map → chunk-YONQYTVH.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/storage/auth-error-utils.ts","../src/storage/SupabaseStorageAdapter.ts"],"sourcesContent":["/**\n * Utilities for detecting storage authentication errors.\n *\n * These utilities help identify when a storage operation failed due to\n * authentication issues (expired tokens, invalid sessions, etc.) that\n * can often be resolved by refreshing the user's session.\n *\n * NOTE: This is a copy of the utility from @pol-studios/db/storage.\n * We maintain a separate copy here to avoid circular dependencies between\n * @pol-studios/powersync and @pol-studios/db.\n */\n\n/**\n * Patterns that indicate an error is authentication-related.\n * These are checked against error messages when the status code alone\n * isn't sufficient to determine if it's an auth error.\n */\nconst AUTH_ERROR_PATTERNS = [/\\btoken\\b/i, /\\bauthoriz/i, /\\bauthenticat/i, /\\bsession\\b/i, /\\bexpired?\\b/i, /\\binvalid.*credential/i, /\\bno.*session\\b/i, /\\bJWT\\b/i] as const;\n\n/**\n * Check if a storage error is an authentication error.\n *\n * These errors can often be fixed by refreshing the session.\n *\n * @param error - The error to check (typically from Supabase Storage operations)\n * @returns true if the error appears to be authentication-related\n *\n * @example\n * ```typescript\n * const { data, error } = await storage.createSignedUrl(path, 3600);\n * if (error && isStorageAuthError(error)) {\n * await supabase.auth.refreshSession();\n * // Retry the request...\n * }\n * ```\n */\nexport function isStorageAuthError(error: unknown): boolean {\n if (!error) return false;\n const errorObj = error as {\n status?: number;\n statusCode?: number;\n message?: string;\n };\n const status = errorObj.status ?? errorObj.statusCode;\n\n // 401 (Unauthorized) and 403 (Forbidden) are always auth errors\n if (status === 401 || status === 403) {\n return true;\n }\n\n // 400 (Bad Request) is only an auth error when the message contains auth-related keywords\n // This is because custom gateways may return 400 with messages like\n // \"querystring must have required property 'token'\" for auth failures,\n // but 400 can also mean malformed parameters unrelated to auth\n if (status === 400) {\n const msg = errorObj.message ?? String(error);\n return /\\btoken\\b/i.test(msg) || /\\bauthoriz/i.test(msg) || /\\bauthenticat/i.test(msg);\n }\n\n // For other status codes (or no status), check the error message for auth-related keywords\n const message = errorObj.message ?? String(error);\n return AUTH_ERROR_PATTERNS.some(pattern => pattern.test(message));\n}\n\n/**\n * Extract a meaningful error message from a storage error.\n *\n * Supabase Storage errors may have different structures:\n * - Standard Error with `.message` property\n * - StorageError with `.message` and optional `.error` property\n * - Response-like object with `status`, `statusText`, `url` properties\n * - Plain string\n *\n * This function handles all these cases and returns a human-readable message.\n *\n * @param error - The error to extract a message from\n * @returns A human-readable error message\n *\n * @example\n * ```typescript\n * const { data, error } = await storage.createSignedUrl(path, 3600);\n * if (error) {\n * console.error(getStorageErrorMessage(error));\n * // \"Invalid path format\" or \"Object not found\" etc.\n * }\n * ```\n */\nexport function getStorageErrorMessage(error: unknown): string {\n if (!error) return 'Unknown error';\n\n // Handle plain strings\n if (typeof error === 'string') {\n return error;\n }\n\n // Handle Error objects and Supabase StorageError\n const errorObj = error as {\n message?: string;\n error?: string;\n status?: number;\n statusCode?: number;\n statusText?: string;\n name?: string;\n cause?: unknown;\n };\n\n // Prefer .message if it exists and is a non-empty string\n if (typeof errorObj.message === 'string' && errorObj.message.length > 0) {\n return errorObj.message;\n }\n\n // Check for .error property (some Supabase errors use this)\n if (typeof errorObj.error === 'string' && errorObj.error.length > 0) {\n return errorObj.error;\n }\n\n // Construct message from status code if available\n const status = errorObj.status ?? errorObj.statusCode;\n if (status) {\n const statusText = errorObj.statusText || getStatusText(status);\n return `HTTP ${status}: ${statusText}`;\n }\n\n // Fall back to JSON stringification, but handle circular references\n try {\n return JSON.stringify(error);\n } catch {\n return String(error);\n }\n}\n\n/**\n * Get a human-readable status text for common HTTP status codes.\n */\nfunction getStatusText(status: number): string {\n switch (status) {\n case 400:\n return 'Bad Request';\n case 401:\n return 'Unauthorized';\n case 403:\n return 'Forbidden';\n case 404:\n return 'Not Found';\n case 409:\n return 'Conflict';\n case 413:\n return 'Payload Too Large';\n case 422:\n return 'Unprocessable Entity';\n case 429:\n return 'Too Many Requests';\n case 500:\n return 'Internal Server Error';\n case 502:\n return 'Bad Gateway';\n case 503:\n return 'Service Unavailable';\n case 504:\n return 'Gateway Timeout';\n default:\n return 'Error';\n }\n}\n\n/**\n * Normalize a storage path by removing leading slashes.\n *\n * Supabase Storage expects paths without leading slashes.\n * This function ensures the path is properly formatted.\n *\n * @param path - The storage path to normalize\n * @returns The normalized path without leading slashes\n *\n * @example\n * ```typescript\n * normalizeStoragePath('/foo/bar.jpg'); // 'foo/bar.jpg'\n * normalizeStoragePath('foo/bar.jpg'); // 'foo/bar.jpg'\n * normalizeStoragePath('//foo/bar.jpg'); // 'foo/bar.jpg'\n * ```\n */\nexport function normalizeStoragePath(path: string): string {\n // Remove leading slashes\n let normalized = path;\n while (normalized.startsWith('/')) {\n normalized = normalized.slice(1);\n }\n return normalized;\n}","/**\n * Supabase Storage Adapter for @pol-studios/powersync\n *\n * Implements the unified SupabaseStorage interface for attachment operations.\n * Uses Supabase Storage with platform-agnostic file system operations.\n *\n * Key features:\n * - Memory-efficient downloads using signed URLs + native file system\n * - Multi-bucket support via BucketConfig/BucketResolver\n * - Platform-agnostic via FileSystemAdapter interface\n * - Implements unified SupabaseStorage interface\n */\n\nimport type { FileSystemAdapter, LoggerAdapter } from '../platform/types';\nimport type { SupabaseStorage, SupabaseClient } from './types';\nimport { resolveBucket } from './types';\nimport { isStorageAuthError, getStorageErrorMessage, normalizeStoragePath } from './auth-error-utils';\nimport { AbortError } from '../utils/retry';\n\n/**\n * Supabase Storage adapter implementing the unified SupabaseStorage interface.\n *\n * Uses PlatformAdapter's fileSystem for I/O operations to remain platform-agnostic.\n *\n * IMPORTANT: This adapter downloads files using signed URLs + platform file system\n * operations to avoid loading entire files into memory. This prevents OOM crashes\n * on large files that occurred with the previous blob-based approach.\n *\n * @example\n * ```typescript\n * const adapter = new SupabaseStorageAdapter(\n * {\n * client: supabaseClient,\n * defaultBucket: 'attachments',\n * bucketMap: new Map([['avatars/', 'user-avatars']]),\n * },\n * platform.fileSystem\n * );\n *\n * // Download returns file:// URI\n * const localUri = await adapter.download('photos/image.jpg');\n *\n * // Upload from local file\n * await adapter.upload('photos/new.jpg', localUri, 'image/jpeg');\n *\n * // Delete from remote storage\n * await adapter.delete('photos/old.jpg');\n * ```\n */\n/**\n * Image transform options for Supabase Storage.\n * Used to compress/resize images on download via Supabase's transform feature.\n */\nexport interface ImageTransformOptions {\n /** Enable image transformation (default: true) */\n enabled?: boolean;\n /** Image width in pixels (default: 2048) */\n width?: number;\n /** Image height in pixels (optional, maintains aspect ratio if omitted) */\n height?: number;\n /** Compression quality 1-100 (default: 70) */\n quality?: number;\n /** Output format (default: 'origin' to keep original format) */\n format?: 'origin' | 'avif' | 'webp';\n /** Resize mode (default: 'contain') */\n resize?: 'cover' | 'contain' | 'fill';\n}\n\n/**\n * Options for SupabaseStorageAdapter constructor.\n */\nexport interface SupabaseStorageAdapterOptions {\n client: SupabaseClient;\n defaultBucket: string;\n bucketMap?: Map<string, string>;\n bucketResolver?: (storagePath: string) => string | undefined;\n signedUrlExpiry?: number;\n logger?: LoggerAdapter;\n /** Image transform options for compression on download */\n imageTransform?: ImageTransformOptions;\n /**\n * Whether to use signed URLs for downloads (default: true).\n * Set to false for public buckets to use getPublicUrl instead of createSignedUrl.\n * This avoids rate limits and simplifies access for public assets.\n */\n useSignedUrls?: boolean;\n /**\n * Custom URL resolver for non-Supabase backends.\n * When provided, getDownloadUrl will use this instead of Supabase Storage API.\n */\n customUrlResolver?: (path: string) => Promise<string> | string;\n}\n\n// Image extensions that support Supabase transform\nconst IMAGE_EXTENSIONS = new Set(['.jpg', '.jpeg', '.png', '.webp', '.avif', '.gif', '.heic', '.heif']);\nexport class SupabaseStorageAdapter implements SupabaseStorage {\n private client: SupabaseClient;\n private defaultBucket: string;\n private bucketMap?: Map<string, string>;\n private bucketResolver?: (storagePath: string) => string | undefined;\n private signedUrlExpiry: number;\n private fileSystem?: FileSystemAdapter;\n private logger?: LoggerAdapter;\n private imageTransform?: ImageTransformOptions;\n private useSignedUrls: boolean;\n private customUrlResolver?: (path: string) => Promise<string> | string;\n constructor(options: SupabaseStorageAdapterOptions, fileSystem?: FileSystemAdapter) {\n this.client = options.client;\n this.defaultBucket = options.defaultBucket;\n this.bucketMap = options.bucketMap;\n this.bucketResolver = options.bucketResolver;\n this.signedUrlExpiry = options.signedUrlExpiry ?? 60;\n this.fileSystem = fileSystem;\n this.logger = options.logger;\n this.imageTransform = options.imageTransform;\n this.useSignedUrls = options.useSignedUrls ?? true; // Default to signed URLs\n this.customUrlResolver = options.customUrlResolver;\n }\n\n /**\n * Update image transform options (can be set after construction).\n */\n setImageTransform(options: ImageTransformOptions): void {\n this.imageTransform = options;\n }\n\n /**\n * Check if a file path is an image that supports transformation.\n */\n private isTransformableImage(path: string): boolean {\n const ext = path.slice(path.lastIndexOf('.')).toLowerCase();\n return IMAGE_EXTENSIONS.has(ext);\n }\n\n /**\n * Set the file system adapter (can be set after construction).\n */\n setFileSystem(fileSystem: FileSystemAdapter): void {\n this.fileSystem = fileSystem;\n }\n\n /**\n * Resolve the storage bucket for a given file path.\n */\n resolveBucket(filePath: string): string {\n return resolveBucket({\n defaultBucket: this.defaultBucket,\n bucketMap: this.bucketMap,\n bucketResolver: this.bucketResolver\n }, filePath);\n }\n\n // ─── SupabaseStorage Interface ──────────────────────────────────────────────\n\n /**\n * Download a file from Supabase Storage and return as a file:// URI.\n *\n * Uses streaming download to a temp file to avoid loading the entire file\n * into memory. This prevents OOM crashes and FileReader hangs that occur\n * with blob-based downloads in React Native after ~115 downloads.\n *\n * Implements SupabaseStorage.download\n *\n * @param path - Remote storage path\n * @returns file:// URI pointing to the downloaded temp file\n */\n async download(path: string): Promise<string> {\n if (!this.fileSystem) {\n throw new Error('FileSystem adapter not configured - cannot download file');\n }\n\n // Use streaming download to temp file (memory-efficient)\n const cacheDir = this.fileSystem.getCacheDirectory();\n const tempFileName = `download_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;\n const tempFilePath = `${cacheDir}${tempFileName}`;\n await this.downloadToPath(path, tempFilePath);\n\n // Return file:// URI for efficient file copy path\n return tempFilePath.startsWith('file://') ? tempFilePath : `file://${tempFilePath}`;\n }\n\n /**\n * Download a file from Supabase Storage to a specific local path.\n *\n * Uses the platform's streaming downloadFile method to avoid loading\n * the entire file into memory (prevents OOM on large files).\n *\n * @param remotePath - Remote storage path\n * @param localPath - Local file path to write to\n */\n async downloadToPath(remotePath: string, localPath: string): Promise<void> {\n if (!this.fileSystem) {\n throw new Error('FileSystem adapter not configured');\n }\n const signedUrl = await this.getDownloadUrl(remotePath);\n\n // Use the platform's streaming download method\n // This writes directly to disk without loading the entire file into memory\n await this.fileSystem.downloadFile(signedUrl, localPath);\n }\n\n /**\n * Upload a local file to Supabase Storage.\n *\n * Implements SupabaseStorage.upload\n *\n * @param path - Remote storage path\n * @param localUri - Local file:// URI to upload from\n * @param mediaType - MIME type of the file\n * @param signal - Optional AbortSignal for cancellation\n */\n async upload(path: string, localUri: string, mediaType: string, signal?: AbortSignal): Promise<void> {\n // Check if already aborted\n if (signal?.aborted) {\n throw new AbortError('Upload aborted');\n }\n if (!this.fileSystem) {\n throw new Error('FileSystem adapter not configured - cannot upload file');\n }\n const normalizedPath = normalizeStoragePath(path);\n const bucket = this.resolveBucket(normalizedPath);\n this.logger?.debug?.(`[SupabaseStorageAdapter] Uploading file`, {\n bucket,\n path: normalizedPath,\n localUri,\n mediaType\n });\n\n // Read file content as base64 and convert to blob\n const base64Content = await this.fileSystem.readFile(localUri, 'base64');\n\n // Check abort after file read\n if (signal?.aborted) {\n throw new AbortError('Upload aborted');\n }\n const binaryString = atob(base64Content);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n const fileData = new Blob([bytes], {\n type: mediaType\n });\n\n // Upload to Supabase\n const {\n error\n } = await this.client.storage.from(bucket).upload(normalizedPath, fileData, {\n contentType: mediaType,\n upsert: true\n });\n if (error) {\n const errorMessage = getStorageErrorMessage(error);\n throw new Error(`Upload failed for '${normalizedPath}' in bucket '${bucket}': ${errorMessage}`);\n }\n this.logger?.info?.(`[SupabaseStorageAdapter] Upload completed`, {\n path: normalizedPath,\n bucket\n });\n }\n\n /**\n * Delete a file from Supabase Storage.\n *\n * Implements SupabaseStorage.delete\n *\n * @param path - Remote storage path to delete\n */\n async delete(path: string): Promise<void> {\n const normalizedPath = normalizeStoragePath(path);\n const bucket = this.resolveBucket(normalizedPath);\n this.logger?.debug?.(`[SupabaseStorageAdapter] Deleting file`, {\n bucket,\n path: normalizedPath\n });\n const {\n error\n } = await this.client.storage.from(bucket).remove([normalizedPath]);\n if (error) {\n const errorMessage = getStorageErrorMessage(error);\n throw new Error(`Delete failed for '${normalizedPath}' in bucket '${bucket}': ${errorMessage}`);\n }\n this.logger?.info?.(`[SupabaseStorageAdapter] Delete completed`, {\n path: normalizedPath,\n bucket\n });\n }\n\n /**\n * Get a download URL for a remote file.\n *\n * Supports three modes:\n * 1. Custom URL resolver (for non-Supabase backends)\n * 2. Public URLs (for public Supabase buckets, when useSignedUrls=false)\n * 3. Signed URLs (default, for private Supabase buckets)\n *\n * Includes session refresh logic for signed URLs to handle stale tokens during background downloads.\n * If the initial request fails with an auth error (400/401/403), refreshes the session\n * and retries once.\n */\n async getDownloadUrl(remotePath: string): Promise<string> {\n // Normalize the path to remove any leading slashes\n // Supabase Storage expects paths without leading slashes\n const normalizedPath = normalizeStoragePath(remotePath);\n\n // Mode 1: Custom URL resolver (non-Supabase backends)\n if (this.customUrlResolver) {\n this.logger?.debug?.(`[SupabaseStorageAdapter] Using custom URL resolver`, {\n path: normalizedPath\n });\n return this.customUrlResolver(normalizedPath);\n }\n const bucket = this.resolveBucket(normalizedPath);\n\n // Mode 2: Public URLs (for public buckets)\n if (!this.useSignedUrls) {\n this.logger?.debug?.(`[SupabaseStorageAdapter] Creating public URL`, {\n bucket,\n path: normalizedPath\n });\n const {\n data\n } = this.client.storage.from(bucket).getPublicUrl(normalizedPath);\n if (!data?.publicUrl) {\n throw new Error(`Failed to create public URL for '${normalizedPath}' in bucket '${bucket}': No URL returned`);\n }\n return data.publicUrl;\n }\n\n // Mode 3: Signed URLs (default, for private buckets)\n // Build transform options for images if enabled\n const useTransform = this.imageTransform?.enabled !== false && this.isTransformableImage(normalizedPath);\n const signedUrlOptions = useTransform && this.imageTransform ? {\n transform: {\n width: this.imageTransform.width ?? 2048,\n height: this.imageTransform.height,\n quality: this.imageTransform.quality ?? 70,\n format: this.imageTransform.format ?? 'origin' as const,\n resize: this.imageTransform.resize ?? 'contain' as const\n }\n } : undefined;\n this.logger?.debug?.(`[SupabaseStorageAdapter] Creating signed URL`, {\n bucket,\n path: normalizedPath,\n originalPath: remotePath !== normalizedPath ? remotePath : undefined,\n transform: useTransform ? signedUrlOptions?.transform : undefined\n });\n\n // First attempt\n const {\n data,\n error\n } = await this.client.storage.from(bucket).createSignedUrl(normalizedPath, this.signedUrlExpiry, signedUrlOptions);\n if (error) {\n const errorMessage = getStorageErrorMessage(error);\n\n // Check if this is an auth error that might be fixed by refreshing the session\n const isAuthError = isStorageAuthError(error);\n if (isAuthError) {\n this.logger?.warn?.(`[SupabaseStorageAdapter] Auth error creating signed URL, refreshing session and retrying:`, {\n path: normalizedPath,\n bucket,\n error: errorMessage\n });\n try {\n // Refresh the session\n await this.client.auth.refreshSession();\n\n // Retry the request with same transform options\n const {\n data: retryData,\n error: retryError\n } = await this.client.storage.from(bucket).createSignedUrl(normalizedPath, this.signedUrlExpiry, signedUrlOptions);\n if (retryError) {\n const retryErrorMessage = getStorageErrorMessage(retryError);\n throw new Error(`Failed to create signed URL after session refresh: ${retryErrorMessage}`);\n }\n if (!retryData?.signedUrl) {\n throw new Error('Failed to create signed URL after session refresh: No URL returned');\n }\n this.logger?.info?.(`[SupabaseStorageAdapter] Successfully created signed URL after session refresh`);\n return retryData.signedUrl;\n } catch (refreshError) {\n // If refresh also fails, throw the original error with context\n throw new Error(`Failed to create signed URL: ${errorMessage} (session refresh also failed: ${refreshError instanceof Error ? refreshError.message : String(refreshError)})`);\n }\n }\n\n // Non-auth error, throw with normalized error message\n throw new Error(`Failed to create signed URL for '${normalizedPath}' in bucket '${bucket}': ${errorMessage}`);\n }\n if (!data?.signedUrl) {\n throw new Error(`Failed to create signed URL for '${normalizedPath}' in bucket '${bucket}': No URL returned`);\n }\n return data.signedUrl;\n }\n\n /**\n * Check if a file exists in remote storage.\n */\n async exists(remotePath: string): Promise<boolean> {\n const bucket = this.resolveBucket(remotePath);\n try {\n // Use list with a specific path prefix to check existence\n const pathParts = remotePath.split('/');\n const fileName = pathParts.pop();\n const directory = pathParts.join('/');\n const {\n data,\n error\n } = await this.client.storage.from(bucket).list(directory, {\n search: fileName,\n limit: 1\n });\n if (error) {\n return false;\n }\n return data?.some((file: {\n name: string;\n }) => file.name === fileName) ?? false;\n } catch {\n return false;\n }\n }\n\n // ─── Backward Compatibility (AttachmentStorageAdapter) ─────────────────────\n\n /**\n * Download a file from remote storage.\n * Alias for download() - for backward compatibility with AttachmentStorageAdapter interface.\n *\n * @param filePath - Remote storage path\n * @returns file:// URI pointing to the downloaded temp file\n */\n async downloadFile(filePath: string): Promise<string> {\n return this.download(filePath);\n }\n\n // ─── Local File Operations ─────────────────────────────────────────────────\n\n /**\n * Write data to a local file.\n */\n async writeFile(fileURI: string, data: string, options?: {\n encoding?: 'utf8' | 'base64';\n }): Promise<void> {\n if (!this.fileSystem) {\n throw new Error('FileSystem adapter not configured');\n }\n const encoding = options?.encoding ?? 'utf8';\n\n // Ensure parent directory exists\n const parentDir = fileURI.substring(0, fileURI.lastIndexOf('/'));\n if (parentDir) {\n await this.fileSystem.makeDirectory(parentDir, {\n intermediates: true\n });\n }\n await this.fileSystem.writeFile(fileURI, data, encoding);\n }\n\n /**\n * Read data from a local file.\n */\n async readFile(fileURI: string, options?: {\n encoding?: 'utf8' | 'base64';\n mediaType?: string;\n }): Promise<ArrayBuffer> {\n if (!this.fileSystem) {\n throw new Error('FileSystem adapter not configured');\n }\n const encoding = options?.encoding ?? 'utf8';\n const content = await this.fileSystem.readFile(fileURI, encoding);\n if (encoding === 'base64') {\n // Decode base64 to ArrayBuffer\n const binaryString = atob(content);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes.buffer;\n }\n\n // For utf8, encode to ArrayBuffer\n const encoder = new TextEncoder();\n return encoder.encode(content).buffer;\n }\n\n /**\n * Delete a local file.\n */\n async deleteFile(uri: string, _options?: {\n filename?: string;\n }): Promise<void> {\n if (!this.fileSystem) {\n throw new Error('FileSystem adapter not configured');\n }\n await this.fileSystem.deleteFile(uri);\n }\n\n /**\n * Check if a local file exists.\n */\n async fileExists(fileURI: string): Promise<boolean> {\n if (!this.fileSystem) {\n throw new Error('FileSystem adapter not configured');\n }\n const info = await this.fileSystem.getFileInfo(fileURI);\n return info?.exists ?? false;\n }\n\n /**\n * Create a directory.\n */\n async makeDir(uri: string): Promise<void> {\n if (!this.fileSystem) {\n throw new Error('FileSystem adapter not configured');\n }\n await this.fileSystem.makeDirectory(uri, {\n intermediates: true\n });\n }\n\n /**\n * Copy a file.\n */\n async copyFile(sourceUri: string, targetUri: string): Promise<void> {\n if (!this.fileSystem) {\n throw new Error('FileSystem adapter not configured');\n }\n await this.fileSystem.copyFile(sourceUri, targetUri);\n }\n\n /**\n * Get the user storage directory.\n */\n getUserStorageDirectory(): string {\n if (!this.fileSystem) {\n throw new Error('FileSystem adapter not configured');\n }\n return this.fileSystem.getDocumentsDirectory();\n }\n}\n\n/**\n * Create a SupabaseStorageAdapter with simplified configuration.\n *\n * @example\n * ```typescript\n * const adapter = createSupabaseStorageAdapter(\n * supabaseClient,\n * 'attachments',\n * platform.fileSystem\n * );\n * ```\n */\nexport function createSupabaseStorageAdapter(client: SupabaseClient, defaultBucket: string, fileSystem?: FileSystemAdapter, options?: {\n bucketMap?: Map<string, string>;\n bucketResolver?: (storagePath: string) => string | undefined;\n signedUrlExpiry?: number;\n logger?: LoggerAdapter;\n}): SupabaseStorageAdapter {\n return new SupabaseStorageAdapter({\n client,\n defaultBucket,\n bucketMap: options?.bucketMap,\n bucketResolver: options?.bucketResolver,\n signedUrlExpiry: options?.signedUrlExpiry,\n logger: options?.logger\n }, fileSystem);\n}"],"mappings":"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","names":["data"]}
|