The repo CHANGELOG had fallen behind. Adds [Unreleased] entries for the recently shipped work and a README for the previously undocumented PdfService. Added (changelog): - Reports — Purchasing spend analytics (cost centres + accounting codes). - Email PO to vendor + the PdfService microservice (cached per PO). - EpfoService + PdfService microservices and their release auto-deploy. - Unsaved-changes prompt on PO create/edit (#18). - Crew login-on-hire for management ranks. - Delivery Locations (#19), T&C catalogue (#11), advance payment (#92). Fixed (changelog): - "Email to vendor" never rendered (auth middleware bounced the svc fetch) — #127. - Reports charts all one colour (RSC client/server boundary) — #120. New: PdfService/README.md (endpoints, token/origin security, env, app integration). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| src | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
PdfService
Renders a PPMS purchase order to a real PDF for the "Email PO to vendor"
feature — a standalone Express + Playwright microservice, mirroring
GstService / EpfoService.
The app's /api/po/:id/export?format=pdf&pdf=1 produces a print-styled HTML page;
PdfService loads that URL in headless Chromium and prints it to an A4 PDF. The
export URL carries a short-lived svc token so the export route serves the
page without a user session (the app's auth middleware allows that one route
through when the token matches — see App/lib/pdf-export-auth.ts).
Endpoints
| Method | Path | Body / Headers | Returns |
|---|---|---|---|
| GET | /health |
— | { status, browser } |
| POST | /pdf |
{ url } + header x-pdf-token |
application/pdf (else 401 / 400 / 403 / 502) |
Security
- Token — when
PDF_SERVICE_TOKENis set,/pdfrequires a matchingx-pdf-tokenheader (the app and PdfService share the secret). - Origin allow-list (anti-SSRF) — when
ALLOWED_ORIGINis set, PdfService only navigates to URLs whose origin matches it. - Both unset (dev) → checks are skipped.
Env
PORT=3005
PDF_SERVICE_TOKEN= # shared secret with the app (app side: PDF_SERVICE_TOKEN)
ALLOWED_ORIGIN= # e.g. http://localhost:3000 (optional)
Run
npm install
npm run dev # tsx watch src/index.ts
npm run build && npm start # node dist/index.js
App integration
App/lib/pdf-service.ts (renderPoPdf) POSTs { url } to /pdf. The app gates
the feature on PDF_SERVICE_URL + PDF_SERVICE_TOKEN (isPdfServiceConfigured()),
uploads the returned PDF to R2 at a per-PO key (reused across sends), and
returns a mailto: with a 7-day presigned link. APP_INTERNAL_URL is the base URL
PdfService reaches the app at (falls back to NEXTAUTH_URL).
On pms1 the service is auto-deployed on each release tag via the root
ecosystem.config.js (pm2 pdf-service, port 3005) — see
Deployment and Operations.