{"version":3,"file":"filesystem.cjs","sources":["@gensx/storage/../../../../src/blob/filesystem.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/only-throw-error */\n\nimport * as crypto from \"node:crypto\";\nimport { createReadStream, createWriteStream } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { Readable } from \"node:stream\";\n\nimport { fromBase64UrlSafe, toBase64UrlSafe } from \"../utils/base64.js\";\nimport {\n  Blob,\n  BlobConflictError,\n  BlobError,\n  BlobInternalError,\n  BlobNotFoundError,\n  BlobOptions,\n  BlobPermissionDeniedError,\n  BlobResponse,\n  BlobStorage,\n  DeleteBlobResult,\n  ListBlobsOptions,\n  ListBlobsResponse,\n} from \"./types.js\";\n\n/**\n * Helper to convert between filesystem errors and BlobErrors\n * @param err The error to convert\n * @param operation The operation that failed\n * @param path The path where the error occurred\n * @throws BlobError with appropriate error code and message\n */\nfunction handleFsError(err: unknown, operation: string, path: string): never {\n  if (err instanceof Error) {\n    const nodeErr = err as NodeJS.ErrnoException;\n\n    if (nodeErr.code === \"ENOENT\") {\n      throw new BlobNotFoundError(`Blob not found at path: ${path}`, err);\n    } else if (nodeErr.code === \"EACCES\") {\n      throw new BlobPermissionDeniedError(\n        `Permission denied for operation ${operation} on path: ${path}`,\n        err,\n      );\n    } else if (nodeErr.code === \"EEXIST\") {\n      throw new BlobConflictError(`File already exists at path: ${path}`, err);\n    } else if (nodeErr.code === \"ENOTEMPTY\") {\n      throw new BlobConflictError(`Directory not empty at path: ${path}`, err);\n    } else if (nodeErr.code === \"ENOTDIR\") {\n      throw new BlobInternalError(`Path is not a directory: ${path}`, err);\n    }\n  }\n\n  // Default error case\n  throw new BlobInternalError(\n    `Error during ${operation}: ${String(err)}`,\n    err as Error,\n  );\n}\n\n/**\n * Calculate an MD5 hash of the content for use as an ETag\n * @param content The content to hash\n * @returns The MD5 hash as a hex string\n */\nfunction calculateEtag(content: string | Buffer): string {\n  return crypto.createHash(\"md5\").update(content).digest(\"hex\");\n}\n\n/**\n * Generate a unique filename for metadata\n * @param filePath The path to the blob file\n * @returns The path to the metadata file\n */\nfunction getMetadataPath(filePath: string): string {\n  return `${filePath}.metadata.json`;\n}\n\n/**\n * Implementation of Blob interface for filesystem storage\n * @template T The type of data stored in the blob\n */\nclass FileSystemBlob<T> implements Blob<T> {\n  private filePath: string;\n  private metadataPath: string;\n\n  /**\n   * Create a new FileSystemBlob\n   * @param filePath The path to the blob file\n   */\n  constructor(filePath: string) {\n    this.filePath = filePath;\n    this.metadataPath = getMetadataPath(filePath);\n  }\n\n  /**\n   * Get JSON data from the blob\n   * @returns The JSON data or null if the blob doesn't exist\n   * @throws BlobError if there's an error reading the blob\n   */\n  async getJSON<R>(): Promise<R | null> {\n    try {\n      const content = await fs.readFile(this.filePath, \"utf8\");\n      return JSON.parse(content) as R;\n    } catch (err) {\n      if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n        return null;\n      }\n      throw handleFsError(err, \"getJSON\", this.filePath);\n    }\n  }\n\n  /**\n   * Get string data from the blob\n   * @returns The string data or null if the blob doesn't exist\n   * @throws BlobError if there's an error reading the blob\n   */\n  async getString(): Promise<string | null> {\n    try {\n      return await fs.readFile(this.filePath, \"utf8\");\n    } catch (err) {\n      if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n        return null;\n      }\n      throw handleFsError(err, \"getString\", this.filePath);\n    }\n  }\n\n  /**\n   * Get a readable stream from the blob\n   * @returns A readable stream of the blob content\n   * @throws BlobError if there's an error creating the stream\n   */\n  async getStream(): Promise<Readable> {\n    try {\n      // Check if file exists first\n      try {\n        await fs.access(this.filePath);\n      } catch (err) {\n        if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n          throw new BlobNotFoundError(\n            `Blob not found at path: ${this.filePath}`,\n          );\n        }\n        throw err;\n      }\n\n      // Create and return readable stream\n      const stream = createReadStream(this.filePath);\n\n      // Handle stream errors\n      stream.on(\"error\", (err) => {\n        throw handleFsError(err, \"getStream:read\", this.filePath);\n      });\n\n      return stream;\n    } catch (err) {\n      throw handleFsError(err, \"getStream\", this.filePath);\n    }\n  }\n\n  /**\n   * Get raw binary data from the blob\n   * @returns The raw data and metadata or null if the blob doesn't exist\n   * @throws BlobError if there's an error reading the blob\n   */\n  async getRaw(): Promise<BlobResponse<Buffer> | null> {\n    try {\n      // Read the raw buffer\n      const content = await fs.readFile(this.filePath);\n      const stats = await fs.stat(this.filePath);\n      const metadataResult = await this.getMetadata();\n\n      const etag = calculateEtag(content);\n\n      // Check if content is base64 encoded\n      const isBase64 = metadataResult?.isBase64 === \"true\";\n      const decodedContent = isBase64\n        ? Buffer.from(content.toString(), \"base64\")\n        : content;\n\n      // Remove contentType and etag from metadata if they exist\n      const { contentType, etag: _, ...metadata } = metadataResult ?? {};\n\n      return {\n        content: decodedContent,\n        etag,\n        lastModified: stats.mtime,\n        size: stats.size,\n        contentType: metadataResult?.contentType ?? \"application/octet-stream\",\n        metadata: metadataResult\n          ? Object.keys(metadata).length > 0\n            ? metadata\n            : undefined\n          : undefined,\n      };\n    } catch (err) {\n      if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n        return null;\n      }\n      throw handleFsError(err, \"getRaw\", this.filePath);\n    }\n  }\n\n  /**\n   * Put JSON data into the blob\n   * @param value The JSON data to store\n   * @param options Optional metadata and ETag\n   * @returns The ETag of the stored data\n   * @throws BlobError if there's an error storing the data\n   */\n  async putJSON(value: T, options?: BlobOptions): Promise<{ etag: string }> {\n    try {\n      await fs.mkdir(path.dirname(this.filePath), { recursive: true });\n      const content = JSON.stringify(value);\n      const newEtag = calculateEtag(content);\n\n      if (options?.etag) {\n        try {\n          const existingContent = await fs.readFile(this.filePath, \"utf8\");\n          const existingEtag = calculateEtag(existingContent);\n\n          if (existingEtag !== options.etag) {\n            throw new BlobConflictError(\n              `ETag mismatch: expected ${options.etag} but found ${existingEtag}`,\n            );\n          }\n        } catch (err) {\n          // If the error is already a BlobError, rethrow it\n          if (err instanceof BlobError) {\n            throw err;\n          }\n          // Only use handleFsError for filesystem errors\n          if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n            throw handleFsError(err, \"putJSON:etag-check\", this.filePath);\n          }\n        }\n      }\n\n      await fs.writeFile(this.filePath, content, \"utf8\");\n\n      // Always create metadata file with content type\n      const metadata = {\n        ...(options?.metadata ?? {}),\n        contentType: options?.contentType ?? \"application/json\",\n      };\n      await this.updateMetadata(metadata);\n\n      return { etag: newEtag };\n    } catch (err) {\n      // If the error is already a BlobError, rethrow it\n      if (err instanceof BlobError) {\n        throw err;\n      }\n      throw handleFsError(err, \"putJSON\", this.filePath);\n    }\n  }\n\n  /**\n   * Put string data into the blob\n   * @param value The string data to store\n   * @param options Optional metadata and ETag\n   * @returns The ETag of the stored data\n   * @throws BlobError if there's an error storing the data\n   */\n  async putString(\n    value: string,\n    options?: BlobOptions,\n  ): Promise<{ etag: string }> {\n    try {\n      await fs.mkdir(path.dirname(this.filePath), { recursive: true });\n      const newEtag = calculateEtag(value);\n\n      if (options?.etag) {\n        try {\n          const existingContent = await fs.readFile(this.filePath, \"utf8\");\n          const existingEtag = calculateEtag(existingContent);\n\n          if (existingEtag !== options.etag) {\n            throw new BlobConflictError(\n              `ETag mismatch: expected ${options.etag} but found ${existingEtag}`,\n            );\n          }\n        } catch (err) {\n          if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n            throw handleFsError(err, \"putString:etag-check\", this.filePath);\n          }\n        }\n      }\n\n      await fs.writeFile(this.filePath, value, \"utf8\");\n\n      // Always create metadata file with content type\n      const metadata = {\n        ...(options?.metadata ?? {}),\n        contentType: options?.contentType ?? \"text/plain\",\n      };\n      await this.updateMetadata(metadata);\n\n      return { etag: newEtag };\n    } catch (err) {\n      throw handleFsError(err, \"putString\", this.filePath);\n    }\n  }\n\n  /**\n   * Put raw binary data into the blob\n   * @param value The binary data to store\n   * @param options Optional metadata and ETag\n   * @returns The ETag of the stored data\n   * @throws BlobError if there's an error storing the data\n   */\n  async putRaw(\n    value: Buffer,\n    options?: BlobOptions,\n  ): Promise<{ etag: string }> {\n    try {\n      await fs.mkdir(path.dirname(this.filePath), { recursive: true });\n      const newEtag = calculateEtag(value);\n\n      if (options?.etag) {\n        try {\n          const existingContent = await fs.readFile(this.filePath);\n          const existingEtag = calculateEtag(existingContent);\n\n          if (existingEtag !== options.etag) {\n            throw new BlobConflictError(\n              `ETag mismatch: expected ${options.etag} but found ${existingEtag}`,\n            );\n          }\n        } catch (err) {\n          if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n            throw handleFsError(err, \"putRaw:etag-check\", this.filePath);\n          }\n        }\n      }\n\n      // Write the raw buffer\n      await fs.writeFile(this.filePath, value);\n\n      // Always create metadata file with content type\n      const metadata = {\n        ...(options?.metadata ?? {}),\n        contentType: options?.contentType ?? \"application/octet-stream\",\n      };\n      await this.updateMetadata(metadata);\n\n      return { etag: newEtag };\n    } catch (err) {\n      throw handleFsError(err, \"putRaw\", this.filePath);\n    }\n  }\n\n  /**\n   * Get the blob content and metadata\n   * @returns The blob content and metadata or null if the blob doesn't exist\n   * @throws BlobError if there's an error reading the blob\n   */\n  async get(): Promise<BlobResponse<T> | null> {\n    try {\n      const content = await fs.readFile(this.filePath, \"utf8\");\n      const stats = await fs.stat(this.filePath);\n      const metadata = await this.getMetadata();\n\n      const etag = calculateEtag(content);\n\n      return {\n        content: JSON.parse(content) as T,\n        etag,\n        lastModified: stats.mtime,\n        size: stats.size,\n        contentType: metadata?.contentType ?? \"application/json\",\n        metadata: metadata ?? undefined,\n      };\n    } catch (err) {\n      if (\n        err instanceof Error &&\n        (err as NodeJS.ErrnoException).code === \"ENOENT\"\n      ) {\n        return null; // File doesn't exist\n      }\n      throw handleFsError(err, \"get\", this.filePath);\n    }\n  }\n\n  /**\n   * Put data from a stream into the blob\n   * @param stream The stream to read from\n   * @param options Optional metadata and ETag\n   * @returns The ETag of the stored data\n   * @throws BlobError if there's an error storing the data\n   */\n  async putStream(\n    stream: Readable,\n    options?: BlobOptions,\n  ): Promise<{ etag: string }> {\n    try {\n      await fs.mkdir(path.dirname(this.filePath), { recursive: true });\n\n      // Create write stream\n      const writeStream = createWriteStream(this.filePath);\n      const chunks: Buffer[] = [];\n\n      // Handle stream errors\n      stream.on(\"error\", (err) => {\n        writeStream.destroy();\n        throw handleFsError(err, \"putStream:read\", this.filePath);\n      });\n\n      writeStream.on(\"error\", (err) => {\n        stream.destroy();\n        throw handleFsError(err, \"putStream:write\", this.filePath);\n      });\n\n      // Collect chunks and write to file\n      for await (const chunk of stream) {\n        const buffer = Buffer.from(chunk as ArrayBufferLike);\n        chunks.push(buffer);\n        writeStream.write(buffer);\n      }\n\n      // Wait for write to complete\n      await new Promise<void>((resolve, reject) => {\n        writeStream.end((err?: Error | null) => {\n          if (err) reject(err);\n          else resolve();\n        });\n      });\n\n      // Calculate etag from all chunks\n      const buffer = Buffer.concat(chunks);\n      const etag = calculateEtag(buffer);\n\n      // Always create metadata file with content type\n      const metadata = {\n        ...(options?.metadata ?? {}),\n        contentType: options?.contentType ?? \"application/octet-stream\",\n      };\n      await this.updateMetadata(metadata);\n\n      return { etag };\n    } catch (err) {\n      throw handleFsError(err, \"putStream\", this.filePath);\n    }\n  }\n\n  /**\n   * Delete the blob\n   * @throws BlobError if there's an error deleting the blob\n   */\n  async delete(): Promise<void> {\n    try {\n      try {\n        await fs.unlink(this.filePath);\n      } catch (err) {\n        if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n          throw handleFsError(err, \"delete:file\", this.filePath);\n        }\n        // File already doesn't exist, continue to delete metadata\n      }\n\n      // Also delete metadata file if it exists\n      try {\n        await fs.unlink(this.metadataPath);\n      } catch (err) {\n        if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n          throw handleFsError(err, \"delete:metadata\", this.metadataPath);\n        }\n        // Metadata file doesn't exist, ignore\n      }\n    } catch (err) {\n      throw handleFsError(err, \"delete\", this.filePath);\n    }\n  }\n\n  /**\n   * Check if the blob exists\n   * @returns true if the blob exists, false otherwise\n   */\n  async exists(): Promise<boolean> {\n    try {\n      await fs.access(this.filePath);\n      return true;\n    } catch {\n      return false;\n    }\n  }\n\n  /**\n   * Get the blob metadata\n   * @returns The blob metadata or null if the blob doesn't exist\n   * @throws BlobError if there's an error reading the metadata\n   */\n  async getMetadata(): Promise<Record<string, string> | null> {\n    try {\n      const content = await fs.readFile(this.metadataPath, \"utf8\");\n      const metadata = JSON.parse(content) as Record<string, string>;\n\n      // Calculate etag from the blob content instead of the metadata content\n      try {\n        const blobContent = await fs.readFile(this.filePath);\n        const etag = calculateEtag(blobContent);\n        return { ...metadata, etag };\n      } catch (blobErr) {\n        if ((blobErr as NodeJS.ErrnoException).code === \"ENOENT\") {\n          // If blob doesn't exist but metadata does, return metadata without etag\n          return metadata;\n        }\n        throw handleFsError(blobErr, \"getMetadata:blob\", this.filePath);\n      }\n    } catch (err) {\n      if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n        return null; // Metadata file doesn't exist\n      }\n      throw handleFsError(err, \"getMetadata\", this.metadataPath);\n    }\n  }\n\n  /**\n   * Update metadata associated with the blob\n   * @param metadata The new metadata to store\n   * @param options Optional ETag for conditional update\n   * @throws BlobError if there's an error updating the metadata\n   */\n  async updateMetadata(\n    metadata: Record<string, string>,\n    options?: BlobOptions,\n  ): Promise<void> {\n    try {\n      // If etag is provided, verify it matches before updating\n      if (options?.etag) {\n        try {\n          const existingContent = await fs.readFile(this.filePath);\n          const existingEtag = calculateEtag(existingContent);\n\n          if (existingEtag !== options.etag) {\n            throw new BlobConflictError(\n              `ETag mismatch: expected ${options.etag} but found ${existingEtag}`,\n            );\n          }\n        } catch (err) {\n          if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n            throw handleFsError(\n              err,\n              \"updateMetadata:etag-check\",\n              this.filePath,\n            );\n          }\n        }\n      }\n\n      await fs.mkdir(path.dirname(this.metadataPath), { recursive: true });\n\n      // Get existing metadata to preserve contentType\n      let existingMetadata: Record<string, string> = {};\n      try {\n        const content = await fs.readFile(this.metadataPath, \"utf8\");\n        existingMetadata = JSON.parse(content) as Record<string, string>;\n      } catch (err) {\n        if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n          throw handleFsError(err, \"updateMetadata:read\", this.metadataPath);\n        }\n      }\n\n      // Preserve contentType if it exists in existing metadata\n      const contentType = existingMetadata.contentType;\n      const newMetadata = { ...metadata };\n      if (contentType) {\n        newMetadata.contentType = contentType;\n      }\n\n      await fs.writeFile(\n        this.metadataPath,\n        JSON.stringify(newMetadata),\n        \"utf8\",\n      );\n    } catch (err) {\n      throw handleFsError(err, \"updateMetadata\", this.metadataPath);\n    }\n  }\n}\n\n/**\n * FileSystem implementation of blob storage\n */\nexport class FileSystemBlobStorage implements BlobStorage {\n  /**\n   * Create a new FileSystemBlobStorage\n   * @param rootDir The root directory for blob storage\n   * @param defaultPrefix Optional default prefix for all blob keys\n   */\n  constructor(\n    private rootDir: string,\n    private defaultPrefix?: string,\n  ) {\n    // Ensure rootDir exists on instantiation\n    void this.ensureRootDir();\n  }\n\n  /**\n   * Ensure the root directory exists\n   * @throws BlobError if there's an error creating the directory\n   */\n  private async ensureRootDir(): Promise<void> {\n    try {\n      await fs.mkdir(this.rootDir, { recursive: true });\n    } catch (err) {\n      throw handleFsError(err, \"ensureRootDir\", this.rootDir);\n    }\n  }\n\n  /**\n   * Get the full path for a blob key\n   * @param key The blob key\n   * @returns The full path to the blob\n   */\n  private getFullPath(key: string): string {\n    // Normalize key by removing leading/trailing slashes\n    const normalizedKey = key.replace(/^\\/+|\\/+$/g, \"\");\n\n    // Apply default prefix if specified\n    const prefixedKey = this.defaultPrefix\n      ? `${this.defaultPrefix}/${normalizedKey}`\n      : normalizedKey;\n\n    return path.join(this.rootDir, prefixedKey);\n  }\n\n  /**\n   * Get a blob by key\n   * @param key The blob key\n   * @returns A Blob instance for the given key\n   */\n  getBlob<T>(key: string): Blob<T> {\n    return new FileSystemBlob<T>(this.getFullPath(key));\n  }\n\n  /**\n   * List all blobs with optional pagination\n   * @param options Options for listing blobs including prefix and pagination\n   * @returns A paginated list of blob keys\n   * @throws BlobError if there's an error listing blobs\n   */\n  async listBlobs(options?: ListBlobsOptions): Promise<ListBlobsResponse> {\n    try {\n      const {\n        prefix = \"\",\n        limit = 100,\n        cursor = undefined,\n      } = (options ?? {}) as {\n        prefix?: string;\n        limit?: number;\n        cursor?: string;\n      };\n      // Normalize prefixes by removing trailing slashes\n      const normalizedDefaultPrefix = this.defaultPrefix?.replace(/\\/$/, \"\");\n      const normalizedPrefix = prefix.replace(/\\/$/, \"\");\n\n      // Build the search prefix\n      const searchPrefix = normalizedDefaultPrefix\n        ? normalizedPrefix\n          ? `${normalizedDefaultPrefix}/${normalizedPrefix}`\n          : normalizedDefaultPrefix\n        : normalizedPrefix;\n\n      const searchPath = path.join(this.rootDir, searchPrefix);\n\n      try {\n        // Check if directory exists\n        await fs.access(searchPath);\n      } catch (err) {\n        if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n          return { blobs: [], nextCursor: undefined }; // Directory doesn't exist\n        }\n        throw handleFsError(err, \"listBlobs:access\", searchPath);\n      }\n\n      // Recursive function to list files with stats\n      const listFilesRecursively = async (\n        dir: string,\n        baseDir: string,\n      ): Promise<{ key: string; lastModified: string; size: number }[]> => {\n        const items = await fs.readdir(dir, { withFileTypes: true });\n        const files: { key: string; lastModified: string; size: number }[] = [];\n\n        for (const item of items) {\n          const fullPath = path.join(dir, item.name);\n          const relativePath = path.relative(baseDir, fullPath);\n\n          if (item.isDirectory()) {\n            const subFiles = await listFilesRecursively(fullPath, baseDir);\n            files.push(...subFiles);\n          } else if (!item.name.endsWith(\".metadata.json\")) {\n            // Get file stats\n            const stats = await fs.stat(fullPath);\n            files.push({\n              key: relativePath,\n              lastModified: stats.mtime.toISOString(),\n              size: stats.size,\n            });\n          }\n        }\n\n        return files.sort((a, b) => a.key.localeCompare(b.key)); // Sort for consistent pagination\n      };\n\n      let allFiles = await listFilesRecursively(searchPath, this.rootDir);\n\n      // Remove default prefix from results if it exists\n      if (normalizedDefaultPrefix) {\n        allFiles = allFiles\n          .filter(\n            (file) =>\n              file.key === normalizedDefaultPrefix ||\n              file.key.startsWith(`${normalizedDefaultPrefix}/`),\n          )\n          .map((file) => ({\n            ...file,\n            key:\n              file.key === normalizedDefaultPrefix\n                ? \"\"\n                : file.key.slice(normalizedDefaultPrefix.length + 1),\n          }));\n      }\n\n      // Handle cursor-based pagination\n      let startIndex = 0;\n      if (cursor) {\n        const decodedCursor = fromBase64UrlSafe(cursor);\n        startIndex = allFiles.findIndex((file) => file.key > decodedCursor);\n        if (startIndex === -1) startIndex = allFiles.length;\n      }\n\n      // Handle limit\n      const endIndex = Math.min(startIndex + limit, allFiles.length);\n      const items = allFiles.slice(startIndex, endIndex);\n\n      // Generate next cursor\n      const nextCursor =\n        endIndex < allFiles.length\n          ? toBase64UrlSafe(allFiles[endIndex - 1].key)\n          : undefined;\n\n      return {\n        blobs: items,\n        nextCursor,\n      };\n    } catch (err) {\n      throw handleFsError(err, \"listBlobs\", this.rootDir);\n    }\n  }\n\n  /**\n   * Check if a blob exists\n   * @param key The blob key\n   * @returns True if the blob exists, false otherwise\n   */\n  async blobExists(key: string): Promise<boolean> {\n    const blob = this.getBlob(key);\n    return blob.exists();\n  }\n\n  /**\n   * Delete a blob\n   * @param key The blob key\n   * @returns The result of the delete operation\n   */\n  async deleteBlob(key: string): Promise<DeleteBlobResult> {\n    try {\n      const blob = this.getBlob(key);\n      const existed = await blob.exists();\n      await blob.delete();\n      return { deleted: existed };\n    } catch (err) {\n      if (err instanceof BlobError) {\n        throw err;\n      }\n      throw handleFsError(err, \"deleteBlob\", this.getFullPath(key));\n    }\n  }\n}\n"],"names":["BlobNotFoundError","BlobPermissionDeniedError","BlobConflictError","BlobInternalError","crypto","fs","createReadStream","path","BlobError","createWriteStream","fromBase64UrlSafe","toBase64UrlSafe"],"mappings":"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"}