@parsrun/storage 0.1.15 → 0.1.16

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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/adapters/memory.ts","../src/adapters/s3.ts","../src/adapters/r2.ts","../src/index.ts"],"sourcesContent":["/**\n * @parsrun/storage - Type Definitions\n * Storage abstraction types for edge-compatible storage\n */\n\n// Re-export types from @parsrun/types for convenience\nexport {\n type,\n fileMetadata,\n uploadOptions as parsUploadOptions,\n signedUrlOptions,\n listFilesOptions,\n listFilesResult,\n localStorageConfig,\n s3StorageConfig,\n r2StorageConfig,\n gcsStorageConfig,\n storageProviderConfig,\n type FileMetadata as ParsFileMetadata,\n type UploadOptions as ParsUploadOptions,\n type SignedUrlOptions,\n type ListFilesOptions,\n type ListFilesResult,\n type LocalStorageConfig,\n type S3StorageConfig,\n type R2StorageConfig,\n type GcsStorageConfig,\n type StorageProviderConfig,\n} from \"@parsrun/types\";\n\n/**\n * Storage adapter type\n */\nexport type StorageAdapterType = \"s3\" | \"r2\" | \"do-spaces\" | \"memory\" | \"custom\";\n\n/**\n * File metadata\n */\nexport interface FileMetadata {\n /** File key/path */\n key: string;\n /** File size in bytes */\n size: number;\n /** Content type (MIME type) */\n contentType: string | undefined;\n /** Last modified date */\n lastModified: Date | undefined;\n /** ETag (entity tag) */\n etag: string | undefined;\n /** Custom metadata */\n metadata: Record<string, string> | undefined;\n}\n\n/**\n * Upload options\n */\nexport interface UploadOptions {\n /** Content type override */\n contentType?: string | undefined;\n /** Content disposition */\n contentDisposition?: string | undefined;\n /** Cache control header */\n cacheControl?: string | undefined;\n /** Content encoding */\n contentEncoding?: string | undefined;\n /** Custom metadata */\n metadata?: Record<string, string> | undefined;\n /** ACL (access control list) */\n acl?: \"private\" | \"public-read\" | undefined;\n}\n\n/**\n * Download options\n */\nexport interface DownloadOptions {\n /** Range start (for partial downloads) */\n rangeStart?: number | undefined;\n /** Range end (for partial downloads) */\n rangeEnd?: number | undefined;\n /** If-None-Match (ETag) */\n ifNoneMatch?: string | undefined;\n /** If-Modified-Since */\n ifModifiedSince?: Date | undefined;\n}\n\n/**\n * List options\n */\nexport interface ListOptions {\n /** Prefix to filter by */\n prefix?: string | undefined;\n /** Delimiter for hierarchy */\n delimiter?: string | undefined;\n /** Maximum keys to return */\n maxKeys?: number | undefined;\n /** Continuation token for pagination */\n continuationToken?: string | undefined;\n}\n\n/**\n * List result\n */\nexport interface ListResult {\n /** List of files */\n files: FileMetadata[];\n /** Common prefixes (for hierarchical listing) */\n prefixes: string[];\n /** Whether there are more results */\n isTruncated: boolean;\n /** Continuation token for next page */\n continuationToken: string | undefined;\n}\n\n/**\n * Presigned URL options\n */\nexport interface PresignedUrlOptions {\n /** URL expiration in seconds (default: 3600) */\n expiresIn?: number | undefined;\n /** Content type (for upload URLs) */\n contentType?: string | undefined;\n /** Content disposition */\n contentDisposition?: string | undefined;\n /** Response cache control */\n responseCacheControl?: string | undefined;\n /** Response content type */\n responseContentType?: string | undefined;\n}\n\n/**\n * Copy options\n */\nexport interface CopyOptions {\n /** Source bucket (if different from destination) */\n sourceBucket?: string | undefined;\n /** Metadata directive */\n metadataDirective?: \"COPY\" | \"REPLACE\" | undefined;\n /** New metadata (if REPLACE) */\n metadata?: Record<string, string> | undefined;\n /** New content type (if REPLACE) */\n contentType?: string | undefined;\n}\n\n/**\n * Delete result\n */\nexport interface DeleteResult {\n /** Whether deletion was successful */\n success: boolean;\n /** Deleted key */\n key: string;\n}\n\n/**\n * Batch delete result\n */\nexport interface BatchDeleteResult {\n /** Successfully deleted keys */\n deleted: string[];\n /** Failed deletions */\n errors: Array<{ key: string; error: string }>;\n}\n\n/**\n * Storage adapter interface\n * All storage adapters must implement this interface\n */\nexport interface StorageAdapter {\n /** Adapter type */\n readonly type: StorageAdapterType;\n\n /** Bucket name */\n readonly bucket: string;\n\n /**\n * Upload a file\n * @param key - File key/path\n * @param data - File data\n * @param options - Upload options\n */\n upload(\n key: string,\n data: Uint8Array | ReadableStream<Uint8Array> | Blob | string,\n options?: UploadOptions\n ): Promise<FileMetadata>;\n\n /**\n * Download a file\n * @param key - File key/path\n * @param options - Download options\n */\n download(key: string, options?: DownloadOptions): Promise<Uint8Array>;\n\n /**\n * Download a file as a stream\n * @param key - File key/path\n * @param options - Download options\n */\n downloadStream(\n key: string,\n options?: DownloadOptions\n ): Promise<ReadableStream<Uint8Array>>;\n\n /**\n * Get file metadata\n * @param key - File key/path\n */\n head(key: string): Promise<FileMetadata | null>;\n\n /**\n * Check if file exists\n * @param key - File key/path\n */\n exists(key: string): Promise<boolean>;\n\n /**\n * Delete a file\n * @param key - File key/path\n */\n delete(key: string): Promise<DeleteResult>;\n\n /**\n * Delete multiple files\n * @param keys - File keys/paths\n */\n deleteMany(keys: string[]): Promise<BatchDeleteResult>;\n\n /**\n * List files\n * @param options - List options\n */\n list(options?: ListOptions): Promise<ListResult>;\n\n /**\n * Copy a file\n * @param sourceKey - Source key\n * @param destKey - Destination key\n * @param options - Copy options\n */\n copy(sourceKey: string, destKey: string, options?: CopyOptions): Promise<FileMetadata>;\n\n /**\n * Move/rename a file\n * @param sourceKey - Source key\n * @param destKey - Destination key\n */\n move(sourceKey: string, destKey: string): Promise<FileMetadata>;\n\n /**\n * Generate a presigned URL for download\n * @param key - File key/path\n * @param options - URL options\n */\n getPresignedUrl(key: string, options?: PresignedUrlOptions): Promise<string>;\n\n /**\n * Generate a presigned URL for upload\n * @param key - File key/path\n * @param options - URL options\n */\n getUploadUrl(key: string, options?: PresignedUrlOptions): Promise<string>;\n}\n\n/**\n * Storage configuration\n */\nexport interface StorageConfig {\n /** Default bucket name */\n bucket: string;\n /** Storage adapter type */\n type: StorageAdapterType;\n /** Base path prefix for all operations */\n basePath?: string | undefined;\n /** Public URL prefix */\n publicUrl?: string | undefined;\n}\n\n/**\n * S3 configuration\n */\nexport interface S3Config extends StorageConfig {\n type: \"s3\" | \"do-spaces\";\n /** AWS region */\n region: string;\n /** Access key ID */\n accessKeyId: string;\n /** Secret access key */\n secretAccessKey: string;\n /** Custom endpoint (for DO Spaces, MinIO, etc.) */\n endpoint?: string | undefined;\n /** Force path style (for MinIO) */\n forcePathStyle?: boolean | undefined;\n}\n\n/**\n * R2 configuration\n */\nexport interface R2Config extends StorageConfig {\n type: \"r2\";\n /** Cloudflare account ID */\n accountId: string;\n /** R2 access key ID */\n accessKeyId: string;\n /** R2 secret access key */\n secretAccessKey: string;\n /** Custom domain for public access */\n customDomain?: string | undefined;\n}\n\n/**\n * Memory storage configuration (for testing)\n */\nexport interface MemoryConfig extends StorageConfig {\n type: \"memory\";\n /** Maximum storage size in bytes */\n maxSize?: number | undefined;\n}\n\n/**\n * Storage error\n */\nexport class StorageError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly statusCode?: number | undefined,\n public readonly cause?: unknown\n ) {\n super(message);\n this.name = \"StorageError\";\n }\n}\n\n/**\n * Common storage error codes\n */\nexport const StorageErrorCodes = {\n NOT_FOUND: \"NOT_FOUND\",\n ACCESS_DENIED: \"ACCESS_DENIED\",\n BUCKET_NOT_FOUND: \"BUCKET_NOT_FOUND\",\n INVALID_KEY: \"INVALID_KEY\",\n UPLOAD_FAILED: \"UPLOAD_FAILED\",\n DOWNLOAD_FAILED: \"DOWNLOAD_FAILED\",\n DELETE_FAILED: \"DELETE_FAILED\",\n COPY_FAILED: \"COPY_FAILED\",\n LIST_FAILED: \"LIST_FAILED\",\n PRESIGN_FAILED: \"PRESIGN_FAILED\",\n QUOTA_EXCEEDED: \"QUOTA_EXCEEDED\",\n INVALID_CONFIG: \"INVALID_CONFIG\",\n ADAPTER_NOT_AVAILABLE: \"ADAPTER_NOT_AVAILABLE\",\n} as const;\n","/**\n * @parsrun/storage - Memory Adapter\n * In-memory storage adapter for development and testing\n */\n\nimport {\n type BatchDeleteResult,\n type CopyOptions,\n type DeleteResult,\n type DownloadOptions,\n type FileMetadata,\n type ListOptions,\n type ListResult,\n type MemoryConfig,\n type PresignedUrlOptions,\n type StorageAdapter,\n type UploadOptions,\n StorageError,\n StorageErrorCodes,\n} from \"../types.js\";\n\n/**\n * Internal file storage structure\n */\ninterface StoredFile {\n data: Uint8Array;\n metadata: FileMetadata;\n}\n\n/**\n * Memory Storage Adapter\n * Stores files in memory - useful for development and testing\n *\n * @example\n * ```typescript\n * const storage = new MemoryAdapter({\n * type: 'memory',\n * bucket: 'test-bucket',\n * });\n *\n * await storage.upload('test.txt', 'Hello, World!');\n * const data = await storage.download('test.txt');\n * ```\n */\nexport class MemoryAdapter implements StorageAdapter {\n readonly type = \"memory\" as const;\n readonly bucket: string;\n\n private files: Map<string, StoredFile> = new Map();\n private maxSize: number;\n private currentSize = 0;\n private basePath: string;\n\n constructor(config: MemoryConfig) {\n this.bucket = config.bucket;\n this.maxSize = config.maxSize ?? Infinity;\n this.basePath = config.basePath ?? \"\";\n }\n\n private getFullKey(key: string): string {\n return this.basePath ? `${this.basePath}/${key}` : key;\n }\n\n private validateKey(key: string): void {\n if (!key || key.includes(\"..\") || key.startsWith(\"/\")) {\n throw new StorageError(\n `Invalid key: ${key}`,\n StorageErrorCodes.INVALID_KEY\n );\n }\n }\n\n private dataToUint8Array(\n data: Uint8Array | ReadableStream<Uint8Array> | Blob | string\n ): Promise<Uint8Array> | Uint8Array {\n if (data instanceof Uint8Array) {\n return data;\n }\n\n if (typeof data === \"string\") {\n return new TextEncoder().encode(data);\n }\n\n if (data instanceof Blob) {\n return data.arrayBuffer().then((buffer) => new Uint8Array(buffer));\n }\n\n // ReadableStream\n return this.streamToUint8Array(data);\n }\n\n private async streamToUint8Array(\n stream: ReadableStream<Uint8Array>\n ): Promise<Uint8Array> {\n const reader = stream.getReader();\n const chunks: Uint8Array[] = [];\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n }\n\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const result = new Uint8Array(totalLength);\n let offset = 0;\n\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n\n return result;\n }\n\n async upload(\n key: string,\n data: Uint8Array | ReadableStream<Uint8Array> | Blob | string,\n options?: UploadOptions\n ): Promise<FileMetadata> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const uint8Data = await this.dataToUint8Array(data);\n\n // Check quota\n const existingFile = this.files.get(fullKey);\n const sizeDiff = uint8Data.length - (existingFile?.data.length ?? 0);\n\n if (this.currentSize + sizeDiff > this.maxSize) {\n throw new StorageError(\n \"Storage quota exceeded\",\n StorageErrorCodes.QUOTA_EXCEEDED\n );\n }\n\n const metadata: FileMetadata = {\n key: fullKey,\n size: uint8Data.length,\n contentType: options?.contentType ?? this.guessContentType(key),\n lastModified: new Date(),\n etag: this.generateEtag(uint8Data),\n metadata: options?.metadata ?? undefined,\n };\n\n this.files.set(fullKey, { data: uint8Data, metadata });\n this.currentSize += sizeDiff;\n\n return metadata;\n }\n\n async download(key: string, _options?: DownloadOptions): Promise<Uint8Array> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const file = this.files.get(fullKey);\n if (!file) {\n throw new StorageError(\n `File not found: ${key}`,\n StorageErrorCodes.NOT_FOUND,\n 404\n );\n }\n\n return file.data;\n }\n\n async downloadStream(\n key: string,\n _options?: DownloadOptions\n ): Promise<ReadableStream<Uint8Array>> {\n const data = await this.download(key);\n\n return new ReadableStream({\n start(controller) {\n controller.enqueue(data);\n controller.close();\n },\n });\n }\n\n async head(key: string): Promise<FileMetadata | null> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const file = this.files.get(fullKey);\n return file?.metadata ?? null;\n }\n\n async exists(key: string): Promise<boolean> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n return this.files.has(fullKey);\n }\n\n async delete(key: string): Promise<DeleteResult> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const file = this.files.get(fullKey);\n if (file) {\n this.currentSize -= file.data.length;\n this.files.delete(fullKey);\n }\n\n return { success: true, key: fullKey };\n }\n\n async deleteMany(keys: string[]): Promise<BatchDeleteResult> {\n const deleted: string[] = [];\n const errors: Array<{ key: string; error: string }> = [];\n\n for (const key of keys) {\n try {\n await this.delete(key);\n deleted.push(this.getFullKey(key));\n } catch (err) {\n errors.push({\n key: this.getFullKey(key),\n error: err instanceof Error ? err.message : \"Unknown error\",\n });\n }\n }\n\n return { deleted, errors };\n }\n\n async list(options?: ListOptions): Promise<ListResult> {\n const prefix = options?.prefix\n ? this.getFullKey(options.prefix)\n : this.basePath;\n const delimiter = options?.delimiter ?? \"/\";\n const maxKeys = options?.maxKeys ?? 1000;\n\n const files: FileMetadata[] = [];\n const prefixSet = new Set<string>();\n\n for (const [key, file] of this.files) {\n if (prefix && !key.startsWith(prefix)) {\n continue;\n }\n\n const relativePath = prefix ? key.slice(prefix.length) : key;\n\n // Handle delimiter for hierarchical listing\n if (delimiter) {\n const delimiterIndex = relativePath.indexOf(delimiter);\n if (delimiterIndex !== -1) {\n const commonPrefix = key.slice(0, prefix.length + delimiterIndex + 1);\n prefixSet.add(commonPrefix);\n continue;\n }\n }\n\n files.push(file.metadata);\n\n if (files.length >= maxKeys) {\n break;\n }\n }\n\n return {\n files,\n prefixes: Array.from(prefixSet),\n isTruncated: files.length >= maxKeys,\n continuationToken: undefined,\n };\n }\n\n async copy(\n sourceKey: string,\n destKey: string,\n options?: CopyOptions\n ): Promise<FileMetadata> {\n this.validateKey(sourceKey);\n this.validateKey(destKey);\n\n const sourceFullKey = this.getFullKey(sourceKey);\n const destFullKey = this.getFullKey(destKey);\n\n const sourceFile = this.files.get(sourceFullKey);\n if (!sourceFile) {\n throw new StorageError(\n `Source file not found: ${sourceKey}`,\n StorageErrorCodes.NOT_FOUND,\n 404\n );\n }\n\n const newMetadata: FileMetadata =\n options?.metadataDirective === \"REPLACE\"\n ? {\n key: destFullKey,\n size: sourceFile.data.length,\n contentType: options.contentType ?? sourceFile.metadata.contentType,\n lastModified: new Date(),\n etag: sourceFile.metadata.etag,\n metadata: options.metadata ?? undefined,\n }\n : {\n ...sourceFile.metadata,\n key: destFullKey,\n lastModified: new Date(),\n };\n\n this.files.set(destFullKey, {\n data: sourceFile.data,\n metadata: newMetadata,\n });\n this.currentSize += sourceFile.data.length;\n\n return newMetadata;\n }\n\n async move(sourceKey: string, destKey: string): Promise<FileMetadata> {\n const metadata = await this.copy(sourceKey, destKey);\n await this.delete(sourceKey);\n return metadata;\n }\n\n async getPresignedUrl(\n key: string,\n options?: PresignedUrlOptions\n ): Promise<string> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n // Memory adapter doesn't support real presigned URLs\n // Return a fake URL for testing purposes\n const expiresIn = options?.expiresIn ?? 3600;\n const expires = Date.now() + expiresIn * 1000;\n\n return `memory://${this.bucket}/${fullKey}?expires=${expires}`;\n }\n\n async getUploadUrl(\n key: string,\n options?: PresignedUrlOptions\n ): Promise<string> {\n return this.getPresignedUrl(key, options);\n }\n\n /**\n * Clear all files (useful for testing)\n */\n clear(): void {\n this.files.clear();\n this.currentSize = 0;\n }\n\n /**\n * Get current storage size\n */\n getSize(): number {\n return this.currentSize;\n }\n\n /**\n * Get file count\n */\n getFileCount(): number {\n return this.files.size;\n }\n\n private guessContentType(key: string): string {\n const ext = key.split(\".\").pop()?.toLowerCase();\n const contentTypes: Record<string, string> = {\n txt: \"text/plain\",\n html: \"text/html\",\n css: \"text/css\",\n js: \"application/javascript\",\n json: \"application/json\",\n xml: \"application/xml\",\n pdf: \"application/pdf\",\n zip: \"application/zip\",\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n svg: \"image/svg+xml\",\n mp3: \"audio/mpeg\",\n mp4: \"video/mp4\",\n webm: \"video/webm\",\n };\n return contentTypes[ext ?? \"\"] ?? \"application/octet-stream\";\n }\n\n private generateEtag(data: Uint8Array): string {\n // Simple hash for testing - not cryptographically secure\n let hash = 0;\n for (const byte of data) {\n hash = ((hash << 5) - hash + byte) | 0;\n }\n return `\"${Math.abs(hash).toString(16)}\"`;\n }\n}\n\n/**\n * Create a memory storage adapter\n */\nexport function createMemoryAdapter(\n config: Omit<MemoryConfig, \"type\">\n): MemoryAdapter {\n return new MemoryAdapter({ ...config, type: \"memory\" });\n}\n","/**\n * @parsrun/storage - S3 Adapter\n * S3-compatible storage adapter (AWS S3, DigitalOcean Spaces, MinIO, etc.)\n */\n\nimport {\n type BatchDeleteResult,\n type CopyOptions,\n type DeleteResult,\n type DownloadOptions,\n type FileMetadata,\n type ListOptions,\n type ListResult,\n type PresignedUrlOptions,\n type S3Config,\n type StorageAdapter,\n type UploadOptions,\n StorageError,\n StorageErrorCodes,\n} from \"../types.js\";\n\n// Types for AWS SDK (dynamically imported)\ntype S3Client = import(\"@aws-sdk/client-s3\").S3Client;\ntype PutObjectCommandInput = import(\"@aws-sdk/client-s3\").PutObjectCommandInput;\n\n/**\n * S3 Storage Adapter\n * Works with AWS S3, DigitalOcean Spaces, MinIO, and other S3-compatible services\n *\n * @example\n * ```typescript\n * // AWS S3\n * const s3 = new S3Adapter({\n * type: 's3',\n * bucket: 'my-bucket',\n * region: 'us-east-1',\n * accessKeyId: process.env.AWS_ACCESS_KEY_ID,\n * secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,\n * });\n *\n * // DigitalOcean Spaces\n * const spaces = new S3Adapter({\n * type: 'do-spaces',\n * bucket: 'my-space',\n * region: 'nyc3',\n * accessKeyId: process.env.DO_SPACES_KEY,\n * secretAccessKey: process.env.DO_SPACES_SECRET,\n * endpoint: 'https://nyc3.digitaloceanspaces.com',\n * });\n *\n * await s3.upload('file.txt', 'Hello, World!');\n * ```\n */\nexport class S3Adapter implements StorageAdapter {\n readonly type: \"s3\" | \"do-spaces\";\n readonly bucket: string;\n\n private client: S3Client | null = null;\n private config: S3Config;\n private basePath: string;\n\n constructor(config: S3Config) {\n this.type = config.type;\n this.bucket = config.bucket;\n this.config = config;\n this.basePath = config.basePath ?? \"\";\n }\n\n /**\n * Lazy load S3 client\n */\n private async getClient(): Promise<S3Client> {\n if (this.client) return this.client;\n\n try {\n const { S3Client } = await import(\"@aws-sdk/client-s3\");\n\n const clientConfig: import(\"@aws-sdk/client-s3\").S3ClientConfig = {\n region: this.config.region,\n credentials: {\n accessKeyId: this.config.accessKeyId,\n secretAccessKey: this.config.secretAccessKey,\n },\n };\n\n // Only add optional properties if defined\n if (this.config.endpoint) {\n clientConfig.endpoint = this.config.endpoint;\n }\n if (this.config.forcePathStyle !== undefined) {\n clientConfig.forcePathStyle = this.config.forcePathStyle;\n }\n\n this.client = new S3Client(clientConfig);\n\n return this.client;\n } catch {\n throw new StorageError(\n \"AWS SDK not installed. Run: npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner\",\n StorageErrorCodes.ADAPTER_NOT_AVAILABLE\n );\n }\n }\n\n private getFullKey(key: string): string {\n return this.basePath ? `${this.basePath}/${key}` : key;\n }\n\n private validateKey(key: string): void {\n if (!key || key.includes(\"..\") || key.startsWith(\"/\")) {\n throw new StorageError(\n `Invalid key: ${key}`,\n StorageErrorCodes.INVALID_KEY\n );\n }\n }\n\n private async dataToBody(\n data: Uint8Array | ReadableStream<Uint8Array> | Blob | string\n ): Promise<Uint8Array | ReadableStream<Uint8Array> | string> {\n if (data instanceof Uint8Array || typeof data === \"string\") {\n return data;\n }\n\n if (data instanceof Blob) {\n const buffer = await data.arrayBuffer();\n return new Uint8Array(buffer);\n }\n\n return data;\n }\n\n async upload(\n key: string,\n data: Uint8Array | ReadableStream<Uint8Array> | Blob | string,\n options?: UploadOptions\n ): Promise<FileMetadata> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const client = await this.getClient();\n const { PutObjectCommand } = await import(\"@aws-sdk/client-s3\");\n\n const body = await this.dataToBody(data);\n\n const params: PutObjectCommandInput = {\n Bucket: this.bucket,\n Key: fullKey,\n Body: body as Uint8Array | string,\n ContentType: options?.contentType,\n ContentDisposition: options?.contentDisposition,\n CacheControl: options?.cacheControl,\n ContentEncoding: options?.contentEncoding,\n Metadata: options?.metadata,\n };\n\n if (options?.acl) {\n params.ACL = options.acl;\n }\n\n try {\n const result = await client.send(new PutObjectCommand(params));\n\n // Get size\n let size = 0;\n if (typeof body === \"string\") {\n size = new TextEncoder().encode(body).length;\n } else if (body instanceof Uint8Array) {\n size = body.length;\n }\n\n return {\n key: fullKey,\n size,\n contentType: options?.contentType ?? undefined,\n lastModified: new Date(),\n etag: result.ETag ?? undefined,\n metadata: options?.metadata ?? undefined,\n };\n } catch (err) {\n throw new StorageError(\n `Upload failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.UPLOAD_FAILED,\n undefined,\n err\n );\n }\n }\n\n async download(key: string, options?: DownloadOptions): Promise<Uint8Array> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const client = await this.getClient();\n const { GetObjectCommand } = await import(\"@aws-sdk/client-s3\");\n\n try {\n const params: import(\"@aws-sdk/client-s3\").GetObjectCommandInput = {\n Bucket: this.bucket,\n Key: fullKey,\n };\n\n if (options?.rangeStart !== undefined || options?.rangeEnd !== undefined) {\n const start = options.rangeStart ?? 0;\n const end = options.rangeEnd ?? \"\";\n params.Range = `bytes=${start}-${end}`;\n }\n\n if (options?.ifNoneMatch) {\n params.IfNoneMatch = options.ifNoneMatch;\n }\n\n if (options?.ifModifiedSince) {\n params.IfModifiedSince = options.ifModifiedSince;\n }\n\n const result = await client.send(new GetObjectCommand(params));\n\n if (!result.Body) {\n throw new StorageError(\n \"Empty response body\",\n StorageErrorCodes.DOWNLOAD_FAILED\n );\n }\n\n // Convert to Uint8Array\n const stream = result.Body as ReadableStream<Uint8Array>;\n return this.streamToUint8Array(stream);\n } catch (err) {\n if (\n err instanceof Error &&\n \"name\" in err &&\n err.name === \"NoSuchKey\"\n ) {\n throw new StorageError(\n `File not found: ${key}`,\n StorageErrorCodes.NOT_FOUND,\n 404\n );\n }\n throw new StorageError(\n `Download failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.DOWNLOAD_FAILED,\n undefined,\n err\n );\n }\n }\n\n async downloadStream(\n key: string,\n options?: DownloadOptions\n ): Promise<ReadableStream<Uint8Array>> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const client = await this.getClient();\n const { GetObjectCommand } = await import(\"@aws-sdk/client-s3\");\n\n try {\n const params: import(\"@aws-sdk/client-s3\").GetObjectCommandInput = {\n Bucket: this.bucket,\n Key: fullKey,\n };\n\n if (options?.rangeStart !== undefined || options?.rangeEnd !== undefined) {\n const start = options.rangeStart ?? 0;\n const end = options.rangeEnd ?? \"\";\n params.Range = `bytes=${start}-${end}`;\n }\n\n const result = await client.send(new GetObjectCommand(params));\n\n if (!result.Body) {\n throw new StorageError(\n \"Empty response body\",\n StorageErrorCodes.DOWNLOAD_FAILED\n );\n }\n\n return result.Body as ReadableStream<Uint8Array>;\n } catch (err) {\n if (\n err instanceof Error &&\n \"name\" in err &&\n err.name === \"NoSuchKey\"\n ) {\n throw new StorageError(\n `File not found: ${key}`,\n StorageErrorCodes.NOT_FOUND,\n 404\n );\n }\n throw err;\n }\n }\n\n async head(key: string): Promise<FileMetadata | null> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const client = await this.getClient();\n const { HeadObjectCommand } = await import(\"@aws-sdk/client-s3\");\n\n try {\n const result = await client.send(\n new HeadObjectCommand({\n Bucket: this.bucket,\n Key: fullKey,\n })\n );\n\n return {\n key: fullKey,\n size: result.ContentLength ?? 0,\n contentType: result.ContentType ?? undefined,\n lastModified: result.LastModified ?? undefined,\n etag: result.ETag ?? undefined,\n metadata: result.Metadata ?? undefined,\n };\n } catch (err) {\n if (\n err instanceof Error &&\n \"name\" in err &&\n (err.name === \"NoSuchKey\" || err.name === \"NotFound\")\n ) {\n return null;\n }\n throw err;\n }\n }\n\n async exists(key: string): Promise<boolean> {\n const metadata = await this.head(key);\n return metadata !== null;\n }\n\n async delete(key: string): Promise<DeleteResult> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const client = await this.getClient();\n const { DeleteObjectCommand } = await import(\"@aws-sdk/client-s3\");\n\n try {\n await client.send(\n new DeleteObjectCommand({\n Bucket: this.bucket,\n Key: fullKey,\n })\n );\n\n return { success: true, key: fullKey };\n } catch (err) {\n throw new StorageError(\n `Delete failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.DELETE_FAILED,\n undefined,\n err\n );\n }\n }\n\n async deleteMany(keys: string[]): Promise<BatchDeleteResult> {\n const client = await this.getClient();\n const { DeleteObjectsCommand } = await import(\"@aws-sdk/client-s3\");\n\n const objects = keys.map((key) => ({\n Key: this.getFullKey(key),\n }));\n\n try {\n const result = await client.send(\n new DeleteObjectsCommand({\n Bucket: this.bucket,\n Delete: { Objects: objects },\n })\n );\n\n const deleted = result.Deleted?.map((d) => d.Key ?? \"\") ?? [];\n const errors =\n result.Errors?.map((e) => ({\n key: e.Key ?? \"\",\n error: e.Message ?? \"Unknown error\",\n })) ?? [];\n\n return { deleted, errors };\n } catch (err) {\n throw new StorageError(\n `Batch delete failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.DELETE_FAILED,\n undefined,\n err\n );\n }\n }\n\n async list(options?: ListOptions): Promise<ListResult> {\n const client = await this.getClient();\n const { ListObjectsV2Command } = await import(\"@aws-sdk/client-s3\");\n\n const prefix = options?.prefix\n ? this.getFullKey(options.prefix)\n : this.basePath || undefined;\n\n try {\n const result = await client.send(\n new ListObjectsV2Command({\n Bucket: this.bucket,\n Prefix: prefix,\n Delimiter: options?.delimiter,\n MaxKeys: options?.maxKeys,\n ContinuationToken: options?.continuationToken,\n })\n );\n\n const files: FileMetadata[] =\n result.Contents?.map((item) => ({\n key: item.Key ?? \"\",\n size: item.Size ?? 0,\n contentType: undefined,\n lastModified: item.LastModified ?? undefined,\n etag: item.ETag ?? undefined,\n metadata: undefined,\n })) ?? [];\n\n const prefixes =\n result.CommonPrefixes?.map((p) => p.Prefix ?? \"\") ?? [];\n\n return {\n files,\n prefixes,\n isTruncated: result.IsTruncated ?? false,\n continuationToken: result.NextContinuationToken ?? undefined,\n };\n } catch (err) {\n throw new StorageError(\n `List failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.LIST_FAILED,\n undefined,\n err\n );\n }\n }\n\n async copy(\n sourceKey: string,\n destKey: string,\n options?: CopyOptions\n ): Promise<FileMetadata> {\n this.validateKey(sourceKey);\n this.validateKey(destKey);\n\n const client = await this.getClient();\n const { CopyObjectCommand } = await import(\"@aws-sdk/client-s3\");\n\n const sourceFullKey = this.getFullKey(sourceKey);\n const destFullKey = this.getFullKey(destKey);\n const sourceBucket = options?.sourceBucket ?? this.bucket;\n\n try {\n const result = await client.send(\n new CopyObjectCommand({\n Bucket: this.bucket,\n Key: destFullKey,\n CopySource: `${sourceBucket}/${sourceFullKey}`,\n MetadataDirective: options?.metadataDirective,\n ContentType: options?.contentType,\n Metadata: options?.metadata,\n })\n );\n\n // Get metadata of copied object\n const metadata = await this.head(destKey);\n\n return metadata ?? {\n key: destFullKey,\n size: 0,\n contentType: options?.contentType ?? undefined,\n lastModified: result.CopyObjectResult?.LastModified ?? new Date(),\n etag: result.CopyObjectResult?.ETag ?? undefined,\n metadata: options?.metadata ?? undefined,\n };\n } catch (err) {\n throw new StorageError(\n `Copy failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.COPY_FAILED,\n undefined,\n err\n );\n }\n }\n\n async move(sourceKey: string, destKey: string): Promise<FileMetadata> {\n const metadata = await this.copy(sourceKey, destKey);\n await this.delete(sourceKey);\n return metadata;\n }\n\n async getPresignedUrl(\n key: string,\n options?: PresignedUrlOptions\n ): Promise<string> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const client = await this.getClient();\n\n try {\n const { getSignedUrl } = await import(\"@aws-sdk/s3-request-presigner\");\n const { GetObjectCommand } = await import(\"@aws-sdk/client-s3\");\n\n const command = new GetObjectCommand({\n Bucket: this.bucket,\n Key: fullKey,\n ResponseCacheControl: options?.responseCacheControl,\n ResponseContentType: options?.responseContentType,\n ResponseContentDisposition: options?.contentDisposition,\n });\n\n return getSignedUrl(client, command, {\n expiresIn: options?.expiresIn ?? 3600,\n });\n } catch (err) {\n throw new StorageError(\n `Presigned URL failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.PRESIGN_FAILED,\n undefined,\n err\n );\n }\n }\n\n async getUploadUrl(\n key: string,\n options?: PresignedUrlOptions\n ): Promise<string> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const client = await this.getClient();\n\n try {\n const { getSignedUrl } = await import(\"@aws-sdk/s3-request-presigner\");\n const { PutObjectCommand } = await import(\"@aws-sdk/client-s3\");\n\n const command = new PutObjectCommand({\n Bucket: this.bucket,\n Key: fullKey,\n ContentType: options?.contentType,\n ContentDisposition: options?.contentDisposition,\n });\n\n return getSignedUrl(client, command, {\n expiresIn: options?.expiresIn ?? 3600,\n });\n } catch (err) {\n throw new StorageError(\n `Upload URL failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.PRESIGN_FAILED,\n undefined,\n err\n );\n }\n }\n\n private async streamToUint8Array(\n stream: ReadableStream<Uint8Array>\n ): Promise<Uint8Array> {\n const reader = stream.getReader();\n const chunks: Uint8Array[] = [];\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value) chunks.push(value);\n }\n\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const result = new Uint8Array(totalLength);\n let offset = 0;\n\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n\n return result;\n }\n}\n\n/**\n * Create an S3 storage adapter\n */\nexport function createS3Adapter(config: S3Config): S3Adapter {\n return new S3Adapter(config);\n}\n\n/**\n * Create a DigitalOcean Spaces adapter\n */\nexport function createDOSpacesAdapter(\n config: Omit<S3Config, \"type\" | \"endpoint\"> & {\n region: string;\n spaceName?: string;\n }\n): S3Adapter {\n return new S3Adapter({\n ...config,\n type: \"do-spaces\",\n endpoint: `https://${config.region}.digitaloceanspaces.com`,\n bucket: config.spaceName ?? config.bucket,\n });\n}\n","/**\n * @parsrun/storage - R2 Adapter\n * Cloudflare R2 storage adapter (edge-native)\n *\n * This adapter works in two modes:\n * 1. Worker binding (native R2 API) - fastest, edge-native\n * 2. S3-compatible API - for non-Worker environments\n */\n\nimport {\n type BatchDeleteResult,\n type CopyOptions,\n type DeleteResult,\n type DownloadOptions,\n type FileMetadata,\n type ListOptions,\n type ListResult,\n type PresignedUrlOptions,\n type R2Config,\n type StorageAdapter,\n type UploadOptions,\n StorageError,\n StorageErrorCodes,\n} from \"../types.js\";\n\n/**\n * Cloudflare R2 Bucket binding type\n */\nexport interface R2Bucket {\n head(key: string): Promise<R2Object | null>;\n get(key: string, options?: R2GetOptions): Promise<R2ObjectBody | null>;\n put(\n key: string,\n value: ArrayBuffer | ArrayBufferView | ReadableStream | string | null | Blob,\n options?: R2PutOptions\n ): Promise<R2Object>;\n delete(keys: string | string[]): Promise<void>;\n list(options?: R2ListOptions): Promise<R2Objects>;\n createMultipartUpload(key: string, options?: R2MultipartOptions): Promise<R2MultipartUpload>;\n}\n\ninterface R2Object {\n key: string;\n version: string;\n size: number;\n etag: string;\n httpEtag: string;\n checksums: R2Checksums;\n uploaded: Date;\n httpMetadata?: R2HTTPMetadata;\n customMetadata?: Record<string, string>;\n range?: R2Range;\n}\n\ninterface R2ObjectBody extends R2Object {\n body: ReadableStream;\n bodyUsed: boolean;\n arrayBuffer(): Promise<ArrayBuffer>;\n text(): Promise<string>;\n json<T>(): Promise<T>;\n blob(): Promise<Blob>;\n}\n\ninterface R2Checksums {\n md5?: ArrayBuffer;\n sha1?: ArrayBuffer;\n sha256?: ArrayBuffer;\n sha384?: ArrayBuffer;\n sha512?: ArrayBuffer;\n}\n\ninterface R2HTTPMetadata {\n contentType?: string;\n contentLanguage?: string;\n contentDisposition?: string;\n contentEncoding?: string;\n cacheControl?: string;\n cacheExpiry?: Date;\n}\n\ninterface R2Range {\n offset: number;\n length: number;\n}\n\ninterface R2GetOptions {\n onlyIf?: R2Conditional;\n range?: R2Range | { offset?: number; length?: number; suffix?: number };\n}\n\ninterface R2PutOptions {\n httpMetadata?: R2HTTPMetadata;\n customMetadata?: Record<string, string>;\n md5?: ArrayBuffer | string;\n sha1?: ArrayBuffer | string;\n sha256?: ArrayBuffer | string;\n sha384?: ArrayBuffer | string;\n sha512?: ArrayBuffer | string;\n}\n\ninterface R2Conditional {\n etagMatches?: string;\n etagDoesNotMatch?: string;\n uploadedBefore?: Date;\n uploadedAfter?: Date;\n}\n\ninterface R2ListOptions {\n prefix?: string;\n cursor?: string;\n delimiter?: string;\n limit?: number;\n include?: (\"httpMetadata\" | \"customMetadata\")[];\n}\n\ninterface R2Objects {\n objects: R2Object[];\n truncated: boolean;\n cursor?: string;\n delimitedPrefixes: string[];\n}\n\ninterface R2MultipartOptions {\n httpMetadata?: R2HTTPMetadata;\n customMetadata?: Record<string, string>;\n}\n\ninterface R2MultipartUpload {\n key: string;\n uploadId: string;\n uploadPart(partNumber: number, value: ArrayBuffer | ArrayBufferView | ReadableStream | string | Blob): Promise<R2UploadedPart>;\n abort(): Promise<void>;\n complete(uploadedParts: R2UploadedPart[]): Promise<R2Object>;\n}\n\ninterface R2UploadedPart {\n partNumber: number;\n etag: string;\n}\n\n/**\n * R2 Storage Adapter\n * Native Cloudflare R2 adapter optimized for Workers/Edge\n *\n * @example\n * ```typescript\n * // In Cloudflare Worker with binding\n * const r2 = new R2Adapter({\n * type: 'r2',\n * bucket: 'my-bucket',\n * accountId: env.CF_ACCOUNT_ID,\n * accessKeyId: env.R2_ACCESS_KEY,\n * secretAccessKey: env.R2_SECRET_KEY,\n * binding: env.MY_BUCKET, // R2 binding\n * });\n *\n * // Using S3-compatible API (non-Worker)\n * const r2 = new R2Adapter({\n * type: 'r2',\n * bucket: 'my-bucket',\n * accountId: env.CF_ACCOUNT_ID,\n * accessKeyId: env.R2_ACCESS_KEY,\n * secretAccessKey: env.R2_SECRET_KEY,\n * });\n * ```\n */\nexport class R2Adapter implements StorageAdapter {\n readonly type = \"r2\" as const;\n readonly bucket: string;\n\n private binding: R2Bucket | null = null;\n private s3Adapter: StorageAdapter | null = null;\n private config: R2Config & { binding?: R2Bucket };\n private basePath: string;\n\n constructor(config: R2Config & { binding?: R2Bucket }) {\n this.bucket = config.bucket;\n this.config = config;\n this.basePath = config.basePath ?? \"\";\n this.binding = config.binding ?? null;\n }\n\n /**\n * Get S3 adapter for fallback\n */\n private async getS3Adapter(): Promise<StorageAdapter> {\n if (this.s3Adapter) return this.s3Adapter;\n\n // Dynamically import S3 adapter\n const { S3Adapter } = await import(\"./s3.js\");\n\n this.s3Adapter = new S3Adapter({\n type: \"s3\",\n bucket: this.bucket,\n region: \"auto\",\n accessKeyId: this.config.accessKeyId,\n secretAccessKey: this.config.secretAccessKey,\n endpoint: `https://${this.config.accountId}.r2.cloudflarestorage.com`,\n });\n\n return this.s3Adapter;\n }\n\n private getFullKey(key: string): string {\n return this.basePath ? `${this.basePath}/${key}` : key;\n }\n\n private validateKey(key: string): void {\n if (!key || key.includes(\"..\") || key.startsWith(\"/\")) {\n throw new StorageError(\n `Invalid key: ${key}`,\n StorageErrorCodes.INVALID_KEY\n );\n }\n }\n\n private async dataToBody(\n data: Uint8Array | ReadableStream<Uint8Array> | Blob | string\n ): Promise<ArrayBuffer | ReadableStream | string | Blob> {\n if (data instanceof Uint8Array) {\n // Create a proper ArrayBuffer from the Uint8Array\n const buffer = new ArrayBuffer(data.length);\n new Uint8Array(buffer).set(data);\n return buffer;\n }\n return data;\n }\n\n async upload(\n key: string,\n data: Uint8Array | ReadableStream<Uint8Array> | Blob | string,\n options?: UploadOptions\n ): Promise<FileMetadata> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n // Use binding if available (Worker environment)\n if (this.binding) {\n const body = await this.dataToBody(data);\n\n // Build httpMetadata only with defined values\n const httpMetadata: R2HTTPMetadata = {};\n if (options?.contentType) httpMetadata.contentType = options.contentType;\n if (options?.contentDisposition) httpMetadata.contentDisposition = options.contentDisposition;\n if (options?.cacheControl) httpMetadata.cacheControl = options.cacheControl;\n if (options?.contentEncoding) httpMetadata.contentEncoding = options.contentEncoding;\n\n const putOptions: R2PutOptions = {\n httpMetadata,\n };\n if (options?.metadata) {\n putOptions.customMetadata = options.metadata;\n }\n\n try {\n const result = await this.binding.put(fullKey, body, putOptions);\n\n return {\n key: fullKey,\n size: result.size,\n contentType: result.httpMetadata?.contentType ?? undefined,\n lastModified: result.uploaded,\n etag: result.etag,\n metadata: result.customMetadata ?? undefined,\n };\n } catch (err) {\n throw new StorageError(\n `Upload failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.UPLOAD_FAILED,\n undefined,\n err\n );\n }\n }\n\n // Fallback to S3-compatible API\n const s3 = await this.getS3Adapter();\n return s3.upload(key, data, options);\n }\n\n async download(key: string, options?: DownloadOptions): Promise<Uint8Array> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n // Use binding if available\n if (this.binding) {\n try {\n const getOptions: R2GetOptions = {};\n\n if (options?.rangeStart !== undefined || options?.rangeEnd !== undefined) {\n const rangeOpts: { offset?: number; length?: number } = {\n offset: options.rangeStart ?? 0,\n };\n if (options.rangeEnd !== undefined) {\n rangeOpts.length = options.rangeEnd - (options.rangeStart ?? 0) + 1;\n }\n getOptions.range = rangeOpts;\n }\n\n if (options?.ifNoneMatch || options?.ifModifiedSince) {\n const conditional: R2Conditional = {};\n if (options.ifNoneMatch) conditional.etagDoesNotMatch = options.ifNoneMatch;\n if (options.ifModifiedSince) conditional.uploadedAfter = options.ifModifiedSince;\n getOptions.onlyIf = conditional;\n }\n\n const result = await this.binding.get(fullKey, getOptions);\n\n if (!result) {\n throw new StorageError(\n `File not found: ${key}`,\n StorageErrorCodes.NOT_FOUND,\n 404\n );\n }\n\n const buffer = await result.arrayBuffer();\n return new Uint8Array(buffer);\n } catch (err) {\n if (err instanceof StorageError) throw err;\n throw new StorageError(\n `Download failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.DOWNLOAD_FAILED,\n undefined,\n err\n );\n }\n }\n\n // Fallback to S3-compatible API\n const s3 = await this.getS3Adapter();\n return s3.download(key, options);\n }\n\n async downloadStream(\n key: string,\n options?: DownloadOptions\n ): Promise<ReadableStream<Uint8Array>> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n // Use binding if available\n if (this.binding) {\n try {\n const getOptions: R2GetOptions = {};\n\n if (options?.rangeStart !== undefined || options?.rangeEnd !== undefined) {\n const rangeOpts: { offset?: number; length?: number } = {\n offset: options.rangeStart ?? 0,\n };\n if (options.rangeEnd !== undefined) {\n rangeOpts.length = options.rangeEnd - (options.rangeStart ?? 0) + 1;\n }\n getOptions.range = rangeOpts;\n }\n\n const result = await this.binding.get(fullKey, getOptions);\n\n if (!result) {\n throw new StorageError(\n `File not found: ${key}`,\n StorageErrorCodes.NOT_FOUND,\n 404\n );\n }\n\n return result.body as ReadableStream<Uint8Array>;\n } catch (err) {\n if (err instanceof StorageError) throw err;\n throw new StorageError(\n `Download failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.DOWNLOAD_FAILED,\n undefined,\n err\n );\n }\n }\n\n // Fallback to S3-compatible API\n const s3 = await this.getS3Adapter();\n return s3.downloadStream(key, options);\n }\n\n async head(key: string): Promise<FileMetadata | null> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n // Use binding if available\n if (this.binding) {\n try {\n const result = await this.binding.head(fullKey);\n\n if (!result) {\n return null;\n }\n\n return {\n key: fullKey,\n size: result.size,\n contentType: result.httpMetadata?.contentType ?? undefined,\n lastModified: result.uploaded,\n etag: result.etag,\n metadata: result.customMetadata ?? undefined,\n };\n } catch {\n return null;\n }\n }\n\n // Fallback to S3-compatible API\n const s3 = await this.getS3Adapter();\n return s3.head(key);\n }\n\n async exists(key: string): Promise<boolean> {\n const metadata = await this.head(key);\n return metadata !== null;\n }\n\n async delete(key: string): Promise<DeleteResult> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n // Use binding if available\n if (this.binding) {\n try {\n await this.binding.delete(fullKey);\n return { success: true, key: fullKey };\n } catch (err) {\n throw new StorageError(\n `Delete failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.DELETE_FAILED,\n undefined,\n err\n );\n }\n }\n\n // Fallback to S3-compatible API\n const s3 = await this.getS3Adapter();\n return s3.delete(key);\n }\n\n async deleteMany(keys: string[]): Promise<BatchDeleteResult> {\n // Use binding if available\n if (this.binding) {\n const fullKeys = keys.map((key) => this.getFullKey(key));\n\n try {\n await this.binding.delete(fullKeys);\n return { deleted: fullKeys, errors: [] };\n } catch (err) {\n return {\n deleted: [],\n errors: fullKeys.map((key) => ({\n key,\n error: err instanceof Error ? err.message : \"Unknown error\",\n })),\n };\n }\n }\n\n // Fallback to S3-compatible API\n const s3 = await this.getS3Adapter();\n return s3.deleteMany(keys);\n }\n\n async list(options?: ListOptions): Promise<ListResult> {\n // Use binding if available\n if (this.binding) {\n try {\n const listOpts: R2ListOptions = {\n include: [\"httpMetadata\", \"customMetadata\"],\n };\n\n // Only add defined options\n const prefix = options?.prefix\n ? this.getFullKey(options.prefix)\n : this.basePath || null;\n if (prefix) listOpts.prefix = prefix;\n if (options?.delimiter) listOpts.delimiter = options.delimiter;\n if (options?.maxKeys) listOpts.limit = options.maxKeys;\n if (options?.continuationToken) listOpts.cursor = options.continuationToken;\n\n const result = await this.binding.list(listOpts);\n\n const files: FileMetadata[] = result.objects.map((obj) => ({\n key: obj.key,\n size: obj.size,\n contentType: obj.httpMetadata?.contentType ?? undefined,\n lastModified: obj.uploaded,\n etag: obj.etag,\n metadata: obj.customMetadata ?? undefined,\n }));\n\n return {\n files,\n prefixes: result.delimitedPrefixes,\n isTruncated: result.truncated,\n continuationToken: result.cursor ?? undefined,\n };\n } catch (err) {\n throw new StorageError(\n `List failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.LIST_FAILED,\n undefined,\n err\n );\n }\n }\n\n // Fallback to S3-compatible API\n const s3 = await this.getS3Adapter();\n return s3.list(options);\n }\n\n async copy(\n sourceKey: string,\n destKey: string,\n options?: CopyOptions\n ): Promise<FileMetadata> {\n // R2 binding doesn't have native copy, download and upload\n if (this.binding) {\n const data = await this.download(sourceKey);\n const sourceMetadata = await this.head(sourceKey);\n\n const uploadOptions: UploadOptions =\n options?.metadataDirective === \"REPLACE\"\n ? {\n contentType: options.contentType,\n metadata: options.metadata,\n }\n : {\n contentType: sourceMetadata?.contentType,\n metadata: sourceMetadata?.metadata,\n };\n\n return this.upload(destKey, data, uploadOptions);\n }\n\n // Fallback to S3-compatible API\n const s3 = await this.getS3Adapter();\n return s3.copy(sourceKey, destKey, options);\n }\n\n async move(sourceKey: string, destKey: string): Promise<FileMetadata> {\n const metadata = await this.copy(sourceKey, destKey);\n await this.delete(sourceKey);\n return metadata;\n }\n\n async getPresignedUrl(\n key: string,\n options?: PresignedUrlOptions\n ): Promise<string> {\n // R2 binding doesn't support presigned URLs, use S3 API\n const s3 = await this.getS3Adapter();\n return s3.getPresignedUrl(key, options);\n }\n\n async getUploadUrl(\n key: string,\n options?: PresignedUrlOptions\n ): Promise<string> {\n // R2 binding doesn't support presigned URLs, use S3 API\n const s3 = await this.getS3Adapter();\n return s3.getUploadUrl(key, options);\n }\n\n /**\n * Get public URL for a file (if custom domain is configured)\n */\n getPublicUrl(key: string): string | null {\n if (!this.config.customDomain) {\n return null;\n }\n\n const fullKey = this.getFullKey(key);\n return `https://${this.config.customDomain}/${fullKey}`;\n }\n}\n\n/**\n * Create an R2 storage adapter\n */\nexport function createR2Adapter(\n config: R2Config & { binding?: R2Bucket }\n): R2Adapter {\n return new R2Adapter(config);\n}\n","/**\n * @parsrun/storage\n * Edge-compatible storage abstraction for Pars\n *\n * Supports:\n * - AWS S3\n * - Cloudflare R2\n * - DigitalOcean Spaces\n * - MinIO (S3-compatible)\n * - Memory (for testing)\n *\n * @example\n * ```typescript\n * import { createStorage } from '@parsrun/storage';\n *\n * // AWS S3\n * const s3 = createStorage({\n * type: 's3',\n * bucket: 'my-bucket',\n * region: 'us-east-1',\n * accessKeyId: process.env.AWS_ACCESS_KEY_ID,\n * secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,\n * });\n *\n * // Cloudflare R2\n * const r2 = createStorage({\n * type: 'r2',\n * bucket: 'my-bucket',\n * accountId: process.env.CF_ACCOUNT_ID,\n * accessKeyId: process.env.R2_ACCESS_KEY,\n * secretAccessKey: process.env.R2_SECRET_KEY,\n * });\n *\n * // Upload\n * await s3.upload('path/to/file.txt', 'Hello, World!');\n *\n * // Download\n * const data = await s3.download('path/to/file.txt');\n *\n * // Get presigned URL\n * const url = await s3.getPresignedUrl('path/to/file.txt', { expiresIn: 3600 });\n * ```\n */\n\n// Types\nexport {\n type StorageAdapterType,\n type FileMetadata,\n type UploadOptions,\n type DownloadOptions,\n type ListOptions,\n type ListResult,\n type PresignedUrlOptions,\n type CopyOptions,\n type DeleteResult,\n type BatchDeleteResult,\n type StorageAdapter,\n type StorageConfig,\n type S3Config,\n type R2Config,\n type MemoryConfig,\n StorageError,\n StorageErrorCodes,\n} from \"./types.js\";\n\n// Adapters\nexport { MemoryAdapter, createMemoryAdapter } from \"./adapters/memory.js\";\nexport { S3Adapter, createS3Adapter, createDOSpacesAdapter } from \"./adapters/s3.js\";\nexport { R2Adapter, createR2Adapter } from \"./adapters/r2.js\";\n\n// Re-export R2 bucket type for typing\nexport type { R2Bucket } from \"./adapters/r2.js\";\n\nimport type { S3Config, R2Config, MemoryConfig, StorageAdapter } from \"./types.js\";\nimport { StorageError, StorageErrorCodes } from \"./types.js\";\n\n/**\n * Combined storage configuration\n */\nexport type AnyStorageConfig = S3Config | R2Config | MemoryConfig;\n\n/**\n * R2 binding type\n */\ntype R2Bucket = import(\"./adapters/r2.js\").R2Bucket;\n\n/**\n * Create a storage adapter based on configuration\n *\n * @param config - Storage configuration\n * @returns Storage adapter instance\n *\n * @example\n * ```typescript\n * // Memory (for testing)\n * const memory = createStorage({ type: 'memory', bucket: 'test' });\n *\n * // AWS S3\n * const s3 = createStorage({\n * type: 's3',\n * bucket: 'my-bucket',\n * region: 'us-east-1',\n * accessKeyId: 'xxx',\n * secretAccessKey: 'xxx',\n * });\n *\n * // Cloudflare R2\n * const r2 = createStorage({\n * type: 'r2',\n * bucket: 'my-bucket',\n * accountId: 'xxx',\n * accessKeyId: 'xxx',\n * secretAccessKey: 'xxx',\n * });\n *\n * // DigitalOcean Spaces\n * const spaces = createStorage({\n * type: 'do-spaces',\n * bucket: 'my-space',\n * region: 'nyc3',\n * accessKeyId: 'xxx',\n * secretAccessKey: 'xxx',\n * endpoint: 'https://nyc3.digitaloceanspaces.com',\n * });\n * ```\n */\nexport async function createStorage(\n config: AnyStorageConfig & { binding?: R2Bucket }\n): Promise<StorageAdapter> {\n switch (config.type) {\n case \"memory\": {\n const { MemoryAdapter } = await import(\"./adapters/memory.js\");\n return new MemoryAdapter(config);\n }\n\n case \"s3\":\n case \"do-spaces\": {\n const { S3Adapter } = await import(\"./adapters/s3.js\");\n return new S3Adapter(config as S3Config);\n }\n\n case \"r2\": {\n const { R2Adapter } = await import(\"./adapters/r2.js\");\n return new R2Adapter(config as R2Config & { binding?: R2Bucket });\n }\n\n default:\n throw new StorageError(\n `Unknown storage type: ${(config as AnyStorageConfig).type}`,\n StorageErrorCodes.INVALID_CONFIG\n );\n }\n}\n\n/**\n * Create storage adapter synchronously\n * Note: Some adapters may require async initialization for full functionality\n *\n * @param config - Storage configuration\n * @returns Storage adapter instance\n */\nexport function createStorageSync(\n config: AnyStorageConfig & { binding?: R2Bucket }\n): StorageAdapter {\n switch (config.type) {\n case \"memory\": {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { MemoryAdapter } = require(\"./adapters/memory.js\") as typeof import(\"./adapters/memory.js\");\n return new MemoryAdapter(config);\n }\n\n case \"s3\":\n case \"do-spaces\": {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { S3Adapter } = require(\"./adapters/s3.js\") as typeof import(\"./adapters/s3.js\");\n return new S3Adapter(config as S3Config);\n }\n\n case \"r2\": {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { R2Adapter } = require(\"./adapters/r2.js\") as typeof import(\"./adapters/r2.js\");\n return new R2Adapter(config as R2Config & { binding?: R2Bucket });\n }\n\n default:\n throw new StorageError(\n `Unknown storage type: ${(config as AnyStorageConfig).type}`,\n StorageErrorCodes.INVALID_CONFIG\n );\n }\n}\n\n/**\n * Storage utilities\n */\nexport const StorageUtils = {\n /**\n * Get file extension from key\n */\n getExtension(key: string): string {\n const parts = key.split(\".\");\n const lastPart = parts[parts.length - 1];\n return parts.length > 1 && lastPart ? lastPart.toLowerCase() : \"\";\n },\n\n /**\n * Get file name from key\n */\n getFileName(key: string): string {\n return key.split(\"/\").pop() ?? key;\n },\n\n /**\n * Get directory from key\n */\n getDirectory(key: string): string {\n const parts = key.split(\"/\");\n parts.pop();\n return parts.join(\"/\");\n },\n\n /**\n * Join paths safely\n */\n joinPath(...parts: string[]): string {\n return parts\n .filter(Boolean)\n .map((p) => p.replace(/^\\/|\\/$/g, \"\"))\n .join(\"/\");\n },\n\n /**\n * Normalize key (remove leading slash, handle ..)\n */\n normalizeKey(key: string): string {\n return key\n .replace(/^\\/+/, \"\")\n .split(\"/\")\n .filter((p) => p !== \"..\" && p !== \".\")\n .join(\"/\");\n },\n\n /**\n * Generate a unique key with timestamp\n */\n generateUniqueKey(prefix: string, extension?: string): string {\n const timestamp = Date.now();\n const random = Math.random().toString(36).slice(2, 10);\n const ext = extension ? `.${extension}` : \"\";\n return `${prefix}/${timestamp}-${random}${ext}`;\n },\n\n /**\n * Guess content type from file extension\n */\n guessContentType(key: string): string {\n const ext = StorageUtils.getExtension(key);\n const contentTypes: Record<string, string> = {\n // Text\n txt: \"text/plain\",\n html: \"text/html\",\n htm: \"text/html\",\n css: \"text/css\",\n csv: \"text/csv\",\n xml: \"text/xml\",\n\n // Application\n js: \"application/javascript\",\n mjs: \"application/javascript\",\n json: \"application/json\",\n pdf: \"application/pdf\",\n zip: \"application/zip\",\n gzip: \"application/gzip\",\n gz: \"application/gzip\",\n tar: \"application/x-tar\",\n doc: \"application/msword\",\n docx: \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n xls: \"application/vnd.ms-excel\",\n xlsx: \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n ppt: \"application/vnd.ms-powerpoint\",\n pptx: \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\n\n // Images\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n svg: \"image/svg+xml\",\n ico: \"image/x-icon\",\n bmp: \"image/bmp\",\n tiff: \"image/tiff\",\n tif: \"image/tiff\",\n\n // Audio\n mp3: \"audio/mpeg\",\n wav: \"audio/wav\",\n ogg: \"audio/ogg\",\n flac: \"audio/flac\",\n aac: \"audio/aac\",\n\n // Video\n mp4: \"video/mp4\",\n webm: \"video/webm\",\n avi: \"video/x-msvideo\",\n mov: \"video/quicktime\",\n mkv: \"video/x-matroska\",\n\n // Fonts\n woff: \"font/woff\",\n woff2: \"font/woff2\",\n ttf: \"font/ttf\",\n otf: \"font/otf\",\n eot: \"application/vnd.ms-fontobject\",\n };\n\n return contentTypes[ext] ?? \"application/octet-stream\";\n },\n\n /**\n * Format file size to human readable string\n */\n formatSize(bytes: number): string {\n const units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n let size = bytes;\n let unitIndex = 0;\n\n while (size >= 1024 && unitIndex < units.length - 1) {\n size /= 1024;\n unitIndex++;\n }\n\n return `${size.toFixed(unitIndex > 0 ? 2 : 0)} ${units[unitIndex]}`;\n },\n\n /**\n * Parse file size string to bytes\n */\n parseSize(size: string): number {\n const units: Record<string, number> = {\n b: 1,\n kb: 1024,\n mb: 1024 * 1024,\n gb: 1024 * 1024 * 1024,\n tb: 1024 * 1024 * 1024 * 1024,\n };\n\n const match = size.toLowerCase().match(/^(\\d+(?:\\.\\d+)?)\\s*([a-z]+)?$/);\n if (!match || !match[1]) return 0;\n\n const value = parseFloat(match[1]);\n const unit = match[2] ?? \"b\";\n\n return Math.floor(value * (units[unit] ?? 1));\n },\n};\n"],"mappings":"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","names":["S3Adapter","uploadOptions","MemoryAdapter","S3Adapter","R2Adapter"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/adapters/memory.ts","../src/adapters/s3.ts","../src/adapters/r2.ts","../src/index.ts"],"sourcesContent":["/**\n * @parsrun/storage - Type Definitions\n * Storage abstraction types for edge-compatible storage\n */\n\n// Re-export types from @parsrun/types for convenience\nexport {\n type,\n fileMetadata,\n uploadOptions as parsUploadOptions,\n signedUrlOptions,\n listFilesOptions,\n listFilesResult,\n localStorageConfig,\n s3StorageConfig,\n r2StorageConfig,\n gcsStorageConfig,\n storageProviderConfig,\n type FileMetadata as ParsFileMetadata,\n type UploadOptions as ParsUploadOptions,\n type SignedUrlOptions,\n type ListFilesOptions,\n type ListFilesResult,\n type LocalStorageConfig,\n type S3StorageConfig,\n type R2StorageConfig,\n type GcsStorageConfig,\n type StorageProviderConfig,\n} from \"@parsrun/types\";\n\n/**\n * Storage adapter type\n */\nexport type StorageAdapterType = \"s3\" | \"r2\" | \"do-spaces\" | \"memory\" | \"custom\";\n\n/**\n * File metadata\n */\nexport interface FileMetadata {\n /** File key/path */\n key: string;\n /** File size in bytes */\n size: number;\n /** Content type (MIME type) */\n contentType: string | undefined;\n /** Last modified date */\n lastModified: Date | undefined;\n /** ETag (entity tag) */\n etag: string | undefined;\n /** Custom metadata */\n metadata: Record<string, string> | undefined;\n}\n\n/**\n * Upload options\n */\nexport interface UploadOptions {\n /** Content type override */\n contentType?: string | undefined;\n /** Content disposition */\n contentDisposition?: string | undefined;\n /** Cache control header */\n cacheControl?: string | undefined;\n /** Content encoding */\n contentEncoding?: string | undefined;\n /** Custom metadata */\n metadata?: Record<string, string> | undefined;\n /** ACL (access control list) */\n acl?: \"private\" | \"public-read\" | undefined;\n}\n\n/**\n * Download options\n */\nexport interface DownloadOptions {\n /** Range start (for partial downloads) */\n rangeStart?: number | undefined;\n /** Range end (for partial downloads) */\n rangeEnd?: number | undefined;\n /** If-None-Match (ETag) */\n ifNoneMatch?: string | undefined;\n /** If-Modified-Since */\n ifModifiedSince?: Date | undefined;\n}\n\n/**\n * List options\n */\nexport interface ListOptions {\n /** Prefix to filter by */\n prefix?: string | undefined;\n /** Delimiter for hierarchy */\n delimiter?: string | undefined;\n /** Maximum keys to return */\n maxKeys?: number | undefined;\n /** Continuation token for pagination */\n continuationToken?: string | undefined;\n}\n\n/**\n * List result\n */\nexport interface ListResult {\n /** List of files */\n files: FileMetadata[];\n /** Common prefixes (for hierarchical listing) */\n prefixes: string[];\n /** Whether there are more results */\n isTruncated: boolean;\n /** Continuation token for next page */\n continuationToken: string | undefined;\n}\n\n/**\n * Presigned URL options\n */\nexport interface PresignedUrlOptions {\n /** URL expiration in seconds (default: 3600) */\n expiresIn?: number | undefined;\n /** Content type (for upload URLs) */\n contentType?: string | undefined;\n /** Content disposition */\n contentDisposition?: string | undefined;\n /** Response cache control */\n responseCacheControl?: string | undefined;\n /** Response content type */\n responseContentType?: string | undefined;\n}\n\n/**\n * Copy options\n */\nexport interface CopyOptions {\n /** Source bucket (if different from destination) */\n sourceBucket?: string | undefined;\n /** Metadata directive */\n metadataDirective?: \"COPY\" | \"REPLACE\" | undefined;\n /** New metadata (if REPLACE) */\n metadata?: Record<string, string> | undefined;\n /** New content type (if REPLACE) */\n contentType?: string | undefined;\n}\n\n/**\n * Delete result\n */\nexport interface DeleteResult {\n /** Whether deletion was successful */\n success: boolean;\n /** Deleted key */\n key: string;\n}\n\n/**\n * Batch delete result\n */\nexport interface BatchDeleteResult {\n /** Successfully deleted keys */\n deleted: string[];\n /** Failed deletions */\n errors: Array<{ key: string; error: string }>;\n}\n\n/**\n * Storage adapter interface\n * All storage adapters must implement this interface\n */\nexport interface StorageAdapter {\n /** Adapter type */\n readonly type: StorageAdapterType;\n\n /** Bucket name */\n readonly bucket: string;\n\n /**\n * Upload a file\n * @param key - File key/path\n * @param data - File data\n * @param options - Upload options\n */\n upload(\n key: string,\n data: Uint8Array | ReadableStream<Uint8Array> | Blob | string,\n options?: UploadOptions\n ): Promise<FileMetadata>;\n\n /**\n * Download a file\n * @param key - File key/path\n * @param options - Download options\n */\n download(key: string, options?: DownloadOptions): Promise<Uint8Array>;\n\n /**\n * Download a file as a stream\n * @param key - File key/path\n * @param options - Download options\n */\n downloadStream(\n key: string,\n options?: DownloadOptions\n ): Promise<ReadableStream<Uint8Array>>;\n\n /**\n * Get file metadata\n * @param key - File key/path\n */\n head(key: string): Promise<FileMetadata | null>;\n\n /**\n * Check if file exists\n * @param key - File key/path\n */\n exists(key: string): Promise<boolean>;\n\n /**\n * Delete a file\n * @param key - File key/path\n */\n delete(key: string): Promise<DeleteResult>;\n\n /**\n * Delete multiple files\n * @param keys - File keys/paths\n */\n deleteMany(keys: string[]): Promise<BatchDeleteResult>;\n\n /**\n * List files\n * @param options - List options\n */\n list(options?: ListOptions): Promise<ListResult>;\n\n /**\n * Copy a file\n * @param sourceKey - Source key\n * @param destKey - Destination key\n * @param options - Copy options\n */\n copy(sourceKey: string, destKey: string, options?: CopyOptions): Promise<FileMetadata>;\n\n /**\n * Move/rename a file\n * @param sourceKey - Source key\n * @param destKey - Destination key\n */\n move(sourceKey: string, destKey: string): Promise<FileMetadata>;\n\n /**\n * Generate a presigned URL for download\n * @param key - File key/path\n * @param options - URL options\n */\n getPresignedUrl(key: string, options?: PresignedUrlOptions): Promise<string>;\n\n /**\n * Generate a presigned URL for upload\n * @param key - File key/path\n * @param options - URL options\n */\n getUploadUrl(key: string, options?: PresignedUrlOptions): Promise<string>;\n}\n\n/**\n * Storage configuration\n */\nexport interface StorageConfig {\n /** Default bucket name */\n bucket: string;\n /** Storage adapter type */\n type: StorageAdapterType;\n /** Base path prefix for all operations */\n basePath?: string | undefined;\n /** Public URL prefix */\n publicUrl?: string | undefined;\n}\n\n/**\n * S3 configuration\n */\nexport interface S3Config extends StorageConfig {\n type: \"s3\" | \"do-spaces\";\n /** AWS region */\n region: string;\n /** Access key ID */\n accessKeyId: string;\n /** Secret access key */\n secretAccessKey: string;\n /** Custom endpoint (for DO Spaces, MinIO, etc.) */\n endpoint?: string | undefined;\n /** Force path style (for MinIO) */\n forcePathStyle?: boolean | undefined;\n}\n\n/**\n * R2 configuration\n */\nexport interface R2Config extends StorageConfig {\n type: \"r2\";\n /** Cloudflare account ID */\n accountId: string;\n /** R2 access key ID */\n accessKeyId: string;\n /** R2 secret access key */\n secretAccessKey: string;\n /** Custom domain for public access */\n customDomain?: string | undefined;\n}\n\n/**\n * Memory storage configuration (for testing)\n */\nexport interface MemoryConfig extends StorageConfig {\n type: \"memory\";\n /** Maximum storage size in bytes */\n maxSize?: number | undefined;\n}\n\n/**\n * Storage error\n */\nexport class StorageError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly statusCode?: number | undefined,\n public readonly cause?: unknown\n ) {\n super(message);\n this.name = \"StorageError\";\n }\n}\n\n/**\n * Common storage error codes\n */\nexport const StorageErrorCodes = {\n NOT_FOUND: \"NOT_FOUND\",\n ACCESS_DENIED: \"ACCESS_DENIED\",\n BUCKET_NOT_FOUND: \"BUCKET_NOT_FOUND\",\n INVALID_KEY: \"INVALID_KEY\",\n UPLOAD_FAILED: \"UPLOAD_FAILED\",\n DOWNLOAD_FAILED: \"DOWNLOAD_FAILED\",\n DELETE_FAILED: \"DELETE_FAILED\",\n COPY_FAILED: \"COPY_FAILED\",\n LIST_FAILED: \"LIST_FAILED\",\n PRESIGN_FAILED: \"PRESIGN_FAILED\",\n QUOTA_EXCEEDED: \"QUOTA_EXCEEDED\",\n INVALID_CONFIG: \"INVALID_CONFIG\",\n ADAPTER_NOT_AVAILABLE: \"ADAPTER_NOT_AVAILABLE\",\n} as const;\n","/**\n * @parsrun/storage - Memory Adapter\n * In-memory storage adapter for development and testing\n */\n\nimport {\n type BatchDeleteResult,\n type CopyOptions,\n type DeleteResult,\n type DownloadOptions,\n type FileMetadata,\n type ListOptions,\n type ListResult,\n type MemoryConfig,\n type PresignedUrlOptions,\n type StorageAdapter,\n type UploadOptions,\n StorageError,\n StorageErrorCodes,\n} from \"../types.js\";\n\n/**\n * Internal file storage structure\n */\ninterface StoredFile {\n data: Uint8Array;\n metadata: FileMetadata;\n}\n\n/**\n * Memory Storage Adapter\n * Stores files in memory - useful for development and testing\n *\n * @example\n * ```typescript\n * const storage = new MemoryAdapter({\n * type: 'memory',\n * bucket: 'test-bucket',\n * });\n *\n * await storage.upload('test.txt', 'Hello, World!');\n * const data = await storage.download('test.txt');\n * ```\n */\nexport class MemoryAdapter implements StorageAdapter {\n readonly type = \"memory\" as const;\n readonly bucket: string;\n\n private files: Map<string, StoredFile> = new Map();\n private maxSize: number;\n private currentSize = 0;\n private basePath: string;\n\n constructor(config: MemoryConfig) {\n this.bucket = config.bucket;\n this.maxSize = config.maxSize ?? Infinity;\n this.basePath = config.basePath ?? \"\";\n }\n\n private getFullKey(key: string): string {\n return this.basePath ? `${this.basePath}/${key}` : key;\n }\n\n private validateKey(key: string): void {\n if (!key || key.includes(\"..\") || key.startsWith(\"/\")) {\n throw new StorageError(\n `Invalid key: ${key}`,\n StorageErrorCodes.INVALID_KEY\n );\n }\n }\n\n private dataToUint8Array(\n data: Uint8Array | ReadableStream<Uint8Array> | Blob | string\n ): Promise<Uint8Array> | Uint8Array {\n if (data instanceof Uint8Array) {\n return data;\n }\n\n if (typeof data === \"string\") {\n return new TextEncoder().encode(data);\n }\n\n if (data instanceof Blob) {\n return data.arrayBuffer().then((buffer) => new Uint8Array(buffer));\n }\n\n // ReadableStream\n return this.streamToUint8Array(data);\n }\n\n private async streamToUint8Array(\n stream: ReadableStream<Uint8Array>\n ): Promise<Uint8Array> {\n const reader = stream.getReader();\n const chunks: Uint8Array[] = [];\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n }\n\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const result = new Uint8Array(totalLength);\n let offset = 0;\n\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n\n return result;\n }\n\n async upload(\n key: string,\n data: Uint8Array | ReadableStream<Uint8Array> | Blob | string,\n options?: UploadOptions\n ): Promise<FileMetadata> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const uint8Data = await this.dataToUint8Array(data);\n\n // Check quota\n const existingFile = this.files.get(fullKey);\n const sizeDiff = uint8Data.length - (existingFile?.data.length ?? 0);\n\n if (this.currentSize + sizeDiff > this.maxSize) {\n throw new StorageError(\n \"Storage quota exceeded\",\n StorageErrorCodes.QUOTA_EXCEEDED\n );\n }\n\n const metadata: FileMetadata = {\n key: fullKey,\n size: uint8Data.length,\n contentType: options?.contentType ?? this.guessContentType(key),\n lastModified: new Date(),\n etag: this.generateEtag(uint8Data),\n metadata: options?.metadata ?? undefined,\n };\n\n this.files.set(fullKey, { data: uint8Data, metadata });\n this.currentSize += sizeDiff;\n\n return metadata;\n }\n\n async download(key: string, _options?: DownloadOptions): Promise<Uint8Array> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const file = this.files.get(fullKey);\n if (!file) {\n throw new StorageError(\n `File not found: ${key}`,\n StorageErrorCodes.NOT_FOUND,\n 404\n );\n }\n\n return file.data;\n }\n\n async downloadStream(\n key: string,\n _options?: DownloadOptions\n ): Promise<ReadableStream<Uint8Array>> {\n const data = await this.download(key);\n\n return new ReadableStream({\n start(controller) {\n controller.enqueue(data);\n controller.close();\n },\n });\n }\n\n async head(key: string): Promise<FileMetadata | null> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const file = this.files.get(fullKey);\n return file?.metadata ?? null;\n }\n\n async exists(key: string): Promise<boolean> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n return this.files.has(fullKey);\n }\n\n async delete(key: string): Promise<DeleteResult> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const file = this.files.get(fullKey);\n if (file) {\n this.currentSize -= file.data.length;\n this.files.delete(fullKey);\n }\n\n return { success: true, key: fullKey };\n }\n\n async deleteMany(keys: string[]): Promise<BatchDeleteResult> {\n const deleted: string[] = [];\n const errors: Array<{ key: string; error: string }> = [];\n\n for (const key of keys) {\n try {\n await this.delete(key);\n deleted.push(this.getFullKey(key));\n } catch (err) {\n errors.push({\n key: this.getFullKey(key),\n error: err instanceof Error ? err.message : \"Unknown error\",\n });\n }\n }\n\n return { deleted, errors };\n }\n\n async list(options?: ListOptions): Promise<ListResult> {\n const prefix = options?.prefix\n ? this.getFullKey(options.prefix)\n : this.basePath;\n const delimiter = options?.delimiter ?? \"/\";\n const maxKeys = options?.maxKeys ?? 1000;\n\n const files: FileMetadata[] = [];\n const prefixSet = new Set<string>();\n\n for (const [key, file] of this.files) {\n if (prefix && !key.startsWith(prefix)) {\n continue;\n }\n\n const relativePath = prefix ? key.slice(prefix.length) : key;\n\n // Handle delimiter for hierarchical listing\n if (delimiter) {\n const delimiterIndex = relativePath.indexOf(delimiter);\n if (delimiterIndex !== -1) {\n const commonPrefix = key.slice(0, prefix.length + delimiterIndex + 1);\n prefixSet.add(commonPrefix);\n continue;\n }\n }\n\n files.push(file.metadata);\n\n if (files.length >= maxKeys) {\n break;\n }\n }\n\n return {\n files,\n prefixes: Array.from(prefixSet),\n isTruncated: files.length >= maxKeys,\n continuationToken: undefined,\n };\n }\n\n async copy(\n sourceKey: string,\n destKey: string,\n options?: CopyOptions\n ): Promise<FileMetadata> {\n this.validateKey(sourceKey);\n this.validateKey(destKey);\n\n const sourceFullKey = this.getFullKey(sourceKey);\n const destFullKey = this.getFullKey(destKey);\n\n const sourceFile = this.files.get(sourceFullKey);\n if (!sourceFile) {\n throw new StorageError(\n `Source file not found: ${sourceKey}`,\n StorageErrorCodes.NOT_FOUND,\n 404\n );\n }\n\n const newMetadata: FileMetadata =\n options?.metadataDirective === \"REPLACE\"\n ? {\n key: destFullKey,\n size: sourceFile.data.length,\n contentType: options.contentType ?? sourceFile.metadata.contentType,\n lastModified: new Date(),\n etag: sourceFile.metadata.etag,\n metadata: options.metadata ?? undefined,\n }\n : {\n ...sourceFile.metadata,\n key: destFullKey,\n lastModified: new Date(),\n };\n\n this.files.set(destFullKey, {\n data: sourceFile.data,\n metadata: newMetadata,\n });\n this.currentSize += sourceFile.data.length;\n\n return newMetadata;\n }\n\n async move(sourceKey: string, destKey: string): Promise<FileMetadata> {\n const metadata = await this.copy(sourceKey, destKey);\n await this.delete(sourceKey);\n return metadata;\n }\n\n async getPresignedUrl(\n key: string,\n options?: PresignedUrlOptions\n ): Promise<string> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n // Memory adapter doesn't support real presigned URLs\n // Return a fake URL for testing purposes\n const expiresIn = options?.expiresIn ?? 3600;\n const expires = Date.now() + expiresIn * 1000;\n\n return `memory://${this.bucket}/${fullKey}?expires=${expires}`;\n }\n\n async getUploadUrl(\n key: string,\n options?: PresignedUrlOptions\n ): Promise<string> {\n return this.getPresignedUrl(key, options);\n }\n\n /**\n * Clear all files (useful for testing)\n */\n clear(): void {\n this.files.clear();\n this.currentSize = 0;\n }\n\n /**\n * Get current storage size\n */\n getSize(): number {\n return this.currentSize;\n }\n\n /**\n * Get file count\n */\n getFileCount(): number {\n return this.files.size;\n }\n\n private guessContentType(key: string): string {\n const ext = key.split(\".\").pop()?.toLowerCase();\n const contentTypes: Record<string, string> = {\n txt: \"text/plain\",\n html: \"text/html\",\n css: \"text/css\",\n js: \"application/javascript\",\n json: \"application/json\",\n xml: \"application/xml\",\n pdf: \"application/pdf\",\n zip: \"application/zip\",\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n svg: \"image/svg+xml\",\n mp3: \"audio/mpeg\",\n mp4: \"video/mp4\",\n webm: \"video/webm\",\n };\n return contentTypes[ext ?? \"\"] ?? \"application/octet-stream\";\n }\n\n private generateEtag(data: Uint8Array): string {\n // Simple hash for testing - not cryptographically secure\n let hash = 0;\n for (const byte of data) {\n hash = ((hash << 5) - hash + byte) | 0;\n }\n return `\"${Math.abs(hash).toString(16)}\"`;\n }\n}\n\n/**\n * Create a memory storage adapter\n */\nexport function createMemoryAdapter(\n config: Omit<MemoryConfig, \"type\">\n): MemoryAdapter {\n return new MemoryAdapter({ ...config, type: \"memory\" });\n}\n","/**\n * @parsrun/storage - S3 Adapter\n * S3-compatible storage adapter (AWS S3, DigitalOcean Spaces, MinIO, etc.)\n */\n\nimport {\n type BatchDeleteResult,\n type CopyOptions,\n type DeleteResult,\n type DownloadOptions,\n type FileMetadata,\n type ListOptions,\n type ListResult,\n type PresignedUrlOptions,\n type S3Config,\n type StorageAdapter,\n type UploadOptions,\n StorageError,\n StorageErrorCodes,\n} from \"../types.js\";\n\n// Types for AWS SDK (dynamically imported)\ntype S3Client = import(\"@aws-sdk/client-s3\").S3Client;\ntype PutObjectCommandInput = import(\"@aws-sdk/client-s3\").PutObjectCommandInput;\n\n/**\n * S3 Storage Adapter\n * Works with AWS S3, DigitalOcean Spaces, MinIO, and other S3-compatible services\n *\n * @example\n * ```typescript\n * // AWS S3\n * const s3 = new S3Adapter({\n * type: 's3',\n * bucket: 'my-bucket',\n * region: 'us-east-1',\n * accessKeyId: process.env.AWS_ACCESS_KEY_ID,\n * secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,\n * });\n *\n * // DigitalOcean Spaces\n * const spaces = new S3Adapter({\n * type: 'do-spaces',\n * bucket: 'my-space',\n * region: 'nyc3',\n * accessKeyId: process.env.DO_SPACES_KEY,\n * secretAccessKey: process.env.DO_SPACES_SECRET,\n * endpoint: 'https://nyc3.digitaloceanspaces.com',\n * });\n *\n * await s3.upload('file.txt', 'Hello, World!');\n * ```\n */\nexport class S3Adapter implements StorageAdapter {\n readonly type: \"s3\" | \"do-spaces\";\n readonly bucket: string;\n\n private client: S3Client | null = null;\n private config: S3Config;\n private basePath: string;\n\n constructor(config: S3Config) {\n this.type = config.type;\n this.bucket = config.bucket;\n this.config = config;\n this.basePath = config.basePath ?? \"\";\n }\n\n /**\n * Lazy load S3 client\n */\n private async getClient(): Promise<S3Client> {\n if (this.client) return this.client;\n\n try {\n const { S3Client } = await import(\"@aws-sdk/client-s3\");\n\n const clientConfig: import(\"@aws-sdk/client-s3\").S3ClientConfig = {\n region: this.config.region,\n credentials: {\n accessKeyId: this.config.accessKeyId,\n secretAccessKey: this.config.secretAccessKey,\n },\n };\n\n // Only add optional properties if defined\n if (this.config.endpoint) {\n clientConfig.endpoint = this.config.endpoint;\n }\n if (this.config.forcePathStyle !== undefined) {\n clientConfig.forcePathStyle = this.config.forcePathStyle;\n }\n\n this.client = new S3Client(clientConfig);\n\n return this.client;\n } catch {\n throw new StorageError(\n \"AWS SDK not installed. Run: npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner\",\n StorageErrorCodes.ADAPTER_NOT_AVAILABLE\n );\n }\n }\n\n private getFullKey(key: string): string {\n return this.basePath ? `${this.basePath}/${key}` : key;\n }\n\n private validateKey(key: string): void {\n if (!key || key.includes(\"..\") || key.startsWith(\"/\")) {\n throw new StorageError(\n `Invalid key: ${key}`,\n StorageErrorCodes.INVALID_KEY\n );\n }\n }\n\n private async dataToBody(\n data: Uint8Array | ReadableStream<Uint8Array> | Blob | string\n ): Promise<Uint8Array | ReadableStream<Uint8Array> | string> {\n if (data instanceof Uint8Array || typeof data === \"string\") {\n return data;\n }\n\n if (data instanceof Blob) {\n const buffer = await data.arrayBuffer();\n return new Uint8Array(buffer);\n }\n\n return data;\n }\n\n async upload(\n key: string,\n data: Uint8Array | ReadableStream<Uint8Array> | Blob | string,\n options?: UploadOptions\n ): Promise<FileMetadata> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const client = await this.getClient();\n const { PutObjectCommand } = await import(\"@aws-sdk/client-s3\");\n\n const body = await this.dataToBody(data);\n\n const params: PutObjectCommandInput = {\n Bucket: this.bucket,\n Key: fullKey,\n Body: body as Uint8Array | string,\n ContentType: options?.contentType,\n ContentDisposition: options?.contentDisposition,\n CacheControl: options?.cacheControl,\n ContentEncoding: options?.contentEncoding,\n Metadata: options?.metadata,\n };\n\n if (options?.acl) {\n params.ACL = options.acl;\n }\n\n try {\n const result = await client.send(new PutObjectCommand(params));\n\n // Get size\n let size = 0;\n if (typeof body === \"string\") {\n size = new TextEncoder().encode(body).length;\n } else if (body instanceof Uint8Array) {\n size = body.length;\n }\n\n return {\n key: fullKey,\n size,\n contentType: options?.contentType ?? undefined,\n lastModified: new Date(),\n etag: result.ETag ?? undefined,\n metadata: options?.metadata ?? undefined,\n };\n } catch (err) {\n throw new StorageError(\n `Upload failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.UPLOAD_FAILED,\n undefined,\n err\n );\n }\n }\n\n async download(key: string, options?: DownloadOptions): Promise<Uint8Array> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const client = await this.getClient();\n const { GetObjectCommand } = await import(\"@aws-sdk/client-s3\");\n\n try {\n const params: import(\"@aws-sdk/client-s3\").GetObjectCommandInput = {\n Bucket: this.bucket,\n Key: fullKey,\n };\n\n if (options?.rangeStart !== undefined || options?.rangeEnd !== undefined) {\n const start = options.rangeStart ?? 0;\n const end = options.rangeEnd ?? \"\";\n params.Range = `bytes=${start}-${end}`;\n }\n\n if (options?.ifNoneMatch) {\n params.IfNoneMatch = options.ifNoneMatch;\n }\n\n if (options?.ifModifiedSince) {\n params.IfModifiedSince = options.ifModifiedSince;\n }\n\n const result = await client.send(new GetObjectCommand(params));\n\n if (!result.Body) {\n throw new StorageError(\n \"Empty response body\",\n StorageErrorCodes.DOWNLOAD_FAILED\n );\n }\n\n // Convert to Uint8Array\n const stream = result.Body as ReadableStream<Uint8Array>;\n return this.streamToUint8Array(stream);\n } catch (err) {\n if (\n err instanceof Error &&\n \"name\" in err &&\n err.name === \"NoSuchKey\"\n ) {\n throw new StorageError(\n `File not found: ${key}`,\n StorageErrorCodes.NOT_FOUND,\n 404\n );\n }\n throw new StorageError(\n `Download failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.DOWNLOAD_FAILED,\n undefined,\n err\n );\n }\n }\n\n async downloadStream(\n key: string,\n options?: DownloadOptions\n ): Promise<ReadableStream<Uint8Array>> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const client = await this.getClient();\n const { GetObjectCommand } = await import(\"@aws-sdk/client-s3\");\n\n try {\n const params: import(\"@aws-sdk/client-s3\").GetObjectCommandInput = {\n Bucket: this.bucket,\n Key: fullKey,\n };\n\n if (options?.rangeStart !== undefined || options?.rangeEnd !== undefined) {\n const start = options.rangeStart ?? 0;\n const end = options.rangeEnd ?? \"\";\n params.Range = `bytes=${start}-${end}`;\n }\n\n const result = await client.send(new GetObjectCommand(params));\n\n if (!result.Body) {\n throw new StorageError(\n \"Empty response body\",\n StorageErrorCodes.DOWNLOAD_FAILED\n );\n }\n\n return result.Body as ReadableStream<Uint8Array>;\n } catch (err) {\n if (\n err instanceof Error &&\n \"name\" in err &&\n err.name === \"NoSuchKey\"\n ) {\n throw new StorageError(\n `File not found: ${key}`,\n StorageErrorCodes.NOT_FOUND,\n 404\n );\n }\n throw err;\n }\n }\n\n async head(key: string): Promise<FileMetadata | null> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const client = await this.getClient();\n const { HeadObjectCommand } = await import(\"@aws-sdk/client-s3\");\n\n try {\n const result = await client.send(\n new HeadObjectCommand({\n Bucket: this.bucket,\n Key: fullKey,\n })\n );\n\n return {\n key: fullKey,\n size: result.ContentLength ?? 0,\n contentType: result.ContentType ?? undefined,\n lastModified: result.LastModified ?? undefined,\n etag: result.ETag ?? undefined,\n metadata: result.Metadata ?? undefined,\n };\n } catch (err) {\n if (\n err instanceof Error &&\n \"name\" in err &&\n (err.name === \"NoSuchKey\" || err.name === \"NotFound\")\n ) {\n return null;\n }\n throw err;\n }\n }\n\n async exists(key: string): Promise<boolean> {\n const metadata = await this.head(key);\n return metadata !== null;\n }\n\n async delete(key: string): Promise<DeleteResult> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const client = await this.getClient();\n const { DeleteObjectCommand } = await import(\"@aws-sdk/client-s3\");\n\n try {\n await client.send(\n new DeleteObjectCommand({\n Bucket: this.bucket,\n Key: fullKey,\n })\n );\n\n return { success: true, key: fullKey };\n } catch (err) {\n throw new StorageError(\n `Delete failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.DELETE_FAILED,\n undefined,\n err\n );\n }\n }\n\n async deleteMany(keys: string[]): Promise<BatchDeleteResult> {\n const client = await this.getClient();\n const { DeleteObjectsCommand } = await import(\"@aws-sdk/client-s3\");\n\n const objects = keys.map((key) => ({\n Key: this.getFullKey(key),\n }));\n\n try {\n const result = await client.send(\n new DeleteObjectsCommand({\n Bucket: this.bucket,\n Delete: { Objects: objects },\n })\n );\n\n const deleted = result.Deleted?.map((d) => d.Key ?? \"\") ?? [];\n const errors =\n result.Errors?.map((e) => ({\n key: e.Key ?? \"\",\n error: e.Message ?? \"Unknown error\",\n })) ?? [];\n\n return { deleted, errors };\n } catch (err) {\n throw new StorageError(\n `Batch delete failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.DELETE_FAILED,\n undefined,\n err\n );\n }\n }\n\n async list(options?: ListOptions): Promise<ListResult> {\n const client = await this.getClient();\n const { ListObjectsV2Command } = await import(\"@aws-sdk/client-s3\");\n\n const prefix = options?.prefix\n ? this.getFullKey(options.prefix)\n : this.basePath || undefined;\n\n try {\n const result = await client.send(\n new ListObjectsV2Command({\n Bucket: this.bucket,\n Prefix: prefix,\n Delimiter: options?.delimiter,\n MaxKeys: options?.maxKeys,\n ContinuationToken: options?.continuationToken,\n })\n );\n\n const files: FileMetadata[] =\n result.Contents?.map((item) => ({\n key: item.Key ?? \"\",\n size: item.Size ?? 0,\n contentType: undefined,\n lastModified: item.LastModified ?? undefined,\n etag: item.ETag ?? undefined,\n metadata: undefined,\n })) ?? [];\n\n const prefixes =\n result.CommonPrefixes?.map((p) => p.Prefix ?? \"\") ?? [];\n\n return {\n files,\n prefixes,\n isTruncated: result.IsTruncated ?? false,\n continuationToken: result.NextContinuationToken ?? undefined,\n };\n } catch (err) {\n throw new StorageError(\n `List failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.LIST_FAILED,\n undefined,\n err\n );\n }\n }\n\n async copy(\n sourceKey: string,\n destKey: string,\n options?: CopyOptions\n ): Promise<FileMetadata> {\n this.validateKey(sourceKey);\n this.validateKey(destKey);\n\n const client = await this.getClient();\n const { CopyObjectCommand } = await import(\"@aws-sdk/client-s3\");\n\n const sourceFullKey = this.getFullKey(sourceKey);\n const destFullKey = this.getFullKey(destKey);\n const sourceBucket = options?.sourceBucket ?? this.bucket;\n\n try {\n const result = await client.send(\n new CopyObjectCommand({\n Bucket: this.bucket,\n Key: destFullKey,\n CopySource: `${sourceBucket}/${sourceFullKey}`,\n MetadataDirective: options?.metadataDirective,\n ContentType: options?.contentType,\n Metadata: options?.metadata,\n })\n );\n\n // Get metadata of copied object\n const metadata = await this.head(destKey);\n\n return metadata ?? {\n key: destFullKey,\n size: 0,\n contentType: options?.contentType ?? undefined,\n lastModified: result.CopyObjectResult?.LastModified ?? new Date(),\n etag: result.CopyObjectResult?.ETag ?? undefined,\n metadata: options?.metadata ?? undefined,\n };\n } catch (err) {\n throw new StorageError(\n `Copy failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.COPY_FAILED,\n undefined,\n err\n );\n }\n }\n\n async move(sourceKey: string, destKey: string): Promise<FileMetadata> {\n const metadata = await this.copy(sourceKey, destKey);\n await this.delete(sourceKey);\n return metadata;\n }\n\n async getPresignedUrl(\n key: string,\n options?: PresignedUrlOptions\n ): Promise<string> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const client = await this.getClient();\n\n try {\n const { getSignedUrl } = await import(\"@aws-sdk/s3-request-presigner\");\n const { GetObjectCommand } = await import(\"@aws-sdk/client-s3\");\n\n const command = new GetObjectCommand({\n Bucket: this.bucket,\n Key: fullKey,\n ResponseCacheControl: options?.responseCacheControl,\n ResponseContentType: options?.responseContentType,\n ResponseContentDisposition: options?.contentDisposition,\n });\n\n return getSignedUrl(client, command, {\n expiresIn: options?.expiresIn ?? 3600,\n });\n } catch (err) {\n throw new StorageError(\n `Presigned URL failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.PRESIGN_FAILED,\n undefined,\n err\n );\n }\n }\n\n async getUploadUrl(\n key: string,\n options?: PresignedUrlOptions\n ): Promise<string> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n const client = await this.getClient();\n\n try {\n const { getSignedUrl } = await import(\"@aws-sdk/s3-request-presigner\");\n const { PutObjectCommand } = await import(\"@aws-sdk/client-s3\");\n\n const command = new PutObjectCommand({\n Bucket: this.bucket,\n Key: fullKey,\n ContentType: options?.contentType,\n ContentDisposition: options?.contentDisposition,\n });\n\n return getSignedUrl(client, command, {\n expiresIn: options?.expiresIn ?? 3600,\n });\n } catch (err) {\n throw new StorageError(\n `Upload URL failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.PRESIGN_FAILED,\n undefined,\n err\n );\n }\n }\n\n private async streamToUint8Array(\n stream: ReadableStream<Uint8Array>\n ): Promise<Uint8Array> {\n const reader = stream.getReader();\n const chunks: Uint8Array[] = [];\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value) chunks.push(value);\n }\n\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const result = new Uint8Array(totalLength);\n let offset = 0;\n\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n\n return result;\n }\n}\n\n/**\n * Create an S3 storage adapter\n */\nexport function createS3Adapter(config: S3Config): S3Adapter {\n return new S3Adapter(config);\n}\n\n/**\n * Create a DigitalOcean Spaces adapter\n */\nexport function createDOSpacesAdapter(\n config: Omit<S3Config, \"type\" | \"endpoint\"> & {\n region: string;\n spaceName?: string;\n }\n): S3Adapter {\n return new S3Adapter({\n ...config,\n type: \"do-spaces\",\n endpoint: `https://${config.region}.digitaloceanspaces.com`,\n bucket: config.spaceName ?? config.bucket,\n });\n}\n","/**\n * @parsrun/storage - R2 Adapter\n * Cloudflare R2 storage adapter (edge-native)\n *\n * This adapter works in two modes:\n * 1. Worker binding (native R2 API) - fastest, edge-native\n * 2. S3-compatible API - for non-Worker environments\n */\n\nimport {\n type BatchDeleteResult,\n type CopyOptions,\n type DeleteResult,\n type DownloadOptions,\n type FileMetadata,\n type ListOptions,\n type ListResult,\n type PresignedUrlOptions,\n type R2Config,\n type StorageAdapter,\n type UploadOptions,\n StorageError,\n StorageErrorCodes,\n} from \"../types.js\";\n\n/**\n * Cloudflare R2 Bucket binding type\n */\nexport interface R2Bucket {\n head(key: string): Promise<R2Object | null>;\n get(key: string, options?: R2GetOptions): Promise<R2ObjectBody | null>;\n put(\n key: string,\n value: ArrayBuffer | ArrayBufferView | ReadableStream | string | null | Blob,\n options?: R2PutOptions\n ): Promise<R2Object>;\n delete(keys: string | string[]): Promise<void>;\n list(options?: R2ListOptions): Promise<R2Objects>;\n createMultipartUpload(key: string, options?: R2MultipartOptions): Promise<R2MultipartUpload>;\n}\n\ninterface R2Object {\n key: string;\n version: string;\n size: number;\n etag: string;\n httpEtag: string;\n checksums: R2Checksums;\n uploaded: Date;\n httpMetadata?: R2HTTPMetadata;\n customMetadata?: Record<string, string>;\n range?: R2Range;\n}\n\ninterface R2ObjectBody extends R2Object {\n body: ReadableStream;\n bodyUsed: boolean;\n arrayBuffer(): Promise<ArrayBuffer>;\n text(): Promise<string>;\n json<T>(): Promise<T>;\n blob(): Promise<Blob>;\n}\n\ninterface R2Checksums {\n md5?: ArrayBuffer;\n sha1?: ArrayBuffer;\n sha256?: ArrayBuffer;\n sha384?: ArrayBuffer;\n sha512?: ArrayBuffer;\n}\n\ninterface R2HTTPMetadata {\n contentType?: string;\n contentLanguage?: string;\n contentDisposition?: string;\n contentEncoding?: string;\n cacheControl?: string;\n cacheExpiry?: Date;\n}\n\ninterface R2Range {\n offset: number;\n length: number;\n}\n\ninterface R2GetOptions {\n onlyIf?: R2Conditional;\n range?: R2Range | { offset?: number; length?: number; suffix?: number };\n}\n\ninterface R2PutOptions {\n httpMetadata?: R2HTTPMetadata;\n customMetadata?: Record<string, string>;\n md5?: ArrayBuffer | string;\n sha1?: ArrayBuffer | string;\n sha256?: ArrayBuffer | string;\n sha384?: ArrayBuffer | string;\n sha512?: ArrayBuffer | string;\n}\n\ninterface R2Conditional {\n etagMatches?: string;\n etagDoesNotMatch?: string;\n uploadedBefore?: Date;\n uploadedAfter?: Date;\n}\n\ninterface R2ListOptions {\n prefix?: string;\n cursor?: string;\n delimiter?: string;\n limit?: number;\n include?: (\"httpMetadata\" | \"customMetadata\")[];\n}\n\ninterface R2Objects {\n objects: R2Object[];\n truncated: boolean;\n cursor?: string;\n delimitedPrefixes: string[];\n}\n\ninterface R2MultipartOptions {\n httpMetadata?: R2HTTPMetadata;\n customMetadata?: Record<string, string>;\n}\n\ninterface R2MultipartUpload {\n key: string;\n uploadId: string;\n uploadPart(partNumber: number, value: ArrayBuffer | ArrayBufferView | ReadableStream | string | Blob): Promise<R2UploadedPart>;\n abort(): Promise<void>;\n complete(uploadedParts: R2UploadedPart[]): Promise<R2Object>;\n}\n\ninterface R2UploadedPart {\n partNumber: number;\n etag: string;\n}\n\n/**\n * R2 Storage Adapter\n * Native Cloudflare R2 adapter optimized for Workers/Edge\n *\n * @example\n * ```typescript\n * // In Cloudflare Worker with binding\n * const r2 = new R2Adapter({\n * type: 'r2',\n * bucket: 'my-bucket',\n * accountId: env.CF_ACCOUNT_ID,\n * accessKeyId: env.R2_ACCESS_KEY,\n * secretAccessKey: env.R2_SECRET_KEY,\n * binding: env.MY_BUCKET, // R2 binding\n * });\n *\n * // Using S3-compatible API (non-Worker)\n * const r2 = new R2Adapter({\n * type: 'r2',\n * bucket: 'my-bucket',\n * accountId: env.CF_ACCOUNT_ID,\n * accessKeyId: env.R2_ACCESS_KEY,\n * secretAccessKey: env.R2_SECRET_KEY,\n * });\n * ```\n */\nexport class R2Adapter implements StorageAdapter {\n readonly type = \"r2\" as const;\n readonly bucket: string;\n\n private binding: R2Bucket | null = null;\n private s3Adapter: StorageAdapter | null = null;\n private config: R2Config & { binding?: R2Bucket };\n private basePath: string;\n\n constructor(config: R2Config & { binding?: R2Bucket }) {\n this.bucket = config.bucket;\n this.config = config;\n this.basePath = config.basePath ?? \"\";\n this.binding = config.binding ?? null;\n }\n\n /**\n * Get S3 adapter for fallback\n */\n private async getS3Adapter(): Promise<StorageAdapter> {\n if (this.s3Adapter) return this.s3Adapter;\n\n // Dynamically import S3 adapter\n const { S3Adapter } = await import(\"./s3.js\");\n\n this.s3Adapter = new S3Adapter({\n type: \"s3\",\n bucket: this.bucket,\n region: \"auto\",\n accessKeyId: this.config.accessKeyId,\n secretAccessKey: this.config.secretAccessKey,\n endpoint: `https://${this.config.accountId}.r2.cloudflarestorage.com`,\n });\n\n return this.s3Adapter;\n }\n\n private getFullKey(key: string): string {\n return this.basePath ? `${this.basePath}/${key}` : key;\n }\n\n private validateKey(key: string): void {\n if (!key || key.includes(\"..\") || key.startsWith(\"/\")) {\n throw new StorageError(\n `Invalid key: ${key}`,\n StorageErrorCodes.INVALID_KEY\n );\n }\n }\n\n private async dataToBody(\n data: Uint8Array | ReadableStream<Uint8Array> | Blob | string\n ): Promise<ArrayBuffer | ReadableStream | string | Blob> {\n if (data instanceof Uint8Array) {\n // Create a proper ArrayBuffer from the Uint8Array\n const buffer = new ArrayBuffer(data.length);\n new Uint8Array(buffer).set(data);\n return buffer;\n }\n return data;\n }\n\n async upload(\n key: string,\n data: Uint8Array | ReadableStream<Uint8Array> | Blob | string,\n options?: UploadOptions\n ): Promise<FileMetadata> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n // Use binding if available (Worker environment)\n if (this.binding) {\n const body = await this.dataToBody(data);\n\n // Build httpMetadata only with defined values\n const httpMetadata: R2HTTPMetadata = {};\n if (options?.contentType) httpMetadata.contentType = options.contentType;\n if (options?.contentDisposition) httpMetadata.contentDisposition = options.contentDisposition;\n if (options?.cacheControl) httpMetadata.cacheControl = options.cacheControl;\n if (options?.contentEncoding) httpMetadata.contentEncoding = options.contentEncoding;\n\n const putOptions: R2PutOptions = {\n httpMetadata,\n };\n if (options?.metadata) {\n putOptions.customMetadata = options.metadata;\n }\n\n try {\n const result = await this.binding.put(fullKey, body, putOptions);\n\n return {\n key: fullKey,\n size: result.size,\n contentType: result.httpMetadata?.contentType ?? undefined,\n lastModified: result.uploaded,\n etag: result.etag,\n metadata: result.customMetadata ?? undefined,\n };\n } catch (err) {\n throw new StorageError(\n `Upload failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.UPLOAD_FAILED,\n undefined,\n err\n );\n }\n }\n\n // Fallback to S3-compatible API\n const s3 = await this.getS3Adapter();\n return s3.upload(key, data, options);\n }\n\n async download(key: string, options?: DownloadOptions): Promise<Uint8Array> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n // Use binding if available\n if (this.binding) {\n try {\n const getOptions: R2GetOptions = {};\n\n if (options?.rangeStart !== undefined || options?.rangeEnd !== undefined) {\n const rangeOpts: { offset?: number; length?: number } = {\n offset: options.rangeStart ?? 0,\n };\n if (options.rangeEnd !== undefined) {\n rangeOpts.length = options.rangeEnd - (options.rangeStart ?? 0) + 1;\n }\n getOptions.range = rangeOpts;\n }\n\n if (options?.ifNoneMatch || options?.ifModifiedSince) {\n const conditional: R2Conditional = {};\n if (options.ifNoneMatch) conditional.etagDoesNotMatch = options.ifNoneMatch;\n if (options.ifModifiedSince) conditional.uploadedAfter = options.ifModifiedSince;\n getOptions.onlyIf = conditional;\n }\n\n const result = await this.binding.get(fullKey, getOptions);\n\n if (!result) {\n throw new StorageError(\n `File not found: ${key}`,\n StorageErrorCodes.NOT_FOUND,\n 404\n );\n }\n\n const buffer = await result.arrayBuffer();\n return new Uint8Array(buffer);\n } catch (err) {\n if (err instanceof StorageError) throw err;\n throw new StorageError(\n `Download failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.DOWNLOAD_FAILED,\n undefined,\n err\n );\n }\n }\n\n // Fallback to S3-compatible API\n const s3 = await this.getS3Adapter();\n return s3.download(key, options);\n }\n\n async downloadStream(\n key: string,\n options?: DownloadOptions\n ): Promise<ReadableStream<Uint8Array>> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n // Use binding if available\n if (this.binding) {\n try {\n const getOptions: R2GetOptions = {};\n\n if (options?.rangeStart !== undefined || options?.rangeEnd !== undefined) {\n const rangeOpts: { offset?: number; length?: number } = {\n offset: options.rangeStart ?? 0,\n };\n if (options.rangeEnd !== undefined) {\n rangeOpts.length = options.rangeEnd - (options.rangeStart ?? 0) + 1;\n }\n getOptions.range = rangeOpts;\n }\n\n const result = await this.binding.get(fullKey, getOptions);\n\n if (!result) {\n throw new StorageError(\n `File not found: ${key}`,\n StorageErrorCodes.NOT_FOUND,\n 404\n );\n }\n\n return result.body as ReadableStream<Uint8Array>;\n } catch (err) {\n if (err instanceof StorageError) throw err;\n throw new StorageError(\n `Download failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.DOWNLOAD_FAILED,\n undefined,\n err\n );\n }\n }\n\n // Fallback to S3-compatible API\n const s3 = await this.getS3Adapter();\n return s3.downloadStream(key, options);\n }\n\n async head(key: string): Promise<FileMetadata | null> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n // Use binding if available\n if (this.binding) {\n try {\n const result = await this.binding.head(fullKey);\n\n if (!result) {\n return null;\n }\n\n return {\n key: fullKey,\n size: result.size,\n contentType: result.httpMetadata?.contentType ?? undefined,\n lastModified: result.uploaded,\n etag: result.etag,\n metadata: result.customMetadata ?? undefined,\n };\n } catch {\n return null;\n }\n }\n\n // Fallback to S3-compatible API\n const s3 = await this.getS3Adapter();\n return s3.head(key);\n }\n\n async exists(key: string): Promise<boolean> {\n const metadata = await this.head(key);\n return metadata !== null;\n }\n\n async delete(key: string): Promise<DeleteResult> {\n this.validateKey(key);\n const fullKey = this.getFullKey(key);\n\n // Use binding if available\n if (this.binding) {\n try {\n await this.binding.delete(fullKey);\n return { success: true, key: fullKey };\n } catch (err) {\n throw new StorageError(\n `Delete failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.DELETE_FAILED,\n undefined,\n err\n );\n }\n }\n\n // Fallback to S3-compatible API\n const s3 = await this.getS3Adapter();\n return s3.delete(key);\n }\n\n async deleteMany(keys: string[]): Promise<BatchDeleteResult> {\n // Use binding if available\n if (this.binding) {\n const fullKeys = keys.map((key) => this.getFullKey(key));\n\n try {\n await this.binding.delete(fullKeys);\n return { deleted: fullKeys, errors: [] };\n } catch (err) {\n return {\n deleted: [],\n errors: fullKeys.map((key) => ({\n key,\n error: err instanceof Error ? err.message : \"Unknown error\",\n })),\n };\n }\n }\n\n // Fallback to S3-compatible API\n const s3 = await this.getS3Adapter();\n return s3.deleteMany(keys);\n }\n\n async list(options?: ListOptions): Promise<ListResult> {\n // Use binding if available\n if (this.binding) {\n try {\n const listOpts: R2ListOptions = {\n include: [\"httpMetadata\", \"customMetadata\"],\n };\n\n // Only add defined options\n const prefix = options?.prefix\n ? this.getFullKey(options.prefix)\n : this.basePath || null;\n if (prefix) listOpts.prefix = prefix;\n if (options?.delimiter) listOpts.delimiter = options.delimiter;\n if (options?.maxKeys) listOpts.limit = options.maxKeys;\n if (options?.continuationToken) listOpts.cursor = options.continuationToken;\n\n const result = await this.binding.list(listOpts);\n\n const files: FileMetadata[] = result.objects.map((obj) => ({\n key: obj.key,\n size: obj.size,\n contentType: obj.httpMetadata?.contentType ?? undefined,\n lastModified: obj.uploaded,\n etag: obj.etag,\n metadata: obj.customMetadata ?? undefined,\n }));\n\n return {\n files,\n prefixes: result.delimitedPrefixes,\n isTruncated: result.truncated,\n continuationToken: result.cursor ?? undefined,\n };\n } catch (err) {\n throw new StorageError(\n `List failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n StorageErrorCodes.LIST_FAILED,\n undefined,\n err\n );\n }\n }\n\n // Fallback to S3-compatible API\n const s3 = await this.getS3Adapter();\n return s3.list(options);\n }\n\n async copy(\n sourceKey: string,\n destKey: string,\n options?: CopyOptions\n ): Promise<FileMetadata> {\n // R2 binding doesn't have native copy, download and upload\n if (this.binding) {\n const data = await this.download(sourceKey);\n const sourceMetadata = await this.head(sourceKey);\n\n const uploadOptions: UploadOptions =\n options?.metadataDirective === \"REPLACE\"\n ? {\n contentType: options.contentType,\n metadata: options.metadata,\n }\n : {\n contentType: sourceMetadata?.contentType,\n metadata: sourceMetadata?.metadata,\n };\n\n return this.upload(destKey, data, uploadOptions);\n }\n\n // Fallback to S3-compatible API\n const s3 = await this.getS3Adapter();\n return s3.copy(sourceKey, destKey, options);\n }\n\n async move(sourceKey: string, destKey: string): Promise<FileMetadata> {\n const metadata = await this.copy(sourceKey, destKey);\n await this.delete(sourceKey);\n return metadata;\n }\n\n async getPresignedUrl(\n key: string,\n options?: PresignedUrlOptions\n ): Promise<string> {\n // R2 binding doesn't support presigned URLs, use S3 API\n const s3 = await this.getS3Adapter();\n return s3.getPresignedUrl(key, options);\n }\n\n async getUploadUrl(\n key: string,\n options?: PresignedUrlOptions\n ): Promise<string> {\n // R2 binding doesn't support presigned URLs, use S3 API\n const s3 = await this.getS3Adapter();\n return s3.getUploadUrl(key, options);\n }\n\n /**\n * Get public URL for a file (if custom domain is configured)\n */\n getPublicUrl(key: string): string | null {\n if (!this.config.customDomain) {\n return null;\n }\n\n const fullKey = this.getFullKey(key);\n return `https://${this.config.customDomain}/${fullKey}`;\n }\n}\n\n/**\n * Create an R2 storage adapter\n */\nexport function createR2Adapter(\n config: R2Config & { binding?: R2Bucket }\n): R2Adapter {\n return new R2Adapter(config);\n}\n","/**\n * @module\n * Edge-compatible storage abstraction for Pars.\n *\n * Supports:\n * - AWS S3\n * - Cloudflare R2\n * - DigitalOcean Spaces\n * - MinIO (S3-compatible)\n * - Memory (for testing)\n *\n * @example\n * ```typescript\n * import { createStorage } from '@parsrun/storage';\n *\n * // AWS S3\n * const s3 = createStorage({\n * type: 's3',\n * bucket: 'my-bucket',\n * region: 'us-east-1',\n * accessKeyId: process.env.AWS_ACCESS_KEY_ID,\n * secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,\n * });\n *\n * // Cloudflare R2\n * const r2 = createStorage({\n * type: 'r2',\n * bucket: 'my-bucket',\n * accountId: process.env.CF_ACCOUNT_ID,\n * accessKeyId: process.env.R2_ACCESS_KEY,\n * secretAccessKey: process.env.R2_SECRET_KEY,\n * });\n *\n * // Upload\n * await s3.upload('path/to/file.txt', 'Hello, World!');\n *\n * // Download\n * const data = await s3.download('path/to/file.txt');\n *\n * // Get presigned URL\n * const url = await s3.getPresignedUrl('path/to/file.txt', { expiresIn: 3600 });\n * ```\n */\n\n// Types\nexport {\n type StorageAdapterType,\n type FileMetadata,\n type UploadOptions,\n type DownloadOptions,\n type ListOptions,\n type ListResult,\n type PresignedUrlOptions,\n type CopyOptions,\n type DeleteResult,\n type BatchDeleteResult,\n type StorageAdapter,\n type StorageConfig,\n type S3Config,\n type R2Config,\n type MemoryConfig,\n StorageError,\n StorageErrorCodes,\n} from \"./types.js\";\n\n// Adapters\nexport { MemoryAdapter, createMemoryAdapter } from \"./adapters/memory.js\";\nexport { S3Adapter, createS3Adapter, createDOSpacesAdapter } from \"./adapters/s3.js\";\nexport { R2Adapter, createR2Adapter } from \"./adapters/r2.js\";\n\n// Re-export R2 bucket type for typing\nexport type { R2Bucket } from \"./adapters/r2.js\";\n\nimport type { S3Config, R2Config, MemoryConfig, StorageAdapter } from \"./types.js\";\nimport { StorageError, StorageErrorCodes } from \"./types.js\";\n\n/**\n * Combined storage configuration\n */\nexport type AnyStorageConfig = S3Config | R2Config | MemoryConfig;\n\n/**\n * R2 binding type\n */\ntype R2Bucket = import(\"./adapters/r2.js\").R2Bucket;\n\n/**\n * Create a storage adapter based on configuration\n *\n * @param config - Storage configuration\n * @returns Storage adapter instance\n *\n * @example\n * ```typescript\n * // Memory (for testing)\n * const memory = createStorage({ type: 'memory', bucket: 'test' });\n *\n * // AWS S3\n * const s3 = createStorage({\n * type: 's3',\n * bucket: 'my-bucket',\n * region: 'us-east-1',\n * accessKeyId: 'xxx',\n * secretAccessKey: 'xxx',\n * });\n *\n * // Cloudflare R2\n * const r2 = createStorage({\n * type: 'r2',\n * bucket: 'my-bucket',\n * accountId: 'xxx',\n * accessKeyId: 'xxx',\n * secretAccessKey: 'xxx',\n * });\n *\n * // DigitalOcean Spaces\n * const spaces = createStorage({\n * type: 'do-spaces',\n * bucket: 'my-space',\n * region: 'nyc3',\n * accessKeyId: 'xxx',\n * secretAccessKey: 'xxx',\n * endpoint: 'https://nyc3.digitaloceanspaces.com',\n * });\n * ```\n */\nexport async function createStorage(\n config: AnyStorageConfig & { binding?: R2Bucket }\n): Promise<StorageAdapter> {\n switch (config.type) {\n case \"memory\": {\n const { MemoryAdapter } = await import(\"./adapters/memory.js\");\n return new MemoryAdapter(config);\n }\n\n case \"s3\":\n case \"do-spaces\": {\n const { S3Adapter } = await import(\"./adapters/s3.js\");\n return new S3Adapter(config as S3Config);\n }\n\n case \"r2\": {\n const { R2Adapter } = await import(\"./adapters/r2.js\");\n return new R2Adapter(config as R2Config & { binding?: R2Bucket });\n }\n\n default:\n throw new StorageError(\n `Unknown storage type: ${(config as AnyStorageConfig).type}`,\n StorageErrorCodes.INVALID_CONFIG\n );\n }\n}\n\n/**\n * Create storage adapter synchronously\n * Note: Some adapters may require async initialization for full functionality\n *\n * @param config - Storage configuration\n * @returns Storage adapter instance\n */\nexport function createStorageSync(\n config: AnyStorageConfig & { binding?: R2Bucket }\n): StorageAdapter {\n switch (config.type) {\n case \"memory\": {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { MemoryAdapter } = require(\"./adapters/memory.js\") as typeof import(\"./adapters/memory.js\");\n return new MemoryAdapter(config);\n }\n\n case \"s3\":\n case \"do-spaces\": {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { S3Adapter } = require(\"./adapters/s3.js\") as typeof import(\"./adapters/s3.js\");\n return new S3Adapter(config as S3Config);\n }\n\n case \"r2\": {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { R2Adapter } = require(\"./adapters/r2.js\") as typeof import(\"./adapters/r2.js\");\n return new R2Adapter(config as R2Config & { binding?: R2Bucket });\n }\n\n default:\n throw new StorageError(\n `Unknown storage type: ${(config as AnyStorageConfig).type}`,\n StorageErrorCodes.INVALID_CONFIG\n );\n }\n}\n\n/**\n * Storage utilities\n */\nexport const StorageUtils = {\n /**\n * Get file extension from key\n */\n getExtension(key: string): string {\n const parts = key.split(\".\");\n const lastPart = parts[parts.length - 1];\n return parts.length > 1 && lastPart ? lastPart.toLowerCase() : \"\";\n },\n\n /**\n * Get file name from key\n */\n getFileName(key: string): string {\n return key.split(\"/\").pop() ?? key;\n },\n\n /**\n * Get directory from key\n */\n getDirectory(key: string): string {\n const parts = key.split(\"/\");\n parts.pop();\n return parts.join(\"/\");\n },\n\n /**\n * Join paths safely\n */\n joinPath(...parts: string[]): string {\n return parts\n .filter(Boolean)\n .map((p) => p.replace(/^\\/|\\/$/g, \"\"))\n .join(\"/\");\n },\n\n /**\n * Normalize key (remove leading slash, handle ..)\n */\n normalizeKey(key: string): string {\n return key\n .replace(/^\\/+/, \"\")\n .split(\"/\")\n .filter((p) => p !== \"..\" && p !== \".\")\n .join(\"/\");\n },\n\n /**\n * Generate a unique key with timestamp\n */\n generateUniqueKey(prefix: string, extension?: string): string {\n const timestamp = Date.now();\n const random = Math.random().toString(36).slice(2, 10);\n const ext = extension ? `.${extension}` : \"\";\n return `${prefix}/${timestamp}-${random}${ext}`;\n },\n\n /**\n * Guess content type from file extension\n */\n guessContentType(key: string): string {\n const ext = StorageUtils.getExtension(key);\n const contentTypes: Record<string, string> = {\n // Text\n txt: \"text/plain\",\n html: \"text/html\",\n htm: \"text/html\",\n css: \"text/css\",\n csv: \"text/csv\",\n xml: \"text/xml\",\n\n // Application\n js: \"application/javascript\",\n mjs: \"application/javascript\",\n json: \"application/json\",\n pdf: \"application/pdf\",\n zip: \"application/zip\",\n gzip: \"application/gzip\",\n gz: \"application/gzip\",\n tar: \"application/x-tar\",\n doc: \"application/msword\",\n docx: \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n xls: \"application/vnd.ms-excel\",\n xlsx: \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n ppt: \"application/vnd.ms-powerpoint\",\n pptx: \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\n\n // Images\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n svg: \"image/svg+xml\",\n ico: \"image/x-icon\",\n bmp: \"image/bmp\",\n tiff: \"image/tiff\",\n tif: \"image/tiff\",\n\n // Audio\n mp3: \"audio/mpeg\",\n wav: \"audio/wav\",\n ogg: \"audio/ogg\",\n flac: \"audio/flac\",\n aac: \"audio/aac\",\n\n // Video\n mp4: \"video/mp4\",\n webm: \"video/webm\",\n avi: \"video/x-msvideo\",\n mov: \"video/quicktime\",\n mkv: \"video/x-matroska\",\n\n // Fonts\n woff: \"font/woff\",\n woff2: \"font/woff2\",\n ttf: \"font/ttf\",\n otf: \"font/otf\",\n eot: \"application/vnd.ms-fontobject\",\n };\n\n return contentTypes[ext] ?? \"application/octet-stream\";\n },\n\n /**\n * Format file size to human readable string\n */\n formatSize(bytes: number): string {\n const units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n let size = bytes;\n let unitIndex = 0;\n\n while (size >= 1024 && unitIndex < units.length - 1) {\n size /= 1024;\n unitIndex++;\n }\n\n return `${size.toFixed(unitIndex > 0 ? 2 : 0)} ${units[unitIndex]}`;\n },\n\n /**\n * Parse file size string to bytes\n */\n parseSize(size: string): number {\n const units: Record<string, number> = {\n b: 1,\n kb: 1024,\n mb: 1024 * 1024,\n gb: 1024 * 1024 * 1024,\n tb: 1024 * 1024 * 1024 * 1024,\n };\n\n const match = size.toLowerCase().match(/^(\\d+(?:\\.\\d+)?)\\s*([a-z]+)?$/);\n if (!match || !match[1]) return 0;\n\n const value = parseFloat(match[1]);\n const unit = match[2] ?? \"b\";\n\n return Math.floor(value * (units[unit] ?? 1));\n },\n};\n"],"mappings":"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","names":["S3Adapter","uploadOptions","MemoryAdapter","S3Adapter","R2Adapter"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parsrun/storage",
3
- "version": "0.1.15",
3
+ "version": "0.1.16",
4
4
  "description": "Edge-compatible storage abstraction for Pars - S3, R2, DO Spaces",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",