upn-with-qr-generator
Version:
A UPN + QR code generator for Slovenian banking system (2024 standard compliant) with environment-aware canvas support and isPNGGenerationAvailable method
168 lines (167 loc) • 8.54 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UPNWriter = void 0;
// src/UPNWriter.ts
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const UPNGenerator_1 = require("./UPNGenerator");
class UPNWriter {
constructor(data) {
this.canvasAvailable = false;
this.upnGenerator = new UPNGenerator_1.UPNGenerator(data);
this.initializeCanvas();
}
initializeCanvas() {
try {
// Try to load canvas - this should work in regular Node.js environments
const { createCanvas, loadImage, registerFont } = require('canvas');
this.canvas = { createCanvas, loadImage, registerFont };
this.canvasAvailable = true;
// Register the Courier Bold font only when canvas is available
try {
// Use require.resolve to find the correct package location
const packageRoot = path_1.default.dirname(require.resolve('upn-with-qr-generator/package.json'));
const fontPath = path_1.default.join(packageRoot, 'assets', 'courbd.ttf');
registerFont(fontPath, { family: 'Courier Bold' });
}
catch (fontError) {
console.warn('Could not register Courier Bold font:', fontError instanceof Error ? fontError.message : String(fontError));
}
}
catch (error) {
// Canvas not available (likely serverless environment or missing dependencies)
console.warn('Canvas not available in this environment:', error instanceof Error ? error.message : String(error));
this.canvasAvailable = false;
}
}
// Method to generate the UPN image on the canvas
generateCanvas() {
return __awaiter(this, void 0, void 0, function* () {
if (!this.canvasAvailable) {
throw new Error('PNG generation requires canvas library which is not available in this environment. ' +
'Use QR code generation only or run in a Node.js environment with canvas support.');
}
// Use require.resolve to find the correct package location
const packageRoot = path_1.default.dirname(require.resolve('upn-with-qr-generator/package.json'));
const templatePath = path_1.default.join(packageRoot, 'assets', 'upn_sl.png');
const templateImage = yield this.canvas.loadImage(templatePath);
const canvas = this.canvas.createCanvas(templateImage.width, templateImage.height);
const context = canvas.getContext('2d');
context.drawImage(templateImage, 0, 0);
const largeFontSize = '24px';
const smallFontSize = '20px';
context.fillStyle = '#000';
// Draw QR code with 10% increased size (242x242)
const qrCodeBuffer = yield this.upnGenerator.generateQRCode();
context.drawImage(yield this.canvas.loadImage(qrCodeBuffer), 415, 42, 250, 250);
const data = this.upnGenerator.getData();
// Large text fields
context.font = `${largeFontSize} "Courier Bold"`;
context.fillText(data.payerName || '', 697, 170);
context.fillText(data.payerAddress || '', 697, 201);
context.fillText(data.payerPost || '', 697, 233);
context.fillText(data.receiverName || '', 418, 507);
context.fillText(data.receiverAddress || '', 418, 538);
context.fillText(data.receiverPost || '', 418, 570);
context.fillText(data.receiverIban || '', 418, 400);
// Handle receiver reference (new structure with fallback to legacy)
const receiverRef = data.receiverReference || data.reference || '';
context.fillText(this.getReferencePrefix(receiverRef), 418, 451);
context.fillText(this.getReferenceSuffix(receiverRef), 528, 451);
context.fillText(data.purpose || '', 528, 340);
context.fillText(data.code || '', 418, 340);
context.fillText('***' + this.formatAmount(data.amount), 750, 285);
// Handle payment date (new DD.MM.YYYY format vs legacy YYYYMMDD)
const paymentDate = data.paymentDate || this.convertLegacyDate(data.dueDate);
if (paymentDate) {
context.fillText(paymentDate, 1155, 340);
}
// Small text fields
context.font = `${smallFontSize} "Courier Bold"`;
context.fillText(data.payerName || '', 30, 62);
context.fillText(data.payerAddress || '', 30, 87);
context.fillText(data.payerPost || '', 30, 112);
context.fillText(data.receiverName || '', 30, 405);
context.fillText(data.receiverAddress || '', 30, 430);
context.fillText(data.receiverPost || '', 30, 455);
context.fillText(data.receiverIban || '', 30, 300);
context.fillText(receiverRef, 30, 351);
context.fillText(data.purpose || '', 30, 165);
if (paymentDate) {
context.fillText(paymentDate, 30, 180);
}
return canvas;
});
}
// Save as PNG file
saveAsPNG(outputPath) {
return __awaiter(this, void 0, void 0, function* () {
if (!this.canvasAvailable) {
throw new Error('PNG generation requires canvas library which is not available in this environment. ' +
'Use QR code generation only or run in a Node.js environment with canvas support.');
}
const canvas = yield this.generateCanvas();
const out = fs_1.default.createWriteStream(outputPath);
const stream = canvas.createPNGStream();
stream.pipe(out);
out.on('finish', () => console.log(`UPN image saved as ${outputPath}`));
});
}
// Get PNG as a base64 string
png() {
return __awaiter(this, void 0, void 0, function* () {
if (!this.canvasAvailable) {
throw new Error('PNG generation requires canvas library which is not available in this environment. ' +
'Use QR code generation only or run in a Node.js environment with canvas support.');
}
const canvas = yield this.generateCanvas();
return canvas.toDataURL('image/png').split(',')[1]; // Remove "data:image/png;base64,"
});
}
// Get image buffer (equivalent to GD resource in PHP)
gdResource() {
return __awaiter(this, void 0, void 0, function* () {
if (!this.canvasAvailable) {
throw new Error('PNG generation requires canvas library which is not available in this environment. ' +
'Use QR code generation only or run in a Node.js environment with canvas support.');
}
const canvas = yield this.generateCanvas();
return canvas.toBuffer('image/png');
});
}
// Add method to check if PNG generation is available
isPNGGenerationAvailable() {
return this.canvasAvailable;
}
getReferencePrefix(reference) {
return reference.slice(0, 4);
}
getReferenceSuffix(reference) {
return reference.slice(4);
}
formatDate(date) {
return `${date.slice(6, 8)}.${date.slice(4, 6)}.${date.slice(0, 4)}`;
}
formatAmount(amount) {
return amount.toFixed(2);
}
convertLegacyDate(date) {
if (!date || date.length !== 8) {
return '';
}
return `${date.slice(6, 8)}.${date.slice(4, 6)}.${date.slice(0, 4)}`;
}
}
exports.UPNWriter = UPNWriter;