mirror of
https://github.com/n8n-io/n8n.git
synced 2024-09-19 22:37:31 -07:00
feat(Mindee Node): Add support for new version (#3596)
* Added versioning, with new credentials * Fix lint issue * 🔥 Remove old import name * Change function name * 🎨 Simplify name of versions within the node mindee * 🎨 Change version type from string to number * 🔥 Removed Mindee from getting ignored by prettier * 🎨 Ran prettier on Mindee folder * 🔥 Removed unused import * 🎨 Moved exceptions that were not working anymore Co-authored-by: Omar Ajoue <krynble@gmail.com>
This commit is contained in:
parent
6cb9aefb0b
commit
1965407030
|
@ -140,7 +140,6 @@ packages/nodes-base/nodes/Medium
|
|||
packages/nodes-base/nodes/Merge
|
||||
packages/nodes-base/nodes/MessageBird
|
||||
packages/nodes-base/nodes/Microsoft
|
||||
packages/nodes-base/nodes/Mindee
|
||||
packages/nodes-base/nodes/Misp
|
||||
packages/nodes-base/nodes/Mocean
|
||||
packages/nodes-base/nodes/MondayCom
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import {
|
||||
ICredentialDataDecryptedObject,
|
||||
ICredentialType,
|
||||
IHttpRequestOptions,
|
||||
INodeProperties,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
|
@ -15,4 +17,14 @@ export class MindeeInvoiceApi implements ICredentialType {
|
|||
default: '',
|
||||
},
|
||||
];
|
||||
async authenticate(credentials: ICredentialDataDecryptedObject, requestOptions: IHttpRequestOptions): Promise<IHttpRequestOptions> {
|
||||
// @ts-ignore
|
||||
const url = requestOptions.url ? requestOptions.url : requestOptions.uri;
|
||||
if(url.includes('https://api.mindee.net/v1/')) {
|
||||
requestOptions.headers!['Authorization'] = `Token ${credentials.apiKey}`;
|
||||
} else {
|
||||
requestOptions.headers!['X-Inferuser-Token'] = `${credentials.apiKey}`;
|
||||
}
|
||||
return requestOptions;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import {
|
||||
ICredentialDataDecryptedObject,
|
||||
ICredentialType,
|
||||
IHttpRequestOptions,
|
||||
INodeProperties,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
|
@ -15,4 +17,14 @@ export class MindeeReceiptApi implements ICredentialType {
|
|||
default: '',
|
||||
},
|
||||
];
|
||||
async authenticate(credentials: ICredentialDataDecryptedObject, requestOptions: IHttpRequestOptions): Promise<IHttpRequestOptions> {
|
||||
// @ts-ignore
|
||||
const url = requestOptions.url ? requestOptions.url : requestOptions.uri;
|
||||
if(url.includes('https://api.mindee.net/v1/')) {
|
||||
requestOptions.headers!['Authorization'] = `Token ${credentials.apiKey}`;
|
||||
} else {
|
||||
requestOptions.headers!['X-Inferuser-Token'] = `${credentials.apiKey}`;
|
||||
}
|
||||
return requestOptions;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,37 +1,42 @@
|
|||
import {
|
||||
OptionsWithUri,
|
||||
} from 'request';
|
||||
import { OptionsWithUri } from 'request';
|
||||
|
||||
import {
|
||||
IExecuteFunctions,
|
||||
IExecuteSingleFunctions,
|
||||
ILoadOptionsFunctions,
|
||||
} from 'n8n-core';
|
||||
import { IExecuteFunctions, IExecuteSingleFunctions, ILoadOptionsFunctions } from 'n8n-core';
|
||||
|
||||
import {
|
||||
IDataObject, NodeApiError,
|
||||
} from 'n8n-workflow';
|
||||
import { IDataObject, NodeApiError } from 'n8n-workflow';
|
||||
|
||||
export async function mindeeApiRequest(
|
||||
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions,
|
||||
method: string,
|
||||
path: string,
|
||||
body: any = {}, // tslint:disable-line:no-any
|
||||
qs: IDataObject = {},
|
||||
option = {},
|
||||
): Promise<any> {// tslint:disable-line:no-any
|
||||
|
||||
export async function mindeeApiRequest(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, path: string, body: any = {}, qs: IDataObject = {}, option = {}): Promise<any> { // tslint:disable-line:no-any
|
||||
|
||||
const resource = this.getNodeParameter('resource', 0) as string;
|
||||
|
||||
let credentials;
|
||||
let service;
|
||||
|
||||
if (resource === 'receipt') {
|
||||
credentials = await this.getCredentials('mindeeReceiptApi');
|
||||
service = 'mindeeReceiptApi';
|
||||
} else {
|
||||
credentials = await this.getCredentials('mindeeInvoiceApi');
|
||||
service = 'mindeeInvoiceApi';
|
||||
}
|
||||
|
||||
const version = this.getNodeParameter('apiVersion', 0) as number;
|
||||
// V1 of mindee is deprecated, we are keeping it for now but now V3 is active
|
||||
const url =
|
||||
version === 1
|
||||
? `https://api.mindee.net/products${path}`
|
||||
: `https://api.mindee.net/v1/products/mindee${path}`;
|
||||
|
||||
const options: OptionsWithUri = {
|
||||
headers: {
|
||||
'X-Inferuser-Token': credentials.apiKey,
|
||||
},
|
||||
headers: {},
|
||||
method,
|
||||
body,
|
||||
qs,
|
||||
uri: `https://api.mindee.net/products${path}`,
|
||||
uri: url,
|
||||
json: true,
|
||||
};
|
||||
try {
|
||||
|
@ -44,19 +49,17 @@ export async function mindeeApiRequest(this: IExecuteFunctions | IExecuteSingleF
|
|||
if (Object.keys(option).length !== 0) {
|
||||
Object.assign(options, option);
|
||||
}
|
||||
//@ts-ignore
|
||||
return await this.helpers.request.call(this, options);
|
||||
|
||||
return await this.helpers.requestWithAuthentication.call(this, service, options);
|
||||
} catch (error) {
|
||||
throw new NodeApiError(this.getNode(), error);
|
||||
}
|
||||
}
|
||||
|
||||
export function cleanData(predictions: IDataObject[]) {
|
||||
|
||||
export function cleanDataPreviousApiVersions(predictions: IDataObject[]) {
|
||||
const newData: IDataObject = {};
|
||||
|
||||
for (const key of Object.keys(predictions[0])) {
|
||||
|
||||
const data = predictions[0][key] as IDataObject | IDataObject[];
|
||||
|
||||
if (key === 'taxes' && data.length) {
|
||||
|
@ -65,13 +68,46 @@ export function cleanData(predictions: IDataObject[]) {
|
|||
rate: (data as IDataObject[])[0].rate,
|
||||
};
|
||||
} else if (key === 'locale') {
|
||||
//@ts-ignore
|
||||
newData['currency'] = data.currency;
|
||||
//@ts-ignore
|
||||
newData['locale'] = data.value;
|
||||
} else {
|
||||
//@ts-ignore
|
||||
newData[key] = data.value || data.name || data.raw || data.degrees || data.amount || data.iban;
|
||||
newData['currency'] = data.currency;
|
||||
//@ts-ignore
|
||||
newData['locale'] = data.value;
|
||||
} else {
|
||||
|
||||
newData[key] =
|
||||
//@ts-ignore
|
||||
data.value || data.name || data.raw || data.degrees || data.amount || data.iban;
|
||||
}
|
||||
}
|
||||
|
||||
return newData;
|
||||
}
|
||||
|
||||
export function cleanData(document: IDataObject) {
|
||||
// @ts-ignore
|
||||
const prediction = document.inference.prediction as IDataObject;
|
||||
const newData: IDataObject = {};
|
||||
newData['id'] = document.id;
|
||||
newData['name'] = document.name;
|
||||
newData['number_of_pages'] = document.n_pages;
|
||||
for (const key of Object.keys(prediction)) {
|
||||
const data = prediction[key] as IDataObject | IDataObject[];
|
||||
|
||||
if (key === 'taxes' && data.length) {
|
||||
newData[key] = {
|
||||
amount: (data as IDataObject[])[0].amount,
|
||||
rate: (data as IDataObject[])[0].rate,
|
||||
};
|
||||
} else if (key === 'locale') {
|
||||
//@ts-ignore
|
||||
newData['currency'] = data.currency;
|
||||
//@ts-ignore
|
||||
newData['locale'] = data.value;
|
||||
} else {
|
||||
|
||||
newData[key] =
|
||||
//@ts-ignore
|
||||
data.value || data.name || data.raw || data.degrees || data.amount || data.iban;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
"node": "n8n-nodes-base.mindee",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": [
|
||||
"Utility"
|
||||
],
|
||||
"categories": ["Utility"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
|
@ -29,4 +27,4 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import {
|
||||
IExecuteFunctions,
|
||||
} from 'n8n-core';
|
||||
import { IExecuteFunctions } from 'n8n-core';
|
||||
|
||||
import {
|
||||
IBinaryData,
|
||||
|
@ -12,10 +10,7 @@ import {
|
|||
NodeOperationError,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import {
|
||||
cleanData,
|
||||
mindeeApiRequest,
|
||||
} from './GenericFunctions';
|
||||
import { cleanData, cleanDataPreviousApiVersions, mindeeApiRequest } from './GenericFunctions';
|
||||
|
||||
export class Mindee implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
|
@ -23,7 +18,7 @@ export class Mindee implements INodeType {
|
|||
name: 'mindee',
|
||||
icon: 'file:mindee.svg',
|
||||
group: ['input'],
|
||||
version: 1,
|
||||
version: [1, 2],
|
||||
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||
description: 'Consume Mindee API',
|
||||
defaults: {
|
||||
|
@ -37,9 +32,7 @@ export class Mindee implements INodeType {
|
|||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'receipt',
|
||||
],
|
||||
resource: ['receipt'],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -48,14 +41,58 @@ export class Mindee implements INodeType {
|
|||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'invoice',
|
||||
],
|
||||
resource: ['invoice'],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
properties: [
|
||||
{
|
||||
displayName: 'API Version',
|
||||
name: 'apiVersion',
|
||||
type: 'options',
|
||||
isNodeSetting: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
'@version': [1],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: '1',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
name: '3',
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
default: 1,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'API Version',
|
||||
name: 'apiVersion',
|
||||
type: 'options',
|
||||
isNodeSetting: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
'@version': [2],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: '1',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
name: '3',
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
default: 3,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Resource',
|
||||
name: 'resource',
|
||||
|
@ -94,16 +131,12 @@ export class Mindee implements INodeType {
|
|||
default: 'data',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: [
|
||||
'predict',
|
||||
],
|
||||
resource: [
|
||||
'receipt',
|
||||
'invoice',
|
||||
],
|
||||
operation: ['predict'],
|
||||
resource: ['receipt', 'invoice'],
|
||||
},
|
||||
},
|
||||
description: 'Name of the binary property which containsthe data for the file to be uploaded',
|
||||
description:
|
||||
'Name of the binary property which containsthe data for the file to be uploaded',
|
||||
},
|
||||
{
|
||||
displayName: 'RAW Data',
|
||||
|
@ -121,8 +154,10 @@ export class Mindee implements INodeType {
|
|||
const length = items.length;
|
||||
const qs: IDataObject = {};
|
||||
let responseData;
|
||||
const version = this.getNodeParameter('apiVersion', 0) as number;
|
||||
const resource = this.getNodeParameter('resource', 0) as string;
|
||||
const operation = this.getNodeParameter('operation', 0) as string;
|
||||
let endpoint;
|
||||
for (let i = 0; i < length; i++) {
|
||||
try {
|
||||
if (resource === 'receipt') {
|
||||
|
@ -141,29 +176,55 @@ export class Mindee implements INodeType {
|
|||
const dataBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
||||
|
||||
if (binaryData === undefined) {
|
||||
throw new NodeOperationError(this.getNode(), `No binary data property "${binaryPropertyName}" does not exists on item!`, { itemIndex: i });
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
`No binary data property "${binaryPropertyName}" does not exists on item!`,
|
||||
);
|
||||
}
|
||||
|
||||
responseData = await mindeeApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
`/expense_receipts/v2/predict`,
|
||||
{},
|
||||
{},
|
||||
{
|
||||
formData: {
|
||||
file: {
|
||||
value: dataBuffer,
|
||||
options: {
|
||||
filename: binaryData.fileName,
|
||||
if (version === 1) {
|
||||
responseData = await mindeeApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
`/expense_receipts/v2/predict`,
|
||||
{},
|
||||
{},
|
||||
{
|
||||
formData: {
|
||||
file: {
|
||||
value: dataBuffer,
|
||||
options: {
|
||||
filename: binaryData.fileName,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
);
|
||||
} else if (version === 3) {
|
||||
endpoint = '/expense_receipts/v3/predict';
|
||||
responseData = await mindeeApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
endpoint,
|
||||
{},
|
||||
{},
|
||||
{
|
||||
formData: {
|
||||
document: {
|
||||
value: dataBuffer,
|
||||
options: {
|
||||
filename: binaryData.fileName,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
if (rawData === false) {
|
||||
responseData = cleanData(responseData.predictions);
|
||||
if (version === 1) {
|
||||
responseData = cleanDataPreviousApiVersions(responseData.predictions);
|
||||
} else if (version === 3) {
|
||||
responseData = cleanData(responseData.document);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -184,29 +245,58 @@ export class Mindee implements INodeType {
|
|||
const dataBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
||||
|
||||
if (binaryData === undefined) {
|
||||
throw new NodeOperationError(this.getNode(), `No binary data property "${binaryPropertyName}" does not exists on item!`, { itemIndex: i });
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
`No binary data property "${binaryPropertyName}" does not exists on item!`,
|
||||
);
|
||||
}
|
||||
|
||||
responseData = await mindeeApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
`/invoices/v1/predict`,
|
||||
{},
|
||||
{},
|
||||
{
|
||||
formData: {
|
||||
file: {
|
||||
value: dataBuffer,
|
||||
options: {
|
||||
filename: binaryData.fileName,
|
||||
if (version === 1) {
|
||||
endpoint = '/invoices/v1/predict';
|
||||
responseData = await mindeeApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
endpoint,
|
||||
{},
|
||||
{},
|
||||
{
|
||||
formData: {
|
||||
file: {
|
||||
value: dataBuffer,
|
||||
options: {
|
||||
filename: binaryData.fileName,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
);
|
||||
} else if (version === 3) {
|
||||
endpoint = '/invoices/v3/predict';
|
||||
responseData = await mindeeApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
endpoint,
|
||||
{},
|
||||
{},
|
||||
{
|
||||
formData: {
|
||||
document: {
|
||||
value: dataBuffer,
|
||||
options: {
|
||||
filename: binaryData.fileName,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
} else {
|
||||
throw new NodeOperationError(this.getNode(), 'Invalid API version');
|
||||
}
|
||||
if (rawData === false) {
|
||||
responseData = cleanData(responseData.predictions);
|
||||
if (version === 1) {
|
||||
responseData = cleanDataPreviousApiVersions(responseData.predictions);
|
||||
} else if (version === 3) {
|
||||
responseData = cleanData(responseData.document);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue