All files / src/utils Binary.ts

100% Statements 35/35
100% Branches 24/24
100% Functions 2/2
100% Lines 34/34

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83                            23x 4x 4x 3x         19x 4x 4x 3x 2x 2x 2x 4x         1x 1x       15x 15x 13x 13x 13x         2x 2x     1x       14x 14x   2x     3x   1x   1x   2x   1x   1x   1x   1x   1x        
import fs from "fs";
import path from "path";
import { logger } from "./logger.js";
 
export interface Base64Data {
  data: string;
  mimeType: string;
}
 
export class BinaryUtils {
  /**
   * Converts a URL (data:, http:, or local path) to a base64 string and mime type.
   */
  static async toBase64(url: string): Promise<Base64Data | null> {
    if (url.startsWith("data:")) {
      const match = url.match(/^data:([^;]+);base64,(.+)$/);
      if (match && match[1] && match[2]) {
        return {
          mimeType: match[1],
          data: match[2]
        };
      }
    } else if (url.startsWith("http")) {
      try {
        const response = await fetch(url);
        if (!response.ok) return null;
        const buffer = await response.arrayBuffer();
        const base64 = Buffer.from(buffer).toString("base64");
        const mimeType = response.headers.get("content-type") || this.guessMimeType(url);
        return {
          mimeType,
          data: base64
        };
      } catch (e) {
        logger.error("Error converting URL to base64:", e as Error);
        return null;
      }
    } else {
      // Assume local file path
      try {
        const buffer = await fs.promises.readFile(url);
        const base64 = buffer.toString("base64");
        const mimeType = this.guessMimeType(url);
        return {
          mimeType,
          data: base64
        };
      } catch (e) {
        logger.error("Error reading local file for base64:", e as Error);
        return null;
      }
    }
    return null;
  }
 
  private static guessMimeType(filePath: string): string {
    const ext = path.extname(filePath).toLowerCase();
    switch (ext) {
      case ".png":
        return "image/png";
      case ".jpg":
      case ".jpeg":
        return "image/jpeg";
      case ".webp":
        return "image/webp";
      case ".gif":
        return "image/gif";
      case ".mp3":
        return "audio/mpeg";
      case ".wav":
        return "audio/wav";
      case ".ogg":
        return "audio/ogg";
      case ".m4a":
        return "audio/mp4";
      case ".pdf":
        return "application/pdf";
      default:
        return "application/octet-stream";
    }
  }
}