diff --git a/packages/nodes-base/credentials/ERPNextApi.credentials.ts b/packages/nodes-base/credentials/ERPNextApi.credentials.ts index d94210600e..1ad997f74c 100644 --- a/packages/nodes-base/credentials/ERPNextApi.credentials.ts +++ b/packages/nodes-base/credentials/ERPNextApi.credentials.ts @@ -20,13 +20,51 @@ export class ERPNextApi implements ICredentialType { type: 'string' as NodePropertyTypes, default: '', }, + { + displayName: 'Environment', + name: 'environment', + type: 'options' as NodePropertyTypes, + default: 'cloudHosted', + options: [ + { + name: 'Cloud-hosted', + value: 'cloudHosted', + }, + { + name: 'Self-hosted', + value: 'selfHosted', + }, + ], + }, { displayName: 'Subdomain', name: 'subdomain', type: 'string' as NodePropertyTypes, default: '', placeholder: 'n8n', - description: 'ERPNext subdomain. For instance, entering n8n will make the url look like: https://n8n.erpnext.com/.', + description: 'Subdomain of cloud-hosted ERPNext instance. For example, "n8n" is the subdomain in: https://n8n.erpnext.com', + displayOptions: { + show: { + environment: [ + 'cloudHosted', + ], + }, + }, + }, + { + displayName: 'Domain', + name: 'domain', + type: 'string' as NodePropertyTypes, + default: '', + placeholder: 'https://www.mydomain.com', + description: 'Fully qualified domain name of self-hosted ERPNext instance.', + displayOptions: { + show: { + environment: [ + 'selfHosted', + ], + }, + }, }, ]; } diff --git a/packages/nodes-base/nodes/ERPNext/GenericFunctions.ts b/packages/nodes-base/nodes/ERPNext/GenericFunctions.ts index 08de44e8e0..4a85c0064a 100644 --- a/packages/nodes-base/nodes/ERPNext/GenericFunctions.ts +++ b/packages/nodes-base/nodes/ERPNext/GenericFunctions.ts @@ -24,8 +24,8 @@ export async function erpNextApiRequest( uri?: string, option: IDataObject = {}, ) { - - const credentials = this.getCredentials('erpNextApi'); + const credentials = this.getCredentials('erpNextApi') as ERPNextApiCredentials; + const baseUrl = getBaseUrl(credentials); if (credentials === undefined) { throw new NodeOperationError(this.getNode(), 'No credentials got returned!'); @@ -40,7 +40,7 @@ export async function erpNextApiRequest( method, body, qs: query, - uri: uri || `https://${credentials.subdomain}.erpnext.com${resource}`, + uri: uri || `${baseUrl}${resource}`, json: true, }; @@ -56,13 +56,12 @@ export async function erpNextApiRequest( try { return await this.helpers.request!(options); } catch (error) { - if (error.statusCode === 403) { - throw new NodeApiError(this.getNode(), { message: `DocType unavailable.` }); + throw new NodeApiError(this.getNode(), { message: 'DocType unavailable.' }); } if (error.statusCode === 307) { - throw new NodeApiError(this.getNode(), { message:`Please ensure the subdomain is correct.` }); + throw new NodeApiError(this.getNode(), { message: 'Please ensure the subdomain is correct.' }); } throw new NodeApiError(this.getNode(), error); @@ -95,3 +94,19 @@ export async function erpNextApiRequestAllItems( return returnData; } + +/** + * Return the base API URL based on the user's environment. + */ +const getBaseUrl = ({ environment, domain, subdomain }: ERPNextApiCredentials) => + environment === 'cloudHosted' + ? `https://${subdomain}.erpnext.com` + : domain; + +type ERPNextApiCredentials = { + apiKey: string; + apiSecret: string; + environment: 'cloudHosted' | 'selfHosted'; + subdomain?: string; + domain?: string; +};