diff --git a/src/clientV2.ts b/src/clientV2.ts index 5ba5350d..36ae9588 100644 --- a/src/clientV2.ts +++ b/src/clientV2.ts @@ -163,9 +163,7 @@ export class ClientV2 { if (inputSource === undefined) { throw new Error("The 'enqueue' function requires an input document."); } - if (!inputSource.isInitialized()) { - await inputSource.init(); - } + await inputSource.init(); return await this.mindeeApi.reqPostInferenceEnqueue(inputSource, params); } diff --git a/src/input/sources/base64Input.ts b/src/input/sources/base64Input.ts index ef73c86f..c4ce6c11 100644 --- a/src/input/sources/base64Input.ts +++ b/src/input/sources/base64Input.ts @@ -1,5 +1,6 @@ import { LocalInputSource } from "./localInputSource"; import { INPUT_TYPE_BASE64 } from "./inputSource"; +import { logger } from "../../logger"; interface Base64InputProps { inputString: string; @@ -19,6 +20,10 @@ export class Base64Input extends LocalInputSource { } async init() { + if (this.initialized) { + return; + } + logger.debug("Loading from base64"); this.fileObject = Buffer.from(this.inputString, "base64"); this.mimeType = await this.checkMimetype(); // clear out the string diff --git a/src/input/sources/bufferInput.ts b/src/input/sources/bufferInput.ts index 6120bc80..aed8908e 100644 --- a/src/input/sources/bufferInput.ts +++ b/src/input/sources/bufferInput.ts @@ -1,5 +1,6 @@ import { LocalInputSource } from "./localInputSource"; import { INPUT_TYPE_BUFFER } from "./inputSource"; +import { logger } from "../../logger"; interface BufferInputProps { buffer: Buffer; @@ -16,6 +17,10 @@ export class BufferInput extends LocalInputSource { } async init(): Promise { + if (this.initialized) { + return; + } + logger.debug("Loading from buffer"); this.mimeType = await this.checkMimetype(); this.initialized = true; } diff --git a/src/input/sources/bytesInput.ts b/src/input/sources/bytesInput.ts index a765ba65..d61eab46 100644 --- a/src/input/sources/bytesInput.ts +++ b/src/input/sources/bytesInput.ts @@ -1,5 +1,6 @@ import { INPUT_TYPE_BYTES } from "./inputSource"; import { LocalInputSource } from "./localInputSource"; +import { logger } from "../../logger"; interface BytesInputProps { inputBytes: Uint8Array; @@ -19,6 +20,10 @@ export class BytesInput extends LocalInputSource { } async init() { + if (this.initialized) { + return; + } + logger.debug("Loading from bytes"); this.fileObject = Buffer.from(this.inputBytes); this.mimeType = await this.checkMimetype(); this.inputBytes = new Uint8Array(0); diff --git a/src/input/sources/pathInput.ts b/src/input/sources/pathInput.ts index 15860f0b..7c39244d 100644 --- a/src/input/sources/pathInput.ts +++ b/src/input/sources/pathInput.ts @@ -21,7 +21,10 @@ export class PathInput extends LocalInputSource { } async init() { - logger.debug(`Loading from: ${this.inputPath}`); + if (this.initialized) { + return; + } + logger.debug(`Loading from path: ${this.inputPath}`); this.fileObject = Buffer.from(await fs.readFile(this.inputPath)); this.mimeType = await this.checkMimetype(); this.initialized = true; diff --git a/src/input/sources/streamInput.ts b/src/input/sources/streamInput.ts index 9d04fdd9..ce7f616c 100644 --- a/src/input/sources/streamInput.ts +++ b/src/input/sources/streamInput.ts @@ -1,6 +1,7 @@ import { Readable } from "stream"; import { LocalInputSource } from "./localInputSource"; import { INPUT_TYPE_STREAM } from "./inputSource"; +import { logger } from "../../logger"; interface StreamInputProps { inputStream: Readable; @@ -20,6 +21,10 @@ export class StreamInput extends LocalInputSource { } async init() { + if (this.initialized) { + return; + } + logger.debug("Loading from stream"); this.fileObject = await this.stream2buffer(this.inputStream); this.mimeType = await this.checkMimetype(); this.initialized = true; diff --git a/src/input/sources/urlInput.ts b/src/input/sources/urlInput.ts index 28b95608..708fcd16 100644 --- a/src/input/sources/urlInput.ts +++ b/src/input/sources/urlInput.ts @@ -6,6 +6,7 @@ import { writeFile } from "fs/promises"; import { request as httpsRequest } from "https"; import { IncomingMessage } from "http"; import { BytesInput } from "./bytesInput"; +import { logger } from "../../logger"; export class UrlInput extends InputSource { public readonly url: string; @@ -16,6 +17,10 @@ export class UrlInput extends InputSource { } async init() { + if (this.initialized) { + return; + } + logger.debug(`source URL: ${this.url}`); if (!this.url.toLowerCase().startsWith("https")) { throw new Error("URL must be HTTPS"); } diff --git a/tests/v2/clientV2.integration.ts b/tests/v2/clientV2.integration.ts index e4223112..c0c89d55 100644 --- a/tests/v2/clientV2.integration.ts +++ b/tests/v2/clientV2.integration.ts @@ -1,9 +1,10 @@ import { expect } from "chai"; import path from "node:path"; -import { ClientV2, InferenceParameters, PathInput, UrlInput } from "../../src"; +import { ClientV2, InferenceParameters, PathInput, UrlInput, Base64Input } from "../../src"; import { SimpleField } from "../../src/parsing/v2/field"; import { MindeeHttpErrorV2 } from "../../src/errors/mindeeError"; +import * as fs from "node:fs"; describe("MindeeClientV2 – integration tests (V2)", () => { let client: ClientV2; @@ -22,6 +23,11 @@ describe("MindeeClientV2 – integration tests (V2)", () => { "financial_document", "default_sample.jpg", ); + const sampleBase64Path = path.join( + dataDir, + "file_types", + "receipt.txt", + ); beforeEach(async () => { const apiKey = process.env["MINDEE_V2_API_KEY"] ?? ""; @@ -30,7 +36,7 @@ describe("MindeeClientV2 – integration tests (V2)", () => { client = new ClientV2({ apiKey }); }); - it("Empty, multi-page PDF – enqueue & get inference must succeed", async () => { + it("Empty, multi-page PDF – PathInput - enqueueAndGetInference must succeed", async () => { const source = new PathInput({ inputPath: emptyPdfPath }); const params: InferenceParameters = { modelId, @@ -61,16 +67,16 @@ describe("MindeeClientV2 – integration tests (V2)", () => { expect(inference.activeOptions?.confidence).to.be.false; }).timeout(60000); - it("Filled, single-page image – enqueue & get inference must succeed", async () => { + it("Filled, single-page image – PathInput - enqueueAndGetInference must succeed", async () => { const source = new PathInput({ inputPath: sampleImagePath }); const params: InferenceParameters = { modelId, rag: false, rawText: true, - polygon: false, + polygon: true, confidence: false, webhookIds: [], - alias: "ts_integration_filled_single" + alias: "ts_integration_binary_filled_single" }; const response = await client.enqueueAndGetInference(source, params); @@ -86,17 +92,49 @@ describe("MindeeClientV2 – integration tests (V2)", () => { expect(supplierField).to.be.instanceOf(SimpleField); expect(supplierField.value).to.equal("John Smith"); - expect(inference.result.rawText).to.exist; expect(inference.activeOptions).to.not.be.null; expect(inference.activeOptions?.rag).to.be.false; expect(inference.activeOptions?.rawText).to.be.true; - expect(inference.activeOptions?.polygon).to.be.false; + expect(inference.activeOptions?.polygon).to.be.true; expect(inference.activeOptions?.confidence).to.be.false; expect(inference.result.rawText?.pages).to.have.lengthOf(1); }).timeout(120000); + it("Filled, single-page image – Base64Input - enqueueAndGetInference must succeed", async () => { + const data = fs.readFileSync(sampleBase64Path, "utf8"); + const source = new Base64Input({ inputString: data, filename: "receipt.jpg" }); + const params: InferenceParameters = { + modelId, + rag: false, + rawText: false, + polygon: false, + confidence: false, + webhookIds: [], + alias: "ts_integration_base64_filled_single" + }; + + const response = await client.enqueueAndGetInference(source, params); + + const inference = response.inference; + expect(inference.file?.name).to.equal("receipt.jpg"); + expect(inference.model?.id).to.equal(modelId); + + expect(inference.result).to.exist; + expect(inference.result.rawText).to.be.undefined; + + const supplierField = inference.result.fields.get("supplier_name") as SimpleField; + expect(supplierField).to.be.instanceOf(SimpleField); + expect(supplierField.value).to.equal("Clachan"); + + expect(inference.activeOptions).to.not.be.null; + expect(inference.activeOptions?.rag).to.be.false; + expect(inference.activeOptions?.rawText).to.be.false; + expect(inference.activeOptions?.polygon).to.be.false; + expect(inference.activeOptions?.confidence).to.be.false; + }).timeout(120000); + it("Invalid model ID – enqueue must raise 422", async () => { const source = new PathInput({ inputPath: emptyPdfPath }); const badParams: InferenceParameters = { modelId: "INVALID MODEL ID" };