mindee 4.33.1 → 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 +12 -0
- package/package.json +2 -2
- package/src/clientV2.d.ts +23 -20
- package/src/http/mindeeApiV2.js +3 -0
- package/src/imageOperations/common/extractedImage.d.ts +7 -0
- package/src/imageOperations/common/extractedImage.js +55 -2
- package/src/imageOperations/common/imageExtractor.js +12 -3
- package/src/input/sources/localInputSource.d.ts +1 -0
- package/src/input/sources/localInputSource.js +4 -4
- package/src/parsing/v2/errorItem.d.ts +4 -1
- package/src/parsing/v2/errorItem.js +3 -0
- package/src/parsing/v2/errorResponse.d.ts +1 -1
- package/src/parsing/v2/inferenceActiveOptions.d.ts +4 -0
- package/src/parsing/v2/inferenceActiveOptions.js +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
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
|
+
|
|
10
|
+
## v4.34.0 - 2025-12-02
|
|
11
|
+
### Changes
|
|
12
|
+
* :sparkles: add support for text context
|
|
13
|
+
|
|
14
|
+
|
|
3
15
|
## v4.33.1 - 2025-10-28
|
|
4
16
|
### Changes
|
|
5
17
|
* :loud_sound: add error code to v2 exceptions
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mindee",
|
|
3
|
-
"version": "4.
|
|
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": ">=
|
|
27
|
+
"node": ">= 18"
|
|
28
28
|
},
|
|
29
29
|
"repository": {
|
|
30
30
|
"type": "git",
|
package/src/clientV2.d.ts
CHANGED
|
@@ -17,12 +17,6 @@ import { MindeeApiV2 } from "./http/mindeeApiV2";
|
|
|
17
17
|
* The `initialTimerOptions` and `recurringTimerOptions` objects let you pass an
|
|
18
18
|
* `AbortSignal` or make the timer `unref`-ed to the `setTimeout()`.
|
|
19
19
|
*
|
|
20
|
-
* @property initialDelaySec Number of seconds to wait **before the first poll**.
|
|
21
|
-
* @property delaySec Interval in seconds between two consecutive polls.
|
|
22
|
-
* @property maxRetries Maximum number of polling attempts (including the first one).
|
|
23
|
-
* @property initialTimerOptions Options passed to the initial `setTimeout()`.
|
|
24
|
-
* @property recurringTimerOptions Options passed to every recurring `setTimeout()`.
|
|
25
|
-
*
|
|
26
20
|
* @category ClientV2
|
|
27
21
|
* @example
|
|
28
22
|
* const params = {
|
|
@@ -34,13 +28,18 @@ import { MindeeApiV2 } from "./http/mindeeApiV2";
|
|
|
34
28
|
* const inference = await client.enqueueAndGetInference(inputDoc, params);
|
|
35
29
|
*/
|
|
36
30
|
export interface PollingOptions {
|
|
31
|
+
/** Number of seconds to wait *before the first poll*. */
|
|
37
32
|
initialDelaySec?: number;
|
|
33
|
+
/** Interval in seconds between two consecutive polls. */
|
|
38
34
|
delaySec?: number;
|
|
35
|
+
/** Maximum number of polling attempts (including the first one). */
|
|
39
36
|
maxRetries?: number;
|
|
37
|
+
/** Options passed to the initial `setTimeout()`. */
|
|
40
38
|
initialTimerOptions?: {
|
|
41
39
|
ref?: boolean;
|
|
42
40
|
signal?: AbortSignal;
|
|
43
41
|
};
|
|
42
|
+
/** Options passed to every recurring `setTimeout()`. */
|
|
44
43
|
recurringTimerOptions?: {
|
|
45
44
|
ref?: boolean;
|
|
46
45
|
signal?: AbortSignal;
|
|
@@ -51,16 +50,6 @@ export interface PollingOptions {
|
|
|
51
50
|
*
|
|
52
51
|
* All fields are optional except `modelId`.
|
|
53
52
|
*
|
|
54
|
-
* @property modelId Identifier of the model that must process the document. **Required**.
|
|
55
|
-
* @property rag Enhance extraction accuracy with Retrieval-Augmented Generation.
|
|
56
|
-
* @property rawText Extract the full text content from the document as strings, and fill the `raw_text` attribute.
|
|
57
|
-
* @property polygon Calculate bounding box polygons for all fields, and fill their `locations` attribute.
|
|
58
|
-
* @property confidence Boost the precision and accuracy of all extractions.
|
|
59
|
-
* Calculate confidence scores for all fields and fill their `confidence` attribute.
|
|
60
|
-
* @property alias Custom alias assigned to the uploaded document.
|
|
61
|
-
* @property webhookIds List of webhook UUIDs that will receive the final API response.
|
|
62
|
-
* @property pollingOptions Client-side polling configuration (see {@link PollingOptions}).
|
|
63
|
-
* @property closeFile By default the file is closed once the upload is finished, set to `false` to keep it open.
|
|
64
53
|
* @category ClientV2
|
|
65
54
|
* @example
|
|
66
55
|
* const params = {
|
|
@@ -75,23 +64,34 @@ export interface PollingOptions {
|
|
|
75
64
|
* };
|
|
76
65
|
*/
|
|
77
66
|
export interface InferenceParameters {
|
|
67
|
+
/** Model ID to use for the inference. **Required** */
|
|
78
68
|
modelId: string;
|
|
69
|
+
/** Use Retrieval-Augmented Generation during inference. */
|
|
79
70
|
rag?: boolean;
|
|
71
|
+
/** Extract the entire text from the document as strings, and fill the `rawText` attribute. */
|
|
80
72
|
rawText?: boolean;
|
|
73
|
+
/** Calculate bounding box polygons for values, and fill the `locations` attribute of fields. */
|
|
81
74
|
polygon?: boolean;
|
|
75
|
+
/** Calculate confidence scores for values, and fill the `confidence` attribute of fields.
|
|
76
|
+
* Useful for automation.*/
|
|
82
77
|
confidence?: boolean;
|
|
78
|
+
/** Use an alias to link the file to your own DB. If empty, no alias will be used. */
|
|
83
79
|
alias?: string;
|
|
80
|
+
/** Additional text context used by the model during inference.
|
|
81
|
+
* *Not recommended*, for specific use only. */
|
|
82
|
+
textContext?: string;
|
|
83
|
+
/** Webhook IDs to call after all processing is finished.
|
|
84
|
+
* If empty, no webhooks will be used. */
|
|
84
85
|
webhookIds?: string[];
|
|
86
|
+
/** Client-side polling configuration (see {@link PollingOptions}). */
|
|
85
87
|
pollingOptions?: PollingOptions;
|
|
88
|
+
/** By default, the file is closed once the upload is finished.
|
|
89
|
+
* Set to `false` to keep it open. */
|
|
86
90
|
closeFile?: boolean;
|
|
87
91
|
}
|
|
88
92
|
/**
|
|
89
93
|
* Options for the V2 Mindee Client.
|
|
90
94
|
*
|
|
91
|
-
* @property apiKey Your API key for all endpoints.
|
|
92
|
-
* @property throwOnError Raise an `Error` on errors.
|
|
93
|
-
* @property debug Log debug messages.
|
|
94
|
-
*
|
|
95
95
|
* @category ClientV2
|
|
96
96
|
* @example
|
|
97
97
|
* const client = new MindeeClientV2({
|
|
@@ -101,8 +101,11 @@ export interface InferenceParameters {
|
|
|
101
101
|
* });
|
|
102
102
|
*/
|
|
103
103
|
export interface ClientOptions {
|
|
104
|
+
/** Your API key for all endpoints. */
|
|
104
105
|
apiKey?: string;
|
|
106
|
+
/** Raise an `Error` on errors. */
|
|
105
107
|
throwOnError?: boolean;
|
|
108
|
+
/** Log debug messages. */
|
|
106
109
|
debug?: boolean;
|
|
107
110
|
}
|
|
108
111
|
/**
|
package/src/http/mindeeApiV2.js
CHANGED
|
@@ -99,6 +99,9 @@ _MindeeApiV2_instances = new WeakSet(), _MindeeApiV2_processResponse = function
|
|
|
99
99
|
if (params.rawText !== undefined && params.rawText !== null) {
|
|
100
100
|
form.append("raw_text", params.rawText.toString().toLowerCase());
|
|
101
101
|
}
|
|
102
|
+
if (params.textContext !== undefined && params.textContext !== null) {
|
|
103
|
+
form.append("text_context", params.textContext);
|
|
104
|
+
}
|
|
102
105
|
if (params.webhookIds && params.webhookIds.length > 0) {
|
|
103
106
|
form.append("webhook_ids", params.webhookIds.join(","));
|
|
104
107
|
}
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { StringDict } from "../common";
|
|
2
|
+
/**
|
|
3
|
+
* Explicit details on a problem.
|
|
4
|
+
*/
|
|
2
5
|
export declare class ErrorItem {
|
|
3
6
|
/**
|
|
4
|
-
*
|
|
7
|
+
* A JSON Pointer to the location of the body property.
|
|
5
8
|
*/
|
|
6
9
|
pointer?: string;
|
|
7
10
|
/**
|
|
@@ -16,6 +16,10 @@ export declare class InferenceActiveOptions {
|
|
|
16
16
|
* Whether the confidence feature was activated.
|
|
17
17
|
*/
|
|
18
18
|
confidence: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Whether the text context feature was activated.
|
|
21
|
+
*/
|
|
22
|
+
textContext: boolean;
|
|
19
23
|
constructor(serverResponse: StringDict);
|
|
20
24
|
toString(): string;
|
|
21
25
|
}
|
|
@@ -7,6 +7,7 @@ class InferenceActiveOptions {
|
|
|
7
7
|
this.rawText = serverResponse["raw_text"];
|
|
8
8
|
this.polygon = serverResponse["polygon"];
|
|
9
9
|
this.confidence = serverResponse["confidence"];
|
|
10
|
+
this.textContext = serverResponse["text_context"];
|
|
10
11
|
}
|
|
11
12
|
toString() {
|
|
12
13
|
return "Active Options\n" +
|