From 0594816ea4ff0f6b08daf3b788211d353eab0640 Mon Sep 17 00:00:00 2001 From: Jackson Roberts Date: Fri, 10 Apr 2026 03:00:31 +0000 Subject: [PATCH] fix(api): include pdfmake Roboto fonts in runtime image --- api/Dockerfile | 3 +++ api/src/modules/pdf-utils/generateQuote.ts | 23 ++++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/api/Dockerfile b/api/Dockerfile index cdac97e..40c3183 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -90,6 +90,9 @@ COPY --from=build /app/dalpuri/generated/ ./dalpuri/generated/ # Copy production node_modules (Prisma adapter needs native bindings) COPY --from=deps /app/node_modules/ ./node_modules/ +# Ensure pdfmake Roboto fonts are present at runtime for PDF generation. +COPY --from=build /app/node_modules/pdfmake/build/fonts/ ./node_modules/pdfmake/build/fonts/ + ENV NODE_ENV=production # ---- Stage 4: API server runtime image ---- diff --git a/api/src/modules/pdf-utils/generateQuote.ts b/api/src/modules/pdf-utils/generateQuote.ts index 81556b5..7f4a856 100644 --- a/api/src/modules/pdf-utils/generateQuote.ts +++ b/api/src/modules/pdf-utils/generateQuote.ts @@ -1,5 +1,5 @@ import PdfPrinter from "pdfmake/src/Printer"; -import { readFileSync } from "node:fs"; +import { existsSync, readFileSync } from "node:fs"; import { join } from "node:path"; export interface QuoteLineItem { @@ -110,7 +110,26 @@ const COMPANY = { const DEFAULT_LOGO_PATH = join(process.cwd(), "logo.png"); -const fontDir = join(process.cwd(), "node_modules/pdfmake/build/fonts/Roboto"); +function resolveRobotoFontDir(): string { + const candidates = [ + join(process.cwd(), "node_modules/pdfmake/build/fonts/Roboto"), + join(import.meta.dir, "../../../node_modules/pdfmake/build/fonts/Roboto"), + join("/app/node_modules/pdfmake/build/fonts/Roboto"), + join("/app/api/node_modules/pdfmake/build/fonts/Roboto"), + ]; + + for (const dir of candidates) { + if (existsSync(join(dir, "Roboto-Medium.ttf"))) { + return dir; + } + } + + throw new Error( + `[pdf] Could not locate pdfmake Roboto fonts. Checked: ${candidates.join(", ")}` + ); +} + +const fontDir = resolveRobotoFontDir(); const fonts = { Roboto: { normal: join(fontDir, "Roboto-Regular.ttf"),