mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
68 lines
2.4 KiB
JavaScript
68 lines
2.4 KiB
JavaScript
/***********************************************************************************************************************************************************************
|
|
* 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');
|
|
const FONT_PATH = path.join(__dirname, '../templates/fonts/Arimo');
|
|
|
|
// The Docker image gets `typst` on PATH via COPY --from=typst. Bare-metal
|
|
// deploys (no Docker involved) don't have that, so TYPST_BIN lets ops point
|
|
// at a manually-installed binary instead.
|
|
const TYPST_BIN = process.env.TYPST_BIN || 'typst';
|
|
|
|
/**
|
|
* @param {{
|
|
* name: string,
|
|
* course: string,
|
|
* date: string,
|
|
* cert_no: string,
|
|
* ref_no: string,
|
|
* instructors?: string,
|
|
* length?: string,
|
|
* }} data
|
|
* @returns {Promise<Buffer>}
|
|
*/
|
|
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,
|
|
'--font-path', FONT_PATH,
|
|
'--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_BIN, args);
|
|
return await fs.readFile(outPath);
|
|
} finally {
|
|
await fs.unlink(outPath).catch(() => {});
|
|
}
|
|
}
|
|
|
|
module.exports = { generateCertificate };
|