import "server-only"; import QRCode, { type QRCodeRenderersOptions } from "qrcode"; import type { QrDesign } from "@/lib/qr/design"; /** Fehler beim Erzeugen des Codes, mit Meldung für die Oberfläche. */ export class QrRenderError extends Error {} function toOptions(design: QrDesign): QRCodeRenderersOptions { return { errorCorrectionLevel: design.ecLevel, margin: design.margin, width: design.size, color: { dark: design.fgColor, light: design.bgColor, }, }; } function wrap(error: unknown): never { const detail = error instanceof Error ? error.message : String(error); if (/too (long|big)|code length overflow|data too long/i.test(detail)) { throw new QrRenderError( "Der Inhalt ist zu lang für einen QR-Code. Kürze die Adresse oder wähle ein niedrigeres Fehlerkorrektur-Level.", ); } throw new QrRenderError(`Der QR-Code konnte nicht erzeugt werden: ${detail}`); } export async function renderSvg( content: string, design: QrDesign, ): Promise { try { return await QRCode.toString(content, { ...toOptions(design), type: "svg" }); } catch (error) { wrap(error); } } export async function renderPng( content: string, design: QrDesign, ): Promise { try { return await QRCode.toBuffer(content, { ...toOptions(design), type: "png" }); } catch (error) { wrap(error); } } export type QrFormat = "png" | "svg"; export const CONTENT_TYPES: Record = { png: "image/png", svg: "image/svg+xml", };