All files / web/src/lib image-generation.ts

0% Statements 0/50
0% Branches 0/1
0% Functions 0/1
0% Lines 0/50

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                                                                                                     
import { getImageProvider } from './image-providers'
import type { ImageOptions } from './image-providers'
import { imageExists, storeImage } from './image-storage'
import type { ImageStorageTarget } from './image-storage'

export type { ImageStorageTarget } from './image-storage'

export interface GenerateAndStoreRequest {
  provider: string
  model: string
  prompt: string
  imageOptions?: ImageOptions
  storageTarget: ImageStorageTarget
  skipIfExists?: boolean
  /** Optional reference image for image-to-image generation (e.g. theme variants). */
  referenceImage?: Buffer
}

export interface GenerateAndStoreResult {
  status: 'generated' | 'skipped'
  publicUrl: string
  sizeBytes?: number
}

export async function generateAndStoreImage(
  req: GenerateAndStoreRequest
): Promise<GenerateAndStoreResult> {
  if (req.skipIfExists && imageExists(req.storageTarget)) {
    const publicUrl =
      req.storageTarget.type === 'static'
        ? `/${req.storageTarget.relativePath}`
        : `/api/images/${req.storageTarget.category}/${req.storageTarget.filename}`
    return { status: 'skipped', publicUrl }
  }

  const provider = getImageProvider(req.provider)
  if (!provider) {
    throw new Error(`Unknown image provider: ${req.provider}`)
  }

  const { imageBuffer } = await provider.generate({
    model: req.model,
    prompt: req.prompt,
    options: req.imageOptions,
    referenceImage: req.referenceImage,
  })

  const { publicUrl, sizeBytes } = storeImage(req.storageTarget, imageBuffer)
  return { status: 'generated', publicUrl, sizeBytes }
}