Skip to content

Commit 2c38ca5

Browse files
committed
allow parsing by response class
1 parent af5b82f commit 2c38ca5

22 files changed

+433
-408
lines changed

README.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ Finally, Node.js away!
1818
```ts
1919
import { Client, InvoiceResponse } from "mindee";
2020

21-
// Init a new client and configure the Invoice API
22-
const mindeeClient = new Client({apiKey: "my-api-key"}).configInvoice({});
21+
// Init a new client
22+
const mindeeClient = new Client({apiKey: "my-api-key"});
2323

2424
// Load a file from disk and parse it
25-
const pathDoc = mindeeClient.docFromPath("/path/to/the/invoice.pdf");
26-
const invoiceResponse = pathDoc.parse(InvoiceResponse, { docType: "invoice" });
25+
const invoiceResponse = mindeeClient.docFromPath("/path/to/the/invoice.pdf")
26+
.parse(InvoiceResponse);
2727

2828
// Print a brief summary of the parsed data
2929
invoiceResponse.then((resp) => {
@@ -36,10 +36,11 @@ invoiceResponse.then((resp) => {
3636
```ts
3737
import { Client, CustomResponse } from "mindee";
3838

39-
// Init a new client and configure your custom document
40-
const mindeeClient = new Client({apiKey: "my-api-key"}).configCustomDoc({
41-
accountName: "john",
42-
documentType: "wsnine",
39+
// Init a new client and add your document endpoint
40+
const mindeeClient = new Client({apiKey: "my-api-key"})
41+
.addEndpoint({
42+
accountName: "john",
43+
documentType: "wsnine",
4344
});
4445

4546
// Load a file from disk and parse it

src/api/endpoint.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const USER_AGENT = `mindee-api-nodejs@v${sdkVersion} nodejs-${
1313
process.version
1414
} ${os.type().toLowerCase()}`;
1515

16-
export const OTS_OWNER = "mindee";
16+
export const STANDARD_API_OWNER = "mindee";
1717
export const API_KEY_ENVVAR_NAME = "MINDEE_API_KEY";
1818

1919
export class Endpoint {
@@ -129,19 +129,19 @@ export class Endpoint {
129129

130130
export class InvoiceEndpoint extends Endpoint {
131131
constructor(apiKey: string) {
132-
super(OTS_OWNER, "invoices", "3", apiKey, "invoice");
132+
super(STANDARD_API_OWNER, "invoices", "3", apiKey, "invoice");
133133
}
134134
}
135135

136136
export class ReceiptEndpoint extends Endpoint {
137137
constructor(apiKey: string) {
138-
super(OTS_OWNER, "expense_receipts", "3", apiKey, "receipt");
138+
super(STANDARD_API_OWNER, "expense_receipts", "3", apiKey, "receipt");
139139
}
140140
}
141141

142142
export class PassportEndpoint extends Endpoint {
143143
constructor(apiKey: string) {
144-
super(OTS_OWNER, "passport", "1", apiKey);
144+
super(STANDARD_API_OWNER, "passport", "1", apiKey);
145145
}
146146
}
147147

src/api/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ export {
22
Response,
33
InvoiceResponse,
44
ReceiptResponse,
5-
FinancialResponse,
5+
FinancialDocResponse,
66
PassportResponse,
77
CustomResponse,
88
} from "./response";
@@ -12,6 +12,6 @@ export {
1212
ReceiptEndpoint,
1313
PassportEndpoint,
1414
CustomEndpoint,
15-
OTS_OWNER,
15+
STANDARD_API_OWNER,
1616
API_KEY_ENVVAR_NAME,
1717
} from "./endpoint";

src/api/response.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export class Response<DocType extends Document> {
4949
}
5050

5151
/**
52-
* Class for all custom endpoint responses.
52+
* Class for all constructed (API Builder) endpoint responses.
5353
*/
5454
export class CustomResponse extends Response<CustomDocument> {
5555
constructor(params: ResponseProps) {
@@ -79,7 +79,7 @@ export class CustomResponse extends Response<CustomDocument> {
7979
}
8080
}
8181

82-
type OtsDocumentSig<DocType extends Document> = {
82+
type StandardDocumentSig<DocType extends Document> = {
8383
new ({
8484
apiPrediction,
8585
inputFile,
@@ -89,12 +89,17 @@ type OtsDocumentSig<DocType extends Document> = {
8989
};
9090

9191
/**
92-
* Generic class for all OTS endpoint responses.
92+
* Generic class for all standard (Off-the-Shelf) endpoint responses.
9393
*/
94-
export class OtsResponse<DocType extends Document> extends Response<DocType> {
95-
documentClass: OtsDocumentSig<DocType>;
94+
export class StandardProductResponse<
95+
DocType extends Document
96+
> extends Response<DocType> {
97+
documentClass: StandardDocumentSig<DocType>;
9698

97-
constructor(documentClass: OtsDocumentSig<DocType>, params: ResponseProps) {
99+
constructor(
100+
documentClass: StandardDocumentSig<DocType>,
101+
params: ResponseProps
102+
) {
98103
super(params);
99104
this.documentClass = documentClass;
100105
if (!params.error) {
@@ -122,25 +127,25 @@ export class OtsResponse<DocType extends Document> extends Response<DocType> {
122127
}
123128
}
124129

125-
export class InvoiceResponse extends OtsResponse<Invoice> {
130+
export class InvoiceResponse extends StandardProductResponse<Invoice> {
126131
constructor(params: ResponseProps) {
127132
super(Invoice, params);
128133
}
129134
}
130135

131-
export class ReceiptResponse extends OtsResponse<Receipt> {
136+
export class ReceiptResponse extends StandardProductResponse<Receipt> {
132137
constructor(params: ResponseProps) {
133138
super(Receipt, params);
134139
}
135140
}
136141

137-
export class FinancialResponse extends OtsResponse<FinancialDocument> {
142+
export class FinancialDocResponse extends StandardProductResponse<FinancialDocument> {
138143
constructor(params: ResponseProps) {
139144
super(FinancialDocument, params);
140145
}
141146
}
142147

143-
export class PassportResponse extends OtsResponse<Passport> {
148+
export class PassportResponse extends StandardProductResponse<Passport> {
144149
constructor(params: ResponseProps) {
145150
super(Passport, params);
146151
}

src/cli.ts

Lines changed: 57 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,137 +1,98 @@
11
import { Command } from "commander";
2-
import { Client } from "./index";
32
import {
43
DOC_TYPE_INVOICE,
54
DOC_TYPE_RECEIPT,
65
DOC_TYPE_PASSPORT,
76
DOC_TYPE_FINANCIAL,
8-
Document,
7+
DOC_TYPE_CUSTOM,
98
} from "./documents";
109
import {
11-
Response,
12-
FinancialResponse,
10+
CustomResponse,
11+
FinancialDocResponse,
1312
InvoiceResponse,
1413
PassportResponse,
1514
ReceiptResponse,
16-
CustomResponse,
15+
STANDARD_API_OWNER,
1716
} from "./api";
17+
import { Client } from "./client";
18+
import { ProductConfigs, ProductConfig } from "./constants";
1819

1920
const program = new Command();
2021

21-
interface OtsCliConfig {
22-
help: string;
23-
docType: string;
24-
responseClass: typeof Response<Document>;
25-
fullText: boolean;
26-
}
27-
2822
const COMMAND_INVOICE = "invoice";
2923
const COMMAND_RECEIPT = "receipt";
3024
const COMMAND_PASSPORT = "passport";
3125
const COMMAND_FINANCIAL = "financial";
3226
const COMMAND_CUSTOM = "custom";
3327

34-
const OTS_DOCUMENTS = new Map<string, OtsCliConfig>([
35-
[
36-
COMMAND_INVOICE,
37-
{
38-
help: "Invoice",
39-
docType: DOC_TYPE_INVOICE,
40-
responseClass: InvoiceResponse,
41-
fullText: true,
42-
},
43-
],
44-
[
45-
COMMAND_RECEIPT,
46-
{
47-
help: "Expense Receipt",
48-
docType: DOC_TYPE_RECEIPT,
49-
responseClass: ReceiptResponse,
50-
fullText: true,
51-
},
52-
],
53-
[
54-
COMMAND_PASSPORT,
55-
{
56-
help: "Passport",
57-
docType: DOC_TYPE_PASSPORT,
58-
responseClass: PassportResponse,
59-
fullText: false,
60-
},
61-
],
62-
[
63-
COMMAND_FINANCIAL,
64-
{
65-
help: "Financial Document (receipt or invoice)",
66-
docType: DOC_TYPE_FINANCIAL,
67-
responseClass: FinancialResponse,
68-
fullText: true,
69-
},
70-
],
71-
[
72-
COMMAND_CUSTOM,
73-
{
74-
help: "A custom document",
75-
docType: "",
76-
responseClass: CustomResponse,
77-
fullText: false,
78-
},
79-
],
28+
const CLI_COMMAND_CONFIG = new Map<string, ProductConfig>([
29+
[COMMAND_INVOICE, ProductConfigs.getByDocType(DOC_TYPE_INVOICE)],
30+
[COMMAND_RECEIPT, ProductConfigs.getByDocType(DOC_TYPE_RECEIPT)],
31+
[COMMAND_PASSPORT, ProductConfigs.getByDocType(DOC_TYPE_PASSPORT)],
32+
[COMMAND_FINANCIAL, ProductConfigs.getByDocType(DOC_TYPE_FINANCIAL)],
33+
[COMMAND_CUSTOM, ProductConfigs.getByDocType(DOC_TYPE_CUSTOM)],
8034
]);
8135

8236
async function predictCall(command: string, inputPath: string, options: any) {
83-
const info = OTS_DOCUMENTS.get(command);
84-
if (!info) {
37+
const conf = CLI_COMMAND_CONFIG.get(command);
38+
if (conf === undefined) {
8539
throw new Error(`Invalid document type ${command}`);
8640
}
8741
const mindeeClient = new Client({
8842
apiKey: options.apiKey,
89-
debug: options.verbose,
43+
debug: options.debug,
9044
});
45+
if (command === COMMAND_CUSTOM) {
46+
mindeeClient.addEndpoint({
47+
accountName: options.user,
48+
documentType: options.documentType,
49+
});
50+
}
51+
const doc = mindeeClient.docFromPath(inputPath);
52+
const params = {
53+
docType: command === COMMAND_CUSTOM ? options.documentType : conf.docType,
54+
username: command === COMMAND_CUSTOM ? options.user : STANDARD_API_OWNER,
55+
cutPages: options.cutPages,
56+
fullText: options.fullText,
57+
};
58+
// Tried setting the response by using the responseClass property in constants.PRODUCTS_CONFIG
59+
// This compiled, but threw an exception:
60+
// TypeError: responseType is not a constructor
61+
//
62+
// So using a switch to explicitly set the response class parameter. Ugly, but works.
63+
// Improvements welcome!
64+
let response;
9165
switch (command) {
92-
case COMMAND_INVOICE: {
93-
mindeeClient.configInvoice();
66+
case COMMAND_INVOICE:
67+
response = await doc.parse(InvoiceResponse, params);
9468
break;
95-
}
96-
case COMMAND_RECEIPT: {
97-
mindeeClient.configReceipt();
69+
case COMMAND_RECEIPT:
70+
response = await doc.parse(ReceiptResponse, params);
9871
break;
99-
}
100-
case COMMAND_PASSPORT: {
101-
mindeeClient.configPassport();
72+
case COMMAND_FINANCIAL:
73+
response = await doc.parse(FinancialDocResponse, params);
10274
break;
103-
}
104-
case COMMAND_FINANCIAL: {
105-
mindeeClient.configFinancialDoc();
75+
case COMMAND_PASSPORT:
76+
response = await doc.parse(PassportResponse, params);
10677
break;
107-
}
108-
case COMMAND_CUSTOM: {
109-
mindeeClient.addEndpoint({
110-
accountName: options.user,
111-
endpointName: options.documentType,
112-
});
78+
case COMMAND_CUSTOM:
79+
response = await doc.parse(CustomResponse, params);
11380
break;
114-
}
81+
default:
82+
throw `Unhandled command: ${command}`;
11583
}
116-
const doc = mindeeClient.docFromPath(inputPath);
117-
const result = await doc.parse(info.responseClass, {
118-
docType: info.docType || options.documentType,
119-
username: options.user || "mindee",
120-
cutPages: options.cutPages,
121-
fullText: options.fullText,
122-
});
123-
if (result.document) {
124-
console.log(`\n${result.document}`);
84+
if (response.document) {
85+
console.log(`\n${response.document}`);
12586
}
12687
}
12788

12889
export function cli() {
12990
program.name("mindee");
130-
program.option("-v, --verbose", "high verbosity mode");
91+
program.option("-d, --debug", "high verbosity mode");
13192

132-
OTS_DOCUMENTS.forEach((info, name) => {
93+
CLI_COMMAND_CONFIG.forEach((info, name) => {
13394
const prog = program.command(name);
134-
prog.description(info.help);
95+
prog.description(info.description);
13596

13697
prog.option("-k, --api-key <api_key>", "API key for document endpoint");
13798
prog.option("-C, --no-cut-pages", "Don't cut document pages");
@@ -143,6 +104,10 @@ export function cli() {
143104
"-u, --user <username>",
144105
"API account name for the endpoint"
145106
);
107+
prog.option(
108+
"-v, --version <version>",
109+
"API account name for the endpoint"
110+
);
146111
prog.argument("<endpoint_name>", "API endpoint name");
147112
}
148113
prog.argument("<input_path>", "Full path to the file");
@@ -157,7 +122,7 @@ export function cli() {
157122
const allOptions = {
158123
...program.opts(),
159124
...options,
160-
endpointName: endpointName,
125+
documentType: endpointName,
161126
};
162127
predictCall(command.name(), inputPath, allOptions);
163128
}

0 commit comments

Comments
 (0)