mindee 4.34.0 → 4.35.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v4.35.0 - 2025-12-16
4
+ ### Changes
5
+ * :sparkles: add multi-receipt custom file saving formats
6
+ ### Fixes
7
+ * :bug: fix image extractor dropping quality of extracted PDFs
8
+
9
+
3
10
  ## v4.34.0 - 2025-12-02
4
11
  ### Changes
5
12
  * :sparkles: add support for text context
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mindee",
3
- "version": "4.34.0",
3
+ "version": "4.35.0",
4
4
  "description": "Mindee Client Library for Node.js",
5
5
  "main": "src/index.js",
6
6
  "bin": "bin/mindee.js",
@@ -24,7 +24,7 @@
24
24
  "CHANGELOG.md"
25
25
  ],
26
26
  "engines": {
27
- "node": ">= 16"
27
+ "node": ">= 18"
28
28
  },
29
29
  "repository": {
30
30
  "type": "git",
@@ -12,6 +12,13 @@ export declare class ExtractedImage {
12
12
  *
13
13
  * @param outputPath Path to save the file to.
14
14
  */
15
+ saveToFileAsync(outputPath: string): Promise<void>;
16
+ /**
17
+ * Attempts to saves the document to a file synchronously.
18
+ * Throws an error if the file extension is not supported or if the file could not be saved to disk for some reason.
19
+ *
20
+ * @param outputPath Path to save the file to.
21
+ */
15
22
  saveToFile(outputPath: string): void;
16
23
  /**
17
24
  * Return the file as a Mindee-compatible BufferInput source.
@@ -10,6 +10,9 @@ const node_fs_1 = require("node:fs");
10
10
  const node_path_1 = __importDefault(require("node:path"));
11
11
  const logger_1 = require("../../logger");
12
12
  const input_1 = require("../../input");
13
+ const localInputSource_1 = require("../../input/sources/localInputSource");
14
+ const node_poppler_1 = require("node-poppler");
15
+ const promises_1 = require("fs/promises");
13
16
  /**
14
17
  * Generic class for image extraction
15
18
  */
@@ -23,9 +26,33 @@ class ExtractedImage {
23
26
  *
24
27
  * @param outputPath Path to save the file to.
25
28
  */
26
- saveToFile(outputPath) {
29
+ async saveToFileAsync(outputPath) {
30
+ const fileExt = node_path_1.default.extname(outputPath).toLowerCase();
31
+ if (!localInputSource_1.MIMETYPES.has(fileExt)) {
32
+ throw new errors_1.MindeeError(`Unsupported file extension: ${fileExt}`);
33
+ }
27
34
  try {
28
- (0, node_fs_1.writeFileSync)(node_path_1.default.resolve(outputPath), this.buffer);
35
+ let outputBuffer = this.buffer;
36
+ if (fileExt !== ".pdf") {
37
+ const poppler = new node_poppler_1.Poppler();
38
+ const options = {
39
+ firstPageToConvert: 1,
40
+ lastPageToConvert: 1,
41
+ singleFile: true,
42
+ };
43
+ if (fileExt === ".png") {
44
+ options.pngFile = true;
45
+ }
46
+ else if (fileExt === ".jpg" || fileExt === ".jpeg") {
47
+ options.jpegFile = true;
48
+ }
49
+ else if (fileExt === ".tiff" || fileExt === ".tif") {
50
+ options.tiffFile = true;
51
+ }
52
+ const result = await poppler.pdfToCairo(this.buffer, undefined, options);
53
+ outputBuffer = node_buffer_1.Buffer.from(result, "latin1");
54
+ }
55
+ await (0, promises_1.writeFile)(node_path_1.default.resolve(outputPath), outputBuffer);
29
56
  logger_1.logger.info(`File saved successfully to ${node_path_1.default.resolve(outputPath)}.`);
30
57
  }
31
58
  catch (e) {
@@ -37,6 +64,32 @@ class ExtractedImage {
37
64
  }
38
65
  }
39
66
  }
67
+ /**
68
+ * Attempts to saves the document to a file synchronously.
69
+ * Throws an error if the file extension is not supported or if the file could not be saved to disk for some reason.
70
+ *
71
+ * @param outputPath Path to save the file to.
72
+ */
73
+ saveToFile(outputPath) {
74
+ const fileExt = node_path_1.default.extname(outputPath).toLowerCase();
75
+ if (fileExt !== ".pdf") {
76
+ throw new errors_1.MindeeError(`Unsupported file extension: ${fileExt}. For image formats, use saveToFileAsync() instead.`);
77
+ }
78
+ else {
79
+ try {
80
+ (0, node_fs_1.writeFileSync)(node_path_1.default.resolve(outputPath), this.buffer);
81
+ logger_1.logger.info(`File saved successfully to ${node_path_1.default.resolve(outputPath)}.`);
82
+ }
83
+ catch (e) {
84
+ if (e instanceof TypeError) {
85
+ throw new errors_1.MindeeError("Invalid path/filename provided.");
86
+ }
87
+ else {
88
+ throw e;
89
+ }
90
+ }
91
+ }
92
+ }
40
93
  /**
41
94
  * Return the file as a Mindee-compatible BufferInput source.
42
95
  *
@@ -12,6 +12,9 @@ const geometry_1 = require("../../geometry");
12
12
  async function extractFromPage(pdfPage, polygons) {
13
13
  const { width, height } = pdfPage.getSize();
14
14
  const extractedElements = [];
15
+ // Manual upscale.
16
+ // Fixes issues with the OCR.
17
+ const qualityScale = 300 / 72;
15
18
  for (const polygon of polygons) {
16
19
  const tempPdf = await pdf_lib_1.PDFDocument.create();
17
20
  const newWidth = width * ((0, geometry_1.getMinMaxX)(polygon).max - (0, geometry_1.getMinMaxX)(polygon).min);
@@ -22,10 +25,16 @@ async function extractFromPage(pdfPage, polygons) {
22
25
  top: height - ((0, geometry_1.getMinMaxY)(polygon).min * height),
23
26
  bottom: height - ((0, geometry_1.getMinMaxY)(polygon).max * height),
24
27
  });
25
- const samplePage = tempPdf.addPage([newWidth, newHeight]);
28
+ const samplePage = tempPdf.addPage([newWidth * qualityScale, newHeight * qualityScale]);
29
+ samplePage.drawRectangle({
30
+ x: 0,
31
+ y: 0,
32
+ width: newWidth * qualityScale,
33
+ height: newHeight * qualityScale,
34
+ });
26
35
  samplePage.drawPage(cropped, {
27
- width: newWidth,
28
- height: newHeight,
36
+ width: newWidth * qualityScale,
37
+ height: newHeight * qualityScale,
29
38
  });
30
39
  extractedElements.push(await tempPdf.save());
31
40
  }
@@ -1,5 +1,6 @@
1
1
  import { PageOptions } from "../pageOptions";
2
2
  import { InputSource, InputConstructor } from "./inputSource";
3
+ export declare const MIMETYPES: Map<string, string>;
3
4
  export declare abstract class LocalInputSource extends InputSource {
4
5
  inputType: string;
5
6
  filename: string;
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.LocalInputSource = void 0;
39
+ exports.LocalInputSource = exports.MIMETYPES = void 0;
40
40
  const handler_1 = require("../../errors/handler");
41
41
  const logger_1 = require("../../logger");
42
42
  const imageOperations_1 = require("../../imageOperations");
@@ -45,7 +45,7 @@ const path_1 = __importDefault(require("path"));
45
45
  const fileType = __importStar(require("file-type"));
46
46
  const pdf_2 = require("../../pdf");
47
47
  const inputSource_1 = require("./inputSource");
48
- const MIMETYPES = new Map([
48
+ exports.MIMETYPES = new Map([
49
49
  [".pdf", "application/pdf"],
50
50
  [".heic", "image/heic"],
51
51
  [".jpg", "image/jpeg"],
@@ -85,7 +85,7 @@ class LocalInputSource extends inputSource_1.InputSource {
85
85
  let mimeType;
86
86
  const fileExt = path_1.default.extname(this.filename);
87
87
  if (fileExt) {
88
- mimeType = MIMETYPES.get(fileExt.toLowerCase()) || "";
88
+ mimeType = exports.MIMETYPES.get(fileExt.toLowerCase()) || "";
89
89
  }
90
90
  else {
91
91
  const guess = await fileType.fromBuffer(this.fileObject);
@@ -97,7 +97,7 @@ class LocalInputSource extends inputSource_1.InputSource {
97
97
  }
98
98
  }
99
99
  if (!mimeType) {
100
- const allowed = Array.from(MIMETYPES.keys()).join(", ");
100
+ const allowed = Array.from(exports.MIMETYPES.keys()).join(", ");
101
101
  const err = new Error(`Invalid file type, must be one of ${allowed}.`);
102
102
  handler_1.errorHandler.throw(err);
103
103
  }