@arela/uploader 1.1.2 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arela/uploader",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "description": "CLI to upload files/directories to Arela",
5
5
  "bin": {
6
6
  "arela": "./src/index.js"
@@ -37,10 +37,10 @@ class Config {
37
37
  const __dirname = path.dirname(__filename);
38
38
  const packageJsonPath = path.resolve(__dirname, '../../package.json');
39
39
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
40
- return packageJson.version || '1.1.2';
40
+ return packageJson.version || '1.1.3';
41
41
  } catch (error) {
42
42
  console.warn('⚠️ Could not read package.json version, using fallback');
43
- return '1.1.2';
43
+ return '1.1.3';
44
44
  }
45
45
  }
46
46
 
@@ -5,6 +5,15 @@ import { PDFParse } from 'pdf-parse';
5
5
  import { extractDocumentFields } from './document-type-shared.js';
6
6
  import { classifyDocument } from './scoring/scoring-engine.js';
7
7
 
8
+ // pdf.js can reject internal worker promises on corrupt PDFs (e.g.
9
+ // XRefEntryException) that no try/catch around getText() can reach. Track the
10
+ // last PDF handed to the parser so the global unhandledRejection handler can
11
+ // name it; the event fires after finally blocks run, so it is never cleared.
12
+ let currentPdfFile = null;
13
+ function getCurrentPdfFile() {
14
+ return currentPdfFile;
15
+ }
16
+
8
17
  // Document types that participate in arela_path composition.
9
18
  const ARELA_PATH_TYPES = new Set([
10
19
  'pedimento_simplificado',
@@ -255,6 +264,7 @@ export class FileDetectionService {
255
264
  */
256
265
  async extractTextFromPDF(filePath) {
257
266
  let parser;
267
+ currentPdfFile = filePath;
258
268
  try {
259
269
  const dataBuffer = fs.readFileSync(filePath);
260
270
  const uint8Array = new Uint8Array(dataBuffer);
@@ -316,4 +326,4 @@ export class FileDetectionService {
316
326
  }
317
327
 
318
328
  export default FileDetectionService;
319
- export { composeArelaPath };
329
+ export { composeArelaPath, getCurrentPdfFile };
package/src/index.js CHANGED
@@ -13,8 +13,21 @@ import watchCommand from './commands/WatchCommand.js';
13
13
  import workerCommand from './commands/WorkerCommand.js';
14
14
  import appConfig from './config/config.js';
15
15
  import ErrorHandler from './errors/ErrorHandler.js';
16
+ import { getCurrentPdfFile } from './file-detection.js';
16
17
  import logger from './services/LoggingService.js';
17
18
 
19
+ // Exception names thrown by pdf.js (used via pdf-parse) when a PDF is
20
+ // malformed, encrypted, or truncated. Matched by error.name because the
21
+ // classes live inside pdfjs-dist and are not exported by pdf-parse.
22
+ const PDFJS_PARSE_ERRORS = new Set([
23
+ 'XRefEntryException',
24
+ 'XRefParseException',
25
+ 'InvalidPDFException',
26
+ 'MissingPDFException',
27
+ 'PasswordException',
28
+ 'FormatError',
29
+ ]);
30
+
18
31
  /**
19
32
  * Arela Uploader CLI
20
33
  * Professional file uploader with document detection and organization
@@ -660,6 +673,22 @@ class ArelaUploaderCLI {
660
673
  process.on('unhandledRejection', (reason, promise) => {
661
674
  const error =
662
675
  reason instanceof Error ? reason : new Error(String(reason));
676
+
677
+ // pdf.js rejects internal worker promises when a PDF is corrupt; those
678
+ // rejections cannot be caught around the parser call, and one bad file
679
+ // must not abort the rest of the batch.
680
+ if (PDFJS_PARSE_ERRORS.has(error.name)) {
681
+ const file = getCurrentPdfFile();
682
+ console.warn(
683
+ `⚠️ Corrupt or unreadable PDF${file ? ` (${file})` : ''}: ${error.message} — skipping`,
684
+ );
685
+ this.errorHandler.handleError(error, {
686
+ context: 'unhandledRejection',
687
+ file,
688
+ });
689
+ return;
690
+ }
691
+
663
692
  this.errorHandler.handleFatalError(error, {
664
693
  context: 'unhandledRejection',
665
694
  promise: promise.toString(),