n8n/packages/nodes-base/nodes/Zoho/GenericFunctions.ts
2021-05-07 10:58:12 +02:00

168 lines
4.7 KiB
TypeScript

import {
IExecuteFunctions,
IHookFunctions,
} from 'n8n-core';
import {
IDataObject,
NodeApiError,
} from 'n8n-workflow';
import {
OptionsWithUri,
} from 'request';
import {
flow,
} from 'lodash';
export async function zohoApiRequest(
this: IExecuteFunctions | IHookFunctions,
method: string,
endpoint: string,
body: IDataObject = {},
qs: IDataObject = {},
uri?: string,
) {
const operation = this.getNodeParameter('operation', 0) as string;
const { oauthTokenData: { api_domain: apiDomain } } = this.getCredentials('zohoOAuth2Api') as { oauthTokenData: { api_domain: string} };
const options: OptionsWithUri = {
body: {
data: [
body,
],
},
method,
qs,
uri: uri ?? `${apiDomain}/crm/v2${endpoint}`,
json: true,
};
if (!Object.keys(body).length) {
delete options.body;
}
if (!Object.keys(qs).length) {
delete options.qs;
}
try {
console.log(JSON.stringify(options, null, 2));
const responseData = await this.helpers.requestOAuth2.call(this, 'zohoOAuth2Api', options);
return operation === 'getAll' ? responseData : responseData.data;
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
}
/**
* Make an authenticated API request to Zoho CRM API and return all items.
*/
export async function zohoApiRequestAllItems(
this: IHookFunctions | IExecuteFunctions,
method: string,
endpoint: string,
body: IDataObject,
qs: IDataObject,
) {
const returnData: IDataObject[] = [];
let responseData;
let uri: string | undefined;
qs.per_page = 200;
qs.page = 0;
do {
responseData = await zohoApiRequest.call(this, method, endpoint, body, qs, uri);
uri = responseData.info.more_records;
returnData.push.apply(returnData, responseData['data']);
qs.page++;
} while (
responseData.info.more_records !== undefined &&
responseData.info.more_records === true
);
return returnData;
}
/**
* Handle a Zoho CRM API listing by returning all items or up to a limit.
*/
export async function handleListing(
this: IExecuteFunctions,
method: string,
endpoint: string,
body: IDataObject = {},
qs: IDataObject = {},
) {
let responseData;
const returnAll = this.getNodeParameter('returnAll', 0);
if (returnAll) {
return await zohoApiRequestAllItems.call(this, method, endpoint, body, qs);
}
const limit = this.getNodeParameter('limit', 0) as number;
responseData = await zohoApiRequestAllItems.call(this, method, endpoint, body, qs);
return responseData.slice(0, limit);
}
// ----------------------------------------
// field adjusters
// ----------------------------------------
/**
* Place a location field's contents at the top level of the payload.
*/
const adjustLocationFields = (locationType: LocationType) => (allFields: IDataObject) => {
const locationField = allFields[locationType];
if (!locationField || !hasAddressFields(locationField)) return allFields;
return { ...omit(locationType, allFields), ...locationField.address_fields };
};
const adjustAddressFields = adjustLocationFields('Address');
const adjustBillingAddressFields = adjustLocationFields('Billing_Address');
const adjustMailingAddressFields = adjustLocationFields('Mailing_Address');
const adjustShippingAddressFields = adjustLocationFields('Shipping_Address');
const adjustOtherAddressFields = adjustLocationFields('Other_Address');
const adjustDateOfBirth = (allFields: { Date_of_Birth: string }) => {
if (!allFields.Date_of_Birth) return allFields;
allFields.Date_of_Birth = allFields.Date_of_Birth.split('T')[0];
return allFields;
};
export const adjustAccountFields = flow(adjustBillingAddressFields, adjustShippingAddressFields);
export const adjustContactFields = flow(adjustMailingAddressFields, adjustOtherAddressFields, adjustDateOfBirth);
export const adjustInvoiceFields = flow(adjustBillingAddressFields, adjustShippingAddressFields); // TODO: product details
export const adjustLeadFields = adjustAddressFields;
export const adjustPurchaseOrderFields = adjustInvoiceFields;
export const adjustQuoteFields = adjustInvoiceFields;
export const adjustSalesOrderFields = adjustInvoiceFields;
// ----------------------------------------
// helpers
// ----------------------------------------
export const omit = (keyToOmit: string, { [keyToOmit]: _, ...omittedPropObj }) => omittedPropObj;
function hasAddressFields(locationField: unknown): locationField is LocationField {
if (typeof locationField !== 'object' || locationField === null) return false;
return locationField.hasOwnProperty('address_fields');
}
// ----------------------------------------
// types
// ----------------------------------------
type LocationType = 'Address' | 'Billing_Address' | 'Mailing_Address' | 'Shipping_Address' | 'Other_Address';
type LocationField = {
address_fields: { [key in LocationType]: string };
};