All files / apps/chatbot/src/utils imageData.ts

100% Statements 13/13
85.71% Branches 12/14
100% Functions 3/3
100% Lines 10/10

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              5x                   1x   1x 6x 5x 5x 3x                   1x 4x 4x    
export type SelectedImage = {
  uri: string;
  fileName?: string;
  type?: string;
  base64?: string;
};
 
export const hasUrlScheme = (value: string) => /^[a-z][a-z0-9+.-]*:/i.test(value.trim());
 
/**
 * Ceiling for one outbound image data URL — mirrors the backend's
 * MAX_IMAGE_DATA_URL_LENGTH. The server caps `images[].url` at this many
 * characters (the unconsumed image is cached in D1, which rejects values over
 * ~1MB), so anything longer is rejected with an HTTP 422 `too_big`. Note this
 * counts base64 CHARACTERS, not binary bytes — base64 inflates bytes by ~4/3,
 * which is why a size check on the raw file bytes let oversize images through.
 */
export const MAX_IMAGE_DATA_URL_LENGTH = 800_000;
 
export const resolveImageData = (image: SelectedImage | null) => {
  if (!image) return null;
  const base64Value = image.base64?.trim() || "";
  if (!base64Value || hasUrlScheme(base64Value)) return null;
  return base64Value.startsWith("data:")
    ? base64Value
    : `data:${image.type || "image/jpeg"};base64,${base64Value}`;
};
 
/**
 * True when the resolved data URL would exceed what the backend accepts.
 * Checks the exact string that gets sent, so the guard can never disagree with
 * the server's own validation. A null/absent image is not "too big".
 */
export const exceedsImageDataUrlLimit = (image: SelectedImage | null) => {
  const dataUrl = resolveImageData(image);
  return dataUrl !== null && dataUrl.length > MAX_IMAGE_DATA_URL_LENGTH;
};