← back to AbramsOS
lib/pdf-parser.js
45 lines
// PDF text extractor for receipt attachments (tier-3 of receipt-extractor pipeline).
// Wraps pdf-parse. Returns extracted plain text + page count + basic metadata.
const fs = require('fs');
const path = require('path');
// Lazy-require pdf-parse to avoid loading its test fixture at startup.
function pdfParse() { return require('pdf-parse'); }
const UPLOADS_DIR = path.join(__dirname, '..', 'uploads');
async function parseFile(absPath) {
const buf = await fs.promises.readFile(absPath);
return parseBuffer(buf);
}
async function parseBuffer(buf) {
const data = await pdfParse()(buf);
return {
text: (data.text || '').trim(),
pages: data.numpages || 0,
info: data.info || {},
metadata: data.metadata || null,
version: data.version || null,
};
}
/**
* Resolve a document.object_path to a real file on disk.
* Drive files are saved as `drive:<id>` with a real file at uploads/drive-<id>.<ext>.
*/
function resolveDocumentPath(objectPath, mime) {
if (objectPath?.startsWith('drive:')) {
const driveId = objectPath.slice('drive:'.length);
const ext = mime === 'application/pdf' ? '.pdf' : mime?.startsWith('image/jpeg') ? '.jpg' : mime?.startsWith('image/png') ? '.png' : '';
return path.join(UPLOADS_DIR, `drive-${driveId}${ext}`);
}
// Future: gmail attachments will save under uploads/gmail-<msg>-<idx>.pdf
if (objectPath && !path.isAbsolute(objectPath)) {
return path.join(UPLOADS_DIR, objectPath);
}
return objectPath;
}
module.exports = { parseFile, parseBuffer, resolveDocumentPath, UPLOADS_DIR };