mirror of
https://github.com/n8n-io/n8n.git
synced 2025-01-30 05:42:00 -08:00
Merge branch 'master' of github.com:n8n-io/n8n into n8n-2349-connectors
This commit is contained in:
commit
4431329ee2
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "n8n",
|
"name": "n8n",
|
||||||
"version": "0.145.0",
|
"version": "0.146.0",
|
||||||
"description": "n8n Workflow Automation Tool",
|
"description": "n8n Workflow Automation Tool",
|
||||||
"license": "SEE LICENSE IN LICENSE.md",
|
"license": "SEE LICENSE IN LICENSE.md",
|
||||||
"homepage": "https://n8n.io",
|
"homepage": "https://n8n.io",
|
||||||
|
@ -110,10 +110,10 @@
|
||||||
"localtunnel": "^2.0.0",
|
"localtunnel": "^2.0.0",
|
||||||
"lodash.get": "^4.4.2",
|
"lodash.get": "^4.4.2",
|
||||||
"mysql2": "~2.3.0",
|
"mysql2": "~2.3.0",
|
||||||
"n8n-core": "~0.90.0",
|
"n8n-core": "~0.91.0",
|
||||||
"n8n-editor-ui": "~0.113.0",
|
"n8n-editor-ui": "~0.114.0",
|
||||||
"n8n-nodes-base": "~0.142.0",
|
"n8n-nodes-base": "~0.143.0",
|
||||||
"n8n-workflow": "~0.73.0",
|
"n8n-workflow": "~0.74.0",
|
||||||
"oauth-1.0a": "^2.2.6",
|
"oauth-1.0a": "^2.2.6",
|
||||||
"open": "^7.0.0",
|
"open": "^7.0.0",
|
||||||
"pg": "^8.3.0",
|
"pg": "^8.3.0",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "n8n-core",
|
"name": "n8n-core",
|
||||||
"version": "0.90.0",
|
"version": "0.91.0",
|
||||||
"description": "Core functionality of n8n",
|
"description": "Core functionality of n8n",
|
||||||
"license": "SEE LICENSE IN LICENSE.md",
|
"license": "SEE LICENSE IN LICENSE.md",
|
||||||
"homepage": "https://n8n.io",
|
"homepage": "https://n8n.io",
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
"lodash.get": "^4.4.2",
|
"lodash.get": "^4.4.2",
|
||||||
"mime-types": "^2.1.27",
|
"mime-types": "^2.1.27",
|
||||||
"n8n-workflow": "~0.73.0",
|
"n8n-workflow": "~0.74.0",
|
||||||
"oauth-1.0a": "^2.2.6",
|
"oauth-1.0a": "^2.2.6",
|
||||||
"p-cancelable": "^2.0.0",
|
"p-cancelable": "^2.0.0",
|
||||||
"qs": "^6.10.1",
|
"qs": "^6.10.1",
|
||||||
|
|
|
@ -71,7 +71,7 @@ import { fromBuffer } from 'file-type';
|
||||||
import { lookup } from 'mime-types';
|
import { lookup } from 'mime-types';
|
||||||
|
|
||||||
import axios, { AxiosProxyConfig, AxiosRequestConfig, Method } from 'axios';
|
import axios, { AxiosProxyConfig, AxiosRequestConfig, Method } from 'axios';
|
||||||
import { URLSearchParams } from 'url';
|
import { URL, URLSearchParams } from 'url';
|
||||||
// eslint-disable-next-line import/no-cycle
|
// eslint-disable-next-line import/no-cycle
|
||||||
import {
|
import {
|
||||||
BINARY_ENCODING,
|
BINARY_ENCODING,
|
||||||
|
@ -86,6 +86,12 @@ import {
|
||||||
axios.defaults.timeout = 300000;
|
axios.defaults.timeout = 300000;
|
||||||
// Prevent axios from adding x-form-www-urlencoded headers by default
|
// Prevent axios from adding x-form-www-urlencoded headers by default
|
||||||
axios.defaults.headers.post = {};
|
axios.defaults.headers.post = {};
|
||||||
|
axios.defaults.paramsSerializer = (params) => {
|
||||||
|
if (params instanceof URLSearchParams) {
|
||||||
|
return params.toString();
|
||||||
|
}
|
||||||
|
return stringify(params, { arrayFormat: 'indices' });
|
||||||
|
};
|
||||||
|
|
||||||
const requestPromiseWithDefaults = requestPromise.defaults({
|
const requestPromiseWithDefaults = requestPromise.defaults({
|
||||||
timeout: 300000, // 5 minutes
|
timeout: 300000, // 5 minutes
|
||||||
|
@ -338,7 +344,63 @@ async function parseRequestObject(requestObject: IDataObject) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requestObject.proxy !== undefined) {
|
if (requestObject.proxy !== undefined) {
|
||||||
axiosConfig.proxy = requestObject.proxy as AxiosProxyConfig;
|
// try our best to parse the url provided.
|
||||||
|
if (typeof requestObject.proxy === 'string') {
|
||||||
|
try {
|
||||||
|
const url = new URL(requestObject.proxy);
|
||||||
|
axiosConfig.proxy = {
|
||||||
|
host: url.hostname,
|
||||||
|
port: parseInt(url.port, 10),
|
||||||
|
protocol: url.protocol,
|
||||||
|
};
|
||||||
|
if (!url.port) {
|
||||||
|
// Sets port to a default if not informed
|
||||||
|
if (url.protocol === 'http') {
|
||||||
|
axiosConfig.proxy.port = 80;
|
||||||
|
} else if (url.protocol === 'https') {
|
||||||
|
axiosConfig.proxy.port = 443;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (url.username || url.password) {
|
||||||
|
axiosConfig.proxy.auth = {
|
||||||
|
username: url.username,
|
||||||
|
password: url.password,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Not a valid URL. We will try to simply parse stuff
|
||||||
|
// such as user:pass@host:port without protocol (we'll assume http)
|
||||||
|
if (requestObject.proxy.includes('@')) {
|
||||||
|
const [userpass, hostport] = requestObject.proxy.split('@');
|
||||||
|
const [username, password] = userpass.split(':');
|
||||||
|
const [hostname, port] = hostport.split(':');
|
||||||
|
axiosConfig.proxy = {
|
||||||
|
host: hostname,
|
||||||
|
port: parseInt(port, 10),
|
||||||
|
protocol: 'http',
|
||||||
|
auth: {
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} else if (requestObject.proxy.includes(':')) {
|
||||||
|
const [hostname, port] = requestObject.proxy.split(':');
|
||||||
|
axiosConfig.proxy = {
|
||||||
|
host: hostname,
|
||||||
|
port: parseInt(port, 10),
|
||||||
|
protocol: 'http',
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
axiosConfig.proxy = {
|
||||||
|
host: requestObject.proxy,
|
||||||
|
port: 80,
|
||||||
|
protocol: 'http',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
axiosConfig.proxy = requestObject.proxy as AxiosProxyConfig;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requestObject.encoding === null) {
|
if (requestObject.encoding === null) {
|
||||||
|
@ -357,6 +419,7 @@ async function parseRequestObject(requestObject: IDataObject) {
|
||||||
if (
|
if (
|
||||||
requestObject.json !== false &&
|
requestObject.json !== false &&
|
||||||
axiosConfig.data !== undefined &&
|
axiosConfig.data !== undefined &&
|
||||||
|
axiosConfig.data !== '' &&
|
||||||
!(axiosConfig.data instanceof Buffer) &&
|
!(axiosConfig.data instanceof Buffer) &&
|
||||||
!allHeaders.some((headerKey) => headerKey.toLowerCase() === 'content-type')
|
!allHeaders.some((headerKey) => headerKey.toLowerCase() === 'content-type')
|
||||||
) {
|
) {
|
||||||
|
@ -406,6 +469,11 @@ async function proxyRequestToAxios(
|
||||||
|
|
||||||
axiosConfig = Object.assign(axiosConfig, await parseRequestObject(configObject));
|
axiosConfig = Object.assign(axiosConfig, await parseRequestObject(configObject));
|
||||||
|
|
||||||
|
Logger.debug('Proxying request to axios', {
|
||||||
|
originalConfig: configObject,
|
||||||
|
parsedConfig: axiosConfig,
|
||||||
|
});
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
axios(axiosConfig)
|
axios(axiosConfig)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "n8n-design-system",
|
"name": "n8n-design-system",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"license": "SEE LICENSE IN LICENSE.md",
|
"license": "SEE LICENSE IN LICENSE.md",
|
||||||
"homepage": "https://n8n.io",
|
"homepage": "https://n8n.io",
|
||||||
"author": {
|
"author": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "n8n-editor-ui",
|
"name": "n8n-editor-ui",
|
||||||
"version": "0.113.0",
|
"version": "0.114.0",
|
||||||
"description": "Workflow Editor UI for n8n",
|
"description": "Workflow Editor UI for n8n",
|
||||||
"license": "SEE LICENSE IN LICENSE.md",
|
"license": "SEE LICENSE IN LICENSE.md",
|
||||||
"homepage": "https://n8n.io",
|
"homepage": "https://n8n.io",
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource/open-sans": "^4.5.0",
|
"@fontsource/open-sans": "^4.5.0",
|
||||||
"n8n-design-system": "~0.5.0",
|
"n8n-design-system": "~0.6.0",
|
||||||
"timeago.js": "^4.0.2",
|
"timeago.js": "^4.0.2",
|
||||||
"v-click-outside": "^3.1.2",
|
"v-click-outside": "^3.1.2",
|
||||||
"vue-fragment": "^1.5.2"
|
"vue-fragment": "^1.5.2"
|
||||||
|
@ -71,7 +71,7 @@
|
||||||
"lodash.debounce": "^4.0.8",
|
"lodash.debounce": "^4.0.8",
|
||||||
"lodash.get": "^4.4.2",
|
"lodash.get": "^4.4.2",
|
||||||
"lodash.set": "^4.3.2",
|
"lodash.set": "^4.3.2",
|
||||||
"n8n-workflow": "~0.73.0",
|
"n8n-workflow": "~0.74.0",
|
||||||
"sass": "^1.26.5",
|
"sass": "^1.26.5",
|
||||||
"normalize-wheel": "^1.0.1",
|
"normalize-wheel": "^1.0.1",
|
||||||
"prismjs": "^1.17.1",
|
"prismjs": "^1.17.1",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "n8n-node-dev",
|
"name": "n8n-node-dev",
|
||||||
"version": "0.30.0",
|
"version": "0.31.0",
|
||||||
"description": "CLI to simplify n8n credentials/node development",
|
"description": "CLI to simplify n8n credentials/node development",
|
||||||
"license": "SEE LICENSE IN LICENSE.md",
|
"license": "SEE LICENSE IN LICENSE.md",
|
||||||
"homepage": "https://n8n.io",
|
"homepage": "https://n8n.io",
|
||||||
|
@ -60,8 +60,8 @@
|
||||||
"change-case": "^4.1.1",
|
"change-case": "^4.1.1",
|
||||||
"copyfiles": "^2.1.1",
|
"copyfiles": "^2.1.1",
|
||||||
"inquirer": "^7.0.1",
|
"inquirer": "^7.0.1",
|
||||||
"n8n-core": "~0.90.0",
|
"n8n-core": "~0.91.0",
|
||||||
"n8n-workflow": "~0.73.0",
|
"n8n-workflow": "~0.74.0",
|
||||||
"oauth-1.0a": "^2.2.6",
|
"oauth-1.0a": "^2.2.6",
|
||||||
"replace-in-file": "^6.0.0",
|
"replace-in-file": "^6.0.0",
|
||||||
"request": "^2.88.2",
|
"request": "^2.88.2",
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
import {
|
||||||
|
ICredentialType,
|
||||||
|
INodeProperties,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
export class MicrosoftDynamicsOAuth2Api implements ICredentialType {
|
||||||
|
name = 'microsoftDynamicsOAuth2Api';
|
||||||
|
extends = [
|
||||||
|
'microsoftOAuth2Api',
|
||||||
|
];
|
||||||
|
displayName = 'Microsoft Dynamics OAuth2 API';
|
||||||
|
documentationUrl = 'microsoft';
|
||||||
|
properties: INodeProperties[] = [
|
||||||
|
//https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent
|
||||||
|
{
|
||||||
|
displayName: 'Subdomain',
|
||||||
|
name: 'subdomain',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
placeholder: 'organization',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Scope',
|
||||||
|
name: 'scope',
|
||||||
|
type: 'hidden',
|
||||||
|
default: '=openid offline_access https://{{$self.subdomain}}.crm.dynamics.com/.default',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
502
packages/nodes-base/nodes/Microsoft/Dynamics/GenericFunctions.ts
Normal file
502
packages/nodes-base/nodes/Microsoft/Dynamics/GenericFunctions.ts
Normal file
|
@ -0,0 +1,502 @@
|
||||||
|
import {
|
||||||
|
OptionsWithUri,
|
||||||
|
} from 'request';
|
||||||
|
|
||||||
|
import {
|
||||||
|
IExecuteFunctions,
|
||||||
|
IExecuteSingleFunctions,
|
||||||
|
ILoadOptionsFunctions,
|
||||||
|
} from 'n8n-core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
IDataObject,
|
||||||
|
INodePropertyOptions,
|
||||||
|
NodeApiError,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
export async function microsoftApiRequest(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, resource: string, body: any = {}, qs: IDataObject = {}, uri?: string, option: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any
|
||||||
|
const credenitals = await this.getCredentials('microsoftDynamicsOAuth2Api') as { subdomain: string };
|
||||||
|
|
||||||
|
let options: OptionsWithUri = {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'accept': 'application/json',
|
||||||
|
'Prefer': 'return=representation',
|
||||||
|
},
|
||||||
|
method,
|
||||||
|
body,
|
||||||
|
qs,
|
||||||
|
uri: uri || `https://${credenitals.subdomain}.crm.dynamics.com/api/data/v9.2${resource}`,
|
||||||
|
json: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (Object.keys(option).length !== 0) {
|
||||||
|
options = Object.assign({}, options, option);
|
||||||
|
}
|
||||||
|
//@ts-ignore
|
||||||
|
return await this.helpers.requestOAuth2.call(this, 'microsoftDynamicsOAuth2Api', options, { property: 'id_token' });
|
||||||
|
} catch (error) {
|
||||||
|
throw new NodeApiError(this.getNode(), error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function microsoftApiRequestAllItems(this: IExecuteFunctions | ILoadOptionsFunctions, propertyName: string, method: string, endpoint: string, body: any = {}, query: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any
|
||||||
|
|
||||||
|
const returnData: IDataObject[] = [];
|
||||||
|
|
||||||
|
let responseData;
|
||||||
|
let uri: string | undefined;
|
||||||
|
query['$top'] = 100;
|
||||||
|
|
||||||
|
do {
|
||||||
|
responseData = await microsoftApiRequest.call(this, method, endpoint, body, query, uri);
|
||||||
|
uri = responseData['@odata.nextLink'];
|
||||||
|
returnData.push.apply(returnData, responseData[propertyName]);
|
||||||
|
} while (
|
||||||
|
responseData['@odata.nextLink'] !== undefined
|
||||||
|
);
|
||||||
|
|
||||||
|
return returnData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getPicklistOptions(this: ILoadOptionsFunctions, entityName: string, attributeName: string): Promise<INodePropertyOptions[]> {
|
||||||
|
const returnData: INodePropertyOptions[] = [];
|
||||||
|
const endpoint = `/EntityDefinitions(LogicalName='${entityName}')/Attributes(LogicalName='${attributeName}')/Microsoft.Dynamics.CRM.PicklistAttributeMetadata?$select=LogicalName&$expand=OptionSet($select=Options),GlobalOptionSet($select=Options)`;
|
||||||
|
const { OptionSet: { Options: options } } = await microsoftApiRequest.call(this, 'GET', endpoint);
|
||||||
|
for (const option of options) {
|
||||||
|
returnData.push({
|
||||||
|
name: option.Label.UserLocalizedLabel.Label,
|
||||||
|
value: option.Value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return returnData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getEntityFields(this: ILoadOptionsFunctions, entityName: string): Promise<IField[]> {
|
||||||
|
const endpoint = `/EntityDefinitions(LogicalName='${entityName}')/Attributes`;
|
||||||
|
const { value } = await microsoftApiRequest.call(this, 'GET', endpoint);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function adjustAddresses(addresses: [{ [key: string]: string }]) {
|
||||||
|
// tslint:disable-next-line: no-any
|
||||||
|
const results: { [key: string]: any } = {};
|
||||||
|
for (const [index, address] of addresses.entries()) {
|
||||||
|
for (const key of Object.keys(address)) {
|
||||||
|
if (address[key] !== '') {
|
||||||
|
results[`address${index + 1}_${key}`] = address[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getAccountFields() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
displayName: 'Account Category',
|
||||||
|
name: 'accountcategorycode',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getAccountCategories',
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
description: 'Category to indicate whether the customer account is standard or preferred',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Account Rating',
|
||||||
|
name: 'accountratingcode',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getAccountRatingCodes',
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Address',
|
||||||
|
name: 'addresses',
|
||||||
|
type: 'fixedCollection',
|
||||||
|
default: {},
|
||||||
|
typeOptions: {
|
||||||
|
multipleValues: true,
|
||||||
|
},
|
||||||
|
placeholder: 'Add Address Field',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
displayName: 'Address Fields',
|
||||||
|
name: 'address',
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
displayName: 'Address Type',
|
||||||
|
name: 'addresstypecode',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getAddressTypes',
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Line1',
|
||||||
|
name: 'line1',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Line2',
|
||||||
|
name: 'line2',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Line3',
|
||||||
|
name: 'line3',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'City',
|
||||||
|
name: 'city',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'State or Province',
|
||||||
|
name: 'stateorprovince',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Country',
|
||||||
|
name: 'country',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Name',
|
||||||
|
name: 'name',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Postalcode',
|
||||||
|
name: 'postalcode',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Primary Contact Name',
|
||||||
|
name: 'primarycontactname',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Telephone1',
|
||||||
|
name: 'telephone1',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Telephone2',
|
||||||
|
name: 'telephone2',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Fax',
|
||||||
|
name: 'fax',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Business Type',
|
||||||
|
name: 'businesstypecode',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getBusinessTypes',
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
description: 'The legal designation or other business type of the account for contracts or reporting purposes',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Customer Size',
|
||||||
|
name: 'customersizecode',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getCustomerSizeCodes',
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Customer Type',
|
||||||
|
name: 'customertypecode',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getCustomerTypeCodes',
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Description',
|
||||||
|
name: 'description',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'Additional information to describe the account, such as an excerpt from the company’s website',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Email Address 1',
|
||||||
|
name: 'emailaddress1',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'The primary email address for the account',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Email Address 2',
|
||||||
|
name: 'emailaddress2',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'The secondary email address for the account',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Email Address 3',
|
||||||
|
name: 'emailaddress3',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'Alternate email address for the account',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Fax',
|
||||||
|
name: 'fax',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'FTP site URL',
|
||||||
|
name: 'ftpsiteurl',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'URL for the account’s FTP site to enable users to access data and share documents',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Industry',
|
||||||
|
name: 'industrycode',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getIndustryCodes',
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
description: 'The account’s primary industry for use in marketing segmentation and demographic analysis',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Name',
|
||||||
|
name: 'name',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
'/resource': [
|
||||||
|
'account',
|
||||||
|
],
|
||||||
|
'/operation': [
|
||||||
|
'update',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
description: 'Company o business name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Credit Limit',
|
||||||
|
name: 'creditlimit',
|
||||||
|
type: 'number',
|
||||||
|
default: '',
|
||||||
|
description: 'Credit limit of the account. This is a useful reference when you address invoice and accounting issues with the customer',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Number Of Employees',
|
||||||
|
name: 'numberofemployees',
|
||||||
|
type: 'number',
|
||||||
|
default: 0,
|
||||||
|
description: 'Number of employees that work at the account for use in marketing segmentation and demographic analysis',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Payment Terms',
|
||||||
|
name: 'paymenttermscode',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getPaymentTermsCodes',
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
description: 'The payment terms to indicate when the customer needs to pay the total amount',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Preferred Appointment Day',
|
||||||
|
name: 'preferredappointmentdaycode',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getPreferredAppointmentDayCodes',
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
description: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Preferred Appointment Time',
|
||||||
|
name: 'preferredappointmenttimecode',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getPreferredAppointmentTimeCodes',
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
description: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Preferred Contact Method',
|
||||||
|
name: 'preferredcontactmethodcode',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getPreferredContactMethodCodes',
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
description: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Primary Satori ID',
|
||||||
|
name: 'primarysatoriid',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Primary Twitter ID',
|
||||||
|
name: 'primarytwitterid',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Revenue',
|
||||||
|
name: 'revenue',
|
||||||
|
type: 'number',
|
||||||
|
default: '',
|
||||||
|
description: 'The annual revenue for the account, used as an indicator in financial performance analysis',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Shares Outstanding',
|
||||||
|
name: 'sharesoutstanding',
|
||||||
|
type: 'number',
|
||||||
|
default: '',
|
||||||
|
description: 'The number of shares available to the public for the account. This number is used as an indicator in financial performance analysis',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Shipping Method',
|
||||||
|
name: 'shippingmethodcode',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getShippingMethodCodes',
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
description: 'Shipping method for deliveries sent to the account’s address to designate the preferred carrier or other delivery option',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'SIC',
|
||||||
|
name: 'sic',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'The Standard Industrial Classification (SIC) code that indicates the account’s primary industry of business, for use in marketing segmentation and demographic analysis',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Stage ID',
|
||||||
|
name: 'stageid',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Stock Exchange',
|
||||||
|
name: 'stockexchange',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'The stock exchange at which the account is listed to track their stock and financial performance of the company',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Telephone 1',
|
||||||
|
name: 'telephone1',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'The main phone number for this account',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Telephone 2',
|
||||||
|
name: 'telephone2',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'The second phone number for this account',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Telephone 3',
|
||||||
|
name: 'telephone3',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'The third phone number for this account',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Territory',
|
||||||
|
name: 'territorycode',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getTerritoryCodes',
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
description: 'Region or territory for the account for use in segmentation and analysis',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Ticker Symbol',
|
||||||
|
name: 'tickersymbol',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'Type the stock exchange symbol for the account to track financial performance of the company. You can click the code entered in this field to access the latest trading information from MSN Money',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Website URL',
|
||||||
|
name: 'websiteurl',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'The account’s website URL to get quick details about the company profile',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Yomi Name',
|
||||||
|
name: 'yominame',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'The phonetic spelling of the company name, if specified in Japanese, to make sure the name is pronounced correctly in phone calls and other communications',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const sort = (a: { name: string }, b: { name: string }) => {
|
||||||
|
if (a.name < b.name) { return -1; }
|
||||||
|
if (a.name > b.name) { return 1; }
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface IField {
|
||||||
|
IsRetrievable: boolean;
|
||||||
|
LogicalName: string;
|
||||||
|
IsSearchable: string;
|
||||||
|
IsValidODataAttribute: string;
|
||||||
|
IsValidForRead: string;
|
||||||
|
CanBeSecuredForRead: string;
|
||||||
|
AttributeType: string;
|
||||||
|
IsSortableEnabled: {
|
||||||
|
Value: boolean,
|
||||||
|
};
|
||||||
|
DisplayName: {
|
||||||
|
UserLocalizedLabel: {
|
||||||
|
Label: string
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,249 @@
|
||||||
|
import {
|
||||||
|
IExecuteFunctions,
|
||||||
|
} from 'n8n-core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
IDataObject,
|
||||||
|
ILoadOptionsFunctions,
|
||||||
|
INodeExecutionData,
|
||||||
|
INodePropertyOptions,
|
||||||
|
INodeType,
|
||||||
|
INodeTypeDescription,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
import {
|
||||||
|
adjustAddresses,
|
||||||
|
getEntityFields,
|
||||||
|
getPicklistOptions,
|
||||||
|
IField,
|
||||||
|
microsoftApiRequest,
|
||||||
|
microsoftApiRequestAllItems,
|
||||||
|
sort,
|
||||||
|
} from './GenericFunctions';
|
||||||
|
|
||||||
|
import {
|
||||||
|
accountFields,
|
||||||
|
accountOperations,
|
||||||
|
} from './descriptions';
|
||||||
|
|
||||||
|
export class MicrosoftDynamicsCrm implements INodeType {
|
||||||
|
description: INodeTypeDescription = {
|
||||||
|
displayName: 'Microsoft Dynamics CRM',
|
||||||
|
name: 'microsoftDynamicsCrm',
|
||||||
|
icon: 'file:dynamicsCrm.svg',
|
||||||
|
group: ['input'],
|
||||||
|
version: 1,
|
||||||
|
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||||
|
description: 'Consume Microsoft Dynamics CRM API',
|
||||||
|
defaults: {
|
||||||
|
name: 'Microsoft Dynamics CRM',
|
||||||
|
color: '#000000',
|
||||||
|
},
|
||||||
|
inputs: ['main'],
|
||||||
|
outputs: ['main'],
|
||||||
|
credentials: [
|
||||||
|
{
|
||||||
|
name: 'microsoftDynamicsOAuth2Api',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
displayName: 'Resource',
|
||||||
|
name: 'resource',
|
||||||
|
type: 'options',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Account',
|
||||||
|
value: 'account',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: 'account',
|
||||||
|
description: 'The resource to operate on',
|
||||||
|
},
|
||||||
|
...accountOperations,
|
||||||
|
...accountFields,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
methods = {
|
||||||
|
loadOptions: {
|
||||||
|
async getAccountCategories(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
return await getPicklistOptions.call(this, 'account', 'accountcategorycode');
|
||||||
|
},
|
||||||
|
async getAccountRatingCodes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
return await getPicklistOptions.call(this, 'account', 'accountratingcode');
|
||||||
|
},
|
||||||
|
async getAddressTypes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
return await getPicklistOptions.call(this, 'account', 'address1_addresstypecode');
|
||||||
|
},
|
||||||
|
async getBusinessTypes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
return await getPicklistOptions.call(this, 'account', 'businesstypecode');
|
||||||
|
},
|
||||||
|
async getCustomerSizeCodes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
return await getPicklistOptions.call(this, 'account', 'customersizecode');
|
||||||
|
},
|
||||||
|
async getCustomerTypeCodes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
return await getPicklistOptions.call(this, 'account', 'customertypecode');
|
||||||
|
},
|
||||||
|
async getIndustryCodes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
return await getPicklistOptions.call(this, 'account', 'industrycode');
|
||||||
|
},
|
||||||
|
async getPaymentTermsCodes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
return await getPicklistOptions.call(this, 'account', 'paymenttermscode');
|
||||||
|
},
|
||||||
|
async getPreferredAppointmentDayCodes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
return await getPicklistOptions.call(this, 'account', 'preferredappointmentdaycode');
|
||||||
|
},
|
||||||
|
async getPreferredAppointmentTimeCodes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
return await getPicklistOptions.call(this, 'account', 'preferredappointmenttimecode');
|
||||||
|
},
|
||||||
|
async getPreferredContactMethodCodes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
return await getPicklistOptions.call(this, 'account', 'preferredcontactmethodcode');
|
||||||
|
},
|
||||||
|
async getShippingMethodCodes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
return await getPicklistOptions.call(this, 'account', 'shippingmethodcode');
|
||||||
|
},
|
||||||
|
async getTerritoryCodes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
return await getPicklistOptions.call(this, 'account', 'territorycode');
|
||||||
|
},
|
||||||
|
async getAccountFields(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
const fields = await getEntityFields.call(this, 'account');
|
||||||
|
const isSelectable = (field: IField) => (field.IsValidForRead && field.CanBeSecuredForRead && field.IsValidODataAttribute && field.LogicalName !== 'slaid');
|
||||||
|
return fields.filter(isSelectable).filter(field => field.DisplayName.UserLocalizedLabel?.Label).map(field => ({ name: field.DisplayName.UserLocalizedLabel.Label, value: field.LogicalName })).sort(sort);
|
||||||
|
},
|
||||||
|
async getExpandableAccountFields(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
const fields = await getEntityFields.call(this, 'account');
|
||||||
|
const isSelectable = (field: IField) => (field.IsValidForRead && field.CanBeSecuredForRead && field.IsValidODataAttribute && field.AttributeType === 'Lookup' && field.LogicalName !== 'slaid');
|
||||||
|
return fields.filter(isSelectable).map(field => ({ name: field.DisplayName.UserLocalizedLabel.Label, value: field.LogicalName })).sort(sort);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||||
|
const items = this.getInputData();
|
||||||
|
const returnData: IDataObject[] = [];
|
||||||
|
const length = items.length as unknown as number;
|
||||||
|
const qs: IDataObject = {};
|
||||||
|
let responseData;
|
||||||
|
const resource = this.getNodeParameter('resource', 0) as string;
|
||||||
|
const operation = this.getNodeParameter('operation', 0) as string;
|
||||||
|
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
try {
|
||||||
|
if (resource === 'account') {
|
||||||
|
//https://docs.microsoft.com/en-us/powerapps/developer/data-platform/webapi/create-entity-web-api
|
||||||
|
if (operation === 'create') {
|
||||||
|
const name = this.getNodeParameter('name', i) as string;
|
||||||
|
// tslint:disable-next-line: no-any
|
||||||
|
const additionalFields = this.getNodeParameter('additionalFields', i) as { addresses: { address: [{ [key: string]: any }] } };
|
||||||
|
const options = this.getNodeParameter('options', i) as { returnFields: string[] };
|
||||||
|
|
||||||
|
const body = {
|
||||||
|
name,
|
||||||
|
...additionalFields,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (body?.addresses?.address) {
|
||||||
|
Object.assign(body, adjustAddresses(body.addresses.address));
|
||||||
|
//@ts-ignore
|
||||||
|
delete body?.addresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.returnFields) {
|
||||||
|
options.returnFields.push('accountid');
|
||||||
|
qs['$select'] = options.returnFields.join(',');
|
||||||
|
} else {
|
||||||
|
qs['$select'] = 'accountid';
|
||||||
|
}
|
||||||
|
|
||||||
|
responseData = await microsoftApiRequest.call(this, 'POST', `/accounts`, body, qs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation === 'delete') {
|
||||||
|
//https://docs.microsoft.com/en-us/powerapps/developer/data-platform/webapi/update-delete-entities-using-web-api#basic-delete
|
||||||
|
const accountId = this.getNodeParameter('accountId', i) as string;
|
||||||
|
await microsoftApiRequest.call(this, 'DELETE', `/accounts(${accountId})`, {}, qs);
|
||||||
|
responseData = { success: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation === 'get') {
|
||||||
|
//https://docs.microsoft.com/en-us/powerapps/developer/data-platform/webapi/retrieve-entity-using-web-api
|
||||||
|
const accountId = this.getNodeParameter('accountId', i) as string;
|
||||||
|
const options = this.getNodeParameter('options', i) as IDataObject;
|
||||||
|
if (options.returnFields) {
|
||||||
|
qs['$select'] = (options.returnFields as string[]).join(',');
|
||||||
|
}
|
||||||
|
if (options.expandFields) {
|
||||||
|
qs['$expand'] = (options.expandFields as string[]).join(',');
|
||||||
|
}
|
||||||
|
responseData = await microsoftApiRequest.call(this, 'GET', `/accounts(${accountId})`, {}, qs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation === 'getAll') {
|
||||||
|
//https://docs.microsoft.com/en-us/powerapps/developer/data-platform/webapi/query-data-web-api
|
||||||
|
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
|
||||||
|
const options = this.getNodeParameter('options', i) as IDataObject;
|
||||||
|
const filters = this.getNodeParameter('filters', i) as IDataObject;
|
||||||
|
if (options.returnFields) {
|
||||||
|
qs['$select'] = (options.returnFields as string[]).join(',');
|
||||||
|
}
|
||||||
|
if (options.expandFields) {
|
||||||
|
qs['$expand'] = (options.expandFields as string[]).join(',');
|
||||||
|
}
|
||||||
|
if (filters.query) {
|
||||||
|
qs['$filter'] = filters.query as string;
|
||||||
|
}
|
||||||
|
if (returnAll) {
|
||||||
|
responseData = await microsoftApiRequestAllItems.call(this, 'value', 'GET', `/accounts`, {}, qs);
|
||||||
|
} else {
|
||||||
|
qs['$top'] = this.getNodeParameter('limit', 0) as number;
|
||||||
|
responseData = await microsoftApiRequest.call(this, 'GET', `/accounts`, {}, qs);
|
||||||
|
responseData = responseData.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation === 'update') {
|
||||||
|
const accountId = this.getNodeParameter('accountId', i) as string;
|
||||||
|
// tslint:disable-next-line: no-any
|
||||||
|
const updateFields = this.getNodeParameter('updateFields', i) as { addresses: { address: [{ [key: string]: any }] } };
|
||||||
|
const options = this.getNodeParameter('options', i) as { returnFields: string[] };
|
||||||
|
|
||||||
|
const body = {
|
||||||
|
...updateFields,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (body?.addresses?.address) {
|
||||||
|
Object.assign(body, adjustAddresses(body.addresses.address));
|
||||||
|
//@ts-ignore
|
||||||
|
delete body?.addresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.returnFields) {
|
||||||
|
options.returnFields.push('accountid');
|
||||||
|
qs['$select'] = options.returnFields.join(',');
|
||||||
|
} else {
|
||||||
|
qs['$select'] = 'accountid';
|
||||||
|
}
|
||||||
|
|
||||||
|
responseData = await microsoftApiRequest.call(this, 'PATCH', `/accounts(${accountId})`, body, qs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(responseData)) {
|
||||||
|
returnData.push(...responseData);
|
||||||
|
} else {
|
||||||
|
returnData.push(responseData as IDataObject);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (this.continueOnFail()) {
|
||||||
|
returnData.push({ error: error.message });
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [this.helpers.returnJsonArray(returnData)];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,274 @@
|
||||||
|
import {
|
||||||
|
INodeProperties,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
import {
|
||||||
|
getAccountFields,
|
||||||
|
} from '../GenericFunctions';
|
||||||
|
|
||||||
|
export const accountOperations = [
|
||||||
|
{
|
||||||
|
displayName: 'Operation',
|
||||||
|
name: 'operation',
|
||||||
|
type: 'options',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'account',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Create',
|
||||||
|
value: 'create',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Delete',
|
||||||
|
value: 'delete',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Get',
|
||||||
|
value: 'get',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Get All',
|
||||||
|
value: 'getAll',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Update',
|
||||||
|
value: 'update',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: 'create',
|
||||||
|
description: 'Operation to perform',
|
||||||
|
},
|
||||||
|
] as INodeProperties[];
|
||||||
|
|
||||||
|
export const accountFields = [
|
||||||
|
// ----------------------------------------
|
||||||
|
// account:create
|
||||||
|
// ----------------------------------------
|
||||||
|
{
|
||||||
|
displayName: 'Name',
|
||||||
|
name: 'name',
|
||||||
|
description: 'Company or business name',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
default: '',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'account',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'create',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Additional Fields',
|
||||||
|
name: 'additionalFields',
|
||||||
|
type: 'collection',
|
||||||
|
placeholder: 'Add Field',
|
||||||
|
default: {},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'account',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'create',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
...getAccountFields(),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// ----------------------------------------
|
||||||
|
// account:get
|
||||||
|
// ----------------------------------------
|
||||||
|
{
|
||||||
|
displayName: 'Account ID',
|
||||||
|
name: 'accountId',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
default: '',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'account',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'delete',
|
||||||
|
'get',
|
||||||
|
'update',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// ----------------------------------------
|
||||||
|
// 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: 10,
|
||||||
|
},
|
||||||
|
default: 5,
|
||||||
|
description: 'How many results to return.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Options',
|
||||||
|
name: 'options',
|
||||||
|
type: 'collection',
|
||||||
|
placeholder: 'Add Option',
|
||||||
|
default: {},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'account',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'get',
|
||||||
|
'getAll',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
displayName: 'Return Fields',
|
||||||
|
name: 'returnFields',
|
||||||
|
type: 'multiOptions',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getAccountFields',
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Expand Fields',
|
||||||
|
name: 'expandFields',
|
||||||
|
type: 'multiOptions',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getExpandableAccountFields',
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Filters',
|
||||||
|
name: 'filters',
|
||||||
|
type: 'collection',
|
||||||
|
placeholder: 'Add Filter',
|
||||||
|
default: {},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'account',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'getAll',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
displayName: 'Query',
|
||||||
|
name: 'query',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'Query to filter the results. Check <a href="https://docs.microsoft.com/en-us/powerapps/developer/data-platform/webapi/query-data-web-api#filter-results" target="_blank">filters</a>',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// ----------------------------------------
|
||||||
|
// account:update
|
||||||
|
// ----------------------------------------
|
||||||
|
{
|
||||||
|
displayName: 'Update Fields',
|
||||||
|
name: 'updateFields',
|
||||||
|
type: 'collection',
|
||||||
|
placeholder: 'Add Field',
|
||||||
|
default: {},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'account',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'update',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
...getAccountFields(),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Options',
|
||||||
|
name: 'options',
|
||||||
|
type: 'collection',
|
||||||
|
placeholder: 'Add Option',
|
||||||
|
default: {},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'account',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'create',
|
||||||
|
'update',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
displayName: 'Return Fields',
|
||||||
|
name: 'returnFields',
|
||||||
|
type: 'multiOptions',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getAccountFields',
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
description: 'Fields the response will include',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
] as INodeProperties[];
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './AccountDescription';
|
|
@ -0,0 +1 @@
|
||||||
|
<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="50px" height="50px"><path d="M 11.986328 0 C 11.815078 0.002 11.645188 0.048671875 11.492188 0.13867188 C 11.188188 0.31867188 11 0.646 11 1 L 11 13.353516 C 11 13.737516 11.219406 14.089859 11.566406 14.255859 L 29.566406 22.900391 C 29.703406 22.966391 29.853 23 30 23 C 30.194 23 30.387688 22.943031 30.554688 22.832031 L 39.554688 16.832031 C 39.844687 16.639031 40.013047 16.307984 39.998047 15.958984 C 39.984047 15.610984 39.789375 15.295953 39.484375 15.126953 L 12.484375 0.12695312 C 12.329375 0.040953125 12.157578 -0.002 11.986328 0 z M 12.025391 17 C 11.850016 16.9955 11.674625 17.038453 11.515625 17.126953 C 11.197625 17.302953 11 17.636 11 18 L 11 48.998047 C 11 49.758047 11.813469 50.241953 12.480469 49.876953 L 40.496094 33.867188 C 40.808094 33.689188 41 33.359 41 33 L 41 20 C 41 19.592 40.753 19.225266 40.375 19.072266 C 39.995 18.920266 39.562297 19.011688 39.279297 19.304688 L 13 47 L 20.955078 23.294922 C 21.088078 22.861922 20.913297 22.392344 20.529297 22.152344 L 12.529297 17.152344 C 12.374797 17.055844 12.200766 17.0045 12.025391 17 z"/></svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "n8n-nodes-base",
|
"name": "n8n-nodes-base",
|
||||||
"version": "0.142.0",
|
"version": "0.143.0",
|
||||||
"description": "Base nodes of n8n",
|
"description": "Base nodes of n8n",
|
||||||
"license": "SEE LICENSE IN LICENSE.md",
|
"license": "SEE LICENSE IN LICENSE.md",
|
||||||
"homepage": "https://n8n.io",
|
"homepage": "https://n8n.io",
|
||||||
|
@ -172,6 +172,7 @@
|
||||||
"dist/credentials/MediumApi.credentials.js",
|
"dist/credentials/MediumApi.credentials.js",
|
||||||
"dist/credentials/MediumOAuth2Api.credentials.js",
|
"dist/credentials/MediumOAuth2Api.credentials.js",
|
||||||
"dist/credentials/MessageBirdApi.credentials.js",
|
"dist/credentials/MessageBirdApi.credentials.js",
|
||||||
|
"dist/credentials/MicrosoftDynamicsOAuth2Api.credentials.js",
|
||||||
"dist/credentials/MicrosoftExcelOAuth2Api.credentials.js",
|
"dist/credentials/MicrosoftExcelOAuth2Api.credentials.js",
|
||||||
"dist/credentials/MicrosoftOAuth2Api.credentials.js",
|
"dist/credentials/MicrosoftOAuth2Api.credentials.js",
|
||||||
"dist/credentials/MicrosoftOneDriveOAuth2Api.credentials.js",
|
"dist/credentials/MicrosoftOneDriveOAuth2Api.credentials.js",
|
||||||
|
@ -486,6 +487,7 @@
|
||||||
"dist/nodes/Medium/Medium.node.js",
|
"dist/nodes/Medium/Medium.node.js",
|
||||||
"dist/nodes/Merge.node.js",
|
"dist/nodes/Merge.node.js",
|
||||||
"dist/nodes/MessageBird/MessageBird.node.js",
|
"dist/nodes/MessageBird/MessageBird.node.js",
|
||||||
|
"dist/nodes/Microsoft/Dynamics/MicrosoftDynamicsCrm.node.js",
|
||||||
"dist/nodes/Microsoft/Excel/MicrosoftExcel.node.js",
|
"dist/nodes/Microsoft/Excel/MicrosoftExcel.node.js",
|
||||||
"dist/nodes/Microsoft/OneDrive/MicrosoftOneDrive.node.js",
|
"dist/nodes/Microsoft/OneDrive/MicrosoftOneDrive.node.js",
|
||||||
"dist/nodes/Microsoft/Outlook/MicrosoftOutlook.node.js",
|
"dist/nodes/Microsoft/Outlook/MicrosoftOutlook.node.js",
|
||||||
|
@ -665,7 +667,7 @@
|
||||||
"@types/xml2js": "^0.4.3",
|
"@types/xml2js": "^0.4.3",
|
||||||
"gulp": "^4.0.0",
|
"gulp": "^4.0.0",
|
||||||
"jest": "^26.4.2",
|
"jest": "^26.4.2",
|
||||||
"n8n-workflow": "~0.73.0",
|
"n8n-workflow": "~0.74.0",
|
||||||
"nodelinter": "^0.1.9",
|
"nodelinter": "^0.1.9",
|
||||||
"ts-jest": "^26.3.0",
|
"ts-jest": "^26.3.0",
|
||||||
"tslint": "^6.1.2",
|
"tslint": "^6.1.2",
|
||||||
|
@ -705,7 +707,7 @@
|
||||||
"mssql": "^6.2.0",
|
"mssql": "^6.2.0",
|
||||||
"mysql2": "~2.3.0",
|
"mysql2": "~2.3.0",
|
||||||
"node-ssh": "^12.0.0",
|
"node-ssh": "^12.0.0",
|
||||||
"n8n-core": "~0.90.0",
|
"n8n-core": "~0.91.0",
|
||||||
"nodemailer": "^6.5.0",
|
"nodemailer": "^6.5.0",
|
||||||
"pdf-parse": "^1.1.1",
|
"pdf-parse": "^1.1.1",
|
||||||
"pg": "^8.3.0",
|
"pg": "^8.3.0",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "n8n-workflow",
|
"name": "n8n-workflow",
|
||||||
"version": "0.73.0",
|
"version": "0.74.0",
|
||||||
"description": "Workflow base code of n8n",
|
"description": "Workflow base code of n8n",
|
||||||
"license": "SEE LICENSE IN LICENSE.md",
|
"license": "SEE LICENSE IN LICENSE.md",
|
||||||
"homepage": "https://n8n.io",
|
"homepage": "https://n8n.io",
|
||||||
|
|
|
@ -415,8 +415,7 @@ export class Workflow {
|
||||||
const currentNameEscaped = currentName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
const currentNameEscaped = currentName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||||
|
|
||||||
parameterValue = parameterValue.replace(
|
parameterValue = parameterValue.replace(
|
||||||
// eslint-disable-next-line no-useless-escape
|
new RegExp(`(\\$node(\\.|\\["|\\['))${currentNameEscaped}((\\.|"\\]|'\\]))`, 'g'),
|
||||||
new RegExp(`(\\$node(\.|\\["|\\[\'))${currentNameEscaped}((\s/g|"\\]|\'\\]))`, 'g'),
|
|
||||||
`$1${newName}$3`,
|
`$1${newName}$3`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue