mindee 5.5.0 → 5.6.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.
Files changed (209) hide show
  1. package/CHANGELOG.md +17 -2
  2. package/package.json +26 -14
  3. package/src/geometry/bbox.d.ts +5 -0
  4. package/src/geometry/bbox.js +1 -0
  5. package/src/geometry/minMax.d.ts +3 -0
  6. package/src/geometry/polygonUtils.d.ts +23 -0
  7. package/src/geometry/polygonUtils.js +23 -0
  8. package/src/http/baseSettings.d.ts +5 -0
  9. package/src/http/baseSettings.js +2 -0
  10. package/src/image/extractedImage.d.ts +4 -0
  11. package/src/image/extractedImages.d.ts +1 -0
  12. package/src/image/extractedImages.js +1 -0
  13. package/src/image/imageCompressor.d.ts +1 -1
  14. package/src/image/imageExtractor.d.ts +5 -6
  15. package/src/image/imageExtractor.js +71 -73
  16. package/src/input/base64Input.d.ts +3 -0
  17. package/src/input/base64Input.js +3 -0
  18. package/src/input/bufferInput.d.ts +2 -0
  19. package/src/input/bufferInput.js +2 -0
  20. package/src/input/bytesInput.d.ts +3 -0
  21. package/src/input/bytesInput.js +3 -0
  22. package/src/input/inputSource.d.ts +15 -0
  23. package/src/input/inputSource.js +15 -0
  24. package/src/input/localInputSource.d.ts +6 -0
  25. package/src/input/localInputSource.js +3 -0
  26. package/src/input/pathInput.d.ts +4 -0
  27. package/src/input/pathInput.js +3 -0
  28. package/src/input/streamInput.d.ts +4 -0
  29. package/src/input/streamInput.js +4 -0
  30. package/src/input/urlInput.d.ts +12 -0
  31. package/src/input/urlInput.js +52 -10
  32. package/src/logger.js +1 -1
  33. package/src/parsing/dateParser.d.ts +4 -0
  34. package/src/parsing/dateParser.js +5 -1
  35. package/src/parsing/localResponseBase.d.ts +2 -0
  36. package/src/parsing/localResponseBase.js +2 -0
  37. package/src/parsing/stringDict.d.ts +1 -0
  38. package/src/pdf/extractedPdf.d.ts +5 -0
  39. package/src/pdf/extractedPdf.js +1 -0
  40. package/src/pdf/extractedPdfs.d.ts +1 -0
  41. package/src/pdf/extractedPdfs.js +1 -0
  42. package/src/pdf/pdfCompressor.js +12 -0
  43. package/src/pdf/pdfExtractor.js +3 -0
  44. package/src/pdf/pdfOperation.d.ts +3 -0
  45. package/src/pdf/pdfOperation.js +3 -0
  46. package/src/pdf/pdfUtils.js +5 -0
  47. package/src/v1/cli.d.ts +3 -0
  48. package/src/v1/cli.js +84 -26
  49. package/src/v1/client.d.ts +16 -16
  50. package/src/v1/extraction/invoiceSplitterExtractor/extractedInvoiceSplitterImage.d.ts +2 -0
  51. package/src/v1/extraction/invoiceSplitterExtractor/invoiceSplitterExtractor.js +14 -0
  52. package/src/v1/extraction/multiReceiptsExtractor/extractedMultiReceiptImage.d.ts +2 -0
  53. package/src/v1/extraction/multiReceiptsExtractor/multiReceiptsExtractor.js +3 -0
  54. package/src/v1/http/apiSettingsV1.d.ts +5 -0
  55. package/src/v1/http/apiSettingsV1.js +4 -0
  56. package/src/v1/http/errors.d.ts +7 -1
  57. package/src/v1/http/errors.js +65 -86
  58. package/src/v1/http/httpParams.d.ts +12 -0
  59. package/src/v1/parsing/common/asyncPredictResponse.d.ts +4 -0
  60. package/src/v1/parsing/common/asyncPredictResponse.js +5 -2
  61. package/src/v1/parsing/common/executionPriority.d.ts +4 -0
  62. package/src/v1/parsing/common/executionPriority.js +4 -0
  63. package/src/v1/parsing/common/extras/cropperExtra.d.ts +2 -0
  64. package/src/v1/parsing/common/extras/cropperExtra.js +3 -0
  65. package/src/v1/parsing/common/extras/extras.d.ts +3 -0
  66. package/src/v1/parsing/common/extras/extras.js +2 -0
  67. package/src/v1/parsing/common/extras/fullTextOcrExtra.d.ts +3 -0
  68. package/src/v1/parsing/common/extras/fullTextOcrExtra.js +1 -0
  69. package/src/v1/parsing/common/extras/ragExtra.d.ts +1 -0
  70. package/src/v1/parsing/common/extras/ragExtra.js +1 -0
  71. package/src/v1/parsing/common/feedback/feedbackResponse.js +1 -0
  72. package/src/v1/parsing/common/index.d.ts +1 -1
  73. package/src/v1/parsing/common/index.js +1 -1
  74. package/src/v1/parsing/common/inference.d.ts +2 -0
  75. package/src/v1/parsing/common/inference.js +2 -0
  76. package/src/v1/parsing/common/prediction.d.ts +1 -0
  77. package/src/v1/parsing/common/prediction.js +1 -0
  78. package/src/v1/parsing/common/summaryHelper.d.ts +12 -1
  79. package/src/v1/parsing/common/summaryHelper.js +18 -1
  80. package/src/v1/parsing/generated/generatedObject.d.ts +6 -0
  81. package/src/v1/parsing/generated/generatedObject.js +38 -27
  82. package/src/v1/parsing/localResponse.d.ts +1 -0
  83. package/src/v1/parsing/localResponse.js +1 -0
  84. package/src/v1/parsing/standard/base.d.ts +6 -0
  85. package/src/v1/parsing/standard/base.js +1 -0
  86. package/src/v1/parsing/standard/boolean.d.ts +1 -1
  87. package/src/v1/parsing/standard/companyRegistration.d.ts +1 -0
  88. package/src/v1/parsing/standard/companyRegistration.js +1 -0
  89. package/src/v1/parsing/standard/date.d.ts +1 -0
  90. package/src/v1/parsing/standard/date.js +1 -0
  91. package/src/v1/parsing/standard/paymentDetails.d.ts +5 -5
  92. package/src/v1/parsing/standard/position.d.ts +2 -2
  93. package/src/v1/parsing/standard/tax.d.ts +1 -0
  94. package/src/v1/parsing/standard/tax.js +1 -0
  95. package/src/v1/parsing/standard/text.d.ts +1 -1
  96. package/src/v1/parsing/standard/word.d.ts +3 -0
  97. package/src/v1/parsing/standard/word.js +1 -0
  98. package/src/v1/product/financialDocument/financialDocumentV1LineItem.js +16 -58
  99. package/src/v1/product/generated/generatedV1Prediction.d.ts +1 -0
  100. package/src/v1/product/generated/generatedV1Prediction.js +2 -1
  101. package/src/v1/product/invoice/invoiceV4LineItem.js +5 -16
  102. package/src/v1/product/receipt/receiptV5LineItem.js +2 -6
  103. package/src/v1/product/resume/resumeV1Certificate.js +5 -21
  104. package/src/v1/product/resume/resumeV1Education.js +8 -36
  105. package/src/v1/product/resume/resumeV1Language.js +3 -11
  106. package/src/v1/product/resume/resumeV1ProfessionalExperience.js +10 -46
  107. package/src/v1/product/resume/resumeV1SocialNetworksUrl.js +3 -11
  108. package/src/v2/cli.d.ts +3 -0
  109. package/src/v2/cli.js +21 -0
  110. package/src/v2/client.d.ts +1 -0
  111. package/src/v2/client.js +1 -0
  112. package/src/v2/clientOptions/pollingOptions.d.ts +5 -0
  113. package/src/v2/clientOptions/pollingOptions.js +2 -0
  114. package/src/v2/parsing/baseResponse.d.ts +2 -0
  115. package/src/v2/parsing/baseResponse.js +1 -0
  116. package/src/v2/parsing/error/errorDetails.d.ts +1 -0
  117. package/src/v2/parsing/index.d.ts +1 -1
  118. package/src/v2/parsing/index.js +1 -1
  119. package/src/v2/parsing/inference/baseInference.d.ts +2 -0
  120. package/src/v2/parsing/inference/baseInference.js +2 -0
  121. package/src/v2/parsing/inference/failedInferenceResponse.d.ts +33 -0
  122. package/src/v2/parsing/inference/failedInferenceResponse.js +17 -0
  123. package/src/v2/parsing/inference/field/baseField.d.ts +3 -0
  124. package/src/v2/parsing/inference/field/fieldConfidence.d.ts +4 -0
  125. package/src/v2/parsing/inference/field/fieldConfidence.js +4 -0
  126. package/src/v2/parsing/inference/field/fieldFactory.d.ts +5 -0
  127. package/src/v2/parsing/inference/field/fieldFactory.js +5 -0
  128. package/src/v2/parsing/inference/field/fieldLocation.d.ts +1 -0
  129. package/src/v2/parsing/inference/field/fieldLocation.js +1 -0
  130. package/src/v2/parsing/inference/field/inferenceFields.d.ts +5 -0
  131. package/src/v2/parsing/inference/field/inferenceFields.js +4 -0
  132. package/src/v2/parsing/inference/field/listField.d.ts +2 -0
  133. package/src/v2/parsing/inference/field/listField.js +2 -0
  134. package/src/v2/parsing/inference/field/objectField.d.ts +4 -0
  135. package/src/v2/parsing/inference/field/objectField.js +3 -0
  136. package/src/v2/parsing/inference/field/ragMetadata.d.ts +1 -0
  137. package/src/v2/parsing/inference/field/ragMetadata.js +1 -0
  138. package/src/v2/parsing/inference/field/rawText.d.ts +2 -0
  139. package/src/v2/parsing/inference/field/rawText.js +2 -0
  140. package/src/v2/parsing/inference/field/simpleField.d.ts +2 -0
  141. package/src/v2/parsing/inference/field/simpleField.js +2 -0
  142. package/src/v2/parsing/inference/inferenceFile.d.ts +2 -0
  143. package/src/v2/parsing/inference/inferenceFile.js +2 -0
  144. package/src/v2/parsing/inference/inferenceModel.d.ts +2 -0
  145. package/src/v2/parsing/inference/inferenceModel.js +2 -0
  146. package/src/v2/parsing/job/job.d.ts +1 -1
  147. package/src/v2/parsing/job/job.js +1 -3
  148. package/src/v2/parsing/job/jobResponse.d.ts +3 -0
  149. package/src/v2/parsing/job/jobResponse.js +3 -0
  150. package/src/v2/product/classification/classification.d.ts +3 -0
  151. package/src/v2/product/classification/classification.js +3 -0
  152. package/src/v2/product/classification/classificationClassifier.d.ts +2 -0
  153. package/src/v2/product/classification/classificationClassifier.js +2 -0
  154. package/src/v2/product/classification/classificationInference.d.ts +2 -0
  155. package/src/v2/product/classification/classificationInference.js +2 -0
  156. package/src/v2/product/classification/classificationResponse.d.ts +1 -0
  157. package/src/v2/product/classification/classificationResponse.js +1 -0
  158. package/src/v2/product/classification/classificationResult.d.ts +2 -0
  159. package/src/v2/product/classification/classificationResult.js +2 -0
  160. package/src/v2/product/crop/crop.d.ts +3 -0
  161. package/src/v2/product/crop/crop.js +3 -0
  162. package/src/v2/product/crop/cropInference.d.ts +2 -0
  163. package/src/v2/product/crop/cropInference.js +2 -0
  164. package/src/v2/product/crop/cropItem.d.ts +2 -0
  165. package/src/v2/product/crop/cropItem.js +2 -0
  166. package/src/v2/product/crop/cropResponse.d.ts +1 -0
  167. package/src/v2/product/crop/cropResponse.js +1 -0
  168. package/src/v2/product/crop/cropResult.d.ts +2 -0
  169. package/src/v2/product/crop/cropResult.js +2 -0
  170. package/src/v2/product/extraction/dataSchemaActiveOption.d.ts +1 -0
  171. package/src/v2/product/extraction/dataSchemaActiveOption.js +1 -0
  172. package/src/v2/product/extraction/extraction.d.ts +3 -0
  173. package/src/v2/product/extraction/extraction.js +3 -0
  174. package/src/v2/product/extraction/extractionActiveOptions.d.ts +2 -0
  175. package/src/v2/product/extraction/extractionActiveOptions.js +2 -0
  176. package/src/v2/product/extraction/extractionInference.d.ts +2 -0
  177. package/src/v2/product/extraction/extractionInference.js +2 -0
  178. package/src/v2/product/extraction/extractionResponse.d.ts +1 -0
  179. package/src/v2/product/extraction/extractionResponse.js +1 -0
  180. package/src/v2/product/extraction/extractionResult.d.ts +2 -0
  181. package/src/v2/product/extraction/extractionResult.js +2 -0
  182. package/src/v2/product/extraction/params/dataSchema.d.ts +9 -6
  183. package/src/v2/product/extraction/params/dataSchema.js +2 -0
  184. package/src/v2/product/extraction/params/dataSchemaField.d.ts +25 -1
  185. package/src/v2/product/extraction/params/dataSchemaField.js +3 -0
  186. package/src/v2/product/extraction/params/dataSchemaReplace.d.ts +9 -4
  187. package/src/v2/product/extraction/params/dataSchemaReplace.js +2 -0
  188. package/src/v2/product/ocr/ocr.d.ts +3 -0
  189. package/src/v2/product/ocr/ocr.js +3 -0
  190. package/src/v2/product/ocr/ocrInference.d.ts +2 -0
  191. package/src/v2/product/ocr/ocrInference.js +2 -0
  192. package/src/v2/product/ocr/ocrPage.d.ts +2 -0
  193. package/src/v2/product/ocr/ocrPage.js +2 -0
  194. package/src/v2/product/ocr/ocrResponse.d.ts +1 -0
  195. package/src/v2/product/ocr/ocrResponse.js +1 -0
  196. package/src/v2/product/ocr/ocrResult.d.ts +1 -0
  197. package/src/v2/product/ocr/ocrResult.js +1 -0
  198. package/src/v2/product/ocr/ocrWord.d.ts +2 -0
  199. package/src/v2/product/ocr/ocrWord.js +2 -0
  200. package/src/v2/product/split/split.d.ts +3 -0
  201. package/src/v2/product/split/split.js +3 -0
  202. package/src/v2/product/split/splitInference.d.ts +2 -0
  203. package/src/v2/product/split/splitInference.js +2 -0
  204. package/src/v2/product/split/splitRange.d.ts +1 -0
  205. package/src/v2/product/split/splitRange.js +1 -0
  206. package/src/v2/product/split/splitResponse.d.ts +1 -0
  207. package/src/v2/product/split/splitResponse.js +1 -0
  208. package/src/v2/product/split/splitResult.d.ts +1 -0
  209. package/src/v2/product/split/splitResult.js +1 -0
@@ -2,15 +2,21 @@ import { PageOptions } from "../input/pageOptions.js";
2
2
  import { InputSource, InputConstructor } from "./inputSource.js";
3
3
  export declare const MIMETYPES: Map<string, string>;
4
4
  export declare abstract class LocalInputSource extends InputSource {
5
+ /** Type of local input source (path, stream, bytes, ...). */
5
6
  inputType: string;
7
+ /** Original filename associated with the input. */
6
8
  filename: string;
9
+ /** Original filepath when available. */
7
10
  filepath?: string;
11
+ /** MIME type detected for the source content. */
8
12
  mimeType: string;
13
+ /** Binary payload for local sources. */
9
14
  fileObject: Buffer | string;
10
15
  /**
11
16
  * @param {InputConstructor} constructor Constructor parameters.
12
17
  */
13
18
  protected constructor({ inputType }: InputConstructor);
19
+ /** Detects and validates the MIME type from the current file object. */
14
20
  protected checkMimetype(): Promise<string>;
15
21
  /**
16
22
  * Returns the file object as a Buffer.
@@ -29,7 +29,9 @@ export class LocalInputSource extends InputSource {
29
29
  */
30
30
  constructor({ inputType }) {
31
31
  super();
32
+ /** Original filename associated with the input. */
32
33
  this.filename = "";
34
+ /** MIME type detected for the source content. */
33
35
  this.mimeType = "";
34
36
  // Check if inputType is valid
35
37
  if (!ALLOWED_INPUT_TYPES.includes(inputType)) {
@@ -39,6 +41,7 @@ export class LocalInputSource extends InputSource {
39
41
  this.inputType = inputType;
40
42
  logger.debug(`Initialized local input source of type: ${inputType}`);
41
43
  }
44
+ /** Detects and validates the MIME type from the current file object. */
42
45
  async checkMimetype() {
43
46
  if (!(this.fileObject instanceof Buffer)) {
44
47
  throw new MindeeInputSourceError(`MIME type cannot be verified on input source of type ${this.inputType}.`);
@@ -2,10 +2,14 @@ import { LocalInputSource } from "./localInputSource.js";
2
2
  interface PathInputProps {
3
3
  inputPath: string;
4
4
  }
5
+ /** Local input source that reads a file from disk by path. */
5
6
  export declare class PathInput extends LocalInputSource {
7
+ /** Path used to read the local file. */
6
8
  readonly inputPath: string;
9
+ /** File content loaded from disk. */
7
10
  fileObject: Buffer;
8
11
  constructor({ inputPath }: PathInputProps);
12
+ /** Reads the file from disk and validates MIME type. */
9
13
  init(): Promise<void>;
10
14
  }
11
15
  export {};
@@ -3,15 +3,18 @@ import { LocalInputSource } from "./localInputSource.js";
3
3
  import path from "path";
4
4
  import { logger } from "../logger.js";
5
5
  import { promises as fs } from "fs";
6
+ /** Local input source that reads a file from disk by path. */
6
7
  export class PathInput extends LocalInputSource {
7
8
  constructor({ inputPath }) {
8
9
  super({
9
10
  inputType: INPUT_TYPE_PATH,
10
11
  });
12
+ /** File content loaded from disk. */
11
13
  this.fileObject = Buffer.alloc(0);
12
14
  this.inputPath = inputPath;
13
15
  this.filename = path.basename(this.inputPath);
14
16
  }
17
+ /** Reads the file from disk and validates MIME type. */
15
18
  async init() {
16
19
  if (this.initialized) {
17
20
  return;
@@ -4,11 +4,15 @@ interface StreamInputProps {
4
4
  inputStream: Readable;
5
5
  filename: string;
6
6
  }
7
+ /** Local input source backed by a readable stream. */
7
8
  export declare class StreamInput extends LocalInputSource {
8
9
  private readonly inputStream;
10
+ /** Buffered payload created from the stream. */
9
11
  fileObject: Buffer;
10
12
  constructor({ inputStream, filename }: StreamInputProps);
13
+ /** Reads the stream to completion and validates MIME type. */
11
14
  init(): Promise<void>;
15
+ /** Converts a readable stream into a single buffer. */
12
16
  stream2buffer(stream: Readable, signal?: AbortSignal): Promise<Buffer>;
13
17
  }
14
18
  export {};
@@ -2,15 +2,18 @@ import { LocalInputSource } from "./localInputSource.js";
2
2
  import { INPUT_TYPE_STREAM } from "./inputSource.js";
3
3
  import { logger } from "../logger.js";
4
4
  import { MindeeInputSourceError } from "../errors/index.js";
5
+ /** Local input source backed by a readable stream. */
5
6
  export class StreamInput extends LocalInputSource {
6
7
  constructor({ inputStream, filename }) {
7
8
  super({
8
9
  inputType: INPUT_TYPE_STREAM,
9
10
  });
11
+ /** Buffered payload created from the stream. */
10
12
  this.fileObject = Buffer.alloc(0);
11
13
  this.filename = filename;
12
14
  this.inputStream = inputStream;
13
15
  }
16
+ /** Reads the stream to completion and validates MIME type. */
14
17
  async init() {
15
18
  if (this.initialized) {
16
19
  return;
@@ -20,6 +23,7 @@ export class StreamInput extends LocalInputSource {
20
23
  this.mimeType = await this.checkMimetype();
21
24
  this.initialized = true;
22
25
  }
26
+ /** Converts a readable stream into a single buffer. */
23
27
  async stream2buffer(stream, signal) {
24
28
  return new Promise((resolve, reject) => {
25
29
  if (stream.closed || stream.destroyed) {
@@ -1,15 +1,24 @@
1
1
  import { InputSource } from "./inputSource.js";
2
2
  import { Dispatcher } from "undici";
3
3
  import { BytesInput } from "./bytesInput.js";
4
+ /** Remote input source represented by a validated HTTPS URL. */
4
5
  export declare class UrlInput extends InputSource {
6
+ /** HTTPS URL of the remote input file. */
5
7
  readonly url: string;
8
+ /** Dispatcher used for HTTP requests. */
6
9
  readonly dispatcher: Dispatcher;
7
10
  constructor({ url, dispatcher }: {
8
11
  url: string;
9
12
  dispatcher?: Dispatcher;
10
13
  });
14
+ /** Initializes this source by validating and storing the URL. */
11
15
  init(): Promise<void>;
16
+ /**
17
+ * Validates that a URL is safe to fetch: scheme must be https.
18
+ */
19
+ static validateUrl(url: string): void;
12
20
  private fetchFileContent;
21
+ /** Downloads the URL content and writes it to disk. */
13
22
  saveToFile(options: {
14
23
  filepath: string;
15
24
  filename?: string;
@@ -19,6 +28,7 @@ export declare class UrlInput extends InputSource {
19
28
  headers?: Record<string, string>;
20
29
  maxRedirects?: number;
21
30
  }): Promise<string>;
31
+ /** Downloads the URL content and returns it as a local bytes source. */
22
32
  asLocalInputSource(options?: {
23
33
  filename?: string;
24
34
  username?: string;
@@ -31,5 +41,7 @@ export declare class UrlInput extends InputSource {
31
41
  private static generateFileName;
32
42
  private static getFileExtension;
33
43
  private fillFilename;
44
+ private static maskCredentials;
45
+ private static isSameOrigin;
34
46
  private makeRequest;
35
47
  }
@@ -7,6 +7,7 @@ import { request, getGlobalDispatcher } from "undici";
7
7
  import { logger } from "../logger.js";
8
8
  import { MindeeInputSourceError } from "../errors/index.js";
9
9
  import { BytesInput } from "./bytesInput.js";
10
+ /** Remote input source represented by a validated HTTPS URL. */
10
11
  export class UrlInput extends InputSource {
11
12
  constructor({ url, dispatcher }) {
12
13
  super();
@@ -14,25 +15,43 @@ export class UrlInput extends InputSource {
14
15
  this.dispatcher = dispatcher ?? getGlobalDispatcher();
15
16
  logger.debug("Initialized URL input source.");
16
17
  }
18
+ /** Initializes this source by validating and storing the URL. */
17
19
  async init() {
18
20
  if (this.initialized) {
19
21
  return;
20
22
  }
21
- logger.debug(`source URL: ${this.url}`);
22
- if (!this.url.toLowerCase().startsWith("https")) {
23
- throw new MindeeInputSourceError("URL must be HTTPS");
24
- }
23
+ logger.debug(`source URL: ${UrlInput.maskCredentials(this.url)}`);
24
+ UrlInput.validateUrl(this.url);
25
25
  this.fileObject = this.url;
26
26
  this.initialized = true;
27
27
  }
28
+ /**
29
+ * Validates that a URL is safe to fetch: scheme must be https.
30
+ */
31
+ static validateUrl(url) {
32
+ let parsed;
33
+ try {
34
+ parsed = new URL(url);
35
+ }
36
+ catch {
37
+ throw new MindeeInputSourceError("Invalid URL");
38
+ }
39
+ if (parsed.protocol !== "https:") {
40
+ throw new MindeeInputSourceError("URL must be HTTPS");
41
+ }
42
+ }
28
43
  async fetchFileContent(options) {
29
44
  const { username, password, token, headers = {}, maxRedirects = 3 } = options;
30
45
  if (token) {
31
46
  headers["Authorization"] = `Bearer ${token}`;
32
47
  }
33
- const auth = username && password ? `${username}:${password}` : undefined;
34
- return await this.makeRequest(this.url, auth, headers, 0, maxRedirects);
48
+ else if (username && password) {
49
+ const encoded = Buffer.from(`${username}:${password}`).toString("base64");
50
+ headers["Authorization"] = `Basic ${encoded}`;
51
+ }
52
+ return await this.makeRequest(this.url, headers, 0, maxRedirects);
35
53
  }
54
+ /** Downloads the URL content and writes it to disk. */
36
55
  async saveToFile(options) {
37
56
  const { filepath, filename, ...fetchOptions } = options;
38
57
  const { content, finalUrl } = await this.fetchFileContent(fetchOptions);
@@ -41,6 +60,7 @@ export class UrlInput extends InputSource {
41
60
  await writeFile(fullPath, content);
42
61
  return fullPath;
43
62
  }
63
+ /** Downloads the URL content and returns it as a local bytes source. */
44
64
  async asLocalInputSource(options = {}) {
45
65
  const { filename, ...fetchOptions } = options;
46
66
  const { content, finalUrl } = await this.fetchFileContent(fetchOptions);
@@ -68,21 +88,43 @@ export class UrlInput extends InputSource {
68
88
  }
69
89
  return filename;
70
90
  }
71
- async makeRequest(url, auth, headers, redirects, maxRedirects) {
91
+ static maskCredentials(url) {
92
+ try {
93
+ const parsed = new URL(url);
94
+ if (parsed.username || parsed.password) {
95
+ parsed.username = "******";
96
+ parsed.password = "******";
97
+ }
98
+ return parsed.toString();
99
+ }
100
+ catch {
101
+ return url;
102
+ }
103
+ }
104
+ static isSameOrigin(a, b) {
105
+ const urlA = new URL(a);
106
+ const urlB = new URL(b);
107
+ return urlA.origin === urlB.origin;
108
+ }
109
+ async makeRequest(url, headers, redirects, maxRedirects) {
72
110
  const parsedUrl = new URL(url);
73
111
  const response = await request(parsedUrl, {
74
112
  method: "GET",
75
113
  headers: headers,
76
- throwOnError: false,
77
114
  dispatcher: this.dispatcher,
78
115
  });
79
116
  if (response.statusCode && response.statusCode >= 300 && response.statusCode < 400) {
80
- logger.debug(`Redirecting to: ${response.headers.location}`);
117
+ logger.debug(`Redirecting to: ${UrlInput.maskCredentials(response.headers.location?.toString() ?? "")}`);
81
118
  if (redirects === maxRedirects) {
82
119
  throw new MindeeInputSourceError(`Can't reach URL after ${redirects} out of ${maxRedirects} redirects, aborting operation.`);
83
120
  }
84
121
  if (response.headers.location) {
85
- return await this.makeRequest(response.headers.location.toString(), auth, headers, redirects + 1, maxRedirects);
122
+ const redirectUrl = new URL(response.headers.location.toString(), url).toString();
123
+ UrlInput.validateUrl(redirectUrl);
124
+ const redirectHeaders = UrlInput.isSameOrigin(url, redirectUrl)
125
+ ? headers
126
+ : Object.fromEntries(Object.entries(headers).filter(([k]) => k.toLowerCase() !== "authorization"));
127
+ return await this.makeRequest(redirectUrl, redirectHeaders, redirects + 1, maxRedirects);
86
128
  }
87
129
  throw new MindeeInputSourceError("Redirect location not found");
88
130
  }
package/src/logger.js CHANGED
@@ -10,7 +10,7 @@ class Logger {
10
10
  if (!(levelToSet in LOG_LEVELS)) {
11
11
  this.level = LOG_LEVELS["debug"];
12
12
  }
13
- this.level = LOG_LEVELS[levelToSet];
13
+ this.level = LOG_LEVELS[levelToSet.toString()];
14
14
  }
15
15
  debug(...args) {
16
16
  if (this.level <= LOG_LEVELS["debug"])
@@ -1 +1,5 @@
1
+ /**
2
+ * Parse a date string into a Date object.
3
+ * @param dateString The date string to parse.
4
+ */
1
5
  export declare function parseDate(dateString: string | null): Date | null;
@@ -1,8 +1,12 @@
1
+ /**
2
+ * Parse a date string into a Date object.
3
+ * @param dateString The date string to parse.
4
+ */
1
5
  export function parseDate(dateString) {
2
6
  if (!dateString) {
3
7
  return null;
4
8
  }
5
- if (!/Z$/.test(dateString) && !/[+-][0-9]{2}:[0-9]{2}$/.test(dateString)) {
9
+ if (!/Z$/.test(dateString) && !/[+-]\d{2}:\d{2}$/.test(dateString)) {
6
10
  dateString += "Z";
7
11
  }
8
12
  return new Date(dateString);
@@ -7,11 +7,13 @@ import { Buffer } from "buffer";
7
7
  export declare abstract class LocalResponseBase {
8
8
  private file;
9
9
  private readonly inputHandle;
10
+ /** Whether the local response payload has been loaded. */
10
11
  protected initialized: boolean;
11
12
  /**
12
13
  * Creates an instance of LocalResponse.
13
14
  */
14
15
  constructor(inputFile: Buffer | string);
16
+ /** Loads the local payload from a string, buffer, or file path. */
15
17
  init(): Promise<void>;
16
18
  /**
17
19
  * Returns the dictionary representation of the file.
@@ -11,10 +11,12 @@ export class LocalResponseBase {
11
11
  * Creates an instance of LocalResponse.
12
12
  */
13
13
  constructor(inputFile) {
14
+ /** Whether the local response payload has been loaded. */
14
15
  this.initialized = false;
15
16
  this.file = Buffer.alloc(0);
16
17
  this.inputHandle = inputFile;
17
18
  }
19
+ /** Loads the local payload from a string, buffer, or file path. */
18
20
  async init() {
19
21
  /**
20
22
  * @param inputFile - The input file, which can be a Buffer, string, or PathLike.
@@ -1,3 +1,4 @@
1
+ /** Generic string-keyed dictionary used for raw API payloads. */
1
2
  export type StringDict = {
2
3
  [index: string]: any;
3
4
  };
@@ -1,9 +1,14 @@
1
1
  import { BufferInput } from "../input/index.js";
2
2
  import { Buffer } from "node:buffer";
3
+ /** Represents a PDF artifact produced by an extraction/splitting operation. */
3
4
  export declare class ExtractedPdf {
5
+ /** Raw bytes of the extracted PDF segment. */
4
6
  readonly buffer: Buffer;
7
+ /** Filename suggested for export. */
5
8
  readonly filename: string;
9
+ /** Number of pages in this extracted PDF. */
6
10
  readonly pageCount: number;
11
+ /** Zero-based indexes of pages included in this extracted PDF. */
7
12
  readonly pageIndexes: number[];
8
13
  constructor(pdfData: Buffer<ArrayBufferLike>, filename: string, pageIndexes: number[]);
9
14
  /**
@@ -4,6 +4,7 @@ import { MindeeError } from "../errors/index.js";
4
4
  import { writeFile } from "fs/promises";
5
5
  import { logger } from "../logger.js";
6
6
  import { writeFileSync } from "node:fs";
7
+ /** Represents a PDF artifact produced by an extraction/splitting operation. */
7
8
  export class ExtractedPdf {
8
9
  constructor(pdfData, filename, pageIndexes) {
9
10
  this.buffer = pdfData;
@@ -1,4 +1,5 @@
1
1
  import { ExtractedPdf } from "../pdf/extractedPdf.js";
2
+ /** Collection of extracted PDF artifacts. */
2
3
  export declare class ExtractedPdfs extends Array<ExtractedPdf> {
3
4
  constructor(...items: ExtractedPdf[]);
4
5
  }
@@ -1,3 +1,4 @@
1
+ /** Collection of extracted PDF artifacts. */
1
2
  export class ExtractedPdfs extends Array {
2
3
  constructor(...items) {
3
4
  super(...items);
@@ -3,6 +3,9 @@ import { compressImage } from "../image/index.js";
3
3
  import { loadOptionalDependency } from "../dependency/index.js";
4
4
  import { extractTextFromPdf, hasSourceText, rasterizePage } from "./pdfUtils.js";
5
5
  let pdfLib = null;
6
+ /**
7
+ * Load the PDF library if not already loaded.
8
+ */
6
9
  async function getPdfLib() {
7
10
  if (!pdfLib) {
8
11
  const pdfLibImport = await loadOptionalDependency("@cantoo/pdf-lib", "Text Embedding");
@@ -155,6 +158,11 @@ async function createNewPdfFromCompressedPages(compressedPages) {
155
158
  const compressedPdfBytes = await newPdfDoc.save();
156
159
  return Buffer.from(compressedPdfBytes);
157
160
  }
161
+ /**
162
+ * Add text to a PDF page.
163
+ * @param page The PDF page to add text to.
164
+ * @param textInfo The extracted text information to add to the page.
165
+ */
158
166
  async function addTextToPdfPage(page, textInfo) {
159
167
  if (textInfo === null) {
160
168
  return;
@@ -172,6 +180,10 @@ async function addTextToPdfPage(page, textInfo) {
172
180
  }
173
181
  }
174
182
  }
183
+ /**
184
+ * Get a font from a given font name.
185
+ * @param fontName The name of the font to get.
186
+ */
175
187
  async function getFontFromName(fontName) {
176
188
  const pdfLib = await getPdfLib();
177
189
  const pdfDoc = await pdfLib.PDFDocument.create();
@@ -6,6 +6,9 @@ import { MindeeInputSourceError, MindeePdfError } from "../errors/index.js";
6
6
  import { ExtractedPdf } from "../pdf/extractedPdf.js";
7
7
  import { createPdfFromInputSource, extractPages } from "../pdf/pdfOperation.js";
8
8
  let pdfLib = null;
9
+ /**
10
+ * Load the PDF library if not already loaded.
11
+ */
9
12
  async function getPdfLib() {
10
13
  if (!pdfLib) {
11
14
  const pdfLibImport = await loadOptionalDependency("@cantoo/pdf-lib", "Text Embedding");
@@ -1,8 +1,11 @@
1
1
  import type * as pdfLibTypes from "@cantoo/pdf-lib";
2
2
  import { PageOptions } from "../input/pageOptions.js";
3
3
  import { LocalInputSource } from "../input/index.js";
4
+ /** Result of a PDF split/extract operation. */
4
5
  export interface SplitPdf {
6
+ /** PDF content after page extraction. */
5
7
  file: Buffer;
8
+ /** Number of pages removed from the source PDF. */
6
9
  totalPagesRemoved: number;
7
10
  }
8
11
  /**
@@ -4,6 +4,9 @@ import { MindeeError, MindeeInputSourceError } from "../errors/index.js";
4
4
  import { logger } from "../logger.js";
5
5
  import { loadOptionalDependency } from "../dependency/index.js";
6
6
  let pdfLib = null;
7
+ /**
8
+ * Load the PDF library if not already loaded.
9
+ */
7
10
  async function getPdfLib() {
8
11
  if (!pdfLib) {
9
12
  const pdfLibImport = await loadOptionalDependency("@cantoo/pdf-lib", "Text Embedding");
@@ -3,6 +3,11 @@ import * as fs from "node:fs";
3
3
  import { MindeePdfError } from "../errors/index.js";
4
4
  import { loadOptionalDependency } from "../dependency/index.js";
5
5
  import { logger } from "../logger.js";
6
+ /**
7
+ * Concatenate the text from all pages in a PDF document.
8
+ * @param pages The pages to concatenate.
9
+ * @returns The concatenated text.
10
+ */
6
11
  function getConcatenatedText(pages) {
7
12
  return pages.flatMap(page => page.content.map(item => item.str)).join(" ");
8
13
  }
package/src/v1/cli.d.ts CHANGED
@@ -1 +1,4 @@
1
+ /**
2
+ * Add the main CLI action.
3
+ */
1
4
  export declare function cli(): void;
package/src/v1/cli.js CHANGED
@@ -1,18 +1,26 @@
1
- import { Command, Option, } from "commander";
2
- import { Client, } from "./client.js";
3
- import { PageOptionsOperation, PathInput, } from "../input/index.js";
1
+ import { PageOptionsOperation, PathInput } from "../input/index.js";
2
+ import { Command, Option } from "commander";
4
3
  import * as console from "console";
5
- import { CLI_COMMAND_CONFIG, COMMAND_GENERATED, } from "./product/cliProducts.js";
4
+ import { Client } from "./client.js";
5
+ import { CLI_COMMAND_CONFIG, COMMAND_GENERATED } from "./product/cliProducts.js";
6
6
  const program = new Command();
7
7
  //
8
8
  // EXECUTE THE COMMANDS
9
9
  //
10
+ /**
11
+ * Load the client with the given options.
12
+ * @param options Command options.
13
+ */
10
14
  function initClient(options) {
11
15
  return new Client({
12
16
  apiKey: options.apiKey,
13
17
  debug: options.debug,
14
18
  });
15
19
  }
20
+ /**
21
+ * Load the product configuration for the given command.
22
+ * @param command Command name.
23
+ */
16
24
  function getConfig(command) {
17
25
  const conf = CLI_COMMAND_CONFIG.get(command);
18
26
  if (conf === undefined) {
@@ -20,6 +28,10 @@ function getConfig(command) {
20
28
  }
21
29
  return conf;
22
30
  }
31
+ /**
32
+ * Load the page options for the given command.
33
+ * @param options Command options.
34
+ */
23
35
  function getPageOptions(options) {
24
36
  let pageOptions = undefined;
25
37
  if (options.cutPages) {
@@ -31,12 +43,23 @@ function getPageOptions(options) {
31
43
  }
32
44
  return pageOptions;
33
45
  }
46
+ /**
47
+ * Load the prediction parameters for the given command.
48
+ * @param options Command options.
49
+ */
34
50
  function getPredictParams(options) {
35
51
  return {
36
52
  allWords: options.allWords,
37
53
  cropper: options.cropper,
38
54
  };
39
55
  }
56
+ /**
57
+ * Call the parse endpoint for the given command.
58
+ * @param productClass Product class.
59
+ * @param command Command name.
60
+ * @param inputPath Input path.
61
+ * @param options Command options.
62
+ */
40
63
  async function callParse(productClass, command, inputPath, options) {
41
64
  const mindeeClient = initClient(options);
42
65
  const predictParams = getPredictParams(options);
@@ -61,6 +84,13 @@ async function callParse(productClass, command, inputPath, options) {
61
84
  }
62
85
  printResponse(response.document, options);
63
86
  }
87
+ /**
88
+ * Call the enqueue and parse endpoint for the given command.
89
+ * @param productClass Product class.
90
+ * @param command Command name.
91
+ * @param inputPath Input path.
92
+ * @param options Command options.
93
+ */
64
94
  async function callEnqueueAndParse(productClass, command, inputPath, options) {
65
95
  const mindeeClient = initClient(options);
66
96
  const predictParams = getPredictParams(options);
@@ -84,11 +114,22 @@ async function callEnqueueAndParse(productClass, command, inputPath, options) {
84
114
  }
85
115
  printResponse(response.document, options);
86
116
  }
117
+ /**
118
+ * Call the get document endpoint for the given command.
119
+ * @param productClass Product class.
120
+ * @param documentId Document ID.
121
+ * @param options Command options.
122
+ */
87
123
  async function callGetDocument(productClass, documentId, options) {
88
124
  const mindeeClient = initClient(options);
89
125
  const response = await mindeeClient.getDocument(productClass, documentId);
90
126
  printResponse(response.document, options);
91
127
  }
128
+ /**
129
+ * Print the response for the given command.
130
+ * @param document Document.
131
+ * @param options Command options.
132
+ */
92
133
  function printResponse(document, options) {
93
134
  if (options.allWords) {
94
135
  document.ocr?.mVisionV1.pages.forEach((page) => {
@@ -107,9 +148,18 @@ function printResponse(document, options) {
107
148
  //
108
149
  // BUILD THE COMMANDS
109
150
  //
151
+ /**
152
+ * Add the main options to the given command.
153
+ * @param prog Command.
154
+ */
110
155
  function addMainOptions(prog) {
111
156
  prog.option("-k, --api-key <api_key>", "API key for document endpoint");
112
157
  }
158
+ /**
159
+ * Add the post options to the given command.
160
+ * @param prog Command.
161
+ * @param info Product configuration.
162
+ */
113
163
  function addPostOptions(prog, info) {
114
164
  prog.option("-c, --cut-pages", "keep only the first 5 pages of the document");
115
165
  if (info.allWords) {
@@ -117,14 +167,28 @@ function addPostOptions(prog, info) {
117
167
  }
118
168
  prog.argument("<input_path>", "full path to the file");
119
169
  }
170
+ /**
171
+ * Add the custom post options to the given command.
172
+ * @param prog Command.
173
+ */
120
174
  function addCustomPostOptions(prog) {
121
175
  prog.requiredOption("-e, --endpoint <endpoint_name>", "API endpoint name (required)");
122
176
  prog.requiredOption("-a, --account <account_name>", "API account name for the endpoint (required)");
123
177
  prog.option("-v, --version <version>", "version for the endpoint, use the latest version if not specified");
124
178
  }
179
+ /**
180
+ * Add the display options to the given command.
181
+ * @param prog Command.
182
+ */
125
183
  function addDisplayOptions(prog) {
126
184
  prog.option("-p, --pages", "show content of individual pages");
127
185
  }
186
+ /**
187
+ * Route the command to the appropriate action.
188
+ * @param command Command.
189
+ * @param inputPath Input path.
190
+ * @param allOptions All options.
191
+ */
128
192
  function routeSwitchboard(command, inputPath, allOptions) {
129
193
  if (command.parent === null || command.parent === undefined) {
130
194
  throw new Error(`Improperly configured command: ${command.name()}`);
@@ -135,30 +199,24 @@ function routeSwitchboard(command, inputPath, allOptions) {
135
199
  }
136
200
  return callParse(docClass, command.name(), inputPath, allOptions);
137
201
  }
202
+ /**
203
+ * Add the predict action to the given command.
204
+ * @param prog Command.
205
+ */
138
206
  function addPredictAction(prog) {
139
- if (prog.name() === COMMAND_GENERATED) {
140
- prog.action(function (inputPath, options, command) {
141
- const allOptions = {
142
- ...prog.parent?.parent?.opts(),
143
- ...prog.parent?.opts(),
144
- ...prog.opts(),
145
- ...options,
146
- };
147
- return routeSwitchboard(command, inputPath, allOptions);
148
- });
149
- }
150
- else {
151
- prog.action(function (inputPath, options, command) {
152
- const allOptions = {
153
- ...prog.parent?.parent?.opts(),
154
- ...prog.parent?.opts(),
155
- ...prog.opts(),
156
- ...options,
157
- };
158
- return routeSwitchboard(command, inputPath, allOptions);
159
- });
160
- }
207
+ prog.action(function (inputPath, options, command) {
208
+ const allOptions = {
209
+ ...prog.parent?.parent?.opts(),
210
+ ...prog.parent?.opts(),
211
+ ...prog.opts(),
212
+ ...options,
213
+ };
214
+ return routeSwitchboard(command, inputPath, allOptions);
215
+ });
161
216
  }
217
+ /**
218
+ * Add the main CLI action.
219
+ */
162
220
  export function cli() {
163
221
  program.name("mindee")
164
222
  .description("Command line interface for Mindee products.")