81 lines
3.1 KiB
JavaScript
81 lines
3.1 KiB
JavaScript
// Prints from a JSON template spec using backend /api/print
|
|
// Usage: node scripts/print_template.js templates/referencia.json
|
|
|
|
process.env.PRINTER_HOST = process.env.PRINTER_HOST || '192.168.87.147';
|
|
process.env.PRINTER_DEVICE_ID = process.env.PRINTER_DEVICE_ID || 'matricial2';
|
|
process.env.PRINTER_TIMEOUT_MS = process.env.PRINTER_TIMEOUT_MS || '60000';
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const axios = require('axios');
|
|
|
|
// Allow running standalone or with server already running
|
|
if (!process.env.TEST_BASE_URL) {
|
|
process.env.PORT = process.env.PORT || '3003';
|
|
process.env.TEST_BASE_URL = `http://localhost:${process.env.PORT}`;
|
|
require('../src/server.js');
|
|
}
|
|
|
|
function padRight(str, len) { str = String(str); return str.length >= len ? str.slice(0, len) : str + ' '.repeat(len - str.length); }
|
|
function padLeft(str, len) { str = String(str); return str.length >= len ? str.slice(0, len) : ' '.repeat(len - str.length) + str; }
|
|
|
|
function buildOpsFromSpec(spec) {
|
|
const ops = [];
|
|
const widthChars = spec.widthChars || 42; // default receipt width (monospace)
|
|
const hrChar = spec.hrChar || '-';
|
|
|
|
const addLines = (lines, align, options = {}) => {
|
|
if (align) ops.push({ op: 'textAlign', align });
|
|
if (options.font) ops.push({ op: 'textFont', font: options.font });
|
|
if (options.size) ops.push({ op: 'textSize', width: options.size.width, height: options.size.height });
|
|
if (options.style) ops.push({ op: 'textStyle', ...options.style });
|
|
for (const ln of lines) ops.push({ op: 'text', value: String(ln) });
|
|
};
|
|
|
|
for (const sec of spec.sections || []) {
|
|
if (sec.lines) {
|
|
addLines(sec.lines, sec.align, sec);
|
|
} else if (sec.hr) {
|
|
ops.push({ op: 'textAlign', align: 'left' });
|
|
ops.push({ op: 'text', value: hrChar.repeat(widthChars) });
|
|
} else if (sec.columns) {
|
|
const widths = sec.columns.widths || [];
|
|
const rows = sec.columns.rows || [];
|
|
for (const row of rows) {
|
|
const cols = [];
|
|
for (let i = 0; i < widths.length; i++) {
|
|
const w = widths[i];
|
|
const v = row[i] == null ? '' : String(row[i]);
|
|
// left pad for last col if numeric
|
|
if (i === widths.length - 1 && /^[0-9$.,\s-]+$/.test(v)) cols.push(padLeft(v, w));
|
|
else cols.push(padRight(v, w));
|
|
}
|
|
ops.push({ op: 'textAlign', align: 'left' });
|
|
ops.push({ op: 'text', value: cols.join('') });
|
|
}
|
|
}
|
|
if (sec.feedLines) ops.push({ op: 'feedLine', line: sec.feedLines });
|
|
if (sec.cut) ops.push({ op: 'cut', type: sec.cut });
|
|
}
|
|
return ops;
|
|
}
|
|
|
|
async function main() {
|
|
const jsonPath = process.argv[2];
|
|
if (!jsonPath) throw new Error('Template JSON path required');
|
|
const spec = JSON.parse(fs.readFileSync(path.resolve(jsonPath), 'utf-8'));
|
|
|
|
const ops = buildOpsFromSpec(spec);
|
|
const base = process.env.TEST_BASE_URL;
|
|
const resp = await axios.post(base + '/api/print', { operations: ops }, { timeout: 180000 });
|
|
console.log(resp.data);
|
|
if (!resp.data || resp.data.ok !== true) {
|
|
throw new Error('Printer did not confirm success.');
|
|
}
|
|
}
|
|
|
|
if (require.main === module) {
|
|
main().catch((e) => { console.error(e.message); process.exit(1); });
|
|
}
|
|
|