From 2eaeb4f4c29b53f46b98987cb1d51a82c5927910 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Mon, 10 Feb 2020 15:55:28 -0500 Subject: [PATCH] :sparkles: salesforce node --- .../SalesforceOAuth2Api.credentials.ts | 40 + .../nodes/Salesforce/AccountDescription.ts | 700 ++++++ .../nodes/Salesforce/AccountInterface.ts | 26 + .../nodes/Salesforce/AttachmentDescription.ts | 347 +++ .../nodes/Salesforce/AttachmentInterface.ts | 10 + .../Salesforce/CampaignMemberInterface.ts | 7 + .../nodes/Salesforce/CaseDescription.ts | 563 +++++ .../nodes/Salesforce/CaseInterface.ts | 25 + .../nodes/Salesforce/ContactDescription.ts | 835 ++++++++ .../nodes/Salesforce/ContactInterface.ts | 34 + .../nodes/Salesforce/GenericFunctions.ts | 50 + .../nodes/Salesforce/LeadDescription.ts | 762 +++++++ .../nodes/Salesforce/LeadInterface.ts | 26 + .../nodes/Salesforce/NoteInterface.ts | 8 + .../Salesforce/OpportunityDescription.ts | 625 ++++++ .../nodes/Salesforce/OpportunityInterface.ts | 17 + .../nodes/Salesforce/Salesforce.node.ts | 1893 +++++++++++++++++ .../nodes/Salesforce/TaskDescription.ts | 810 +++++++ .../nodes/Salesforce/TaskInterface.ts | 27 + .../nodes/Salesforce/salesforce.png | Bin 0 -> 3210 bytes packages/nodes-base/package.json | 2 + 21 files changed, 6807 insertions(+) create mode 100644 packages/nodes-base/credentials/SalesforceOAuth2Api.credentials.ts create mode 100644 packages/nodes-base/nodes/Salesforce/AccountDescription.ts create mode 100644 packages/nodes-base/nodes/Salesforce/AccountInterface.ts create mode 100644 packages/nodes-base/nodes/Salesforce/AttachmentDescription.ts create mode 100644 packages/nodes-base/nodes/Salesforce/AttachmentInterface.ts create mode 100644 packages/nodes-base/nodes/Salesforce/CampaignMemberInterface.ts create mode 100644 packages/nodes-base/nodes/Salesforce/CaseDescription.ts create mode 100644 packages/nodes-base/nodes/Salesforce/CaseInterface.ts create mode 100644 packages/nodes-base/nodes/Salesforce/ContactDescription.ts create mode 100644 packages/nodes-base/nodes/Salesforce/ContactInterface.ts create mode 100644 packages/nodes-base/nodes/Salesforce/GenericFunctions.ts create mode 100644 packages/nodes-base/nodes/Salesforce/LeadDescription.ts create mode 100644 packages/nodes-base/nodes/Salesforce/LeadInterface.ts create mode 100644 packages/nodes-base/nodes/Salesforce/NoteInterface.ts create mode 100644 packages/nodes-base/nodes/Salesforce/OpportunityDescription.ts create mode 100644 packages/nodes-base/nodes/Salesforce/OpportunityInterface.ts create mode 100644 packages/nodes-base/nodes/Salesforce/Salesforce.node.ts create mode 100644 packages/nodes-base/nodes/Salesforce/TaskDescription.ts create mode 100644 packages/nodes-base/nodes/Salesforce/TaskInterface.ts create mode 100644 packages/nodes-base/nodes/Salesforce/salesforce.png diff --git a/packages/nodes-base/credentials/SalesforceOAuth2Api.credentials.ts b/packages/nodes-base/credentials/SalesforceOAuth2Api.credentials.ts new file mode 100644 index 0000000000..23739bf118 --- /dev/null +++ b/packages/nodes-base/credentials/SalesforceOAuth2Api.credentials.ts @@ -0,0 +1,40 @@ +import { + ICredentialType, + NodePropertyTypes, +} from 'n8n-workflow'; + +export class SalesforceOAuth2Api implements ICredentialType { + name = 'salesforceOAuth2Api'; + extends = [ + 'oAuth2Api', + ]; + displayName = 'Salesforce OAuth2 API'; + properties = [ + { + displayName: 'Authorization URL', + name: 'authUrl', + type: 'hidden' as NodePropertyTypes, + default: 'https://login.salesforce.com/services/oauth2/authorize', + required: true, + }, + { + displayName: 'Access Token URL', + name: 'accessTokenUrl', + type: 'string' as NodePropertyTypes, + default: 'https://yourcompany.salesforce.com/services/oauth2/token', + required: true, + }, + { + displayName: 'Scope', + name: 'scope', + type: 'hidden' as NodePropertyTypes, + default: 'full', + }, + { + displayName: 'Auth URI Query Parameters', + name: 'authQueryParameters', + type: 'hidden' as NodePropertyTypes, + default: '', + }, + ]; +} diff --git a/packages/nodes-base/nodes/Salesforce/AccountDescription.ts b/packages/nodes-base/nodes/Salesforce/AccountDescription.ts new file mode 100644 index 0000000000..0c9d336065 --- /dev/null +++ b/packages/nodes-base/nodes/Salesforce/AccountDescription.ts @@ -0,0 +1,700 @@ +import { INodeProperties } from 'n8n-workflow'; + +export const accountOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'account', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create an account', + }, + { + name: 'Update', + value: 'update', + description: 'Update an account', + }, + { + name: 'Get', + value: 'get', + description: 'Get an account', + }, + { + name: 'Get Summary', + value: 'getSummary', + description: `Returns an overview of account's metadata.`, + }, + { + name: 'Get All', + value: 'getAll', + description: 'Get all accounts', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete an account', + }, + { + name: 'Add Note', + value: 'addNote', + description: 'Add note to an account', + }, + ], + default: 'create', + description: 'The operation to perform.', + }, +] as INodeProperties[]; + +export const accountFields = [ + +/* -------------------------------------------------------------------------- */ +/* account:create */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Name', + name: 'name', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'account', + ], + operation: [ + 'create', + ] + }, + }, + description: 'Name of the account. Maximum size is 255 characters.', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'account', + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + displayName: 'Fax', + name: 'fax', + type: 'string', + default: '', + description: 'Fax number for the account.', + }, + { + displayName: 'Type', + name: 'type', + type: 'options', + default: '', + typeOptions: { + loadOptionsMethod: 'getAccountTypes', + }, + description: 'Type of account', + }, + { + displayName: 'Phone', + name: 'phone', + type: 'string', + default: '', + description: 'Phone number for the account.', + }, + { + displayName: 'Jigsaw', + name: 'jigsaw', + type: 'string', + default: '', + description: 'references the ID of a company in Data.com', + }, + { + displayName: 'Owner', + name: 'owner', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getUsers', + }, + default: '', + description: 'The owner of the account.', + }, + { + displayName: 'SicDesc', + name: 'sicDesc', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + description: 'A brief description of an organization’s line of business, based on its SIC code.', + }, + { + displayName: 'Website', + name: 'website', + type: 'string', + default: '', + description: 'The website of this account. Maximum of 255 characters.', + }, + { + displayName: 'Industry', + name: 'industry', + type: 'string', + default: '', + description: 'The website of this account. Maximum of 255 characters.', + }, + { + displayName: 'Parent Id', + name: 'parentId', + type: 'string', + default: '', + description: 'ID of the parent object, if any.', + }, + { + displayName: 'Billing City', + name: 'billingCity', + type: 'string', + default: '', + description: 'Details for the billing address of this account. Maximum size is 40 characters.', + }, + { + displayName: 'Description', + name: 'description', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: 'Text description of the account. Limited to 32,000 KB.', + }, + { + displayName: 'Billing State', + name: 'billingState', + type: 'string', + default: '', + description: 'Details for the billing address of this account. Maximum size is 80 characters.', + }, + { + displayName: 'Shipping City', + name: 'shippingCity', + type: 'string', + default: '', + description: 'Details of the shipping address for this account. City maximum size is 40 characters', + }, + { + displayName: 'Account Source', + name: 'accountSource', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getAccountSources', + }, + default: '', + description: 'The source of the account record', + }, + { + displayName: 'Annual Revenue', + name: 'annualRevenue', + type: 'number', + typeOptions: { + numberPrecision: 2, + }, + default: '', + description: 'Estimated annual revenue of the account.', + }, + { + displayName: 'Billing Street', + name: 'billingStreet', + type: 'string', + default: '', + description: 'Street address for the billing address of this account.', + }, + { + displayName: 'Shipping State', + name: 'shippingState', + type: 'string', + default: '', + description: 'Details of the shipping address for this account. State maximum size is 80 characters.', + }, + { + displayName: 'Billing Country', + name: 'billingCountry', + type: 'string', + default: '', + description: 'Details for the billing address of this account. Maximum size is 80 characters.', + }, + { + displayName: 'Shipping Street', + name: 'shippingStreet', + type: 'string', + default: '', + description: 'The street address of the shipping address for this account. Maximum of 255 characters.', + }, + { + displayName: 'Shipping Country', + name: 'shippingCountry', + type: 'string', + default: '', + description: 'Details of the shipping address for this account. Country maximum size is 80 characters.', + }, + { + displayName: 'Billing Postal Code', + name: 'billingPostalCode', + type: 'string', + default: '', + description: 'Details for the billing address of this account. Maximum size is 20 characters.', + }, + { + displayName: 'Number Of Employees', + name: 'numberOfEmployees', + type: 'integer', + default: '', + description: 'Number of employees', + }, + { + displayName: 'Shipping Postal Code', + name: 'shippingPostalCode', + type: 'string', + default: '', + description: 'Details of the shipping address for this account. Postal code maximum size is 20 characters.', + }, + ], + }, +/* -------------------------------------------------------------------------- */ +/* account:update */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Account ID', + name: 'accountId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'account', + ], + operation: [ + 'update', + ] + }, + }, + description: 'Id of account that needs to be fetched', + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'account', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + description: 'Name of the account. Maximum size is 255 characters.', + }, + { + displayName: 'Fax', + name: 'fax', + type: 'string', + default: '', + description: 'Fax number for the account.', + }, + { + displayName: 'Type', + name: 'type', + type: 'options', + default: '', + typeOptions: { + loadOptionsMethod: 'getAccountTypes', + }, + description: 'Type of account', + }, + { + displayName: 'Phone', + name: 'phone', + type: 'string', + default: '', + description: 'Phone number for the account.', + }, + { + displayName: 'Jigsaw', + name: 'jigsaw', + type: 'string', + default: '', + description: 'references the ID of a company in Data.com', + }, + { + displayName: 'Owner', + name: 'ownerId', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getUsers', + }, + default: '', + description: 'The owner of the account.', + }, + { + displayName: 'SicDesc', + name: 'sicDesc', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + description: 'A brief description of an organization’s line of business, based on its SIC code.', + }, + { + displayName: 'Website', + name: 'website', + type: 'string', + default: '', + description: 'The website of this account. Maximum of 255 characters.', + }, + { + displayName: 'Industry', + name: 'industry', + type: 'string', + default: '', + description: 'The website of this account. Maximum of 255 characters.', + }, + { + displayName: 'Parent Id', + name: 'parentId', + type: 'string', + default: '', + description: 'ID of the parent object, if any.', + }, + { + displayName: 'Billing City', + name: 'billingCity', + type: 'string', + default: '', + description: 'Details for the billing address of this account. Maximum size is 40 characters.', + }, + { + displayName: 'Description', + name: 'description', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: 'Text description of the account. Limited to 32,000 KB.', + }, + { + displayName: 'Billing State', + name: 'billingState', + type: 'string', + default: '', + description: 'Details for the billing address of this account. Maximum size is 80 characters.', + }, + { + displayName: 'Shipping City', + name: 'shippingCity', + type: 'string', + default: '', + description: 'Details of the shipping address for this account. City maximum size is 40 characters', + }, + { + displayName: 'Account Source', + name: 'accountSource', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getAccountSources', + }, + default: '', + description: 'The source of the account record', + }, + { + displayName: 'Annual Revenue', + name: 'annualRevenue', + type: 'number', + typeOptions: { + numberPrecision: 2, + }, + default: '', + description: 'Estimated annual revenue of the account.', + }, + { + displayName: 'Billing Street', + name: 'billingStreet', + type: 'string', + default: '', + description: 'Street address for the billing address of this account.', + }, + { + displayName: 'Shipping State', + name: 'shippingState', + type: 'string', + default: '', + description: 'Details of the shipping address for this account. State maximum size is 80 characters.', + }, + { + displayName: 'Billing Country', + name: 'billingCountry', + type: 'string', + default: '', + description: 'Details for the billing address of this account. Maximum size is 80 characters.', + }, + { + displayName: 'Shipping Street', + name: 'shippingStreet', + type: 'string', + default: '', + description: 'The street address of the shipping address for this account. Maximum of 255 characters.', + }, + { + displayName: 'Shipping Country', + name: 'shippingCountry', + type: 'string', + default: '', + description: 'Details of the shipping address for this account. Country maximum size is 80 characters.', + }, + { + displayName: 'Billing Postal Code', + name: 'billingPostalCode', + type: 'string', + default: '', + description: 'Details for the billing address of this account. Maximum size is 20 characters.', + }, + { + displayName: 'Number Of Employees', + name: 'numberOfEmployees', + type: 'integer', + default: '', + description: 'Number of employees', + }, + { + displayName: 'Shipping Postal Code', + name: 'shippingPostalCode', + type: 'string', + default: '', + description: 'Details of the shipping address for this account. Postal code maximum size is 20 characters.', + }, + ], + }, + +/* -------------------------------------------------------------------------- */ +/* account:get */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Account ID', + name: 'accountId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'account', + ], + operation: [ + 'get', + ] + }, + }, + description: 'Id of account that needs to be fetched', + }, +/* -------------------------------------------------------------------------- */ +/* account:delete */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Account ID', + name: 'accountId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'account', + ], + operation: [ + 'delete', + ] + }, + }, + description: 'Id of account that needs to be fetched', + }, +/* -------------------------------------------------------------------------- */ +/* account:getAll */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource: [ + 'account', + ], + operation: [ + 'getAll', + ], + }, + }, + default: false, + description: 'If all results should be returned or only up to a given limit.', + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + resource: [ + 'account', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 100, + }, + default: 50, + description: 'How many results to return.', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'account', + ], + operation: [ + 'getAll', + ], + }, + }, + options: [ + { + displayName: 'Fields', + name: 'fields', + type: 'string', + default: '', + description: 'Fields to include separated by ,', + }, + ] + }, +/* -------------------------------------------------------------------------- */ +/* account:addNote */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Account ID', + name: 'accountId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'account', + ], + operation: [ + 'addNote', + ] + }, + }, + description: 'Id of account that needs to be fetched', + }, + { + displayName: 'Title', + name: 'title', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'account', + ], + operation: [ + 'addNote', + ] + }, + }, + description: 'Title of the note.', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'account', + ], + operation: [ + 'addNote', + ], + }, + }, + options: [ + { + displayName: 'Body', + name: 'body', + type: 'string', + default: '', + typeOptions: { + alwaysOpenEditWindow: true, + }, + description: 'Body of the note. Limited to 32 KB.', + }, + { + displayName: 'Owner', + name: 'ownerId', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getUsers', + }, + default: '', + description: 'ID of the user who owns the note.', + }, + { + displayName: 'Is Private', + name: 'isPrivate', + type: 'boolean', + default: false, + description: 'If true, only the note owner or a user with the “Modify All Data” permission can view the note or query it via the API', + }, + ] + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Salesforce/AccountInterface.ts b/packages/nodes-base/nodes/Salesforce/AccountInterface.ts new file mode 100644 index 0000000000..c42b485105 --- /dev/null +++ b/packages/nodes-base/nodes/Salesforce/AccountInterface.ts @@ -0,0 +1,26 @@ +export interface IAccount { + Name?: string; + Fax?: string; + Type?: string; + Phone?: string; + Jigsaw?: string; + OwnerId?: string; + SicDesc?: string; + Website?: string; + Industry?: string; + ParentId?: string; + BillingCity?: string; + Description?: string; + BillingState?: string; + ShippingStreet?: string; + ShippingCity?:string; + AccountSource?: string; + AnnualRevenue?: number; + BillingStreet?: string; + ShippingState?: string; + BillingCountry?: string; + ShippingCountry?: string; + BillingPostalCode?: string; + NumberOfEmployees?: string; + ShippingPostalCode?: string; +} diff --git a/packages/nodes-base/nodes/Salesforce/AttachmentDescription.ts b/packages/nodes-base/nodes/Salesforce/AttachmentDescription.ts new file mode 100644 index 0000000000..60158a7e52 --- /dev/null +++ b/packages/nodes-base/nodes/Salesforce/AttachmentDescription.ts @@ -0,0 +1,347 @@ +import { INodeProperties } from 'n8n-workflow'; + +export const attachmentOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'attachment', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a attachment', + }, + { + name: 'Update', + value: 'update', + description: 'Update a attachment', + }, + { + name: 'Get', + value: 'get', + description: 'Get a attachment', + }, + { + name: 'Get Summary', + value: 'getSummary', + description: `Returns an overview of attachment's metadata.`, + }, + { + name: 'Get All', + value: 'getAll', + description: 'Get all attachments', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a attachment', + }, + ], + default: 'create', + description: 'The operation to perform.', + }, +] as INodeProperties[]; + +export const attachmentFields = [ + +/* -------------------------------------------------------------------------- */ +/* attachment:create */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Parent ID', + name: 'parentId', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + resource: [ + 'attachment', + ], + operation: [ + 'create' + ], + }, + }, + description: '', + }, + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + resource: [ + 'attachment', + ], + operation: [ + 'create' + ], + }, + }, + description: 'Required. Name of the attached file. Maximum size is 255 characters. Label is File Name.', + }, + { + displayName: 'Binary Property', + name: 'binaryPropertyName', + type: 'string', + default: 'data', + required: true, + displayOptions: { + show: { + resource: [ + 'attachment', + ], + operation: [ + 'create' + ], + }, + }, + placeholder: '', + description: 'Name of the binary property which contains
the data for the file to be uploaded.', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'attachment', + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + displayName: 'Owner', + name: 'owner', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getUsers', + }, + default: '', + description: 'ID of the User who owns the attachment.', + }, + { + displayName: 'Is Private', + name: 'isPrivate', + type: 'boolean', + default: false, + description: 'Indicates whether this record is viewable only by the owner and administrators (true) or viewable by all otherwise-allowed users (false). ', + }, + { + displayName: 'Description', + name: 'description', + type: 'string', + default: '', + description: `Text description of the Document. Limit: 255 characters.`, + }, + ], + }, +/* -------------------------------------------------------------------------- */ +/* attachment:update */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Attachment ID', + name: 'attachmentId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'attachment', + ], + operation: [ + 'update', + ] + }, + }, + description: 'Id of attachment that needs to be fetched', + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'attachment', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + description: 'Required. Name of the attached file. Maximum size is 255 characters. Label is File Name.', + }, + { + displayName: 'Owner', + name: 'owner', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getUsers', + }, + default: '', + description: 'ID of the User who owns the attachment.', + }, + { + displayName: 'Is Private', + name: 'isPrivate', + type: 'boolean', + default: false, + description: 'Indicates whether this record is viewable only by the owner and administrators (true) or viewable by all otherwise-allowed users (false). ', + }, + { + displayName: 'Description', + name: 'description', + type: 'string', + default: '', + description: `Text description of the Document. Limit: 255 characters.`, + }, + { + displayName: 'Binary Property', + name: 'binaryPropertyName', + type: 'string', + default: 'data', + placeholder: '', + description: 'Name of the binary property which contains
the data for the file to be uploaded.', + }, + ], + }, + +/* -------------------------------------------------------------------------- */ +/* attachment:get */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Attachment ID', + name: 'attachmentId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'attachment', + ], + operation: [ + 'get', + ] + }, + }, + description: 'Id of attachment that needs to be fetched', + }, +/* -------------------------------------------------------------------------- */ +/* attachment:delete */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Attachment ID', + name: 'attachmentId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'attachment', + ], + operation: [ + 'delete', + ] + }, + }, + description: 'Id of attachment that needs to be fetched', + }, +/* -------------------------------------------------------------------------- */ +/* attachment:getAll */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource: [ + 'attachment', + ], + operation: [ + 'getAll', + ], + }, + }, + default: false, + description: 'If all results should be returned or only up to a given limit.', + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + resource: [ + 'attachment', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 100, + }, + default: 50, + description: 'How many results to return.', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'attachment', + ], + operation: [ + 'getAll', + ], + }, + }, + options: [ + { + displayName: 'Fields', + name: 'fields', + type: 'string', + default: '', + description: 'Fields to include separated by ,', + }, + ] + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Salesforce/AttachmentInterface.ts b/packages/nodes-base/nodes/Salesforce/AttachmentInterface.ts new file mode 100644 index 0000000000..e63558a496 --- /dev/null +++ b/packages/nodes-base/nodes/Salesforce/AttachmentInterface.ts @@ -0,0 +1,10 @@ + +export interface IAttachment { + ParentId?: string; + Name?: string; + Body?: string; + OwnerId?: string; + IsPrivate?: boolean; + ContentType?: string; + Description?: string; +} diff --git a/packages/nodes-base/nodes/Salesforce/CampaignMemberInterface.ts b/packages/nodes-base/nodes/Salesforce/CampaignMemberInterface.ts new file mode 100644 index 0000000000..3b025c0ce9 --- /dev/null +++ b/packages/nodes-base/nodes/Salesforce/CampaignMemberInterface.ts @@ -0,0 +1,7 @@ + +export interface ICampaignMember { + CampaignId?: string; + ContactId?: string; + LeadId?: string; + Status?: string; +} diff --git a/packages/nodes-base/nodes/Salesforce/CaseDescription.ts b/packages/nodes-base/nodes/Salesforce/CaseDescription.ts new file mode 100644 index 0000000000..9b9c458bac --- /dev/null +++ b/packages/nodes-base/nodes/Salesforce/CaseDescription.ts @@ -0,0 +1,563 @@ +import { INodeProperties } from 'n8n-workflow'; + +export const caseOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'case', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a case', + }, + { + name: 'Update', + value: 'update', + description: 'Update a case', + }, + { + name: 'Get', + value: 'get', + description: 'Get a case', + }, + { + name: 'Get Summary', + value: 'getSummary', + description: `Returns an overview of case's metadata.`, + }, + { + name: 'Get All', + value: 'getAll', + description: 'Get all cases', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a case', + }, + { + name: 'Add Comment', + value: 'addComment', + description: 'Add a comment to a case', + }, + ], + default: 'create', + description: 'The operation to perform.', + }, +] as INodeProperties[]; + +export const caseFields = [ + +/* -------------------------------------------------------------------------- */ +/* case:create */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Type', + name: 'type', + type: 'options', + required: true, + typeOptions: { + loadOptionsMethod: 'getCaseTypes', + }, + displayOptions: { + show: { + resource: [ + 'case', + ], + operation: [ + 'create', + ], + }, + }, + default: '', + description: 'The type of case', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'case', + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + displayName: 'Origin', + name: 'origin', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getCaseOrigins', + }, + default: '', + description: 'The source of the case, such as Email, Phone, or Web. Label is Case Origin.', + }, + { + displayName: 'Reason', + name: 'reason', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getCaseReasons', + }, + default: '', + description: 'The reason why the case was created, such as Instructions not clear, or User didn’t attend training.', + }, + { + displayName: 'Status', + name: 'status', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getCaseStatuses', + }, + default: '', + description: 'The status of the case, such as “New,” “Closed,” or “Escalated.” This field directly controls the IsClosed flag', + }, + { + displayName: 'Owner', + name: 'owner', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getUsers', + }, + default: '', + description: 'The owner of the case.', + }, + { + displayName: 'Subject', + name: 'subject', + type: 'string', + default: '', + description: 'The subject of the case. Limit: 255 characters.', + }, + { + displayName: 'Parent Id', + name: 'ParentId', + type: 'string', + default: '', + description: 'The ID of the parent case in the hierarchy. The label is Parent Case.', + }, + { + displayName: 'Priority', + name: 'priority', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getCasePriorities', + }, + default: '', + description: 'The importance or urgency of the case, such as High, Medium, or Low.', + }, + { + displayName: 'Account Id', + name: 'accountId', + type: 'string', + default: '', + description: 'ID of the account associated with this case.', + }, + { + displayName: 'Contact Id', + name: 'contactId', + type: 'string', + default: '', + description: 'IID of the associated Contact.', + }, + { + displayName: 'Description', + name: 'description', + type: 'string', + default: '', + description: 'A text description of the case. Limit: 32 KB.', + }, + { + displayName: 'Is Escalated', + name: 'isEscalated', + type: 'boolean', + default: false, + description: 'Indicates whether the case has been escalated (true) or not.', + }, + { + displayName: 'Supplied Name', + name: 'suppliedName', + type: 'string', + default: '', + description: `The name that was entered when the case was created. This field can't be updated after the case has been created`, + }, + { + displayName: 'Supplied Email', + name: 'suppliedEmail', + type: 'string', + default: '', + description: `The email address that was entered when the case was created. This field can't be updated after the case has been created.`, + }, + { + displayName: 'Supplied Phone', + name: 'suppliedPhone', + type: 'string', + default: '', + description: `The phone number that was entered when the case was created. This field can't be updated after the case has been created.`, + }, + { + displayName: 'Supplied Company', + name: 'suppliedCompany', + type: 'string', + default: '', + description: `The company name that was entered when the case was created. This field can't be updated after the case has been created..`, + }, + ], + }, +/* -------------------------------------------------------------------------- */ +/* case:update */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Case ID', + name: 'caseId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'case', + ], + operation: [ + 'update', + ] + }, + }, + description: 'Id of case that needs to be fetched', + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'case', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + displayName: 'Type', + name: 'type', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getCaseTypes', + }, + default: '', + description: 'The type of case', + }, + { + displayName: 'Origin', + name: 'origin', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getCaseOrigins', + }, + default: '', + description: 'The source of the case, such as Email, Phone, or Web. Label is Case Origin.', + }, + { + displayName: 'Reason', + name: 'reason', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getCaseReasons', + }, + default: '', + description: 'The reason why the case was created, such as Instructions not clear, or User didn’t attend training.', + }, + { + displayName: 'Status', + name: 'status', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getCaseStatuses', + }, + default: '', + description: 'The status of the case, such as “New,” “Closed,” or “Escalated.” This field directly controls the IsClosed flag', + }, + { + displayName: 'Owner', + name: 'owner', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getUsers', + }, + default: '', + description: 'The owner of the case.', + }, + { + displayName: 'Subject', + name: 'subject', + type: 'string', + default: '', + description: 'The subject of the case. Limit: 255 characters.', + }, + { + displayName: 'Parent Id', + name: 'ParentId', + type: 'string', + default: '', + description: 'The ID of the parent case in the hierarchy. The label is Parent Case.', + }, + { + displayName: 'Priority', + name: 'priority', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getCasePriorities', + }, + default: '', + description: 'The importance or urgency of the case, such as High, Medium, or Low.', + }, + { + displayName: 'Account Id', + name: 'accountId', + type: 'string', + default: '', + description: 'ID of the account associated with this case.', + }, + { + displayName: 'Contact Id', + name: 'contactId', + type: 'string', + default: '', + description: 'IID of the associated Contact.', + }, + { + displayName: 'Description', + name: 'description', + type: 'string', + default: '', + description: 'A text description of the case. Limit: 32 KB.', + }, + { + displayName: 'Is Escalated', + name: 'isEscalated', + type: 'boolean', + default: false, + description: 'Indicates whether the case has been escalated (true) or not.', + }, + { + displayName: 'Supplied Name', + name: 'suppliedName', + type: 'string', + default: '', + description: `The name that was entered when the case was created. This field can't be updated after the case has been created`, + }, + { + displayName: 'Supplied Email', + name: 'suppliedEmail', + type: 'string', + default: '', + description: `The email address that was entered when the case was created. This field can't be updated after the case has been created.`, + }, + { + displayName: 'Supplied Phone', + name: 'suppliedPhone', + type: 'string', + default: '', + description: `The phone number that was entered when the case was created. This field can't be updated after the case has been created.`, + }, + { + displayName: 'Supplied Company', + name: 'suppliedCompany', + type: 'string', + default: '', + description: `The company name that was entered when the case was created. This field can't be updated after the case has been created..`, + }, + ], + }, + +/* -------------------------------------------------------------------------- */ +/* case:get */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Case ID', + name: 'caseId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'case', + ], + operation: [ + 'get', + ] + }, + }, + description: 'Id of case that needs to be fetched', + }, +/* -------------------------------------------------------------------------- */ +/* case:delete */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Case ID', + name: 'caseId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'case', + ], + operation: [ + 'delete', + ] + }, + }, + description: 'Id of case that needs to be fetched', + }, +/* -------------------------------------------------------------------------- */ +/* case:getAll */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource: [ + 'case', + ], + operation: [ + 'getAll', + ], + }, + }, + default: false, + description: 'If all results should be returned or only up to a given limit.', + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + resource: [ + 'case', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 100, + }, + default: 50, + description: 'How many results to return.', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'case', + ], + operation: [ + 'getAll', + ], + }, + }, + options: [ + { + displayName: 'Fields', + name: 'fields', + type: 'string', + default: '', + description: 'Fields to include separated by ,', + }, + ] + }, + +/* -------------------------------------------------------------------------- */ +/* case:addComment */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Case ID', + name: 'caseId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'case', + ], + operation: [ + 'addComment', + ] + }, + }, + description: 'Id of case that needs to be fetched', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'case', + ], + operation: [ + 'addComment', + ], + }, + }, + options: [ + { + displayName: 'Comment Body', + name: 'commentBody', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: 'Text of the CaseComment. The maximum size of the comment body is 4,000 bytes. Label is Body.', + }, + { + displayName: 'Is Published', + name: 'isPublished', + type: 'boolean', + default: false, + description: 'Indicates whether the CaseComment is visible to customers in the Self-Service portal (true) or not (false). ', + }, + ] + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Salesforce/CaseInterface.ts b/packages/nodes-base/nodes/Salesforce/CaseInterface.ts new file mode 100644 index 0000000000..169d47c14d --- /dev/null +++ b/packages/nodes-base/nodes/Salesforce/CaseInterface.ts @@ -0,0 +1,25 @@ + +export interface ICase { + Type?: string; + Origin?: string; + Reason?: string; + Status?: string; + OwnerId?: string; + Subject?: string; + ParentId?: string; + Priority?: string; + AccountId?: string; + ContactId?: string; + Description?: string; + IsEscalated?: boolean; + SuppliedName?: string; + SuppliedEmail?: string; + SuppliedPhone?: string; + SuppliedCompany?: string; +} + +export interface ICaseComment { + CommentBody?: string; + ParentId?: string; + IsPublished?: boolean; +} diff --git a/packages/nodes-base/nodes/Salesforce/ContactDescription.ts b/packages/nodes-base/nodes/Salesforce/ContactDescription.ts new file mode 100644 index 0000000000..bda804e6d6 --- /dev/null +++ b/packages/nodes-base/nodes/Salesforce/ContactDescription.ts @@ -0,0 +1,835 @@ +import { INodeProperties } from 'n8n-workflow'; + +export const contactOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'contact', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a contact', + }, + { + name: 'Update', + value: 'update', + description: 'Update a contact', + }, + { + name: 'Get', + value: 'get', + description: 'Get a contact', + }, + { + name: 'Get Summary', + value: 'getSummary', + description: `Returns an overview of contact's metadata.`, + }, + { + name: 'Get All', + value: 'getAll', + description: 'Get all contacts', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a contact', + }, + { + name: 'Add Lead To Campaign', + value: 'addToCampaign', + description: 'Add lead to a campaign', + }, + { + name: 'Add Note', + value: 'addNote', + description: 'Add note to a contact', + }, + ], + default: 'create', + description: 'The operation to perform.', + }, +] as INodeProperties[]; + +export const contactFields = [ + +/* -------------------------------------------------------------------------- */ +/* contact:create */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Last Name', + name: 'lastname', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'create', + ] + }, + }, + description: 'Required. Last name of the contact. Limited to 80 characters.', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + displayName: 'Fax', + name: 'fax', + type: 'string', + default: '', + description: 'Fax number for the contact. Label is Business Fax.', + }, + { + displayName: 'Email', + name: 'email', + type: 'string', + default: '', + description: 'Email address for the contact.', + }, + { + displayName: 'Phone', + name: 'phone', + type: 'string', + default: '', + description: 'Phone number for the contact.', + }, + { + displayName: 'Title', + name: 'title', + type: 'string', + default: '', + description: 'Title of the contact such as CEO or Vice President.', + }, + { + displayName: 'Jigsaw', + name: 'jigsaw', + type: 'string', + default: '', + description: `references the ID of a contact in Data.com. + If a contact has a value in this field, it means that a contact was imported as a contact from Data.com.`, + }, + { + displayName: 'Owner', + name: 'owner', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getUsers', + }, + default: '', + description: 'The owner of the contact.', + }, + { + displayName: 'Account', + name: 'acconuntId', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getAccounts', + }, + default: '', + description: 'ID of the account that is the parent of this contact.', + }, + { + displayName: 'Birthdate', + name: 'birthdate', + type: 'string', + default: '', + description: 'The birthdate of the contact.', + }, + { + displayName: 'First Name', + name: 'firstName', + type: 'string', + default: '', + description: 'First name of the contact. Maximum size is 40 characters.', + }, + { + displayName: 'Home Phone', + name: 'homePhone', + type: 'string', + default: '', + description: 'Home telephone number for the contact', + }, + { + displayName: 'Other City', + name: 'otherCity', + type: 'string', + default: '', + }, + { + displayName: 'Department', + name: 'department', + type: 'string', + default: '', + description: 'The department of the contact.', + }, + { + displayName: 'Lead Source', + name: 'leadSource', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getLeadSources', + }, + default: '', + description: 'Source from which the lead was obtained.', + }, + { + displayName: 'Other Phone', + name: 'otherPhone', + type: 'string', + default: '', + description: 'Telephone for alternate address.', + }, + { + displayName: 'Other State', + name: 'otherState', + type: 'string', + default: '', + }, + { + displayName: 'Salutation', + name: 'salutation', + type: 'string', + default: '', + description: 'Honorific abbreviation, word, or phrase to be used in front of name in greetings, such as Dr. or Mrs.', + }, + { + displayName: 'Description', + name: 'description', + type: 'string', + default: '', + description: 'A description of the contact. Label is Contact Description. Limit: 32 KB.', + }, + { + displayName: 'Mailing City', + name: 'mailingCity', + type: 'string', + default: '', + }, + { + displayName: 'Mobile Phone', + name: 'mobilePhone', + type: 'string', + default: '', + description: `Contact’s mobile phone number.`, + }, + { + displayName: 'Other Street', + name: 'otherStreet', + type: 'string', + default: '', + description: 'Street for alternate address.', + }, + { + displayName: 'Mailing State', + name: 'mailingState', + type: 'string', + default: '', + }, + { + displayName: 'Other Country', + name: 'otherCountry', + type: 'string', + default: '', + }, + { + displayName: 'Assistant Name', + name: 'assistantName', + type: 'string', + default: '', + description: 'The name of the assistant.', + }, + { + displayName: 'Mailing Street', + name: 'mailingStreet', + type: 'string', + default: '', + description: 'Street address for mailing address.', + }, + { + displayName: 'Assistant Phone', + name: 'Assistant Phone', + type: 'string', + default: '', + description: 'The telephone number of the assistant.', + }, + { + displayName: 'Mailing Country', + name: 'mailingCountry', + type: 'string', + default: '', + }, + { + displayName: 'Other Postal Code', + name: 'otherPostalCode', + type: 'string', + default: '', + }, + { + displayName: 'Email Bounced Date', + name: 'otherPostalCode', + type: 'dateTime', + default: '', + description: 'If bounce management is activated and an email sent to the contact bounces, the date and time the bounce occurred.', + }, + { + displayName: 'Mailing Postal Code', + name: 'mailingPostalCode', + type: 'string', + default: '', + }, + { + displayName: 'Email Bounced Reason', + name: 'emailBouncedReason', + type: 'string', + default: '', + description: 'If bounce management is activated and an email sent to the contact bounces, the reason the bounce occurred.', + }, + ], + }, +/* -------------------------------------------------------------------------- */ +/* contact:update */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Contact ID', + name: 'contactId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'update', + ] + }, + }, + description: 'Id of contact that needs to be fetched', + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + displayName: 'Fax', + name: 'fax', + type: 'string', + default: '', + description: 'Fax number for the contact. Label is Business Fax.', + }, + { + displayName: 'Email', + name: 'email', + type: 'string', + default: '', + description: 'Email address for the contact.', + }, + { + displayName: 'Phone', + name: 'phone', + type: 'string', + default: '', + description: 'Phone number for the contact.', + }, + { + displayName: 'Title', + name: 'title', + type: 'string', + default: '', + description: 'Title of the contact such as CEO or Vice President.', + }, + { + displayName: 'Jigsaw', + name: 'jigsaw', + type: 'string', + default: '', + description: `references the ID of a contact in Data.com. + If a contact has a value in this field, it means that a contact was imported as a contact from Data.com.`, + }, + { + displayName: 'Owner', + name: 'owner', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getUsers', + }, + default: '', + description: 'The owner of the contact.', + }, + { + displayName: 'Account', + name: 'acconuntId', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getAccounts', + }, + default: '', + description: 'ID of the account that is the parent of this contact.', + }, + { + displayName: 'Birthdate', + name: 'birthdate', + type: 'string', + default: '', + description: 'The birthdate of the contact.', + }, + { + displayName: 'First Name', + name: 'firstName', + type: 'string', + default: '', + description: 'First name of the contact. Maximum size is 40 characters.', + }, + { + displayName: 'Home Phone', + name: 'homePhone', + type: 'string', + default: '', + description: 'Home telephone number for the contact.', + }, + { + displayName: 'Other City', + name: 'otherCity', + type: 'string', + default: '', + }, + { + displayName: 'Department', + name: 'department', + type: 'string', + default: '', + description: 'The department of the contact.', + }, + { + displayName: 'Lead Source', + name: 'leadSource', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getLeadSources', + }, + default: '', + description: 'Source from which the lead was obtained.', + }, + { + displayName: 'Other Phone', + name: 'otherPhone', + type: 'string', + default: '', + description: 'Telephone for alternate address.', + }, + { + displayName: 'Other State', + name: 'otherState', + type: 'string', + default: '', + }, + { + displayName: 'Salutation', + name: 'salutation', + type: 'string', + default: '', + description: 'Honorific abbreviation, word, or phrase to be used in front of name in greetings, such as Dr. or Mrs.', + }, + { + displayName: 'Description', + name: 'description', + type: 'string', + default: '', + description: 'A description of the contact. Label is Contact Description. Limit: 32 KB.', + }, + { + displayName: 'Mailing City', + name: 'mailingCity', + type: 'string', + default: '', + }, + { + displayName: 'Mobile Phone', + name: 'mobilePhone', + type: 'string', + default: '', + description: `Contact’s mobile phone number.`, + }, + { + displayName: 'Other Street', + name: 'otherStreet', + type: 'string', + default: '', + description: 'Street for alternate address.', + }, + { + displayName: 'Mailing State', + name: 'mailingState', + type: 'string', + default: '', + }, + { + displayName: 'Other Country', + name: 'otherCountry', + type: 'string', + default: '', + }, + { + displayName: 'Assistant Name', + name: 'assistantName', + type: 'string', + default: '', + description: 'The name of the assistant.', + }, + { + displayName: 'Mailing Street', + name: 'mailingStreet', + type: 'string', + default: '', + description: 'Street address for mailing address.', + }, + { + displayName: 'Assistant Phone', + name: 'Assistant Phone', + type: 'string', + default: '', + description: 'The telephone number of the assistant.', + }, + { + displayName: 'Mailing Country', + name: 'mailingCountry', + type: 'string', + default: '', + }, + { + displayName: 'Other Postal Code', + name: 'otherPostalCode', + type: 'string', + default: '', + }, + { + displayName: 'Email Bounced Date', + name: 'emailBouncedDate', + type: 'dateTime', + default: '', + description: 'If bounce management is activated and an email sent to the contact bounces, the date and time the bounce occurred.', + }, + { + displayName: 'Mailing Postal Code', + name: 'mailingPostalCode', + type: 'string', + default: '', + }, + { + displayName: 'Email Bounced Reason', + name: 'emailBouncedReason', + type: 'string', + default: '', + description: 'If bounce management is activated and an email sent to the contact bounces, the reason the bounce occurred.', + }, + ], + }, + +/* -------------------------------------------------------------------------- */ +/* contact:get */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Contact ID', + name: 'contactId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'get', + ] + }, + }, + description: 'Id of contact that needs to be fetched', + }, +/* -------------------------------------------------------------------------- */ +/* contact:delete */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Contact ID', + name: 'contactId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'delete', + ] + }, + }, + description: 'Id of contact that needs to be fetched', + }, +/* -------------------------------------------------------------------------- */ +/* contact:getAll */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'getAll', + ], + }, + }, + default: false, + description: 'If all results should be returned or only up to a given limit.', + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 100, + }, + default: 50, + description: 'How many results to return.', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'getAll', + ], + }, + }, + options: [ + { + displayName: 'Fields', + name: 'fields', + type: 'string', + default: '', + description: 'Fields to include separated by ,', + }, + ] + }, + +/* -------------------------------------------------------------------------- */ +/* contact:addToCampaign */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Contact ID', + name: 'contactId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'addToCampaign', + ] + }, + }, + description: 'Id of contact that needs to be fetched', + }, + { + displayName: 'Campaign', + name: 'campaignId', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getCampaigns', + }, + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'addToCampaign', + ] + }, + }, + description: 'Id of the campaign that needs to be fetched', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'addToCampaign', + ], + }, + }, + options: [ + { + displayName: 'Status', + name: 'status', + type: 'string', + default: '', + description: 'Controls the HasResponded flag on this object', + }, + ] + }, +/* -------------------------------------------------------------------------- */ +/* contact:addNote */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Contact ID', + name: 'contactId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'addNote', + ] + }, + }, + description: 'Id of contact that needs to be fetched', + }, + { + displayName: 'Title', + name: 'title', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'addNote', + ] + }, + }, + description: 'Title of the note.', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'contact', + ], + operation: [ + 'addNote', + ], + }, + }, + options: [ + { + displayName: 'Body', + name: 'body', + type: 'string', + default: '', + typeOptions: { + alwaysOpenEditWindow: true, + }, + description: 'Body of the note. Limited to 32 KB.', + }, + { + displayName: 'Owner', + name: 'owner', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getUsers', + }, + default: '', + description: 'ID of the user who owns the note.', + }, + { + displayName: 'Is Private', + name: 'isPrivate', + type: 'boolean', + default: false, + description: 'If true, only the note owner or a user with the “Modify All Data” permission can view the note or query it via the API', + }, + ] + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Salesforce/ContactInterface.ts b/packages/nodes-base/nodes/Salesforce/ContactInterface.ts new file mode 100644 index 0000000000..e51090b88f --- /dev/null +++ b/packages/nodes-base/nodes/Salesforce/ContactInterface.ts @@ -0,0 +1,34 @@ + +export interface IContact { + LastName?: string; + Fax?: string; + Email?: string; + Phone?: string; + Title?: string; + Jigsaw?: string; + OwnerId?: string; + AccountId?: string; + Birthdate?:string; + FirstName?: string; + HomePhone?: string; + OtherCity?: string; + Department?: string; + LeadSource?: string; + OtherPhone?: string; + OtherState?: string; + Salutation?: string; + Description?: string; + MailingCity?: string; + MobilePhone?: string; + OtherStreet?: string; + MailingState?: string; + OtherCountry?: string; + AssistantName?: string; + MailingStreet?: string; + AssistantPhone?: string; + MailingCountry?: string; + OtherPostalCode?: string; + MailingPostalCode?: string; + EmailBouncedDate?: string; + EmailBouncedReason?: string; +} diff --git a/packages/nodes-base/nodes/Salesforce/GenericFunctions.ts b/packages/nodes-base/nodes/Salesforce/GenericFunctions.ts new file mode 100644 index 0000000000..33fec16bf3 --- /dev/null +++ b/packages/nodes-base/nodes/Salesforce/GenericFunctions.ts @@ -0,0 +1,50 @@ +import { OptionsWithUri } from 'request'; +import { + IExecuteFunctions, + IExecuteSingleFunctions, + ILoadOptionsFunctions, +} from 'n8n-core'; +import { + IDataObject +} from 'n8n-workflow'; + +export async function salesforceApiRequest(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, resource: string, body: any = {}, qs: IDataObject = {}, uri?: string, option: IDataObject = {}): Promise { // tslint:disable-line:no-any + const credentials = this.getCredentials('salesforceOAuth2Api'); + const subdomain = (credentials!.accessTokenUrl as string).split('.')[0].split('/')[2]; + const options: OptionsWithUri = { + method, + body, + qs, + uri: uri || `https://${subdomain}.salesforce.com/services/data/v39.0${resource}`, + json: true + }; + try { + //@ts-ignore + return await this.helpers.requestOAuth.call(this, 'salesforceOAuth2Api', options); + } catch (error) { + if (error.response && error.response.body && error.response.body[0].message) { + // Try to return the error prettier + throw new Error(`Salesforce error response [${error.statusCode}]: ${error.response.body[0].message}`); + } + throw error; + } +} + +export async function salesforceApiRequestAllItems(this: IExecuteFunctions | ILoadOptionsFunctions, propertyName: string ,method: string, endpoint: string, body: any = {}, query: IDataObject = {}): Promise { // tslint:disable-line:no-any + + const returnData: IDataObject[] = []; + + let responseData; + let uri: string | undefined; + + do { + responseData = await salesforceApiRequest.call(this, method, endpoint, body, query, uri); + uri = responseData.nextRecordsUrl; + returnData.push.apply(returnData, responseData[propertyName]); + } while ( + responseData.nextRecordsUrl !== undefined && + responseData.nextRecordsUrl !== null + ); + + return returnData; +} diff --git a/packages/nodes-base/nodes/Salesforce/LeadDescription.ts b/packages/nodes-base/nodes/Salesforce/LeadDescription.ts new file mode 100644 index 0000000000..ba9134741d --- /dev/null +++ b/packages/nodes-base/nodes/Salesforce/LeadDescription.ts @@ -0,0 +1,762 @@ +import { INodeProperties } from 'n8n-workflow'; + +export const leadOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'lead', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a lead', + }, + { + name: 'Update', + value: 'update', + description: 'Update a lead', + }, + { + name: 'Get', + value: 'get', + description: 'Get a lead', + }, + { + name: 'Get Summary', + value: 'getSummary', + description: `Returns an overview of Lead's metadata.`, + }, + { + name: 'Get All', + value: 'getAll', + description: 'Get all leads', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a lead', + }, + { + name: 'Add Lead To Campaign', + value: 'addToCampaign', + description: 'Add lead to a campaign', + }, + { + name: 'Add Note', + value: 'addNote', + description: 'Add note to a lead', + }, + ], + default: 'create', + description: 'The operation to perform.', + }, +] as INodeProperties[]; + +export const leadFields = [ + +/* -------------------------------------------------------------------------- */ +/* lead:create */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Company', + name: 'company', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'create', + ] + }, + }, + description: 'Company of the lead. If person account record types have been enabled, and if the value of Company is null, the lead converts to a person account.', + }, + { + displayName: 'Last Name', + name: 'lastname', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'create', + ] + }, + }, + description: 'Required. Last name of the lead. Limited to 80 characters.', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + displayName: 'City', + name: 'city', + type: 'string', + default: '', + description: 'City for the address of the lead.', + }, + { + displayName: 'Email', + name: 'email', + type: 'string', + default: '', + description: 'Email address for the lead.', + }, + { + displayName: 'Phone', + name: 'phone', + type: 'string', + default: '', + description: 'Phone number for the lead.', + }, + { + displayName: 'State', + name: 'state', + type: 'string', + default: '', + description: 'State for the address of the lead.', + }, + { + displayName: 'Title', + name: 'title', + type: 'string', + default: '', + description: 'Title for the lead, for example CFO or CEO.', + }, + { + displayName: 'Jigsaw', + name: 'jigsaw', + type: 'string', + default: '', + description: `references the ID of a contact in Data.com. + If a lead has a value in this field, it means that a contact was imported as a lead from Data.com.`, + }, + { + displayName: 'Rating', + name: 'rating', + type: 'string', + default: '', + description: 'Rating of the lead.', + }, + { + displayName: 'Status', + name: 'status', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getLeadStatuses', + }, + default: '', + description: 'Status code for this converted lead.', + }, + { + displayName: 'Street', + name: 'street', + type: 'string', + default: '', + description: 'Street number and name for the address of the lead', + }, + { + displayName: 'Owner', + name: 'owner', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getUsers', + }, + default: '', + description: 'The owner of the lead.', + }, + { + displayName: 'Website', + name: 'website', + type: 'string', + default: '', + description: 'Website for the lead.', + }, + { + displayName: 'Industry', + name: 'industry', + type: 'string', + default: '', + description: 'Website for the lead.', + }, + { + displayName: 'Fist Name', + name: 'firstname', + type: 'string', + default: '', + description: 'First name of the lead. Limited to 40 characters.', + }, + { + displayName: 'Lead Source', + name: 'leadSource', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getLeadSources', + }, + default: '', + description: 'Source from which the lead was obtained.', + }, + { + displayName: 'Postal Code', + name: 'postalCode', + type: 'string', + default: '', + description: 'Postal code for the address of the lead. Label is Zip/Postal Code.', + }, + { + displayName: 'Salutation', + name: 'salutation', + type: 'string', + default: '', + description: 'Salutation for the lead.', + }, + { + displayName: 'Description', + name: 'description', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: 'Description of the lead.', + }, + { + displayName: 'Annual Revenue', + name: 'annualRevenue', + type: 'number', + typeOptions: { + numberPrecision: 2, + numberStepSize: 1, + }, + default: '', + description: 'Annual revenue for the company of the lead.', + }, + { + displayName: 'Number Of Employees', + name: 'numberOfEmployees', + type: 'number', + typeOptions: { + numberStepSize: 1, + }, + default: '', + description: 'Number of employees at the lead’s company. Label is Employees.', + }, + { + displayName: 'Is Unread By Owner', + name: 'IsUnreadByOwner', + type: 'Boolean', + default: false, + description: 'If true, lead has been assigned, but not yet viewed. See Unread Leads for more information. Label is Unread By Owner.', + }, + ] + }, +/* -------------------------------------------------------------------------- */ +/* lead:update */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Lead ID', + name: 'leadId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'update', + ] + }, + }, + description: 'Id of Lead that needs to be fetched', + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + displayName: 'Company', + name: 'company', + type: 'string', + default: '', + description: 'Company of the lead. If person account record types have been enabled, and if the value of Company is null, the lead converts to a person account.', + }, + { + displayName: 'Last Name', + name: 'lastname', + type: 'string', + default: '', + description: 'Required. Last name of the lead. Limited to 80 characters.', + }, + { + displayName: 'City', + name: 'city', + type: 'string', + default: '', + description: 'City for the address of the lead.', + }, + { + displayName: 'Email', + name: 'email', + type: 'string', + default: '', + description: 'Email address for the lead.', + }, + { + displayName: 'Phone', + name: 'phone', + type: 'string', + default: '', + description: 'Phone number for the lead.', + }, + { + displayName: 'State', + name: 'state', + type: 'string', + default: '', + description: 'State for the address of the lead.', + }, + { + displayName: 'Title', + name: 'title', + type: 'string', + default: '', + description: 'Title for the lead, for example CFO or CEO.', + }, + { + displayName: 'Jigsaw', + name: 'jigsaw', + type: 'string', + default: '', + description: `references the ID of a contact in Data.com. + If a lead has a value in this field, it means that a contact was imported as a lead from Data.com.`, + }, + { + displayName: 'Rating', + name: 'rating', + type: 'string', + default: '', + description: 'Rating of the lead.', + }, + { + displayName: 'Status', + name: 'status', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getLeadStatuses', + }, + default: '', + description: 'Status code for this converted lead.', + }, + { + displayName: 'Street', + name: 'street', + type: 'string', + default: '', + description: 'Street number and name for the address of the lead', + }, + { + displayName: 'Owner', + name: 'owner', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getUsers', + }, + default: '', + description: 'The owner of the lead.', + }, + { + displayName: 'Website', + name: 'website', + type: 'string', + default: '', + description: 'Website for the lead.', + }, + { + displayName: 'Industry', + name: 'industry', + type: 'string', + default: '', + description: 'Website for the lead.', + }, + { + displayName: 'Fist Name', + name: 'firstname', + type: 'string', + default: '', + description: 'First name of the lead. Limited to 40 characters.', + }, + { + displayName: 'Lead Source', + name: 'leadSource', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getLeadSources', + }, + default: '', + description: 'Source from which the lead was obtained.', + }, + { + displayName: 'Postal Code', + name: 'postalCode', + type: 'string', + default: '', + description: 'Postal code for the address of the lead. Label is Zip/Postal Code.', + }, + { + displayName: 'Salutation', + name: 'salutation', + type: 'string', + default: '', + description: 'Salutation for the lead.', + }, + { + displayName: 'Description', + name: 'description', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: 'Description of the lead.', + }, + { + displayName: 'Annual Revenue', + name: 'annualRevenue', + type: 'number', + typeOptions: { + numberPrecision: 2, + numberStepSize: 1, + }, + default: '', + description: 'Annual revenue for the company of the lead.', + }, + { + displayName: 'Number Of Employees', + name: 'numberOfEmployees', + type: 'number', + typeOptions: { + numberStepSize: 1, + }, + default: '', + description: 'Number of employees at the lead’s company. Label is Employees.', + }, + { + displayName: 'Is Unread By Owner', + name: 'IsUnreadByOwner', + type: 'Boolean', + default: false, + description: 'If true, lead has been assigned, but not yet viewed. See Unread Leads for more information. Label is Unread By Owner.', + }, + ] + }, + +/* -------------------------------------------------------------------------- */ +/* lead:get */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Lead ID', + name: 'leadId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'get', + ] + }, + }, + description: 'Id of Lead that needs to be fetched', + }, +/* -------------------------------------------------------------------------- */ +/* lead:delete */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Lead ID', + name: 'leadId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'delete', + ] + }, + }, + description: 'Id of Lead that needs to be fetched', + }, +/* -------------------------------------------------------------------------- */ +/* lead:getAll */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'getAll', + ], + }, + }, + default: false, + description: 'If all results should be returned or only up to a given limit.', + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 100, + }, + default: 50, + description: 'How many results to return.', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'getAll', + ], + }, + }, + options: [ + { + displayName: 'Fields', + name: 'fields', + type: 'string', + default: '', + description: 'Fields to include separated by ,', + }, + ] + }, +/* -------------------------------------------------------------------------- */ +/* contact:addToCampaign */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Lead ID', + name: 'leadId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'addToCampaign', + ] + }, + }, + description: 'Id of contact that needs to be fetched', + }, + { + displayName: 'Campaign', + name: 'campaignId', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getCampaigns', + }, + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'addToCampaign', + ] + }, + }, + description: 'Id of the campaign that needs to be fetched', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'addToCampaign', + ], + }, + }, + options: [ + { + displayName: 'Status', + name: 'status', + type: 'string', + default: '', + description: 'Controls the HasResponded flag on this object', + }, + ] + }, +/* -------------------------------------------------------------------------- */ +/* lead:addNote */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Lead ID', + name: 'leadId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'addNote', + ] + }, + }, + description: 'Id of lead that needs to be fetched', + }, + { + displayName: 'Title', + name: 'title', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'addNote', + ] + }, + }, + description: 'Title of the note.', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'lead', + ], + operation: [ + 'addNote', + ], + }, + }, + options: [ + { + displayName: 'Body', + name: 'body', + type: 'string', + default: '', + typeOptions: { + alwaysOpenEditWindow: true, + }, + description: 'Body of the note. Limited to 32 KB.', + }, + { + displayName: 'Owner', + name: 'owner', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getUsers', + }, + default: '', + description: 'ID of the user who owns the note.', + }, + { + displayName: 'Is Private', + name: 'isPrivate', + type: 'boolean', + default: false, + description: 'If true, only the note owner or a user with the “Modify All Data” permission can view the note or query it via the API', + }, + ] + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Salesforce/LeadInterface.ts b/packages/nodes-base/nodes/Salesforce/LeadInterface.ts new file mode 100644 index 0000000000..c6cd047394 --- /dev/null +++ b/packages/nodes-base/nodes/Salesforce/LeadInterface.ts @@ -0,0 +1,26 @@ + +export interface ILead { + Company?: string; + LastName?: string; + Email?: string; + City?: string; + Phone?: string; + State?: string; + Title?: string; + Jigsaw?: string; + Rating?: string; + Status?: string; + Street?: string; + Country?: string; + OwnerId?: string; + Website?: string; + Industry?: string; + FirstName?: string; + LeadSource?: string; + PostalCode?: string; + Salutation?: string; + Description?: string; + AnnualRevenue?: number; + IsUnreadByOwner?: boolean; + NumberOfEmployees?: number; +} diff --git a/packages/nodes-base/nodes/Salesforce/NoteInterface.ts b/packages/nodes-base/nodes/Salesforce/NoteInterface.ts new file mode 100644 index 0000000000..2036cfea21 --- /dev/null +++ b/packages/nodes-base/nodes/Salesforce/NoteInterface.ts @@ -0,0 +1,8 @@ + +export interface INote { + Title?: string; + ParentId?: string; + Body?: string; + OwnerId?: string; + IsPrivate?: boolean; +} diff --git a/packages/nodes-base/nodes/Salesforce/OpportunityDescription.ts b/packages/nodes-base/nodes/Salesforce/OpportunityDescription.ts new file mode 100644 index 0000000000..89efd96478 --- /dev/null +++ b/packages/nodes-base/nodes/Salesforce/OpportunityDescription.ts @@ -0,0 +1,625 @@ +import { INodeProperties } from 'n8n-workflow'; + +export const opportunityOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'opportunity', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create an opportunity', + }, + { + name: 'Update', + value: 'update', + description: 'Update an opportunity', + }, + { + name: 'Get', + value: 'get', + description: 'Get an opportunity', + }, + { + name: 'Get Summary', + value: 'getSummary', + description: `Returns an overview of opportunity's metadata.`, + }, + { + name: 'Get All', + value: 'getAll', + description: 'Get all opportunitys', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete an opportunity', + }, + { + name: 'Add Note', + value: 'addNote', + description: 'Add note to an opportunity', + }, + ], + default: 'create', + description: 'The operation to perform.', + }, +] as INodeProperties[]; + +export const opportunityFields = [ + +/* -------------------------------------------------------------------------- */ +/* opportunity:create */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Name', + name: 'name', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'opportunity', + ], + operation: [ + 'create', + ] + }, + }, + description: 'Required. Last name of the opportunity. Limited to 80 characters.', + }, + { + displayName: 'Close Date', + name: 'closeDate', + type: 'dateTime', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'opportunity', + ], + operation: [ + 'create', + ] + }, + }, + description: 'Required. Date when the opportunity is expected to close.', + }, + { + displayName: 'Stage Name', + name: 'stageName', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getStages' + }, + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'opportunity', + ], + operation: [ + 'create', + ] + }, + }, + description: 'Required. Date when the opportunity is expected to close.', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'opportunity', + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + displayName: 'Type', + name: 'type', + type: 'options', + default: '', + options: [ + { + name: 'Business', + valie: 'Business', + }, + { + name: 'New Business', + valie: 'New Business', + }, + ], + description: 'Type of opportunity. For example, Existing Business or New Business. Label is Opportunity Type.', + }, + { + displayName: 'Amount', + name: 'amount', + type: 'number', + typeOptions: { + numberPrecision: 2, + }, + default: '', + description: 'Estimated total sale amount', + }, + { + displayName: 'Phone', + name: 'phone', + type: 'string', + default: '', + description: 'Phone number for the opportunity.', + }, + { + displayName: 'Owner', + name: 'owner', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getUsers', + }, + default: '', + description: 'The owner of the opportunity.', + }, + { + displayName: 'Next Step', + name: 'nextStep', + type: 'string', + default: '', + description: 'Description of next task in closing opportunity. Limit: 255 characters.', + }, + { + displayName: 'Account', + name: 'accountId', + type: 'options', + default: '', + typeOptions: { + loadOptionsMethod: 'getAccounts', + }, + description: 'ID of the account associated with this opportunity.', + }, + { + displayName: 'Campaign', + name: 'campaignId', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getCampaigns', + }, + default: '', + description: 'Id of the campaign that needs to be fetched', + }, + { + displayName: 'Lead Source', + name: 'leadSource', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getLeadSources', + }, + default: '', + description: 'Source from which the lead was obtained.', + }, + { + displayName: 'Description', + name: 'description', + type: 'string', + default: '', + description: 'A description of the opportunity. Label is Contact Description. Limit: 32 KB.', + }, + { + displayName: 'Probability', + name: 'probability', + type: 'number', + typeOptions: { + numberPrecision: 1, + }, + default: '', + description: 'Percentage of estimated confidence in closing the opportunity', + }, + { + displayName: 'Pricebook2 Id', + name: 'pricebook2Id', + type: 'string', + default: '', + description: 'ID of a related Pricebook2 object', + }, + { + displayName: 'Forecast Category Name', + name: 'forecastCategoryName', + type: 'string', + default: '', + description: 'It is implied, but not directly controlled, by the StageName field', + }, + ], + }, +/* -------------------------------------------------------------------------- */ +/* opportunity:update */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Opportunity ID', + name: 'opportunityId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'opportunity', + ], + operation: [ + 'update', + ] + }, + }, + description: 'Id of opportunity that needs to be fetched', + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'opportunity', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + description: 'Required. Last name of the opportunity. Limited to 80 characters.', + }, + { + displayName: 'Close Date', + name: 'closeDate', + type: 'dateTime', + default: '', + description: 'Required. Date when the opportunity is expected to close.', + }, + { + displayName: 'Stage Name', + name: 'stageName', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getStages' + }, + default: '', + description: 'Required. Date when the opportunity is expected to close.', + }, + { + displayName: 'Type', + name: 'type', + type: 'options', + default: '', + options: [ + { + name: 'Business', + valie: 'Business', + }, + { + name: 'New Business', + valie: 'New Business', + }, + ], + description: 'Type of opportunity. For example, Existing Business or New Business. Label is Opportunity Type.', + }, + { + displayName: 'Amount', + name: 'amount', + type: 'number', + typeOptions: { + numberPrecision: 2, + }, + default: '', + description: 'Estimated total sale amount', + }, + { + displayName: 'Phone', + name: 'phone', + type: 'string', + default: '', + description: 'Phone number for the opportunity.', + }, + { + displayName: 'Owner', + name: 'owner', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getUsers', + }, + default: '', + description: 'The owner of the opportunity.', + }, + { + displayName: 'Next Step', + name: 'nextStep', + type: 'string', + default: '', + description: 'Description of next task in closing opportunity. Limit: 255 characters.', + }, + { + displayName: 'Account', + name: 'accountId', + type: 'options', + default: '', + typeOptions: { + loadOptionsMethod: 'getAccounts', + }, + description: 'ID of the account associated with this opportunity.', + }, + { + displayName: 'Campaign', + name: 'campaignId', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getCampaigns', + }, + default: '', + description: 'Id of the campaign that needs to be fetched', + }, + { + displayName: 'Lead Source', + name: 'leadSource', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getLeadSources', + }, + default: '', + description: 'Source from which the lead was obtained.', + }, + { + displayName: 'Description', + name: 'description', + type: 'string', + default: '', + description: 'A description of the opportunity. Label is Contact Description. Limit: 32 KB.', + }, + { + displayName: 'Probability', + name: 'probability', + type: 'number', + typeOptions: { + numberPrecision: 1, + }, + default: '', + description: 'Percentage of estimated confidence in closing the opportunity', + }, + { + displayName: 'Pricebook2 Id', + name: 'pricebook2Id', + type: 'string', + default: '', + description: 'ID of a related Pricebook2 object', + }, + { + displayName: 'Forecast Category Name', + name: 'forecastCategoryName', + type: 'string', + default: '', + description: 'It is implied, but not directly controlled, by the StageName field', + }, + ], + }, + +/* -------------------------------------------------------------------------- */ +/* opportunity:get */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Opportunity ID', + name: 'opportunityId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'opportunity', + ], + operation: [ + 'get', + ] + }, + }, + description: 'Id of opportunity that needs to be fetched', + }, +/* -------------------------------------------------------------------------- */ +/* opportunity:delete */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Opportunity ID', + name: 'opportunityId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'opportunity', + ], + operation: [ + 'delete', + ] + }, + }, + description: 'Id of opportunity that needs to be fetched', + }, +/* -------------------------------------------------------------------------- */ +/* opportunity:getAll */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource: [ + 'opportunity', + ], + operation: [ + 'getAll', + ], + }, + }, + default: false, + description: 'If all results should be returned or only up to a given limit.', + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + resource: [ + 'opportunity', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 100, + }, + default: 50, + description: 'How many results to return.', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'opportunity', + ], + operation: [ + 'getAll', + ], + }, + }, + options: [ + { + displayName: 'Fields', + name: 'fields', + type: 'string', + default: '', + description: 'Fields to include separated by ,', + }, + ] + }, + +/* -------------------------------------------------------------------------- */ +/* opportunity:addNote */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Opportunity ID', + name: 'opportunityId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'opportunity', + ], + operation: [ + 'addNote', + ] + }, + }, + description: 'Id of opportunity that needs to be fetched', + }, + { + displayName: 'Title', + name: 'title', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'opportunity', + ], + operation: [ + 'addNote', + ] + }, + }, + description: 'Title of the note.', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'opportunity', + ], + operation: [ + 'addNote', + ], + }, + }, + options: [ + { + displayName: 'Body', + name: 'body', + type: 'string', + default: '', + typeOptions: { + alwaysOpenEditWindow: true, + }, + description: 'Body of the note. Limited to 32 KB.', + }, + { + displayName: 'Owner', + name: 'owner', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getUsers', + }, + default: '', + description: 'ID of the user who owns the note.', + }, + { + displayName: 'Is Private', + name: 'isPrivate', + type: 'boolean', + default: false, + description: 'If true, only the note owner or a user with the “Modify All Data” permission can view the note or query it via the API', + }, + ] + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Salesforce/OpportunityInterface.ts b/packages/nodes-base/nodes/Salesforce/OpportunityInterface.ts new file mode 100644 index 0000000000..bad4852648 --- /dev/null +++ b/packages/nodes-base/nodes/Salesforce/OpportunityInterface.ts @@ -0,0 +1,17 @@ + +export interface IOpportunity { + Name?: string; + StageName?: string; + CloseDate?: string; + Type?: string; + Amount?: number; + OwnerId?: string; + NextStep?: string; + AccountId?: string; + CampaignId?: string; + LeadSource?: string; + Description?: string; + Probability?: number; + Pricebook2Id?:string; + ForecastCategoryName?: string; +} diff --git a/packages/nodes-base/nodes/Salesforce/Salesforce.node.ts b/packages/nodes-base/nodes/Salesforce/Salesforce.node.ts new file mode 100644 index 0000000000..0c07520d61 --- /dev/null +++ b/packages/nodes-base/nodes/Salesforce/Salesforce.node.ts @@ -0,0 +1,1893 @@ +import { + IExecuteFunctions, +} from 'n8n-core'; +import { + IDataObject, + ILoadOptionsFunctions, + INodeTypeDescription, + INodeExecutionData, + INodeType, + INodePropertyOptions, +} from 'n8n-workflow'; +import { + salesforceApiRequest, + salesforceApiRequestAllItems, +} from './GenericFunctions'; +import { + leadFields, + leadOperations, +} from './LeadDescription'; +import { + contactFields, + contactOperations, +} from './ContactDescription'; +import { + opportunityOperations, + opportunityFields, + } from './OpportunityDescription'; + import { + accountOperations, + accountFields, + } from './AccountDescription'; + import { + caseOperations, + caseFields, + } from './CaseDescription'; + import { + taskOperations, + taskFields, + } from './TaskDescription'; + import { + attachmentOperations, + attachmentFields, + } from './AttachmentDescription'; + import { + IOpportunity, +} from './OpportunityInterface'; +import { + ICampaignMember, +} from './CampaignMemberInterface'; +import { + ILead, +} from './LeadInterface'; +import { + IContact, + } from './ContactInterface'; + import { + IAccount, + } from './AccountInterface'; + import { + INote, +} from './NoteInterface'; +import { + ICase, + ICaseComment, +} from './CaseInterface'; +import { + ITask, +} from './TaskInterface'; +import { + IAttachment, +} from './AttachmentInterface'; + +export class Salesforce implements INodeType { + description: INodeTypeDescription = { + displayName: 'Salesforce', + name: 'salesforce', + icon: 'file:salesforce.png', + group: ['output'], + version: 1, + subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', + description: 'Consume Salesforce API', + defaults: { + name: 'Salesforce', + color: '#429fd9', + }, + inputs: ['main'], + outputs: ['main'], + credentials: [ + { + name: 'salesforceOAuth2Api', + required: true, + }, + ], + properties: [ + { + displayName: 'Resource', + name: 'resource', + type: 'options', + options: [ + { + name: 'Lead', + value: 'lead', + description: 'Represents a prospect or potential .', + }, + { + name: 'Contact', + value: 'contact', + description: 'Represents a contact, which is an individual associated with an account.', + }, + { + name: 'Opportunity', + value: 'opportunity', + description: 'Represents an opportunity, which is a sale or pending deal.', + }, + { + name: 'Account', + value: 'account', + description: 'Represents an individual account, which is an organization or person involved with your business (such as customers, competitors, and partners).', + }, + { + name: 'Case', + value: 'case', + description: 'Represents a case, which is a customer issue or problem.', + }, + { + name: 'Task', + value: 'task', + description: 'Represents a business activity such as making a phone call or other to-do items. In the user interface, and records are collectively referred to as activities.', + }, + { + name: 'Attachment', + value: 'attachment', + description: 'Represents a file that a has uploaded and attached to a parent object.', + }, + ], + default: 'lead', + description: 'Resource to consume.', + }, + ...leadOperations, + ...leadFields, + ...contactOperations, + ...contactFields, + ...opportunityOperations, + ...opportunityFields, + ...accountOperations, + ...accountFields, + ...caseOperations, + ...caseFields, + ...taskOperations, + ...taskFields, + ...attachmentOperations, + ...attachmentFields, + ], + }; + + methods = { + loadOptions: { + // Get all the lead statuses to display them to user so that he can + // select them easily + async getLeadStatuses(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + const qs = { + q: 'SELECT id, MasterLabel FROM LeadStatus', + }; + const statuses = await salesforceApiRequestAllItems.call(this, 'records', 'GET', '/query', {}, qs); + for (const status of statuses) { + const statusName = status.MasterLabel; + const statusId = status.Id; + returnData.push({ + name: statusName, + value: statusId, + }); + } + return returnData; + }, + // Get all the users to display them to user so that he can + // select them easily + async getUsers(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + const qs = { + q: 'SELECT id, Name FROM User', + }; + const users = await salesforceApiRequestAllItems.call(this, 'records', 'GET', '/query', {}, qs); + for (const user of users) { + const userName = user.Name; + const userId = user.Id; + returnData.push({ + name: userName, + value: userId, + }); + } + return returnData; + }, + // Get all the lead sources to display them to user so that he can + // select them easily + async getLeadSources(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + //find a way to filter this object to get just the lead sources instead of the whole object + const { fields } = await salesforceApiRequest.call(this, 'GET', '/sobjects/lead/describe'); + for (const field of fields) { + if (field.name === 'LeadSource') { + for (const pickValue of field.picklistValues) { + const pickValueName = pickValue.label; + const pickValueId = pickValue.value; + returnData.push({ + name: pickValueName, + value: pickValueId, + }); + } + } + } + return returnData; + }, + // Get all the accounts to display them to user so that he can + // select them easily + async getAccounts(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + const qs = { + q: 'SELECT id, Name FROM Account', + }; + const accounts = await salesforceApiRequestAllItems.call(this, 'records', 'GET', '/query', {}, qs); + for (const account of accounts) { + const accountName = account.Name; + const accountId = account.Id; + returnData.push({ + name: accountName, + value: accountId, + }); + } + return returnData; + }, + // Get all the campaigns to display them to user so that he can + // select them easily + async getCampaigns(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + const qs = { + q: 'SELECT id, Name FROM Campaign', + }; + const campaigns = await salesforceApiRequestAllItems.call(this, 'records', 'GET', '/query', {}, qs); + for (const campaign of campaigns) { + const campaignName = campaign.Name; + const campaignId = campaign.Id; + returnData.push({ + name: campaignName, + value: campaignId, + }); + } + return returnData; + }, + // Get all the stages to display them to user so that he can + // select them easily + async getStages(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + //find a way to filter this object to get just the lead sources instead of the whole object + const { fields } = await salesforceApiRequest.call(this, 'GET', '/sobjects/opportunity/describe'); + for (const field of fields) { + if (field.name === 'StageName') { + for (const pickValue of field.picklistValues) { + const pickValueName = pickValue.label; + const pickValueId = pickValue.value; + returnData.push({ + name: pickValueName, + value: pickValueId, + }); + } + } + } + return returnData; + }, + // Get all the stages to display them to user so that he can + // select them easily + async getAccountTypes(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + //find a way to filter this object to get just the lead sources instead of the whole object + const { fields } = await salesforceApiRequest.call(this, 'GET', '/sobjects/account/describe'); + for (const field of fields) { + if (field.name === 'Type') { + for (const pickValue of field.picklistValues) { + const pickValueName = pickValue.label; + const pickValueId = pickValue.value; + returnData.push({ + name: pickValueName, + value: pickValueId, + }); + } + } + } + return returnData; + }, + // Get all the account sources to display them to user so that he can + // select them easily + async getAccountSources(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + //find a way to filter this object to get just the lead sources instead of the whole object + const { fields } = await salesforceApiRequest.call(this, 'GET', '/sobjects/account/describe'); + for (const field of fields) { + if (field.name === 'AccountSource') { + for (const pickValue of field.picklistValues) { + const pickValueName = pickValue.label; + const pickValueId = pickValue.value; + returnData.push({ + name: pickValueName, + value: pickValueId, + }); + } + } + } + return returnData; + }, + // Get all the case types to display them to user so that he can + // select them easily + async getCaseTypes(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + //find a way to filter this object to get just the lead sources instead of the whole object + const { fields } = await salesforceApiRequest.call(this, 'GET', '/sobjects/case/describe'); + for (const field of fields) { + if (field.name === 'Type') { + for (const pickValue of field.picklistValues) { + const pickValueName = pickValue.label; + const pickValueId = pickValue.value; + returnData.push({ + name: pickValueName, + value: pickValueId, + }); + } + } + } + return returnData; + }, + // Get all the case statuses to display them to user so that he can + // select them easily + async getCaseStatuses(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + //find a way to filter this object to get just the lead sources instead of the whole object + const { fields } = await salesforceApiRequest.call(this, 'GET', '/sobjects/case/describe'); + for (const field of fields) { + if (field.name === 'Status') { + for (const pickValue of field.picklistValues) { + const pickValueName = pickValue.label; + const pickValueId = pickValue.value; + returnData.push({ + name: pickValueName, + value: pickValueId, + }); + } + } + } + return returnData; + }, + // Get all the case reasons to display them to user so that he can + // select them easily + async getCaseReasons(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + //find a way to filter this object to get just the lead sources instead of the whole object + const { fields } = await salesforceApiRequest.call(this, 'GET', '/sobjects/case/describe'); + for (const field of fields) { + if (field.name === 'Reason') { + for (const pickValue of field.picklistValues) { + const pickValueName = pickValue.label; + const pickValueId = pickValue.value; + returnData.push({ + name: pickValueName, + value: pickValueId, + }); + } + } + } + return returnData; + }, + // Get all the case origins to display them to user so that he can + // select them easily + async getCaseOrigins(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + //find a way to filter this object to get just the lead sources instead of the whole object + const { fields } = await salesforceApiRequest.call(this, 'GET', '/sobjects/case/describe'); + for (const field of fields) { + if (field.name === 'Origin') { + for (const pickValue of field.picklistValues) { + const pickValueName = pickValue.label; + const pickValueId = pickValue.value; + returnData.push({ + name: pickValueName, + value: pickValueId, + }); + } + } + } + return returnData; + }, + // Get all the case priorities to display them to user so that he can + // select them easily + async getCasePriorities(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + //find a way to filter this object to get just the lead sources instead of the whole object + const { fields } = await salesforceApiRequest.call(this, 'GET', '/sobjects/case/describe'); + for (const field of fields) { + if (field.name === 'Priority') { + for (const pickValue of field.picklistValues) { + const pickValueName = pickValue.label; + const pickValueId = pickValue.value; + returnData.push({ + name: pickValueName, + value: pickValueId, + }); + } + } + } + return returnData; + }, + // Get all the task statuses to display them to user so that he can + // select them easily + async getTaskStatuses(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + //find a way to filter this object to get just the lead sources instead of the whole object + const { fields } = await salesforceApiRequest.call(this, 'GET', '/sobjects/task/describe'); + for (const field of fields) { + if (field.name === 'Status') { + for (const pickValue of field.picklistValues) { + const pickValueName = pickValue.label; + const pickValueId = pickValue.value; + returnData.push({ + name: pickValueName, + value: pickValueId, + }); + } + } + } + return returnData; + }, + // Get all the task subjects to display them to user so that he can + // select them easily + async getTaskSubjects(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + //find a way to filter this object to get just the lead sources instead of the whole object + const { fields } = await salesforceApiRequest.call(this, 'GET', '/sobjects/task/describe'); + for (const field of fields) { + if (field.name === 'Subject') { + for (const pickValue of field.picklistValues) { + const pickValueName = pickValue.label; + const pickValueId = pickValue.value; + returnData.push({ + name: pickValueName, + value: pickValueId, + }); + } + } + } + return returnData; + }, + // Get all the task call types to display them to user so that he can + // select them easily + async getTaskCallTypes(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + //find a way to filter this object to get just the lead sources instead of the whole object + const { fields } = await salesforceApiRequest.call(this, 'GET', '/sobjects/task/describe'); + for (const field of fields) { + if (field.name === 'CallType') { + for (const pickValue of field.picklistValues) { + const pickValueName = pickValue.label; + const pickValueId = pickValue.value; + returnData.push({ + name: pickValueName, + value: pickValueId, + }); + } + } + } + return returnData; + }, + // Get all the task call priorities to display them to user so that he can + // select them easily + async getTaskPriorities(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + //find a way to filter this object to get just the lead sources instead of the whole object + const { fields } = await salesforceApiRequest.call(this, 'GET', '/sobjects/task/describe'); + for (const field of fields) { + if (field.name === 'Priority') { + for (const pickValue of field.picklistValues) { + const pickValueName = pickValue.label; + const pickValueId = pickValue.value; + returnData.push({ + name: pickValueName, + value: pickValueId, + }); + } + } + } + return returnData; + }, + // Get all the task recurrence types to display them to user so that he can + // select them easily + async getTaskRecurrenceTypes(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + //find a way to filter this object to get just the lead sources instead of the whole object + const { fields } = await salesforceApiRequest.call(this, 'GET', '/sobjects/task/describe'); + for (const field of fields) { + if (field.name === 'RecurrenceType') { + for (const pickValue of field.picklistValues) { + const pickValueName = pickValue.label; + const pickValueId = pickValue.value; + returnData.push({ + name: pickValueName, + value: pickValueId, + }); + } + } + } + return returnData; + }, + // Get all the task recurrence instances to display them to user so that he can + // select them easily + async getTaskRecurrenceInstances(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + //find a way to filter this object to get just the lead sources instead of the whole object + const { fields } = await salesforceApiRequest.call(this, 'GET', '/sobjects/task/describe'); + for (const field of fields) { + if (field.name === 'RecurrenceInstance') { + for (const pickValue of field.picklistValues) { + const pickValueName = pickValue.label; + const pickValueId = pickValue.value; + returnData.push({ + name: pickValueName, + value: pickValueId, + }); + } + } + } + return returnData; + }, + }, + }; + + async execute(this: IExecuteFunctions): Promise { + const items = this.getInputData(); + const returnData: IDataObject[] = []; + const length = items.length as unknown as number; + let responseData; + const qs: IDataObject = {}; + const resource = this.getNodeParameter('resource', 0) as string; + const operation = this.getNodeParameter('operation', 0) as string; + + for (let i = 0; i < length; i++) { + if (resource === 'lead') { + //https://developer.salesforce.com/docs/api-explorer/sobject/Lead/post-lead + if (operation === 'create') { + const company = this.getNodeParameter('company', i) as string; + const lastname = this.getNodeParameter('lastname', i) as string; + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + const body: ILead = { + Company: company, + LastName: lastname, + }; + if (additionalFields.email) { + body.Email = additionalFields.email as string; + } + if (additionalFields.city) { + body.City = additionalFields.city as string; + } + if (additionalFields.phone) { + body.Phone = additionalFields.phone as string; + } + if (additionalFields.state) { + body.State = additionalFields.state as string; + } + if (additionalFields.title) { + body.Title = additionalFields.title as string; + } + if (additionalFields.jigsaw) { + body.Jigsaw = additionalFields.jigsaw as string; + } + if (additionalFields.rating) { + body.Rating = additionalFields.rating as string; + } + if (additionalFields.status) { + body.Status = additionalFields.status as string; + } + if (additionalFields.street) { + body.Street = additionalFields.street as string; + } + if (additionalFields.country) { + body.Country = additionalFields.country as string; + } + if (additionalFields.owner) { + body.OwnerId = additionalFields.owner as string; + } + if (additionalFields.website) { + body.Website = additionalFields.website as string; + } + if (additionalFields.industry) { + body.Industry = additionalFields.industry as string; + } + if (additionalFields.firstName) { + body.FirstName = additionalFields.firstName as string; + } + if (additionalFields.leadSource) { + body.LeadSource = additionalFields.leadSource as string; + } + if (additionalFields.postalCode) { + body.PostalCode = additionalFields.postalCode as string; + } + if (additionalFields.salutation) { + body.Salutation = additionalFields.salutation as string; + } + if (additionalFields.description) { + body.Description = additionalFields.description as string; + } + if (additionalFields.annualRevenue) { + body.AnnualRevenue = additionalFields.annualRevenue as number; + } + if (additionalFields.isUnreadByOwner) { + body.IsUnreadByOwner = additionalFields.isUnreadByOwner as boolean; + } + if (additionalFields.numberOfEmployees) { + body.NumberOfEmployees = additionalFields.numberOfEmployees as number; + } + responseData = await salesforceApiRequest.call(this, 'POST', '/sobjects/lead', body); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Lead/patch-lead-id + if (operation === 'update') { + const leadId = this.getNodeParameter('leadId', i) as string; + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + const body: ILead = {}; + if (!Object.keys(updateFields).length) { + throw new Error('You must add at least one update field'); + } + if (updateFields.lastname) { + body.LastName = updateFields.lastname as string; + } + if (updateFields.company) { + body.Company = updateFields.company as string; + } + if (updateFields.email) { + body.Email = updateFields.email as string; + } + if (updateFields.city) { + body.City = updateFields.city as string; + } + if (updateFields.phone) { + body.Phone = updateFields.phone as string; + } + if (updateFields.state) { + body.State = updateFields.state as string; + } + if (updateFields.title) { + body.Title = updateFields.title as string; + } + if (updateFields.jigsaw) { + body.Jigsaw = updateFields.jigsaw as string; + } + if (updateFields.rating) { + body.Rating = updateFields.rating as string; + } + if (updateFields.status) { + body.Status = updateFields.status as string; + } + if (updateFields.street) { + body.Street = updateFields.street as string; + } + if (updateFields.country) { + body.Country = updateFields.country as string; + } + if (updateFields.owner) { + body.OwnerId = updateFields.owner as string; + } + if (updateFields.website) { + body.Website = updateFields.website as string; + } + if (updateFields.industry) { + body.Industry = updateFields.industry as string; + } + if (updateFields.firstName) { + body.FirstName = updateFields.firstName as string; + } + if (updateFields.leadSource) { + body.LeadSource = updateFields.leadSource as string; + } + if (updateFields.postalCode) { + body.PostalCode = updateFields.postalCode as string; + } + if (updateFields.salutation) { + body.Salutation = updateFields.salutation as string; + } + if (updateFields.description) { + body.Description = updateFields.description as string; + } + if (updateFields.annualRevenue) { + body.AnnualRevenue = updateFields.annualRevenue as number; + } + if (updateFields.isUnreadByOwner) { + body.IsUnreadByOwner = updateFields.isUnreadByOwner as boolean; + } + if (updateFields.numberOfEmployees) { + body.NumberOfEmployees = updateFields.numberOfEmployees as number; + } + responseData = await salesforceApiRequest.call(this, 'PATCH', `/sobjects/lead/${leadId}`, body); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Lead/get-lead-id + if (operation === 'get') { + const leadId = this.getNodeParameter('leadId', i) as string; + responseData = await salesforceApiRequest.call(this, 'GET', `/sobjects/lead/${leadId}`); + } + //https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_query.htm + if (operation === 'getAll') { + const returnAll = this.getNodeParameter('returnAll', i) as boolean; + const options = this.getNodeParameter('options', i) as IDataObject; + const fields = ['id']; + if (options.fields) { + // @ts-ignore + fields.push(...options.fields.split(',')) + } + try { + if (returnAll) { + qs.q = `SELECT ${fields.join(',')} FROM Lead`, + responseData = await salesforceApiRequestAllItems.call(this, 'records', 'GET', '/query', {}, qs); + } else { + const limit = this.getNodeParameter('limit', i) as number; + qs.q = `SELECT ${fields.join(',')} FROM Lead Limit ${limit}`; + responseData = await salesforceApiRequestAllItems.call(this, 'records', 'GET', '/query', {}, qs); + } + } catch(err) { + throw new Error(`Salesforce Error: ${err}`); + } + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Lead/delete-lead-id + if (operation === 'delete') { + const leadId = this.getNodeParameter('leadId', i) as string; + try { + responseData = await salesforceApiRequest.call(this, 'DELETE', `/sobjects/lead/${leadId}`); + } catch(err) { + throw new Error(`Salesforce Error: ${err}`); + } + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Lead/get-lead + if (operation === 'getSummary') { + responseData = await salesforceApiRequest.call(this, 'GET', '/sobjects/lead'); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/CampaignMember + if (operation === 'addToCampaign') { + const leadId = this.getNodeParameter('leadId', i) as string; + const campaignId = this.getNodeParameter('campaignId', i) as string; + const options = this.getNodeParameter('options', i) as IDataObject; + const body: ICampaignMember = { + LeadId: leadId, + CampaignId: campaignId, + }; + if (options.status) { + body.Status = options.status as string; + } + responseData = await salesforceApiRequest.call(this, 'POST', '/sobjects/CampaignMember', body); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Note/post-note + if (operation === 'addNote') { + const leadId = this.getNodeParameter('leadId', i) as string; + const title = this.getNodeParameter('title', i) as string; + const options = this.getNodeParameter('options', i) as IDataObject; + const body: INote = { + Title: title, + ParentId: leadId, + }; + if (options.body) { + body.Body = options.body as string; + } + if (options.owner) { + body.OwnerId = options.owner as string; + } + if (options.isPrivate) { + body.IsPrivate = options.isPrivate as boolean; + } + responseData = await salesforceApiRequest.call(this, 'POST', '/sobjects/note', body); + } + } + if (resource === 'contact') { + //https://developer.salesforce.com/docs/api-explorer/sobject/Contact/post-contact + if (operation === 'create') { + const lastname = this.getNodeParameter('lastname', i) as string; + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + const body: IContact = { + LastName: lastname, + }; + if (additionalFields.fax) { + body.Fax = additionalFields.fax as string; + } + if (additionalFields.email) { + body.Email = additionalFields.email as string; + } + if (additionalFields.phone) { + body.Phone = additionalFields.phone as string; + } + if (additionalFields.title) { + body.Title = additionalFields.title as string; + } + if (additionalFields.jigsaw) { + body.Jigsaw = additionalFields.jigsaw as string; + } + if (additionalFields.owner) { + body.OwnerId = additionalFields.owner as string; + } + if (additionalFields.acconuntId) { + body.AccountId = additionalFields.acconuntId as string; + } + if (additionalFields.birthdate) { + body.Birthdate = additionalFields.birthdate as string; + } + if (additionalFields.firstName) { + body.FirstName = additionalFields.firstName as string; + } + if (additionalFields.homePhone) { + body.HomePhone = additionalFields.homePhone as string; + } + if (additionalFields.otherCity) { + body.OtherCity = additionalFields.otherCity as string; + } + if (additionalFields.department) { + body.Department = additionalFields.department as string; + } + if (additionalFields.leadSource) { + body.LeadSource = additionalFields.leadSource as string; + } + if (additionalFields.otherPhone) { + body.OtherPhone = additionalFields.otherPhone as string; + } + if (additionalFields.otherState) { + body.OtherState = additionalFields.otherState as string; + } + if (additionalFields.salutation) { + body.Salutation = additionalFields.salutation as string; + } + if (additionalFields.description) { + body.Description = additionalFields.description as string; + } + if (additionalFields.mailingCity) { + body.MailingCity = additionalFields.mailingCity as string; + } + if (additionalFields.mobilePhone) { + body.MobilePhone = additionalFields.mobilePhone as string; + } + if (additionalFields.otherStreet) { + body.OtherStreet = additionalFields.otherStreet as string; + } + if (additionalFields.mailingState) { + body.MailingState = additionalFields.mailingState as string; + } + if (additionalFields.otherCountry) { + body.OtherCountry = additionalFields.otherCountry as string; + } + if (additionalFields.assistantName) { + body.AssistantName = additionalFields.assistantName as string; + } + if (additionalFields.mailingStreet) { + body.MailingStreet = additionalFields.mailingStreet as string; + } + if (additionalFields.assistantPhone) { + body.AssistantPhone = additionalFields.assistantPhone as string; + } + if (additionalFields.mailingCountry) { + body.MailingCountry = additionalFields.mailingCountry as string; + } + if (additionalFields.otherPostalCode) { + body.OtherPostalCode = additionalFields.otherPostalCode as string; + } + if (additionalFields.emailBouncedDate) { + body.EmailBouncedDate = additionalFields.emailBouncedDate as string; + } + if (additionalFields.mailingPostalCode) { + body.MailingPostalCode = additionalFields.mailingPostalCode as string; + } + if (additionalFields.emailBouncedReason) { + body.EmailBouncedReason = additionalFields.emailBouncedReason as string; + } + responseData = await salesforceApiRequest.call(this, 'POST', '/sobjects/contact', body); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Contact/patch-contact-id + if (operation === 'update') { + const contactId = this.getNodeParameter('contactId', i) as string; + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + const body: IContact = {}; + if (!Object.keys(updateFields).length) { + throw new Error('You must add at least one update field'); + } + if (updateFields.fax) { + body.Fax = updateFields.fax as string; + } + if (updateFields.email) { + body.Email = updateFields.email as string; + } + if (updateFields.phone) { + body.Phone = updateFields.phone as string; + } + if (updateFields.title) { + body.Title = updateFields.title as string; + } + if (updateFields.jigsaw) { + body.Jigsaw = updateFields.jigsaw as string; + } + if (updateFields.owner) { + body.OwnerId = updateFields.owner as string; + } + if (updateFields.acconuntId) { + body.AccountId = updateFields.acconuntId as string; + } + if (updateFields.birthdate) { + body.Birthdate = updateFields.birthdate as string; + } + if (updateFields.firstName) { + body.FirstName = updateFields.firstName as string; + } + if (updateFields.homePhone) { + body.HomePhone = updateFields.homePhone as string; + } + if (updateFields.otherCity) { + body.OtherCity = updateFields.otherCity as string; + } + if (updateFields.department) { + body.Department = updateFields.department as string; + } + if (updateFields.leadSource) { + body.LeadSource = updateFields.leadSource as string; + } + if (updateFields.otherPhone) { + body.OtherPhone = updateFields.otherPhone as string; + } + if (updateFields.otherState) { + body.OtherState = updateFields.otherState as string; + } + if (updateFields.salutation) { + body.Salutation = updateFields.salutation as string; + } + if (updateFields.description) { + body.Description = updateFields.description as string; + } + if (updateFields.mailingCity) { + body.MailingCity = updateFields.mailingCity as string; + } + if (updateFields.mobilePhone) { + body.MobilePhone = updateFields.mobilePhone as string; + } + if (updateFields.otherStreet) { + body.OtherStreet = updateFields.otherStreet as string; + } + if (updateFields.mailingState) { + body.MailingState = updateFields.mailingState as string; + } + if (updateFields.otherCountry) { + body.OtherCountry = updateFields.otherCountry as string; + } + if (updateFields.assistantName) { + body.AssistantName = updateFields.assistantName as string; + } + if (updateFields.mailingStreet) { + body.MailingStreet = updateFields.mailingStreet as string; + } + if (updateFields.assistantPhone) { + body.AssistantPhone = updateFields.assistantPhone as string; + } + if (updateFields.mailingCountry) { + body.MailingCountry = updateFields.mailingCountry as string; + } + if (updateFields.otherPostalCode) { + body.OtherPostalCode = updateFields.otherPostalCode as string; + } + if (updateFields.emailBouncedDate) { + body.EmailBouncedDate = updateFields.emailBouncedDate as string; + } + if (updateFields.mailingPostalCode) { + body.MailingPostalCode = updateFields.mailingPostalCode as string; + } + if (updateFields.emailBouncedReason) { + body.EmailBouncedReason = updateFields.emailBouncedReason as string; + } + responseData = await salesforceApiRequest.call(this, 'PATCH', `/sobjects/contact/${contactId}`, body); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Contact/get-contact-id + if (operation === 'get') { + const contactId = this.getNodeParameter('contactId', i) as string; + responseData = await salesforceApiRequest.call(this, 'GET', `/sobjects/contact/${contactId}`); + } + //https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_query.htm + if (operation === 'getAll') { + const returnAll = this.getNodeParameter('returnAll', i) as boolean; + const options = this.getNodeParameter('options', i) as IDataObject; + const fields = ['id']; + if (options.fields) { + // @ts-ignore + fields.push(...options.fields.split(',')) + } + try { + if (returnAll) { + qs.q = `SELECT ${fields.join(',')} FROM Contact`, + responseData = await salesforceApiRequestAllItems.call(this, 'records', 'GET', '/query', {}, qs); + } else { + const limit = this.getNodeParameter('limit', i) as number; + qs.q = `SELECT ${fields.join(',')} FROM Contact Limit ${limit}`; + responseData = await salesforceApiRequestAllItems.call(this, 'records', 'GET', '/query', {}, qs); + } + } catch(err) { + throw new Error(`Salesforce Error: ${err}`); + } + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Contact/delete-contact-id + if (operation === 'delete') { + const contactId = this.getNodeParameter('contactId', i) as string; + try { + responseData = await salesforceApiRequest.call(this, 'DELETE', `/sobjects/contact/${contactId}`); + } catch(err) { + throw new Error(`Salesforce Error: ${err}`); + } + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Contact/get-contact + if (operation === 'getSummary') { + responseData = await salesforceApiRequest.call(this, 'GET', '/sobjects/contact'); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/CampaignMember + if (operation === 'addToCampaign') { + const contactId = this.getNodeParameter('contactId', i) as string; + const campaignId = this.getNodeParameter('campaignId', i) as string; + const options = this.getNodeParameter('options', i) as IDataObject; + const body: ICampaignMember = { + ContactId: contactId, + CampaignId: campaignId, + }; + if (options.status) { + body.Status = options.status as string; + } + responseData = await salesforceApiRequest.call(this, 'POST', '/sobjects/CampaignMember', body); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Note/post-note + if (operation === 'addNote') { + const contactId = this.getNodeParameter('contactId', i) as string; + const title = this.getNodeParameter('title', i) as string; + const options = this.getNodeParameter('options', i) as IDataObject; + const body: INote = { + Title: title, + ParentId: contactId, + }; + if (options.body) { + body.Body = options.body as string; + } + if (options.owner) { + body.OwnerId = options.owner as string; + } + if (options.isPrivate) { + body.IsPrivate = options.isPrivate as boolean; + } + responseData = await salesforceApiRequest.call(this, 'POST', '/sobjects/note', body); + } + } + if (resource === 'opportunity') { + //https://developer.salesforce.com/docs/api-explorer/sobject/Opportunity/post-opportunity + if (operation === 'create') { + const name = this.getNodeParameter('name', i) as string; + const closeDate = this.getNodeParameter('closeDate', i) as string; + const stageName = this.getNodeParameter('stageName', i) as string; + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + const body: IOpportunity = { + Name: name, + CloseDate: closeDate, + StageName: stageName, + }; + if (additionalFields.type) { + body.Type = additionalFields.type as string; + } + if (additionalFields.ammount) { + body.Amount = additionalFields.ammount as number; + } + if (additionalFields.owner) { + body.OwnerId = additionalFields.owner as string; + } + if (additionalFields.nextStep) { + body.NextStep = additionalFields.nextStep as string; + } + if (additionalFields.accountId) { + body.AccountId = additionalFields.accountId as string; + } + if (additionalFields.campaignId) { + body.CampaignId = additionalFields.campaignId as string; + } + if (additionalFields.leadSource) { + body.LeadSource = additionalFields.leadSource as string; + } + if (additionalFields.description) { + body.Description = additionalFields.description as string; + } + if (additionalFields.probability) { + body.Probability = additionalFields.probability as number; + } + if (additionalFields.pricebook2Id) { + body.Pricebook2Id = additionalFields.pricebook2Id as string; + } + if (additionalFields.forecastCategoryName) { + body.ForecastCategoryName = additionalFields.forecastCategoryName as string; + } + responseData = await salesforceApiRequest.call(this, 'POST', '/sobjects/opportunity', body); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Opportunity/post-opportunity + if (operation === 'update') { + const opportunityId = this.getNodeParameter('opportunityId', i) as string; + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + const body: IOpportunity = {}; + if (updateFields.name) { + body.Name = updateFields.name as string; + } + if (updateFields.closeDate) { + body.CloseDate = updateFields.closeDate as string; + } + if (updateFields.stageName) { + body.StageName = updateFields.stageName as string; + } + if (updateFields.type) { + body.Type = updateFields.type as string; + } + if (updateFields.ammount) { + body.Amount = updateFields.ammount as number; + } + if (updateFields.owner) { + body.OwnerId = updateFields.owner as string; + } + if (updateFields.nextStep) { + body.NextStep = updateFields.nextStep as string; + } + if (updateFields.accountId) { + body.AccountId = updateFields.accountId as string; + } + if (updateFields.campaignId) { + body.CampaignId = updateFields.campaignId as string; + } + if (updateFields.leadSource) { + body.LeadSource = updateFields.leadSource as string; + } + if (updateFields.description) { + body.Description = updateFields.description as string; + } + if (updateFields.probability) { + body.Probability = updateFields.probability as number; + } + if (updateFields.pricebook2Id) { + body.Pricebook2Id = updateFields.pricebook2Id as string; + } + if (updateFields.forecastCategoryName) { + body.ForecastCategoryName = updateFields.forecastCategoryName as string; + } + responseData = await salesforceApiRequest.call(this, 'PATCH', `/sobjects/opportunity/${opportunityId}`, body); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Opportunity/get-opportunity-id + if (operation === 'get') { + const opportunityId = this.getNodeParameter('opportunityId', i) as string; + responseData = await salesforceApiRequest.call(this, 'GET', `/sobjects/opportunity/${opportunityId}`); + } + //https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_query.htm + if (operation === 'getAll') { + const returnAll = this.getNodeParameter('returnAll', i) as boolean; + const options = this.getNodeParameter('options', i) as IDataObject; + const fields = ['id']; + if (options.fields) { + // @ts-ignore + fields.push(...options.fields.split(',')) + } + try { + if (returnAll) { + qs.q = `SELECT ${fields.join(',')} FROM Opportunity`, + responseData = await salesforceApiRequestAllItems.call(this, 'records', 'GET', '/query', {}, qs); + } else { + const limit = this.getNodeParameter('limit', i) as number; + qs.q = `SELECT ${fields.join(',')} FROM Opportunity Limit ${limit}`; + responseData = await salesforceApiRequestAllItems.call(this, 'records', 'GET', '/query', {}, qs); + } + } catch(err) { + throw new Error(`Salesforce Error: ${err}`); + } + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Opportunity/delete-opportunity-id + if (operation === 'delete') { + const opportunityId = this.getNodeParameter('opportunityId', i) as string; + try { + responseData = await salesforceApiRequest.call(this, 'DELETE', `/sobjects/opportunity/${opportunityId}`); + } catch(err) { + throw new Error(`Salesforce Error: ${err}`); + } + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Opportunity/get-opportunity + if (operation === 'getSummary') { + responseData = await salesforceApiRequest.call(this, 'GET', '/sobjects/opportunity'); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Note/post-note + if (operation === 'addNote') { + const opportunityId = this.getNodeParameter('opportunityId', i) as string; + const title = this.getNodeParameter('title', i) as string; + const options = this.getNodeParameter('options', i) as IDataObject; + const body: INote = { + Title: title, + ParentId: opportunityId, + }; + if (options.body) { + body.Body = options.body as string; + } + if (options.owner) { + body.OwnerId = options.owner as string; + } + if (options.isPrivate) { + body.IsPrivate = options.isPrivate as boolean; + } + responseData = await salesforceApiRequest.call(this, 'POST', '/sobjects/note', body); + } + } + if (resource === 'account') { + //https://developer.salesforce.com/docs/api-explorer/sobject/Account/post-account + if (operation === 'create') { + const name = this.getNodeParameter('name', i) as string; + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + const body: IAccount = { + Name: name, + }; + if (additionalFields.fax) { + body.Fax = additionalFields.fax as string; + } + if (additionalFields.type) { + body.Type = additionalFields.type as string; + } + if (additionalFields.jigsaw) { + body.Jigsaw = additionalFields.jigsaw as string; + } + if (additionalFields.phone) { + body.Phone = additionalFields.phone as string; + } + if (additionalFields.owner) { + body.OwnerId = additionalFields.owner as string; + } + if (additionalFields.sicDesc) { + body.SicDesc = additionalFields.sicDesc as string; + } + if (additionalFields.website) { + body.Website = additionalFields.website as string; + } + if (additionalFields.industry) { + body.Industry = additionalFields.industry as string; + } + if (additionalFields.parentId) { + body.ParentId = additionalFields.parentId as string; + } + if (additionalFields.billingCity) { + body.BillingCity = additionalFields.billingCity as string; + } + if (additionalFields.description) { + body.Description = additionalFields.description as string; + } + if (additionalFields.billingState) { + body.BillingState = additionalFields.billingState as string; + } + if (additionalFields.shippingCity) { + body.ShippingCity = additionalFields.shippingCity as string; + } + if (additionalFields.accountSource) { + body.AccountSource = additionalFields.accountSource as string; + } + if (additionalFields.annualRevenue) { + body.AnnualRevenue = additionalFields.annualRevenue as number; + } + if (additionalFields.billingStreet) { + body.BillingStreet = additionalFields.billingStreet as string; + } + if (additionalFields.shippingState) { + body.ShippingState = additionalFields.shippingState as string; + } + if (additionalFields.billingCountry) { + body.BillingCountry = additionalFields.billingCountry as string; + } + if (additionalFields.shippingStreet) { + body.ShippingStreet = additionalFields.shippingStreet as string; + } + if (additionalFields.shippingCountry) { + body.ShippingCountry = additionalFields.shippingCountry as string; + } + if (additionalFields.billingPostalCode) { + body.BillingPostalCode = additionalFields.billingPostalCode as string; + } + if (additionalFields.numberOfEmployees) { + body.NumberOfEmployees = additionalFields.numberOfEmployees as string; + } + if (additionalFields.shippingPostalCode) { + body.ShippingPostalCode = additionalFields.shippingPostalCode as string; + } + if (additionalFields.shippingPostalCode) { + body.ShippingPostalCode = additionalFields.shippingPostalCode as string; + } + responseData = await salesforceApiRequest.call(this, 'POST', '/sobjects/account', body); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Account/patch-account-id + if (operation === 'update') { + const accountId = this.getNodeParameter('accountId', i) as string; + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + const body: IAccount = {}; + if (updateFields.name) { + body.Name = updateFields.name as string; + } + if (updateFields.fax) { + body.Fax = updateFields.fax as string; + } + if (updateFields.type) { + body.Type = updateFields.type as string; + } + if (updateFields.jigsaw) { + body.Jigsaw = updateFields.jigsaw as string; + } + if (updateFields.phone) { + body.Phone = updateFields.phone as string; + } + if (updateFields.owner) { + body.OwnerId = updateFields.owner as string; + } + if (updateFields.sicDesc) { + body.SicDesc = updateFields.sicDesc as string; + } + if (updateFields.website) { + body.Website = updateFields.website as string; + } + if (updateFields.industry) { + body.Industry = updateFields.industry as string; + } + if (updateFields.parentId) { + body.ParentId = updateFields.parentId as string; + } + if (updateFields.billingCity) { + body.BillingCity = updateFields.billingCity as string; + } + if (updateFields.description) { + body.Description = updateFields.description as string; + } + if (updateFields.billingState) { + body.BillingState = updateFields.billingState as string; + } + if (updateFields.shippingCity) { + body.ShippingCity = updateFields.shippingCity as string; + } + if (updateFields.accountSource) { + body.AccountSource = updateFields.accountSource as string; + } + if (updateFields.annualRevenue) { + body.AnnualRevenue = updateFields.annualRevenue as number; + } + if (updateFields.billingStreet) { + body.BillingStreet = updateFields.billingStreet as string; + } + if (updateFields.shippingState) { + body.ShippingState = updateFields.shippingState as string; + } + if (updateFields.billingCountry) { + body.BillingCountry = updateFields.billingCountry as string; + } + if (updateFields.shippingStreet) { + body.ShippingStreet = updateFields.shippingStreet as string; + } + if (updateFields.shippingCountry) { + body.ShippingCountry = updateFields.shippingCountry as string; + } + if (updateFields.billingPostalCode) { + body.BillingPostalCode = updateFields.billingPostalCode as string; + } + if (updateFields.numberOfEmployees) { + body.NumberOfEmployees = updateFields.numberOfEmployees as string; + } + if (updateFields.shippingPostalCode) { + body.ShippingPostalCode = updateFields.shippingPostalCode as string; + } + if (updateFields.shippingPostalCode) { + body.ShippingPostalCode = updateFields.shippingPostalCode as string; + } + responseData = await salesforceApiRequest.call(this, 'PATCH', `/sobjects/account/${accountId}`, body); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Account/get-account-id + if (operation === 'get') { + const accountId = this.getNodeParameter('accountId', i) as string; + responseData = await salesforceApiRequest.call(this, 'GET', `/sobjects/account/${accountId}`); + } + //https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_query.htm + if (operation === 'getAll') { + const returnAll = this.getNodeParameter('returnAll', i) as boolean; + const options = this.getNodeParameter('options', i) as IDataObject; + const fields = ['id']; + if (options.fields) { + // @ts-ignore + fields.push(...options.fields.split(',')) + } + try { + if (returnAll) { + qs.q = `SELECT ${fields.join(',')} FROM Account`, + responseData = await salesforceApiRequestAllItems.call(this, 'records', 'GET', '/query', {}, qs); + } else { + const limit = this.getNodeParameter('limit', i) as number; + qs.q = `SELECT ${fields.join(',')} FROM Account Limit ${limit}`; + responseData = await salesforceApiRequestAllItems.call(this, 'records', 'GET', '/query', {}, qs); + } + } catch(err) { + throw new Error(`Salesforce Error: ${err}`); + } + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Account/delete-account-id + if (operation === 'delete') { + const accountId = this.getNodeParameter('accountId', i) as string; + try { + responseData = await salesforceApiRequest.call(this, 'DELETE', `/sobjects/account/${accountId}`); + } catch(err) { + throw new Error(`Salesforce Error: ${err}`); + } + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Account/get-account + if (operation === 'getSummary') { + responseData = await salesforceApiRequest.call(this, 'GET', '/sobjects/account'); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Note/post-note + if (operation === 'addNote') { + const accountId = this.getNodeParameter('accountId', i) as string; + const title = this.getNodeParameter('title', i) as string; + const options = this.getNodeParameter('options', i) as IDataObject; + const body: INote = { + Title: title, + ParentId: accountId, + }; + if (options.body) { + body.Body = options.body as string; + } + if (options.owner) { + body.OwnerId = options.owner as string; + } + if (options.isPrivate) { + body.IsPrivate = options.isPrivate as boolean; + } + responseData = await salesforceApiRequest.call(this, 'POST', '/sobjects/note', body); + } + } + if (resource === 'case') { + //https://developer.salesforce.com/docs/api-explorer/sobject/Case/post-case + if (operation === 'create') { + const type = this.getNodeParameter('type', i) as string; + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + const body: ICase = { + Type: type, + }; + if (additionalFields.origin) { + body.Origin = additionalFields.origin as string; + } + if (additionalFields.reason) { + body.Reason = additionalFields.reason as string; + } + if (additionalFields.owner) { + body.OwnerId = additionalFields.owner as string; + } + if (additionalFields.subject) { + body.Subject = additionalFields.subject as string; + } + if (additionalFields.parentId) { + body.ParentId = additionalFields.parentId as string; + } + if (additionalFields.priority) { + body.Priority = additionalFields.priority as string; + } + if (additionalFields.accountId) { + body.AccountId = additionalFields.accountId as string; + } + if (additionalFields.contactId) { + body.ContactId = additionalFields.contactId as string; + } + if (additionalFields.description) { + body.Description = additionalFields.description as string; + } + if (additionalFields.isEscalated) { + body.IsEscalated = additionalFields.isEscalated as boolean; + } + if (additionalFields.suppliedName) { + body.SuppliedName = additionalFields.suppliedName as string; + } + if (additionalFields.suppliedEmail) { + body.SuppliedEmail = additionalFields.suppliedEmail as string; + } + if (additionalFields.suppliedPhone) { + body.SuppliedPhone = additionalFields.suppliedPhone as string; + } + if (additionalFields.suppliedCompany) { + body.SuppliedCompany = additionalFields.suppliedCompany as string; + } + responseData = await salesforceApiRequest.call(this, 'POST', '/sobjects/case', body); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Case/patch-case-id + if (operation === 'update') { + const caseId = this.getNodeParameter('caseId', i) as string; + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + const body: ICase = {}; + if (updateFields.type) { + body.Type = updateFields.type as string; + } + if (updateFields.origin) { + body.Origin = updateFields.origin as string; + } + if (updateFields.reason) { + body.Reason = updateFields.reason as string; + } + if (updateFields.owner) { + body.OwnerId = updateFields.owner as string; + } + if (updateFields.subject) { + body.Subject = updateFields.subject as string; + } + if (updateFields.parentId) { + body.ParentId = updateFields.parentId as string; + } + if (updateFields.priority) { + body.Priority = updateFields.priority as string; + } + if (updateFields.accountId) { + body.AccountId = updateFields.accountId as string; + } + if (updateFields.contactId) { + body.ContactId = updateFields.contactId as string; + } + if (updateFields.description) { + body.Description = updateFields.description as string; + } + if (updateFields.isEscalated) { + body.IsEscalated = updateFields.isEscalated as boolean; + } + if (updateFields.suppliedName) { + body.SuppliedName = updateFields.suppliedName as string; + } + if (updateFields.suppliedEmail) { + body.SuppliedEmail = updateFields.suppliedEmail as string; + } + if (updateFields.suppliedPhone) { + body.SuppliedPhone = updateFields.suppliedPhone as string; + } + if (updateFields.suppliedCompany) { + body.SuppliedCompany = updateFields.suppliedCompany as string; + } + responseData = await salesforceApiRequest.call(this, 'PATCH', `/sobjects/case/${caseId}`, body); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Case/get-case-id + if (operation === 'get') { + const caseId = this.getNodeParameter('caseId', i) as string; + responseData = await salesforceApiRequest.call(this, 'GET', `/sobjects/case/${caseId}`); + } + //https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_query.htm + if (operation === 'getAll') { + const returnAll = this.getNodeParameter('returnAll', i) as boolean; + const options = this.getNodeParameter('options', i) as IDataObject; + const fields = ['id']; + if (options.fields) { + // @ts-ignore + fields.push(...options.fields.split(',')) + } + try { + if (returnAll) { + qs.q = `SELECT ${fields.join(',')} FROM Case`, + responseData = await salesforceApiRequestAllItems.call(this, 'records', 'GET', '/query', {}, qs); + } else { + const limit = this.getNodeParameter('limit', i) as number; + qs.q = `SELECT ${fields.join(',')} FROM Case Limit ${limit}`; + responseData = await salesforceApiRequestAllItems.call(this, 'records', 'GET', '/query', {}, qs); + } + } catch(err) { + throw new Error(`Salesforce Error: ${err}`); + } + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Case/delete-case-id + if (operation === 'delete') { + const caseId = this.getNodeParameter('caseId', i) as string; + try { + responseData = await salesforceApiRequest.call(this, 'DELETE', `/sobjects/case/${caseId}`); + } catch(err) { + throw new Error(`Salesforce Error: ${err}`); + } + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Case/get-case + if (operation === 'getSummary') { + responseData = await salesforceApiRequest.call(this, 'GET', '/sobjects/case'); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/CaseComment/post-casecomment + if (operation === 'addComment') { + const caseId = this.getNodeParameter('caseId', i) as string; + const options = this.getNodeParameter('options', i) as IDataObject; + const body: ICaseComment = { + ParentId: caseId, + }; + if (options.commentBody) { + body.CommentBody = options.commentBody as string; + } + if (options.isPublished) { + body.IsPublished = options.isPublished as boolean; + } + responseData = await salesforceApiRequest.call(this, 'POST', '/sobjects/casecomment', body); + } + } + if (resource === 'task') { + //https://developer.salesforce.com/docs/api-explorer/sobject/Task/post-task + if (operation === 'create') { + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + const status = this.getNodeParameter('status', i) as string; + const body: ITask = { + Status: status, + }; + if (additionalFields.whoId) { + body.WhoId = additionalFields.whoId as string; + } + if (additionalFields.whatId) { + body.WhatId = additionalFields.whatId as string; + } + if (additionalFields.owner) { + body.OwnerId = additionalFields.owner as string; + } + if (additionalFields.subject) { + body.Subject = additionalFields.subject as string; + } + if (additionalFields.callType) { + body.CallType = additionalFields.callType as string; + } + if (additionalFields.priority) { + body.Priority = additionalFields.priority as string; + } + if (additionalFields.callObject) { + body.CallObject = additionalFields.callObject as string; + } + if (additionalFields.description) { + body.Description = additionalFields.description as string; + } + if (additionalFields.activityDate) { + body.ActivityDate = additionalFields.activityDate as string; + } + if (additionalFields.isReminderSet) { + body.IsReminderSet = additionalFields.isReminderSet as boolean; + } + if (additionalFields.recurrenceType) { + body.RecurrenceType = additionalFields.recurrenceType as string; + } + if (additionalFields.callDisposition) { + body.CallDisposition = additionalFields.callDisposition as string; + } + if (additionalFields.reminderDateTime) { + body.ReminderDateTime = additionalFields.reminderDateTime as string; + } + if (additionalFields.recurrenceInstance) { + body.RecurrenceInstance = additionalFields.recurrenceInstance as string; + } + if (additionalFields.recurrenceInterval) { + body.RecurrenceInterval = additionalFields.recurrenceInterval as number; + } + if (additionalFields.recurrenceDayOfMonth) { + body.RecurrenceDayOfMonth = additionalFields.recurrenceDayOfMonth as number; + } + if (additionalFields.callDurationInSeconds) { + body.CallDurationInSeconds = additionalFields.callDurationInSeconds as number; + } + if (additionalFields.recurrenceEndDateOnly) { + body.RecurrenceEndDateOnly = additionalFields.recurrenceEndDateOnly as string; + } + if (additionalFields.recurrenceMonthOfYear) { + body.RecurrenceMonthOfYear = additionalFields.recurrenceMonthOfYear as string; + } + if (additionalFields.recurrenceDayOfWeekMask) { + body.RecurrenceDayOfWeekMask = additionalFields.recurrenceDayOfWeekMask as string; + } + if (additionalFields.recurrenceStartDateOnly) { + body.RecurrenceStartDateOnly = additionalFields.recurrenceStartDateOnly as string; + } + if (additionalFields.recurrenceTimeZoneSidKey) { + body.RecurrenceTimeZoneSidKey = additionalFields.recurrenceTimeZoneSidKey as string; + } + if (additionalFields.recurrenceRegeneratedType) { + body.RecurrenceRegeneratedType = additionalFields.recurrenceRegeneratedType as string; + } + responseData = await salesforceApiRequest.call(this, 'POST', '/sobjects/task', body); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Task/patch-task-id + if (operation === 'update') { + const taskId = this.getNodeParameter('taskId', i) as string; + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + const body: ITask = {}; + if (updateFields.whoId) { + body.WhoId = updateFields.whoId as string; + } + if (updateFields.status) { + body.Status = updateFields.status as string; + } + if (updateFields.whatId) { + body.WhatId = updateFields.whatId as string; + } + if (updateFields.owner) { + body.OwnerId = updateFields.owner as string; + } + if (updateFields.subject) { + body.Subject = updateFields.subject as string; + } + if (updateFields.callType) { + body.CallType = updateFields.callType as string; + } + if (updateFields.priority) { + body.Priority = updateFields.priority as string; + } + if (updateFields.callObject) { + body.CallObject = updateFields.callObject as string; + } + if (updateFields.description) { + body.Description = updateFields.description as string; + } + if (updateFields.activityDate) { + body.ActivityDate = updateFields.activityDate as string; + } + if (updateFields.isReminderSet) { + body.IsReminderSet = updateFields.isReminderSet as boolean; + } + if (updateFields.recurrenceType) { + body.RecurrenceType = updateFields.recurrenceType as string; + } + if (updateFields.callDisposition) { + body.CallDisposition = updateFields.callDisposition as string; + } + if (updateFields.reminderDateTime) { + body.ReminderDateTime = updateFields.reminderDateTime as string; + } + if (updateFields.recurrenceInstance) { + body.RecurrenceInstance = updateFields.recurrenceInstance as string; + } + if (updateFields.recurrenceInterval) { + body.RecurrenceInterval = updateFields.recurrenceInterval as number; + } + if (updateFields.recurrenceDayOfMonth) { + body.RecurrenceDayOfMonth = updateFields.recurrenceDayOfMonth as number; + } + if (updateFields.callDurationInSeconds) { + body.CallDurationInSeconds = updateFields.callDurationInSeconds as number; + } + if (updateFields.recurrenceEndDateOnly) { + body.RecurrenceEndDateOnly = updateFields.recurrenceEndDateOnly as string; + } + if (updateFields.recurrenceMonthOfYear) { + body.RecurrenceMonthOfYear = updateFields.recurrenceMonthOfYear as string; + } + if (updateFields.recurrenceDayOfWeekMask) { + body.RecurrenceDayOfWeekMask = updateFields.recurrenceDayOfWeekMask as string; + } + if (updateFields.recurrenceStartDateOnly) { + body.RecurrenceStartDateOnly = updateFields.recurrenceStartDateOnly as string; + } + if (updateFields.recurrenceTimeZoneSidKey) { + body.RecurrenceTimeZoneSidKey = updateFields.recurrenceTimeZoneSidKey as string; + } + if (updateFields.recurrenceRegeneratedType) { + body.RecurrenceRegeneratedType = updateFields.recurrenceRegeneratedType as string; + } + responseData = await salesforceApiRequest.call(this, 'PATCH', `/sobjects/task/${taskId}`, body); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Task/get-task-id + if (operation === 'get') { + const taskId = this.getNodeParameter('taskId', i) as string; + responseData = await salesforceApiRequest.call(this, 'GET', `/sobjects/task/${taskId}`); + } + //https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_query.htm + if (operation === 'getAll') { + const returnAll = this.getNodeParameter('returnAll', i) as boolean; + const options = this.getNodeParameter('options', i) as IDataObject; + const fields = ['id']; + if (options.fields) { + // @ts-ignore + fields.push(...options.fields.split(',')) + } + try { + if (returnAll) { + qs.q = `SELECT ${fields.join(',')} FROM Task`, + responseData = await salesforceApiRequestAllItems.call(this, 'records', 'GET', '/query', {}, qs); + } else { + const limit = this.getNodeParameter('limit', i) as number; + qs.q = `SELECT ${fields.join(',')} FROM Task Limit ${limit}`; + responseData = await salesforceApiRequestAllItems.call(this, 'records', 'GET', '/query', {}, qs); + } + } catch(err) { + throw new Error(`Salesforce Error: ${err}`); + } + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Task/delete-task-id + if (operation === 'delete') { + const taskId = this.getNodeParameter('taskId', i) as string; + try { + responseData = await salesforceApiRequest.call(this, 'DELETE', `/sobjects/task/${taskId}`); + } catch(err) { + throw new Error(`Salesforce Error: ${err}`); + } + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Task/get-task + if (operation === 'getSummary') { + responseData = await salesforceApiRequest.call(this, 'GET', '/sobjects/task'); + } + } + if (resource === 'attachment') { + //https://developer.salesforce.com/docs/api-explorer/sobject/Attachment/post-attachment + if (operation === 'create') { + const name = this.getNodeParameter('name', i) as string; + const parentId = this.getNodeParameter('parentId', i) as string; + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i) as string; + const body: IAttachment = { + Name: name, + ParentId: parentId, + }; + if (items[i].binary && items[i].binary![binaryPropertyName]) { + body.Body = items[i].binary![binaryPropertyName].data; + body.ContentType = items[i].binary![binaryPropertyName].mimeType; + } else { + throw new Error(`The property ${binaryPropertyName} does not exist`); + } + if (additionalFields.description) { + body.Description = additionalFields.description as string; + } + if (additionalFields.owner) { + body.OwnerId = additionalFields.owner as string; + } + if (additionalFields.isPrivate) { + body.IsPrivate = additionalFields.isPrivate as boolean; + } + responseData = await salesforceApiRequest.call(this, 'POST', '/sobjects/attachment', body); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Attachment/patch-attachment-id + if (operation === 'update') { + const attachmentId = this.getNodeParameter('attachmentId', i) as string; + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + const body: IAttachment = {}; + if (updateFields.binaryPropertyName) { + const binaryPropertyName = updateFields.binaryPropertyName as string; + if (items[i].binary && items[i].binary![binaryPropertyName]) { + body.Body = items[i].binary![binaryPropertyName].data; + body.ContentType = items[i].binary![binaryPropertyName].mimeType; + } else { + throw new Error(`The property ${binaryPropertyName} does not exist`); + } + } + if (updateFields.name) { + body.Name = updateFields.name as string; + } + if (updateFields.description) { + body.Description = updateFields.description as string; + } + if (updateFields.owner) { + body.OwnerId = updateFields.owner as string; + } + if (updateFields.isPrivate) { + body.IsPrivate = updateFields.isPrivate as boolean; + } + responseData = await salesforceApiRequest.call(this, 'PATCH', `/sobjects/attachment/${attachmentId}`, body); + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Attachment/get-attachment-id + if (operation === 'get') { + const attachmentId = this.getNodeParameter('attachmentId', i) as string; + responseData = await salesforceApiRequest.call(this, 'GET', `/sobjects/attachment/${attachmentId}`); + } + //https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_query.htm + if (operation === 'getAll') { + const returnAll = this.getNodeParameter('returnAll', i) as boolean; + const options = this.getNodeParameter('options', i) as IDataObject; + const fields = ['id']; + if (options.fields) { + // @ts-ignore + fields.push(...options.fields.split(',')) + } + try { + if (returnAll) { + qs.q = `SELECT ${fields.join(',')} FROM Attachment`, + responseData = await salesforceApiRequestAllItems.call(this, 'records', 'GET', '/query', {}, qs); + } else { + const limit = this.getNodeParameter('limit', i) as number; + qs.q = `SELECT ${fields.join(',')} FROM Attachment Limit ${limit}`; + responseData = await salesforceApiRequestAllItems.call(this, 'records', 'GET', '/query', {}, qs); + } + } catch(err) { + throw new Error(`Salesforce Error: ${err}`); + } + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Attachment/delete-attachment-id + if (operation === 'delete') { + const attachmentId = this.getNodeParameter('attachmentId', i) as string; + try { + responseData = await salesforceApiRequest.call(this, 'DELETE', `/sobjects/attachment/${attachmentId}`); + } catch(err) { + throw new Error(`Salesforce Error: ${err}`); + } + } + //https://developer.salesforce.com/docs/api-explorer/sobject/Attachment/get-attachment-id + if (operation === 'getSummary') { + responseData = await salesforceApiRequest.call(this, 'GET', '/sobjects/attachment'); + } + } + if (Array.isArray(responseData)) { + returnData.push.apply(returnData, responseData as IDataObject[]); + } else { + returnData.push(responseData as IDataObject); + } + } + return [this.helpers.returnJsonArray(returnData)]; + } +} diff --git a/packages/nodes-base/nodes/Salesforce/TaskDescription.ts b/packages/nodes-base/nodes/Salesforce/TaskDescription.ts new file mode 100644 index 0000000000..79e13ec34f --- /dev/null +++ b/packages/nodes-base/nodes/Salesforce/TaskDescription.ts @@ -0,0 +1,810 @@ +import { INodeProperties } from 'n8n-workflow'; + +export const taskOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'task', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a task', + }, + { + name: 'Update', + value: 'update', + description: 'Update a task', + }, + { + name: 'Get', + value: 'get', + description: 'Get a task', + }, + { + name: 'Get Summary', + value: 'getSummary', + description: `Returns an overview of task's metadata.`, + }, + { + name: 'Get All', + value: 'getAll', + description: 'Get all tasks', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a task', + }, + ], + default: 'create', + description: 'The operation to perform.', + }, +] as INodeProperties[]; + +export const taskFields = [ + +/* -------------------------------------------------------------------------- */ +/* task:create */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Status', + name: 'status', + type: 'options', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'create', + ], + }, + }, + typeOptions: { + loadOptionsMethod: 'getTaskStatuses', + }, + description: 'The current status of the task, such as In Progress or Completed.', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + displayName: 'Who Id', + name: 'whoId', + type: 'string', + default: '', + description: `The WhoId represents a human such as a lead or a contact.
+ WhoIds are polymorphic. Polymorphic means a WhoId is equivalent to a contact’s ID or a lead’s ID.`, + }, + { + displayName: 'What Id', + name: 'whatId', + type: 'string', + default: '', + description: `The WhatId represents nonhuman objects such as accounts, opportunities,
+ campaigns, cases, or custom objects. WhatIds are polymorphic. Polymorphic means a
+ WhatId is equivalent to the ID of a related object.`, + }, + { + displayName: 'Owner', + name: 'owner', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getUsers', + }, + default: '', + description: 'ID of the User who owns the record.', + }, + { + displayName: 'Subject', + name: 'subject', + type: 'options', + default: '', + typeOptions: { + loadOptionsMethod: 'getTaskSubjects', + }, + description: 'The subject line of the task, such as “Call” or “Send Quote.” Limit: 255 characters.', + }, + { + displayName: 'Call Type', + name: 'callType', + type: 'options', + default: '', + typeOptions: { + loadOptionsMethod: 'getTaskCallTypes', + }, + description: 'The type of call being answered: Inbound, Internal, or Outbound.', + }, + { + displayName: 'Priority', + name: 'priority', + type: 'options', + default: '', + typeOptions: { + loadOptionsMethod: 'getTaskPriorities', + }, + description: `Indicates the importance or urgency of a task, such as high or low.`, + }, + { + displayName: 'Call Object', + name: 'callObject', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: `Name of a call center. Limit is 255 characters.
+ Not subject to field-level security, available for any user in an
+ organization with Salesforce CRM Call Center.`, + }, + { + displayName: 'Description', + name: 'description', + type: 'string', + default: '', + typeOptions: { + alwaysOpenEditWindow: true, + }, + description: 'Contains a text description of the task.', + }, + { + displayName: 'Activity Date', + name: 'activityDate', + type: 'dateTime', + default: '', + description: `Represents the due date of the task.
+ This field has a timestamp that is always set to midnight
+ in the Coordinated Universal Time (UTC) time zone.`, + }, + { + displayName: 'Is ReminderSet', + name: 'isReminderSet', + type: 'boolean', + default: false, + description: 'Indicates whether a popup reminder has been set for the task (true) or not (false).', + }, + { + displayName: 'Recurrence Type', + name: 'recurrenceType', + type: 'options', + default: '', + typeOptions: { + loadOptionsMethod: 'getTaskRecurrenceTypes' + }, + description: 'Website for the task.', + }, + { + displayName: 'Call Disposition', + name: 'callDisposition', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: `Represents the result of a given call, for example, “we'll call back,” or “call
+ unsuccessful.” Limit is 255 characters. Not subject to field-level security, available for any user
+ in an organization with Salesforce CRM Call Center.`, + }, + { + displayName: 'Reminder Date Time', + name: 'reminderDateTime', + type: 'dateTime', + default: '', + description: `Represents the time when the reminder is scheduled to fire,
+ if IsReminderSet is set to true. If IsReminderSet is set to false, then the
+ user may have deselected the reminder checkbox in the Salesforce user interface,
+ or the reminder has already fired at the time indicated by the value.`, + }, + { + displayName: 'Recurrence Instance', + name: 'recurrenceInstance', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getTaskRecurrenceInstances', + }, + default: '', + description: `The frequency of the recurring task. For example, “2nd” or “3rd.”`, + }, + { + displayName: 'Recurrence Interval', + name: 'recurrenceInterval', + type: 'number', + default: '', + description: 'The interval between recurring tasks.', + }, + { + displayName: 'Recurrence Day Of Month', + name: 'recurrenceDayOfMonth', + type: 'number', + default: '', + description: 'The day of the month in which the task repeats.', + }, + { + displayName: 'Call Duration In Seconds', + name: 'callDurationInSeconds', + type: 'number', + default: '', + description: `Duration of the call in seconds. Not subject to field-level security,
+ available for any user in an organization with Salesforce CRM Call Cente`, + }, + { + displayName: 'Recurrence End Date Only', + name: 'recurrenceEndDateOnly', + type: 'dateTime', + default: '', + description: `The last date on which the task repeats. This field has a timestamp that
+ is always set to midnight in the Coordinated Universal Time (UTC) time zone.`, + }, + { + displayName: 'Recurrence Month Of Year', + name: 'recurrenceMonthOfYear', + type: 'options', + options: [ + { + name: 'January', + value: 'January' + }, + { + name: 'February', + value: 'February' + }, + { + name: 'March', + value: 'March' + }, + { + name: 'April', + value: 'April' + }, + { + name: 'May', + value: 'May' + }, + { + name: 'June', + value: 'June' + }, + { + name: 'July', + value: 'July' + }, + { + name: 'August', + value: 'August' + }, + { + name: 'September', + value: 'September' + }, + { + name: 'October', + value: 'October' + }, + { + name: 'November', + value: 'November' + }, + { + name: 'December', + value: 'December' + } + ], + default: '', + description: 'The month of the year in which the task repeats.', + }, + { + displayName: 'Recurrence Day Of Week Mask', + name: 'recurrenceDayOfWeekMask', + type: 'number', + default: '', + description: `The day or days of the week on which the task repeats.
+ This field contains a bitmask. The values are as follows: Sunday = 1 Monday = 2
+ Tuesday = 4 Wednesday = 8 Thursday = 16 Friday = 32 Saturday = 64
+ Multiple days are represented as the sum of their numerical values.
+ For example, Tuesday and Thursday = 4 + 16 = 20.`, + }, + { + displayName: 'recurrence Start Date Only', + name: 'recurrenceEndDateOnly', + type: 'dateTime', + default: '', + description: `The date when the recurring task begins.
+ Must be a date and time before RecurrenceEndDateOnly.`, + }, + { + displayName: 'Recurrence TimeZone SidKey', + name: 'recurrenceTimeZoneSidKey', + type: 'string', + default: '', + description: `The time zone associated with the recurring task.
+ For example, “UTC-8:00” for Pacific Standard Time.`, + }, + { + displayName: 'Recurrence Regenerated Type', + name: 'recurrenceRegeneratedType', + type: 'options', + default: '', + options: [ + { + name: 'After due date', + value: 'RecurrenceRegenerateAfterDueDate' + }, + { + name: 'After date completed', + value: 'RecurrenceRegenerateAfterToday' + }, + { + name: '(Task Closed)', + value: 'RecurrenceRegenerated' + } + ], + description: `Represents what triggers a repeating task to repeat.
+ Add this field to a page layout together with the RecurrenceInterval field,
+ which determines the number of days between the triggering date (due date or close date)
+ and the due date of the next repeating task in the series.Label is Repeat This Task.`, + }, + ] + }, +/* -------------------------------------------------------------------------- */ +/* task:update */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Task ID', + name: 'taskId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'update', + ] + }, + }, + description: 'Id of task that needs to be fetched', + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + displayName: 'Who Id', + name: 'whoId', + type: 'string', + default: '', + description: `The WhoId represents a human such as a lead or a contact.
+ WhoIds are polymorphic. Polymorphic means a WhoId is equivalent to a contact’s ID or a lead’s ID.`, + }, + { + displayName: 'Status', + name: 'status', + type: 'options', + default: '', + typeOptions: { + loadOptionsMethod: 'getTaskStatuses', + }, + description: 'The current status of the task, such as In Progress or Completed.', + }, + { + displayName: 'What Id', + name: 'whatId', + type: 'string', + default: '', + description: `The WhatId represents nonhuman objects such as accounts, opportunities,
+ campaigns, cases, or custom objects. WhatIds are polymorphic. Polymorphic means a
+ WhatId is equivalent to the ID of a related object.`, + }, + { + displayName: 'Owner', + name: 'owner', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getUsers', + }, + default: '', + description: 'ID of the User who owns the record.', + }, + { + displayName: 'Subject', + name: 'subject', + type: 'options', + default: '', + typeOptions: { + loadOptionsMethod: 'getTaskSubjects', + }, + description: 'The subject line of the task, such as “Call” or “Send Quote.” Limit: 255 characters.', + }, + { + displayName: 'Call Type', + name: 'callType', + type: 'options', + default: '', + typeOptions: { + loadOptionsMethod: 'getTaskCallTypes', + }, + description: 'The type of call being answered: Inbound, Internal, or Outbound.', + }, + { + displayName: 'Priority', + name: 'priority', + type: 'options', + default: '', + typeOptions: { + loadOptionsMethod: 'getTaskPriorities', + }, + description: `Indicates the importance or urgency of a task, such as high or low.`, + }, + { + displayName: 'Call Object', + name: 'callObject', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: `Name of a call center. Limit is 255 characters.
+ Not subject to field-level security, available for any user in an
+ organization with Salesforce CRM Call Center.`, + }, + { + displayName: 'Description', + name: 'description', + type: 'string', + default: '', + typeOptions: { + alwaysOpenEditWindow: true, + }, + description: 'Contains a text description of the task.', + }, + { + displayName: 'Activity Date', + name: 'activityDate', + type: 'dateTime', + default: '', + description: `Represents the due date of the task.
+ This field has a timestamp that is always set to midnight
+ in the Coordinated Universal Time (UTC) time zone.`, + }, + { + displayName: 'Is ReminderSet', + name: 'isReminderSet', + type: 'boolean', + default: false, + description: 'Indicates whether a popup reminder has been set for the task (true) or not (false).', + }, + { + displayName: 'Recurrence Type', + name: 'recurrenceType', + type: 'options', + default: '', + typeOptions: { + loadOptionsMethod: 'getTaskRecurrenceTypes' + }, + description: 'Website for the task.', + }, + { + displayName: 'Call Disposition', + name: 'callDisposition', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: `Represents the result of a given call, for example, “we'll call back,” or “call
+ unsuccessful.” Limit is 255 characters. Not subject to field-level security, available for any user
+ in an organization with Salesforce CRM Call Center.`, + }, + { + displayName: 'Reminder Date Time', + name: 'reminderDateTime', + type: 'dateTime', + default: '', + description: `Represents the time when the reminder is scheduled to fire,
+ if IsReminderSet is set to true. If IsReminderSet is set to false, then the
+ user may have deselected the reminder checkbox in the Salesforce user interface,
+ or the reminder has already fired at the time indicated by the value.`, + }, + { + displayName: 'Recurrence Instance', + name: 'recurrenceInstance', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getTaskRecurrenceInstances', + }, + default: '', + description: `The frequency of the recurring task. For example, “2nd” or “3rd.”`, + }, + { + displayName: 'Recurrence Interval', + name: 'recurrenceInterval', + type: 'number', + default: '', + description: 'The interval between recurring tasks.', + }, + { + displayName: 'Recurrence Day Of Month', + name: 'recurrenceDayOfMonth', + type: 'number', + default: '', + description: 'The day of the month in which the task repeats.', + }, + { + displayName: 'Call Duration In Seconds', + name: 'callDurationInSeconds', + type: 'number', + default: '', + description: `Duration of the call in seconds. Not subject to field-level security,
+ available for any user in an organization with Salesforce CRM Call Cente`, + }, + { + displayName: 'Recurrence End Date Only', + name: 'recurrenceEndDateOnly', + type: 'dateTime', + default: '', + description: `The last date on which the task repeats. This field has a timestamp that
+ is always set to midnight in the Coordinated Universal Time (UTC) time zone.`, + }, + { + displayName: 'Recurrence Month Of Year', + name: 'recurrenceMonthOfYear', + type: 'options', + options: [ + { + name: 'January', + value: 'January' + }, + { + name: 'February', + value: 'February' + }, + { + name: 'March', + value: 'March' + }, + { + name: 'April', + value: 'April' + }, + { + name: 'May', + value: 'May' + }, + { + name: 'June', + value: 'June' + }, + { + name: 'July', + value: 'July' + }, + { + name: 'August', + value: 'August' + }, + { + name: 'September', + value: 'September' + }, + { + name: 'October', + value: 'October' + }, + { + name: 'November', + value: 'November' + }, + { + name: 'December', + value: 'December' + } + ], + default: '', + description: 'The month of the year in which the task repeats.', + }, + { + displayName: 'Recurrence Day Of Week Mask', + name: 'recurrenceDayOfWeekMask', + type: 'number', + default: '', + description: `The day or days of the week on which the task repeats.
+ This field contains a bitmask. The values are as follows: Sunday = 1 Monday = 2
+ Tuesday = 4 Wednesday = 8 Thursday = 16 Friday = 32 Saturday = 64
+ Multiple days are represented as the sum of their numerical values.
+ For example, Tuesday and Thursday = 4 + 16 = 20.`, + }, + { + displayName: 'recurrence Start Date Only', + name: 'recurrenceEndDateOnly', + type: 'dateTime', + default: '', + description: `The date when the recurring task begins.
+ Must be a date and time before RecurrenceEndDateOnly.`, + }, + { + displayName: 'Recurrence TimeZone SidKey', + name: 'recurrenceTimeZoneSidKey', + type: 'string', + default: '', + description: `The time zone associated with the recurring task.
+ For example, “UTC-8:00” for Pacific Standard Time.`, + }, + { + displayName: 'Recurrence Regenerated Type', + name: 'recurrenceRegeneratedType', + type: 'options', + default: '', + options: [ + { + name: 'After due date', + value: 'RecurrenceRegenerateAfterDueDate' + }, + { + name: 'After date completed', + value: 'RecurrenceRegenerateAfterToday' + }, + { + name: '(Task Closed)', + value: 'RecurrenceRegenerated' + } + ], + description: `Represents what triggers a repeating task to repeat.
+ Add this field to a page layout together with the RecurrenceInterval field,
+ which determines the number of days between the triggering date (due date or close date)
+ and the due date of the next repeating task in the series.Label is Repeat This Task.`, + }, + ] + }, + +/* -------------------------------------------------------------------------- */ +/* task:get */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Task ID', + name: 'taskId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'get', + ] + }, + }, + description: 'Id of task that needs to be fetched', + }, +/* -------------------------------------------------------------------------- */ +/* task:delete */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Task ID', + name: 'taskId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'delete', + ] + }, + }, + description: 'Id of task that needs to be fetched', + }, +/* -------------------------------------------------------------------------- */ +/* task:getAll */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'getAll', + ], + }, + }, + default: false, + description: 'If all results should be returned or only up to a given limit.', + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 100, + }, + default: 50, + description: 'How many results to return.', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'getAll', + ], + }, + }, + options: [ + { + displayName: 'Fields', + name: 'fields', + type: 'string', + default: '', + description: 'Fields to include separated by ,', + }, + ] + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Salesforce/TaskInterface.ts b/packages/nodes-base/nodes/Salesforce/TaskInterface.ts new file mode 100644 index 0000000000..06f932e799 --- /dev/null +++ b/packages/nodes-base/nodes/Salesforce/TaskInterface.ts @@ -0,0 +1,27 @@ + +export interface ITask { + WhoId?: string; + Status?: string; + WhatId?: string; + OwnerId?: string; + Subject?: string; + CallType?: string; + Priority?: string; + CallObject?: string; + Description?: string; + ActivityDate?: string; + IsReminderSet?: boolean; + RecurrenceType?: string; + CallDisposition?:string; + ReminderDateTime?: string; + RecurrenceInstance?: string; + RecurrenceInterval?: number; + RecurrenceDayOfMonth?: number; + CallDurationInSeconds?: number; + RecurrenceEndDateOnly?: string; + RecurrenceMonthOfYear?: string; + RecurrenceDayOfWeekMask?: string; + RecurrenceStartDateOnly?: string; + RecurrenceTimeZoneSidKey?: string; + RecurrenceRegeneratedType?: string; +} diff --git a/packages/nodes-base/nodes/Salesforce/salesforce.png b/packages/nodes-base/nodes/Salesforce/salesforce.png new file mode 100644 index 0000000000000000000000000000000000000000..17876e8dea85a243646b59dc3590f58e1f938232 GIT binary patch literal 3210 zcmd5<`9DtaMj_0Yv5b8wP0C)@ zY}uEYF*6ujma)$m^EvbWen0=i=e+K7Kj(E{&vjk*bHC2{;l$ZknI1fF^Z)<=2VrJL zaB#I_-#naPKJ{gC4O}<^;iiT_X}8220B`~}7Iwy_eilG}N6nO69OA9698Feg8|(p5Oo>3|oZF0{h7U)yP0Li382n z`M3CgrXY8cO$XJ`)8HPE2nM*H1EhdGW5)lV`w47=%n8b7ks%lgsL8fKf`SwdG#P>> z134rB>>u<(kvQ2WVv9h~;OW>Ik~_l*4k4S!$wnz`9Ttl-n+RkRK?;yT0J5k68k_)e zABxC{B(lJfW)Xl)0vCv86M%F)@Cgqomg&hhNkFGSfQ0Er6Na z+hf&CZ$gS!Ah}e(_Qhi2`jI@6b?xlvDqSR>WK%mE*|R)BqcfO$$Z;BCc(stY9^AR~ zXK5#Gght)mt)^_05Z4>1TQ1EDcbgYTYYZTH49LV=FP=*UzY8D;ZeyIX3@wjV;mM4Z{6*@1wR-pUg3zc9m@Y z^&X6Vo#EDb@7uWI(s>*b7j-;RO>W(r$K^@@#_7x(H=fpwugS-%{jz^gB(TK)rVvW& zm_#B=I`Z1l+-vmu6PK;!$g91^lWOop$hEK15@k}$l(kn)@_ZKqfBEL`y3+cOz32@V zs$WQL>-@rh7;5mAIX$$RY~=pQO3%NwW3Ucbc`B_h2NhQEoR>aV5vSmET2!MwuH|P) zQKqk}-isUcH>$nc3(K)R3^Y-Sv-O#4%8Z7ZLjvU|R6>mI=l>?0DGj_*1xU6RRL;b@ z!>Sa#Cmb83WvVW%m`7SBkc`AgDJytXRd4N=wV;Ystr(abRH`f?v%coaY33pBA2gGM z;9#?p#a{zF<#?pfjX1+$T_-IV94VL~-~`{)7bW$zj()xWBaSfT6VId861er4nDKeJ zUw-^Ku;Qe=b_nN?DYoJaT@Xl-Dd&1)Gjh+m?M?WBm0InRLn;z=8O`tFXAUpHW}~*o znk#1g0j^TM@cDLX>gmjCl{R^Jy$*`=xD+iHhau7LQLx$E`A`}AdI z8)sjR7~GY;V_Bo6ONy$H)097&;_S#!tTL0xKsdQ37P!XYZlBRwYLH9}7x3i^ocdy{7FUR!O34f4${aGLVUd15s@ zA9rWW(@t~rNQ#Zubj;-&gD+!(N4$ES!UXMMEuX^kPZmD!&zdH@#91JTFx2%=InA@VhJdDC!zYwnvL7VJa&^{dU{*)8eJi5)RBt%hqGVI_Va&N!8Vc_pRRf8i9IV$45jpvr zH%ME*EguR`Nq97olH`5ar`=))qqT3SH}ug5H^&t719u6Mj*jrqn<_>3EzzaTL4#iZ zsBRp;WD|OpbEvbjAf>zxb9BZ#_aRp-Yv)L@uI>ZjsvSd>u_d>yN{KT@U6WZsagG)%b`WWsazZLn zO5%dkQW8pk@R3Ruy&tS`KQ4b>X|JiB-Yu3{@u5RCjE@x%*&Xg@mxbRILSSp~-ldF0 zOy^C3cD*Ebf}Ve!A~8JH)!-LzycnvVVI1u7!_~+B*y-9)*PV9*{;}a(64SU_7X1e} z5$3srjT8n6rjo)^DM3U$v-j_Ogj9K3pRYVcTl0j8kb>w%t+7b*h(n zQ-m=!WTXC2L6xx@4Pk>Y1cz#q)1YP1iB@{9Q3QQ81D9%gnjtByZfr% z?I$+&S-)(8ZVqDQHr%g<-93j$?|Ybs5x$*v$MRZC<%t9X6I;af5C*mr=IkKZqp5}0 zobdsgsA4X+_ezsbu#&DRe|zo0v(HkdHK{Y{v*Kp@K!9DHn9`Nw4&rWHmS{&Ajq-OL zW>niV;}IgGd!^r=`fs(hwCIT6Ol+-k9+h+pue8usA@Lmi{1xC z*NL|wMQcS=CG^)3eP0f8cX(A2kKXG%bN-^Llw*L0ykFYl1?%y=3N?DBBxiB3S-u2a z!FpUF!jl{iH;)yP^~HCmmAcXLeB1)0loKD{+MCF_>TEso>K&JY!so8=Z)l@6=YlB# zJ>osbgqil+k{7c%hrC{1aTobej+m0;w;ocW`YtNVCzTGF3RYYaYB`2ThrCg@(opkm zda*REB)F?IFndw>&b9Y^Azp+Y**lKfk9XFWRPt?sq$(e$hbzy>>CT+270;$j7YT!& zC!RAN8B*6raT>q*5A~ZuYl|ftqD}@3XINy59xA#Usy(o(7N(dscSq}0xk%K9h6Ode zc*pMZ#x>Ce3YqL`5w+>mB_t06v)`|57{2Dq-q@_N%`46jT7&XV=EViR z*AA;xx=|LlHd=$yvq&9%ds383uErtV^D{ALvWqgjZNVSQbL%-&yiK$5>QA9Kqy9#> ztwta|g6}%-xaZ}1*APru#{RONIPR5q>NRulYZR@0+kD!uq<0OvFUhtpTngRN=sOiM z`(~Gj>RUzdj*c`y($VH(IEW2#5hDQ|4N7ZP@Hz+?X7QJLTdT-;GTq5-T=a$d*x z>DW51D&yBrqv!suCTCAy9`}TGG9j+-%`>g??G#?^Dc=W7Mp-fkl`hcc#IN2-7@NA_ zGp?a)*lW|?99@ZbHFa86nQ@d3F literal 0 HcmV?d00001 diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index 0ae62f9f07..938424c6c9 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -69,6 +69,7 @@ "dist/credentials/SlackApi.credentials.js", "dist/credentials/Smtp.credentials.js", "dist/credentials/StripeApi.credentials.js", + "dist/credentials/SalesforceOAuth2Api.credentials.js", "dist/credentials/TelegramApi.credentials.js", "dist/credentials/TodoistApi.credentials.js", "dist/credentials/TrelloApi.credentials.js", @@ -160,6 +161,7 @@ "dist/nodes/Stripe/StripeTrigger.node.js", "dist/nodes/Shopify/ShopifyTrigger.node.js", "dist/nodes/Switch.node.js", + "dist/nodes/Salesforce/Salesforce.node.js", "dist/nodes/Telegram/Telegram.node.js", "dist/nodes/Telegram/TelegramTrigger.node.js", "dist/nodes/Todoist/Todoist.node.js",