safeer-pdf-generator
Version:
Framework-agnostic PDF generation library with chunking, merging, S3 upload, and email delivery
258 lines • 10.5 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.mergePdfs = mergePdfs;
exports.mergePdfFiles = mergePdfFiles;
exports.analyzePdfs = analyzePdfs;
exports.validatePdfs = validatePdfs;
exports.splitPdf = splitPdf;
exports.extractPages = extractPages;
exports.getPdfInfo = getPdfInfo;
exports.mergePdfsWithRanges = mergePdfsWithRanges;
exports.batchMergePdfs = batchMergePdfs;
const MergeService_js_1 = require("../core/MergeService.js");
const guards_js_1 = require("../utils/guards.js");
const errors_js_1 = require("../core/errors.js");
const defaults_js_1 = require("../config/defaults.js");
/**
* Merge multiple PDF buffers into a single PDF
*/
async function mergePdfs(pdfBuffers, options = {}) {
const logger = options.logging || defaults_js_1.noOpLogger;
// Validate inputs
if (!Array.isArray(pdfBuffers) || pdfBuffers.length === 0) {
throw new errors_js_1.MergeError('At least one PDF buffer is required');
}
// Validate all inputs are buffers
for (let i = 0; i < pdfBuffers.length; i++) {
if (!(0, guards_js_1.isBuffer)(pdfBuffers[i])) {
throw new errors_js_1.MergeError(`Item at index ${i} is not a buffer`);
}
}
const mergeService = new MergeService_js_1.MergeService(logger);
return await mergeService.mergePdfs(pdfBuffers, options);
}
/**
* Merge PDF files from file paths
*/
async function mergePdfFiles(filePaths, options = {}) {
const { promises: fs } = await Promise.resolve().then(() => __importStar(require('fs')));
const logger = options.logging || defaults_js_1.noOpLogger;
if (!Array.isArray(filePaths) || filePaths.length === 0) {
throw new errors_js_1.MergeError('At least one file path is required');
}
logger.info(`Loading ${filePaths.length} PDF files for merging`);
// Read all files
const buffers = [];
for (let i = 0; i < filePaths.length; i++) {
const filePath = filePaths[i];
try {
logger.debug(`Reading file: ${filePath}`);
const buffer = await fs.readFile(filePath);
buffers.push(buffer);
}
catch (error) {
throw new errors_js_1.MergeError(`Failed to read file at index ${i}: ${filePath}`, filePaths.length, error);
}
}
return await mergePdfs(buffers, options);
}
/**
* Analyze PDF buffers without merging
*/
async function analyzePdfs(pdfBuffers, options = {}) {
const logger = options.logging || defaults_js_1.noOpLogger;
if (!Array.isArray(pdfBuffers) || pdfBuffers.length === 0) {
throw new errors_js_1.MergeError('At least one PDF buffer is required for analysis');
}
const mergeService = new MergeService_js_1.MergeService(logger);
return await mergeService.analyzePdfs(pdfBuffers);
}
/**
* Validate PDF buffers
*/
async function validatePdfs(pdfBuffers, options = {}) {
const logger = options.logging || defaults_js_1.noOpLogger;
if (!Array.isArray(pdfBuffers)) {
return {
valid: false,
errors: [{ chunkIndex: -1, error: 'Input is not an array' }],
};
}
if (pdfBuffers.length === 0) {
return {
valid: false,
errors: [{ chunkIndex: -1, error: 'No PDF buffers provided' }],
};
}
const mergeService = new MergeService_js_1.MergeService(logger);
return await mergeService.validatePdfs(pdfBuffers);
}
/**
* Split a PDF into individual page buffers
*/
async function splitPdf(pdfBuffer, options = {}) {
const logger = options.logging || defaults_js_1.noOpLogger;
if (!(0, guards_js_1.isBuffer)(pdfBuffer)) {
throw new errors_js_1.MergeError('Input must be a buffer');
}
if (pdfBuffer.length === 0) {
throw new errors_js_1.MergeError('PDF buffer is empty');
}
const mergeService = new MergeService_js_1.MergeService(logger);
return await mergeService.splitPdf(pdfBuffer);
}
/**
* Extract specific pages from a PDF
*/
async function extractPages(pdfBuffer, pageIndices, options = {}) {
const logger = options.logging || defaults_js_1.noOpLogger;
if (!(0, guards_js_1.isBuffer)(pdfBuffer)) {
throw new errors_js_1.MergeError('Input must be a buffer');
}
if (!Array.isArray(pageIndices) || pageIndices.length === 0) {
throw new errors_js_1.MergeError('Page indices must be a non-empty array');
}
// Validate page indices are numbers (but allow negative/out-of-range, service will filter)
for (const index of pageIndices) {
if (typeof index !== 'number' || !Number.isInteger(index)) {
throw new errors_js_1.MergeError('All page indices must be integers');
}
}
const mergeService = new MergeService_js_1.MergeService(logger);
return await mergeService.extractPages(pdfBuffer, pageIndices);
}
/**
* Get information about a PDF
*/
async function getPdfInfo(pdfBuffer, options = {}) {
const logger = options.logging || defaults_js_1.noOpLogger;
if (!(0, guards_js_1.isBuffer)(pdfBuffer)) {
throw new errors_js_1.MergeError('Input must be a buffer');
}
if (pdfBuffer.length === 0) {
throw new errors_js_1.MergeError('PDF buffer is empty');
}
const mergeService = new MergeService_js_1.MergeService(logger);
return await mergeService.getPdfInfo(pdfBuffer);
}
/**
* Merge PDFs with custom page ranges
*/
async function mergePdfsWithRanges(inputs, options = {}) {
const logger = options.logging || defaults_js_1.noOpLogger;
if (!Array.isArray(inputs) || inputs.length === 0) {
throw new errors_js_1.MergeError('At least one input is required');
}
logger.info(`Merging ${inputs.length} PDFs with custom page ranges`);
const extractedBuffers = [];
const mergeService = new MergeService_js_1.MergeService(logger);
for (let i = 0; i < inputs.length; i++) {
const input = inputs[i];
if (!(0, guards_js_1.isBuffer)(input.buffer)) {
throw new errors_js_1.MergeError(`Input at index ${i} must have a buffer property`);
}
try {
let pageIndices;
if (input.pages) {
// Use specific pages
pageIndices = input.pages;
}
else if (input.startPage !== undefined || input.endPage !== undefined) {
// Use page range
const pdfInfo = await mergeService.getPdfInfo(input.buffer);
const startPage = input.startPage || 0;
const endPage = input.endPage !== undefined ? input.endPage : pdfInfo.pages - 1;
pageIndices = [];
for (let page = startPage; page <= Math.min(endPage, pdfInfo.pages - 1); page++) {
pageIndices.push(page);
}
}
else {
// Include all pages - just add the buffer as-is
extractedBuffers.push(input.buffer);
continue;
}
// Extract the specified pages
const extractedBuffer = await mergeService.extractPages(input.buffer, pageIndices);
extractedBuffers.push(extractedBuffer);
logger.debug(`Processed input ${i + 1}: extracted ${pageIndices.length} pages`);
}
catch (error) {
throw new errors_js_1.MergeError(`Failed to process input at index ${i}`, inputs.length, error);
}
}
// Merge all extracted buffers
return await mergePdfs(extractedBuffers, options);
}
/**
* Batch merge multiple sets of PDFs
*/
async function batchMergePdfs(batches, options = {}) {
const logger = options.logging || defaults_js_1.noOpLogger;
const concurrency = options.concurrency || 2;
if (!Array.isArray(batches) || batches.length === 0) {
throw new errors_js_1.MergeError('At least one batch is required');
}
logger.info(`Batch merging ${batches.length} PDF sets with concurrency ${concurrency}`);
const results = [];
let currentIndex = 0;
const processBatch = async () => {
while (currentIndex < batches.length) {
const index = currentIndex++;
if (index >= batches.length)
return;
const batch = batches[index];
const batchName = options.batchNames?.[index] || `batch-${index + 1}`;
try {
logger.debug(`Processing ${batchName} with ${batch.length} PDFs`);
const mergedBuffer = await mergePdfs(batch, options);
results[index] = mergedBuffer;
logger.debug(`Completed ${batchName}`);
}
catch (error) {
throw new errors_js_1.MergeError(`Failed to merge ${batchName}`, batches.length, error);
}
}
};
// Create worker promises with concurrency limit
const workers = Array(Math.min(concurrency, batches.length))
.fill(null)
.map(() => processBatch());
await Promise.all(workers);
logger.info(`Batch merge completed: ${results.length} merged PDFs`);
return results;
}
//# sourceMappingURL=mergePdfs.js.map