All files / backend/src/jobs create-thumbnail-job.ts

86.66% Statements 13/15
88.88% Branches 8/9
100% Functions 1/1
86.66% Lines 13/15

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                              15x   15x 1x     14x   14x     14x 3x 3x         11x 11x                     11x 11x       11x          
import fs from 'fs-extra'
import sharp from 'sharp'
import path from 'path'
 
export interface CreateThumbnailParams {
  src: string
  dest: string
}
 
/**
 * Creates a thumbnail image from a source image.
 * For GIF, SVG, and ICO files, simply copies the original.
 * For other image types, scales to fit within 400x400 pixels.
 */
export async function createThumbnailJob(params: CreateThumbnailParams): Promise<string> {
  const { src, dest } = params
 
  if (!fs.existsSync(src)) {
    throw new Error('image file does not exist')
  }
 
  await fs.ensureDir(path.dirname(dest))
 
  const ext = path.extname(src).toLowerCase()
 
  // For GIF, SVG, and ICO, just copy the original
  if (ext === '.gif' || ext === '.svg' || ext === '.ico') {
    await fs.copy(src, dest)
    return 'image copied'
  }
 
  // For other image types, create a scaled thumbnail using Sharp
  // Sharp can handle very large images (200MP+) efficiently with low memory usage
  try {
    await sharp(src)
      .resize(400, 400, {
        fit: 'inside', // Maintain aspect ratio, fit within 400x400
        withoutEnlargement: true // Don't upscale small images
      })
      .toFile(dest)
  } catch (e) {
    throw new Error(`Failed to create thumbnail: ${e}`)
  }
 
  // Verify the thumbnail was created
  const thumbExists = fs.existsSync(dest)
  Iif (!thumbExists) {
    throw new Error('Thumbnail creation failed - file does not exist after processing')
  }
 
  return 'thumbnail created'
}
 
// Export as default for worker-wrapper
export default createThumbnailJob