diff --git a/docs/code_samples/default_v2.txt b/docs/code_samples/default_v2.txt index 51cbc21b5..15c9e2e57 100644 --- a/docs/code_samples/default_v2.txt +++ b/docs/code_samples/default_v2.txt @@ -2,12 +2,15 @@ const mindee = require("mindee"); // for TS or modules: // import * as mindee from "mindee"; -// Init a new client -const mindeeClient = new mindee.ClientV2({ apiKey: "MY_API_KEY" }); +const apiKey = "MY_API_KEY"; +const filePath = "/path/to/the/file.ext"; const modelId = "MY_MODEL_ID"; +// Init a new client +const mindeeClient = new mindee.ClientV2({ apiKey: apiKey }); + // Load a file from disk -const inputSource = mindeeClient.docFromPath("/path/to/the/file.ext"); +const inputSource = mindeeClient.sourceFromPath(filePath); const params = { modelId: modelId, // If set to `true`, will enable Retrieval-Augmented Generation. diff --git a/src/baseClient.ts b/src/baseClient.ts deleted file mode 100644 index aa7e2a554..000000000 --- a/src/baseClient.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { Base64Input, BufferInput, BytesInput, PathInput, StreamInput, UrlInput } from "./input"; -import { Readable } from "stream"; - - -export abstract class BaseClient { - /** - * Load an input document from a local path. - * @param inputPath - */ - docFromPath(inputPath: string): PathInput { - return new PathInput({ - inputPath: inputPath, - }); - } - - /** - * Load an input document from a base64 encoded string. - * @param inputString input content, as a string. - * @param filename file name. - */ - docFromBase64(inputString: string, filename: string): Base64Input { - return new Base64Input({ - inputString: inputString, - filename: filename, - }); - } - - /** - * Load an input document from a `stream.Readable` object. - * @param inputStream input content, as a readable stream. - * @param filename file name. - */ - docFromStream(inputStream: Readable, filename: string): StreamInput { - return new StreamInput({ - inputStream: inputStream, - filename: filename, - }); - } - - /** - * Load an input document from bytes. - * @param inputBytes input content, as a Uint8Array or Buffer. - * @param filename file name. - */ - docFromBytes(inputBytes: Uint8Array, filename: string): BytesInput { - return new BytesInput({ - inputBytes: inputBytes, - filename: filename, - }); - } - - /** - * Load an input document from a URL. - * @param url input url. Must be HTTPS. - */ - docFromUrl(url: string): UrlInput { - return new UrlInput({ - url: url, - }); - } - - /** - * Load an input document from a Buffer. - * @param buffer input content, as a buffer. - * @param filename file name. - */ - docFromBuffer(buffer: Buffer, filename: string): BufferInput { - return new BufferInput({ - buffer: buffer, - filename: filename, - }); - } -} diff --git a/src/client.ts b/src/client.ts index 7df1bff49..3f5510d01 100644 --- a/src/client.ts +++ b/src/client.ts @@ -21,7 +21,8 @@ import { setTimeout } from "node:timers/promises"; import { MindeeError } from "./errors"; import { WorkflowResponse } from "./parsing/common/workflowResponse"; import { WorkflowEndpoint } from "./http/workflowEndpoint"; -import { BaseClient } from "./baseClient"; +import { Base64Input, BufferInput, BytesInput, PathInput, StreamInput, UrlInput } from "./input"; +import { Readable } from "stream"; /** * Common options for workflows & predictions. @@ -129,7 +130,7 @@ export interface ClientOptions { * * @category Client */ -export class Client extends BaseClient { +export class Client { /** Key of the API. */ protected apiKey: string; @@ -143,7 +144,6 @@ export class Client extends BaseClient { debug: false, } ) { - super(); this.apiKey = apiKey ? apiKey : ""; errorHandler.throwOnError = throwOnError ?? true; logger.level = @@ -565,4 +565,72 @@ Job status: ${pollResults.job.status}.` InferenceFactory.getEndpoint(productClass); return [endpointName, endpointVersion]; } + + /** + * Load an input document from a local path. + * @param inputPath + */ + docFromPath(inputPath: string): PathInput { + return new PathInput({ + inputPath: inputPath, + }); + } + + /** + * Load an input document from a base64 encoded string. + * @param inputString input content, as a string. + * @param filename file name. + */ + docFromBase64(inputString: string, filename: string): Base64Input { + return new Base64Input({ + inputString: inputString, + filename: filename, + }); + } + + /** + * Load an input document from a `stream.Readable` object. + * @param inputStream input content, as a readable stream. + * @param filename file name. + */ + docFromStream(inputStream: Readable, filename: string): StreamInput { + return new StreamInput({ + inputStream: inputStream, + filename: filename, + }); + } + + /** + * Load an input document from bytes. + * @param inputBytes input content, as a Uint8Array or Buffer. + * @param filename file name. + */ + docFromBytes(inputBytes: Uint8Array, filename: string): BytesInput { + return new BytesInput({ + inputBytes: inputBytes, + filename: filename, + }); + } + + /** + * Load an input document from a URL. + * @param url input url. Must be HTTPS. + */ + docFromUrl(url: string): UrlInput { + return new UrlInput({ + url: url, + }); + } + + /** + * Load an input document from a Buffer. + * @param buffer input content, as a buffer. + * @param filename file name. + */ + docFromBuffer(buffer: Buffer, filename: string): BufferInput { + return new BufferInput({ + buffer: buffer, + filename: filename, + }); + } } diff --git a/src/clientV2.ts b/src/clientV2.ts index 5e83abb0c..abfd4f638 100644 --- a/src/clientV2.ts +++ b/src/clientV2.ts @@ -1,5 +1,6 @@ import { - LocalInputSource, + Base64Input, BufferInput, BytesInput, + LocalInputSource, PathInput, StreamInput, UrlInput, } from "./input"; import { errorHandler } from "./errors/handler"; import { LOG_LEVELS, logger } from "./logger"; @@ -7,8 +8,8 @@ import { LOG_LEVELS, logger } from "./logger"; import { setTimeout } from "node:timers/promises"; import { ErrorResponse, InferenceResponse, JobResponse } from "./parsing/v2"; import { MindeeApiV2 } from "./http/mindeeApiV2"; -import { BaseClient } from "./baseClient"; import { MindeeHttpErrorV2 } from "./errors/mindeeError"; +import { Readable } from "stream"; /** * Parameters for the internal polling loop in {@link ClientV2.enqueueAndGetInference | enqueueAndGetInference()} . @@ -122,7 +123,7 @@ export interface ClientOptions { * * @category ClientV2 */ -export class ClientV2 extends BaseClient { +export class ClientV2 { /** Key of the API. */ protected mindeeApi: MindeeApiV2; @@ -136,7 +137,6 @@ export class ClientV2 extends BaseClient { debug: false, } ) { - super(); this.mindeeApi = new MindeeApiV2(apiKey); errorHandler.throwOnError = throwOnError ?? true; logger.level = @@ -283,4 +283,72 @@ Job status: ${pollResults.job.status}.` " seconds" ); } + + /** + * Load an input source from a local path. + * @param inputPath + */ + sourceFromPath(inputPath: string): PathInput { + return new PathInput({ + inputPath: inputPath, + }); + } + + /** + * Load an input source from a base64 encoded string. + * @param inputString input content, as a string. + * @param filename file name. + */ + sourceFromBase64(inputString: string, filename: string): Base64Input { + return new Base64Input({ + inputString: inputString, + filename: filename, + }); + } + + /** + * Load an input source from a `stream.Readable` object. + * @param inputStream input content, as a readable stream. + * @param filename file name. + */ + sourceFromStream(inputStream: Readable, filename: string): StreamInput { + return new StreamInput({ + inputStream: inputStream, + filename: filename, + }); + } + + /** + * Load an input source from bytes. + * @param inputBytes input content, as a Uint8Array or Buffer. + * @param filename file name. + */ + sourceFromBytes(inputBytes: Uint8Array, filename: string): BytesInput { + return new BytesInput({ + inputBytes: inputBytes, + filename: filename, + }); + } + + /** + * Load an input source from a Buffer. + * @param buffer input content, as a buffer. + * @param filename file name. + */ + sourceFromBuffer(buffer: Buffer, filename: string): BufferInput { + return new BufferInput({ + buffer: buffer, + filename: filename, + }); + } + + /** + * Load an input source from a URL. + * @param url input url. Must be HTTPS. + */ + sourceFromUrl(url: string): UrlInput { + return new UrlInput({ + url: url, + }); + } } diff --git a/src/index.ts b/src/index.ts index 114ba5991..276d6663d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,6 +9,6 @@ export { Document, Page, } from "./parsing/common"; -export { InputSource, PageOptionsOperation, LocalResponse } from "./input"; +export { InputSource, PageOptions, PageOptionsOperation, LocalResponse } from "./input"; export * as internal from "./internal"; export * as imageOperations from "./imageOperations"; diff --git a/tests/inputs/pageOperations.spec.ts b/tests/inputs/pageOperations.spec.ts index d0c0088d3..0431c1120 100644 --- a/tests/inputs/pageOperations.spec.ts +++ b/tests/inputs/pageOperations.spec.ts @@ -13,7 +13,7 @@ describe("High level multi-page operations", () => { inputPath: path.join(__dirname, "../data/file_types/pdf/multipage.pdf"), }); await input.init(); - await input.cutPdf({ + await input.applyPageOptions({ operation: PageOptionsOperation.KeepOnly, pageIndexes: [0, -2, -1], onMinPages: 5, diff --git a/tests/pdf/pdfOperation.spec.ts b/tests/pdf/pdfOperation.spec.ts index ab0033fa6..90eaf31a8 100644 --- a/tests/pdf/pdfOperation.spec.ts +++ b/tests/pdf/pdfOperation.spec.ts @@ -2,46 +2,47 @@ import * as pdf from "../../src/pdf"; import * as path from "path"; import * as fs from "fs"; import { expect } from "chai"; -import { PathInput, PageOptions, PageOptionsOperation } from "../../src/input"; +import { PageOptions, PageOptionsOperation } from "../../src"; +import { PathInput } from "../../src/input"; describe("Test pdf operation", () => { it("should cut a PDF to get 2 pages", async () => { - const inputDoc = new PathInput({ + const inputSource = new PathInput({ inputPath: path.join(__dirname, "../data/file_types/pdf/multipage.pdf"), }); - await inputDoc.init(); + await inputSource.init(); const pageOptions: PageOptions = { pageIndexes: [0, 1], operation: PageOptionsOperation.KeepOnly, onMinPages: 1, }; - const splitPdf = await pdf.extractPages(inputDoc.fileObject, pageOptions); + const splitPdf = await pdf.extractPages(inputSource.fileObject, pageOptions); expect(splitPdf.totalPagesRemoved).to.eq(10); expect(await pdf.countPages(splitPdf.file)).to.eq(2); }); it("should cut a PDF to get only the first page", async () => { - const inputDoc = new PathInput({ + const inputSource = new PathInput({ inputPath: path.join(__dirname, "../data/file_types/pdf/multipage.pdf"), }); - await inputDoc.init(); + await inputSource.init(); const pageOptions: PageOptions = { pageIndexes: [0], operation: PageOptionsOperation.KeepOnly, onMinPages: 1, }; - const splitPdf = await pdf.extractPages(inputDoc.fileObject, pageOptions); + const splitPdf = await pdf.extractPages(inputSource.fileObject, pageOptions); expect(splitPdf.totalPagesRemoved).to.eq(11); expect(await pdf.countPages(splitPdf.file)).to.eq(1); }); it("should not cut a PDF but throw exception because index page out of range", async () => { - const inputDoc = new PathInput({ + const inputSource = new PathInput({ inputPath: path.join(__dirname, "../data/file_types/pdf/multipage_cut-1.pdf"), }); - await inputDoc.init(); + await inputSource.init(); const pageOptions: PageOptions = { pageIndexes: [10], @@ -49,7 +50,7 @@ describe("Test pdf operation", () => { onMinPages: 1, }; try { - await pdf.extractPages(inputDoc.fileObject, pageOptions); + await pdf.extractPages(inputSource.fileObject, pageOptions); } catch (error: any) { expect(error).to.be.an("error"); expect(error.name).to.be.eq("MindeeError"); @@ -57,10 +58,10 @@ describe("Test pdf operation", () => { }); it("should not cut a PDF but throw exception because too many indexes compare to the total of pages", async () => { - const inputDoc = new PathInput({ + const inputSource = new PathInput({ inputPath: path.join(__dirname, "../data/file_types/pdf/multipage_cut-1.pdf"), }); - await inputDoc.init(); + await inputSource.init(); const pageOptions: PageOptions = { pageIndexes: [0, 1, 2], @@ -69,7 +70,7 @@ describe("Test pdf operation", () => { }; try { - await pdf.extractPages(inputDoc.fileObject, pageOptions); + await pdf.extractPages(inputSource.fileObject, pageOptions); } catch (error: any) { expect(error).to.be.an("error"); expect(error.name).to.be.eq("MindeeError"); @@ -77,10 +78,10 @@ describe("Test pdf operation", () => { }); it("should remove pages from a PDF", async () => { - const inputDoc = new PathInput({ + const inputSource = new PathInput({ inputPath: path.join(__dirname, "../data/file_types/pdf/multipage.pdf"), }); - await inputDoc.init(); + await inputSource.init(); const pageOptions: PageOptions = { pageIndexes: [0, 1, 2], @@ -88,56 +89,56 @@ describe("Test pdf operation", () => { onMinPages: 1, }; - const splitPdf = await pdf.extractPages(inputDoc.fileObject, pageOptions); + const splitPdf = await pdf.extractPages(inputSource.fileObject, pageOptions); expect(splitPdf.totalPagesRemoved).to.eq(3); expect(await pdf.countPages(splitPdf.file)).to.eq(9); }); it("should not remove pages from a PDF because min pages are not met", async () => { - const inputDoc = new PathInput({ + const inputSource = new PathInput({ inputPath: path.join(__dirname, "../data/file_types/pdf/multipage_cut-2.pdf"), }); - await inputDoc.init(); + await inputSource.init(); const pageOptions: PageOptions = { pageIndexes: [0], operation: PageOptionsOperation.Remove, onMinPages: 5, }; - const splitPdf = await pdf.extractPages(inputDoc.fileObject, pageOptions); + const splitPdf = await pdf.extractPages(inputSource.fileObject, pageOptions); expect(splitPdf.totalPagesRemoved).to.eq(0); expect(await pdf.countPages(splitPdf.file)).to.eq(2); }); it("should not cut pages from a PDF because min pages are not met", async () => { - const inputDoc = new PathInput({ + const inputSource = new PathInput({ inputPath: path.join(__dirname, "../data/file_types/pdf/multipage_cut-2.pdf"), }); - await inputDoc.init(); + await inputSource.init(); const pageOptions: PageOptions = { pageIndexes: [0, 1, 3, 4], operation: PageOptionsOperation.KeepOnly, onMinPages: 12, }; - const splitPdf = await pdf.extractPages(inputDoc.fileObject, pageOptions); + const splitPdf = await pdf.extractPages(inputSource.fileObject, pageOptions); expect(splitPdf.totalPagesRemoved).to.eq(0); expect(await pdf.countPages(splitPdf.file)).to.eq(2); }); it("should cut the first and the 2 last pages from a PDF", async () => { - const inputDoc = new PathInput({ + const inputSource = new PathInput({ inputPath: path.join(__dirname, "../data/file_types/pdf/multipage.pdf"), }); - await inputDoc.init(); + await inputSource.init(); const pageOptions: PageOptions = { pageIndexes: [0, -2, -1], operation: PageOptionsOperation.KeepOnly, onMinPages: 0, }; - const newPdf = await pdf.extractPages(inputDoc.fileObject, pageOptions); + const newPdf = await pdf.extractPages(inputSource.fileObject, pageOptions); expect(newPdf.totalPagesRemoved).to.eq(9); expect(await pdf.countPages(newPdf.file)).to.eq(3); @@ -150,10 +151,10 @@ describe("Test pdf operation", () => { "utf-8" ); - inputDoc.fileObject = Buffer.from(newPdf.file); + inputSource.fileObject = Buffer.from(newPdf.file); const expectedLengths = expectedResult.match(lengthRE); const inputDocLengths = - inputDoc.fileObject.toString("utf-8").match(lengthRE) || []; + inputSource.fileObject.toString("utf-8").match(lengthRE) || []; expect(expectedLengths).to.have.ordered.members(inputDocLengths); }); }); diff --git a/tests/v2/clientV2.spec.ts b/tests/v2/clientV2.spec.ts index c4c154560..7eb164e8f 100644 --- a/tests/v2/clientV2.spec.ts +++ b/tests/v2/clientV2.spec.ts @@ -78,7 +78,7 @@ describe("ClientV2", () => { it("enqueue(path) rejects with MindeeHttpErrorV2 on 4xx", async () => { const filePath = path.join(fileTypesDir, "receipt.jpg"); - const inputDoc = client.docFromPath(filePath); + const inputDoc = client.sourceFromPath(filePath); await assert.rejects( client.enqueueInference(inputDoc, { modelId: "dummy-model" }), @@ -88,7 +88,7 @@ describe("ClientV2", () => { it("enqueueAndParse(path) rejects with MindeeHttpErrorV2 on 4xx", async () => { const filePath = path.join(fileTypesDir, "receipt.jpg"); - const inputDoc = client.docFromPath(filePath); + const inputDoc = client.sourceFromPath(filePath); await assert.rejects( client.enqueueAndGetInference( inputDoc,