/*********************************************************************************************************************************************************************** * File Name: certificate.service.js * Type of Program: Service * Description: Generates a PDF certificate by compiling a Typst template. * Data is passed to the template via --input CLI flags (no temp files needed for input). * Output is written to a temp file, read into a Buffer, then cleaned up. * * Author: Kenneth Obsequio (@lash0000) * Date Created: Jun. 18, 2026 ***********************************************************************************************************************************************************************/ 'use strict'; const { execFile } = require('child_process'); const { promisify } = require('util'); const fs = require('fs/promises'); const path = require('path'); const crypto = require('crypto'); const os = require('os'); const execFileAsync = promisify(execFile); const TEMPLATE_PATH = path.join(__dirname, '../templates/certificate.typ'); /** * @param {{ * name: string, * course: string, * date: string, * cert_no: string, * ref_no: string, * instructors?: string, * length?: string, * }} data * @returns {Promise} */ async function generateCertificate({ name, course, date, cert_no, ref_no, instructors = '', length = '' }) { const outPath = path.join(os.tmpdir(), `cert_${crypto.randomUUID()}.pdf`); const args = [ 'compile', TEMPLATE_PATH, outPath, '--input', `name=${name}`, '--input', `course=${course}`, '--input', `date=${date}`, '--input', `cert_no=${cert_no}`, '--input', `ref_no=${ref_no}`, ]; if (instructors) args.push('--input', `instructors=${instructors}`); if (length) args.push('--input', `length=${length}`); try { await execFileAsync('typst', args); return await fs.readFile(outPath); } finally { await fs.unlink(outPath).catch(() => {}); } } module.exports = { generateCertificate };