const allCurrencies = [
	{ name: 'Euro', value: 'eur' },
	{ name: 'United States Dollar', value: 'usd' },
	{ name: 'British Pound Sterling', value: 'gbp' },
	{ name: 'Swiss Franc', value: 'chf' },
	{ name: 'Renminbi', value: 'cny' },
	{ name: '--------', value: '' },
	{ name: 'United Arab Emirates Dirham', value: 'aed' },
	{ name: 'Afghan Afghani', value: 'afn' },
	{ name: 'Albanian Lek', value: 'all' },
	{ name: 'Armenian Dram', value: 'amd' },
	{ name: 'Netherlands Antillean Guilder', value: 'ang' },
	{ name: 'Angolan Kwanza', value: 'aoa' },
	{ name: 'Argentine Peso', value: 'ars' },
	{ name: 'Australian Dollar', value: 'aud' },
	{ name: 'Aruban Florin', value: 'awg' },
	{ name: 'Azerbaijani Manat', value: 'azn' },
	{ name: 'Bosnia-Herzegovina Convertible Mark', value: 'bam' },
	{ name: 'Barbadian Dollar', value: 'bbd' },
	{ name: 'Bangladeshi Taka', value: 'bdt' },
	{ name: 'Bulgarian Lev', value: 'bgn' },
	{ name: 'Bahraini Dinar', value: 'bhd' },
	{ name: 'Burundian Franc', value: 'bif' },
	{ name: 'Bermudan Dollar', value: 'bmd' },
	{ name: 'Brunei Dollar', value: 'bnd' },
	{ name: 'Bolivian Boliviano', value: 'bob' },
	{ name: 'Brazilian Real', value: 'brl' },
	{ name: 'Bahamian Dollar', value: 'bsd' },
	{ name: 'Bitcoin', value: 'btc' },
	{ name: 'Bhutanese Ngultrum', value: 'btn' },
	{ name: 'Botswanan Pula', value: 'bwp' },
	{ name: 'Belarusian Ruble', value: 'byn' },
	{ name: 'Belize Dollar', value: 'bzd' },
	{ name: 'Canadian Dollar', value: 'cad' },
	{ name: 'Congolese Franc', value: 'cdf' },
	{ name: 'Chilean Unit of Account (UF)', value: 'clf' },
	{ name: 'Chilean Peso', value: 'clp' },
	{ name: 'Chinese Yuan (Offshore)', value: 'cnh' },
	{ name: 'Colombian Peso', value: 'cop' },
	{ name: 'Costa Rican Colón', value: 'crc' },
	{ name: 'Cuban Convertible Peso', value: 'cuc' },
	{ name: 'Cuban Peso', value: 'cup' },
	{ name: 'Cape Verdean Escudo', value: 'cve' },
	{ name: 'Czech Republic Koruna', value: 'czk' },
	{ name: 'Djiboutian Franc', value: 'djf' },
	{ name: 'Danish Krone', value: 'dkk' },
	{ name: 'Dominican Peso', value: 'dop' },
	{ name: 'Algerian Dinar', value: 'dzd' },
	{ name: 'Egyptian Pound', value: 'egp' },
	{ name: 'Eritrean Nakfa', value: 'ern' },
	{ name: 'Ethiopian Birr', value: 'etb' },
	{ name: 'Fijian Dollar', value: 'fjd' },
	{ name: 'Falkland Islands Pound', value: 'fkp' },
	{ name: 'Georgian Lari', value: 'gel' },
	{ name: 'Guernsey Pound', value: 'ggp' },
	{ name: 'Ghanaian Cedi', value: 'ghs' },
	{ name: 'Gibraltar Pound', value: 'gip' },
	{ name: 'Gambian Dalasi', value: 'gmd' },
	{ name: 'Guinean Franc', value: 'gnf' },
	{ name: 'Guatemalan Quetzal', value: 'gtq' },
	{ name: 'Guyanaese Dollar', value: 'gyd' },
	{ name: 'Hong Kong Dollar', value: 'hkd' },
	{ name: 'Honduran Lempira', value: 'hnl' },
	{ name: 'Croatian Kuna', value: 'hrk' },
	{ name: 'Haitian Gourde', value: 'htg' },
	{ name: 'Hungarian Forint', value: 'huf' },
	{ name: 'Indonesian Rupiah', value: 'idr' },
	{ name: 'Israeli New Sheqel', value: 'ils' },
	{ name: 'Manx pound', value: 'imp' },
	{ name: 'Indian Rupee', value: 'inr' },
	{ name: 'Iraqi Dinar', value: 'iqd' },
	{ name: 'Iranian Rial', value: 'irr' },
	{ name: 'Icelandic Króna', value: 'isk' },
	{ name: 'Jersey Pound', value: 'jep' },
	{ name: 'Jamaican Dollar', value: 'jmd' },
	{ name: 'Jordanian Dinar', value: 'jod' },
	{ name: 'Japanese Yen', value: 'jpy' },
	{ name: 'Kenyan Shilling', value: 'kes' },
	{ name: 'Kyrgystani Som', value: 'kgs' },
	{ name: 'Cambodian Riel', value: 'khr' },
	{ name: 'Comorian Franc', value: 'kmf' },
	{ name: 'North Korean Won', value: 'kpw' },
	{ name: 'South Korean Won', value: 'krw' },
	{ name: 'Kuwaiti Dinar', value: 'kwd' },
	{ name: 'Cayman Islands Dollar', value: 'kyd' },
	{ name: 'Kazakhstani Tenge', value: 'kzt' },
	{ name: 'Laotian Kip', value: 'lak' },
	{ name: 'Lebanese Pound', value: 'lbp' },
	{ name: 'Sri Lankan Rupee', value: 'lkr' },
	{ name: 'Liberian Dollar', value: 'lrd' },
	{ name: 'Lesotho Loti', value: 'lsl' },
	{ name: 'Libyan Dinar', value: 'lyd' },
	{ name: 'Moroccan Dirham', value: 'mad' },
	{ name: 'Moldovan Leu', value: 'mdl' },
	{ name: 'Malagasy Ariary', value: 'mga' },
	{ name: 'Macedonian Denar', value: 'mkd' },
	{ name: 'Myanma Kyat', value: 'mmk' },
	{ name: 'Mongolian Tugrik', value: 'mnt' },
	{ name: 'Macanese Pataca', value: 'mop' },
	{ name: 'Mauritanian Ouguiya (pre-2018)', value: 'mro' },
	{ name: 'Mauritanian Ouguiya', value: 'mru' },
	{ name: 'Mauritian Rupee', value: 'mur' },
	{ name: 'Maldivian Rufiyaa', value: 'mvr' },
	{ name: 'Malawian Kwacha', value: 'mwk' },
	{ name: 'Mexican Peso', value: 'mxn' },
	{ name: 'Malaysian Ringgit', value: 'myr' },
	{ name: 'Mozambican Metical', value: 'mzn' },
	{ name: 'Namibian Dollar', value: 'nad' },
	{ name: 'Nigerian Naira', value: 'ngn' },
	{ name: 'Nicaraguan Córdoba', value: 'nio' },
	{ name: 'Norwegian Krone', value: 'nok' },
	{ name: 'Nepalese Rupee', value: 'npr' },
	{ name: 'New Zealand Dollar', value: 'nzd' },
	{ name: 'Omani Rial', value: 'omr' },
	{ name: 'Panamanian Balboa', value: 'pab' },
	{ name: 'Peruvian Nuevo Sol', value: 'pen' },
	{ name: 'Papua New Guinean Kina', value: 'pgk' },
	{ name: 'Philippine Peso', value: 'php' },
	{ name: 'Pakistani Rupee', value: 'pkr' },
	{ name: 'Polish Zloty', value: 'pln' },
	{ name: 'Paraguayan Guarani', value: 'pyg' },
	{ name: 'Qatari Rial', value: 'qar' },
	{ name: 'Romanian Leu', value: 'ron' },
	{ name: 'Serbian Dinar', value: 'rsd' },
	{ name: 'Russian Ruble', value: 'rub' },
	{ name: 'Rwandan Franc', value: 'rwf' },
	{ name: 'Saudi Riyal', value: 'sar' },
	{ name: 'Solomon Islands Dollar', value: 'sbd' },
	{ name: 'Seychellois Rupee', value: 'scr' },
	{ name: 'Sudanese Pound', value: 'sdg' },
	{ name: 'Swedish Krona', value: 'sek' },
	{ name: 'Singapore Dollar', value: 'sgd' },
	{ name: 'Saint Helena Pound', value: 'shp' },
	{ name: 'Sierra Leonean Leone', value: 'sll' },
	{ name: 'Somali Shilling', value: 'sos' },
	{ name: 'Surinamese Dollar', value: 'srd' },
	{ name: 'South Sudanese Pound', value: 'ssp' },
	{ name: 'São Tomé and Príncipe Dobra (pre-2018)', value: 'std' },
	{ name: 'São Tomé and Príncipe Dobra', value: 'stn' },
	{ name: 'Salvadoran Colón', value: 'svc' },
	{ name: 'Syrian Pound', value: 'syp' },
	{ name: 'Swazi Lilangeni', value: 'szl' },
	{ name: 'Thai Baht', value: 'thb' },
	{ name: 'Tajikistani Somoni', value: 'tjs' },
	{ name: 'Turkmenistani Manat', value: 'tmt' },
	{ name: 'Tunisian Dinar', value: 'tnd' },
	{ name: `Tongan Pa'anga`, value: 'top' },
	{ name: 'Turkish Lira', value: 'try' },
	{ name: 'Trinidad and Tobago Dollar', value: 'ttd' },
	{ name: 'New Taiwan Dollar', value: 'twd' },
	{ name: 'Tanzanian Shilling', value: 'tzs' },
	{ name: 'Ukrainian Hryvnia', value: 'uah' },
	{ name: 'Ugandan Shilling', value: 'ugx' },
	{ name: 'Uruguayan Peso', value: 'uyu' },
	{ name: 'Uzbekistan Som', value: 'uzs' },
	{ name: 'Venezuelan Bolívar Fuerte', value: 'vef' },
	{ name: 'Vietnamese Dong', value: 'vnd' },
	{ name: 'Vanuatu Vatu', value: 'vuv' },
	{ name: 'Samoan Tala', value: 'wst' },
	{ name: 'CFA Franc BEAC', value: 'xaf' },
	{ name: 'Silver Ounce', value: 'xag' },
	{ name: 'Gold Ounce', value: 'xau' },
	{ name: 'East Caribbean Dollar', value: 'xcd' },
	{ name: 'Special Drawing Rights', value: 'xdr' },
	{ name: 'CFA Franc BCEAO', value: 'xof' },
	{ name: 'Palladium Ounce', value: 'xpd' },
	{ name: 'CFP Franc', value: 'xpf' },
	{ name: 'Platinum Ounce', value: 'xpt' },
	{ name: 'Yemeni Rial', value: 'yer' },
	{ name: 'South African Rand', value: 'zar' },
	{ name: 'Zambian Kwacha', value: 'zmw' },
	{ name: 'Zimbabwean Dollar', value: 'zwl' },
	// tslint:disable-next-line: semicolon
]


isCtrlKeyPressed (e: MouseEvent | KeyboardEvent): boolean {

keep keep keep keep replace replace keep keep keep keep keep

const nodeViewEl = this.$el.querySelector('#node-view') as HTMLDivElement;

import {
	ICredentialType,
	NodePropertyTypes,
} from 'n8n-workflow';

const scopes = [
	'https://www.googleapis.com/auth/drive.file',
	'https://www.googleapis.com/auth/spreadsheets',
];

export class GoogleSheetsOAuth2Api implements ICredentialType {
	name = 'googleSheetsOAuth2Api';
	extends = [
		'googleOAuth2Api',
	];
	displayName = 'Google Sheets OAuth2 API';
	documentationUrl = 'google';
	properties = [
		{
			displayName: 'Scope',
			name: 'scope',
			type: 'hidden' as NodePropertyTypes,
			default: scopes.join(' '),
		},
	];
}


* Gets mouse position within the node view. Both node view offset and scale (zoom) are considered when

* @param event - mouse event within node view

getMousePositionWithinNodeView (event: MouseEvent) {

const nodeViewScale = this.nodeViewScale;

x: (event.pageX - offsetPosition[0]) / nodeViewScale,

y: (event.pageY - offsetPosition[1]) / nodeViewScale,

import { INodeUi } from '@/Interface';

import mixins from 'vue-typed-mixins';

import { deviceSupportHelpers } from '@/components/mixins/deviceSupportHelpers';
import { nodeIndex } from '@/components/mixins/nodeIndex';

export const mouseSelect = mixins(
	deviceSupportHelpers,
	nodeIndex,
).extend({
	data () {
		return {
			selectActive: false,
			selectBox: document.createElement('span'),
		};
	},
	mounted () {
		this.createSelectBox();
	},
	methods: {
		createSelectBox () {
			this.selectBox.id = 'select-box';
			this.selectBox.style.margin = '0px auto';
			this.selectBox.style.border = '2px dotted #FF0000';
			this.selectBox.style.position = 'fixed';
			this.selectBox.style.zIndex = '100';
			this.selectBox.style.visibility = 'hidden';

			this.selectBox.addEventListener('mouseup', this.mouseUpMouseSelect);

			// document.body.appendChild(this.selectBox);
			this.$el.appendChild(this.selectBox);
		},
		isCtrlKeyPressed (e: MouseEvent | KeyboardEvent): boolean {
			if (this.isTouchDevice === true) {
				return true;
			}
			if (this.isMacOs) {
				return e.metaKey;
			}
			return e.ctrlKey;
		},
		showSelectBox (event: MouseEvent) {
			// @ts-ignore
			this.selectBox.x = event.pageX;
			// @ts-ignore
			this.selectBox.y = event.pageY;

			this.selectBox.style.left = event.pageX + 'px';
			this.selectBox.style.top = event.pageY + 'px';
			this.selectBox.style.visibility = 'visible';

			this.selectActive = true;
		},
		updateSelectBox (event: MouseEvent) {
			const selectionBox = this.getSelectionBox(event);
			this.selectBox.style.left = selectionBox.x + 'px';
			this.selectBox.style.top = selectionBox.y + 'px';

			this.selectBox.style.width = selectionBox.width + 'px';
			this.selectBox.style.height = selectionBox.height + 'px';
		},
		hideSelectBox () {
			this.selectBox.style.visibility = 'hidden';
			// @ts-ignore
			this.selectBox.x = 0;
			// @ts-ignore
			this.selectBox.y = 0;
			this.selectBox.style.left = '0px';
			this.selectBox.style.top = '0px';
			this.selectBox.style.width = '0px';
			this.selectBox.style.height = '0px';

			this.selectActive = false;
		},
		getSelectionBox (event: MouseEvent) {
			return {
				// @ts-ignore
				x: Math.min(event.pageX, this.selectBox.x),
				// @ts-ignore
				y: Math.min(event.pageY, this.selectBox.y),
				// @ts-ignore
				width: Math.abs(event.pageX - this.selectBox.x),
				// @ts-ignore
				height: Math.abs(event.pageY - this.selectBox.y),
			};
		},
		getNodesInSelection (event: MouseEvent): INodeUi[] {
			const returnNodes: INodeUi[] = [];
			const selectionBox = this.getSelectionBox(event);
			const offsetPosition = this.$store.getters.getNodeViewOffsetPosition;

			// Consider the offset of the workflow when it got moved
			selectionBox.x -= offsetPosition[0];
			selectionBox.y -= offsetPosition[1];

			// Go through all nodes and check if they are selected
			this.$store.getters.allNodes.forEach((node: INodeUi) => {
				// TODO: Currently always uses the top left corner for checking. Should probably use the center instead
				if (node.position[0] < selectionBox.x || node.position[0] > (selectionBox.x + selectionBox.width)) {
					return;
				}
				if (node.position[1] < selectionBox.y || node.position[1] > (selectionBox.y + selectionBox.height)) {
					return;
				}
				returnNodes.push(node);
			});

			return returnNodes;
		},
		mouseDownMouseSelect (e: MouseEvent) {
			if (this.isCtrlKeyPressed(e) === true) {
				// We only care about it when the ctrl key is not pressed at the same time.
				// So we exit when it is pressed.
				return;
			}

			if (this.$store.getters.isActionActive('dragActive')) {
				// If a node does currently get dragged we do not activate the selection
				return;
			}
			this.showSelectBox(e);

			// @ts-ignore // Leave like this. Do not add a anonymous function because then remove would not work anymore
			this.$el.addEventListener('mousemove', this.mouseMoveSelect);
		},
		mouseUpMouseSelect (e: MouseEvent) {
			if (this.selectActive === false) {
				if (this.isTouchDevice === true) {
					// @ts-ignore
					if (e.target && e.target.id.includes('node-view')) {
						// Deselect all nodes
						this.deselectAllNodes();
					}
				}
				// If it is not active return direcly.
				// Else normal node dragging will not work.
				return;
			}

			// @ts-ignore
			this.$el.removeEventListener('mousemove', this.mouseMoveSelect);

			// Deselect all nodes
			this.deselectAllNodes();

			// Select the nodes which are in the selection box
			const selectedNodes = this.getNodesInSelection(e);
			selectedNodes.forEach((node) => {
				this.nodeSelected(node);
			});

			this.hideSelectBox();
		},
		mouseMoveSelect (e: MouseEvent) {
			if (e.buttons === 0) {
				// Mouse button is not pressed anymore so stop selection mode
				// Happens normally when mouse leave the view pressed and then
				// comes back unpressed.
				this.mouseUpMouseSelect(e);
				return;
			}

			this.updateSelectBox(e);
		},

		nodeDeselected (node: INodeUi) {
			this.$store.commit('removeNodeFromSelection', node);
			const nodeElement = `node-${this.getNodeIndex(node.name)}`;
			// @ts-ignore
			this.instance.removeFromDragSelection(nodeElement);
		},
		nodeSelected (node: INodeUi) {
			this.$store.commit('addSelectedNode', node);
			const nodeElement = `node-${this.getNodeIndex(node.name)}`;
			// @ts-ignore
			this.instance.addToDragSelection(nodeElement);
		},
		deselectAllNodes () {
			// @ts-ignore
			this.instance.clearDragSelection();
			this.$store.commit('resetSelectedNodes');
			this.$store.commit('setLastSelectedNode', null);
			this.$store.commit('setLastSelectedNodeOutputIndex', null);
			this.$store.commit('setActiveNode', null);
		},
	},
});


import {
	INodeProperties,
} from 'n8n-workflow';

export const companyOperations = [
	{
		displayName: 'Operation',
		name: 'operation',
		type: 'options',
		displayOptions: {
			show: {
				resource: [
					'company',
				],
			},
		},
		options: [
			{
				name: 'Create',
				value: 'create',
				description: 'Create a company',
			},
			{
				name: 'Delete',
				value: 'delete',
				description: 'Delete a company',
			},
			{
				name: 'Get',
				value: 'get',
				description: 'Get a company',
			},
			{
				name: 'Get All',
				value: 'getAll',
				description: 'Get all companies',
			},
			{
				name: 'Get Recently Created',
				value: 'getRecentlyCreated',
				description: 'Get recently created companies',
			},
			{
				name: 'Get Recently Modified',
				value: 'getRecentlyModified',
				description: 'Get recently modified companies',
			},
			{
				name: 'Search By Domain',
				value: 'searchByDomain',
				description: 'Search companies by domain',
			},
			{
				name: 'Update',
				value: 'update',
				description: 'Update a company',
			},
		],
		default: 'create',
		description: 'The operation to perform.',
	},
] as INodeProperties[];

export const companyFields = [

	/* -------------------------------------------------------------------------- */
	/*                                company:create                              */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Name',
		name: 'name',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				resource: [
					'company',
				],
				operation: [
					'create',
				],
			},
		},
		default: '',
	},
	{
		displayName: 'Additional Fields',
		name: 'additionalFields',
		type: 'collection',
		placeholder: 'Add Field',
		default: {},
		displayOptions: {
			show: {
				resource: [
					'company',
				],
				operation: [
					'create',
				],
			},
		},
		options: [
			{
				displayName: 'About Us',
				name: 'aboutUs',
				type: 'string',
				typeOptions: {
					alwaysOpenEditWindow: true,
				},
				default: '',
			},
			{
				displayName: 'Annual Revenue',
				name: 'annualRevenue',
				type: 'number',
				typeOptions: {
					minValue: 0,
				},
				default: 0,
				description: 'The actual or estimated annual revenue of the company',
			},
			{
				displayName: 'City',
				name: 'city',
				type: 'string',
				default: '',
				description: 'The city where the company is located.',
			},
			{
				displayName: 'Close Date',
				name: 'closeDate',
				type: 'dateTime',
				default: '',
				description: 'The date the company or organization was closed as a customer',
			},
			{
				displayName: 'Company Domain Name',
				name: 'companyDomainName',
				type: 'string',
				default: '',
				description: 'The domain name of the company or organization',
			},
			{
				displayName: 'Company Owner',
				name: 'companyOwner',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getOwners',
				},
				default: '',
				description: 'The owner of the company',
			},
			{
				displayName: 'Country/Region',
				name: 'countryRegion',
				type: 'string',
				default: '',
				description: 'The country/region in which the company or organization is located.',
			},
			{
				displayName: 'Custom Properties',
				name: 'customPropertiesUi',
				placeholder: 'Add Custom Property',
				type: 'fixedCollection',
				typeOptions: {
					multipleValues: true,
				},
				default: {},
				options: [
					{
						name: 'customPropertiesValues',
						displayName: 'Custom Property',
						values: [
							{
								displayName: 'Property',
								name: 'property',
								type: 'options',
								typeOptions: {
									loadOptionsMethod: 'getCompanyCustomProperties',
								},
								default: '',
								description: 'Name of the property.',
							},
							{
								displayName: 'Value',
								name: 'value',
								type: 'string',
								default: '',
								description: 'Value of the property',
							},
						],
					},
				],
			},
			{
				displayName: 'Description',
				name: 'description',
				type: 'string',
				default: '',
				description: `A short statement about the company's mission and goals.`,
			},
			{
				displayName: 'Facebook Fans',
				name: 'facebookFans',
				type: 'number',
				typeOptions: {
					minValue: 0,
				},
				default: 0,
				description: 'Number of facebook fans',
			},
			{
				displayName: 'Google Plus Page',
				name: 'googlePlusPage',
				type: 'string',
				default: '',
				description: 'The URL of the Google Plus page for the company or organization',
			},
			{
				displayName: 'Industry',
				name: 'industry',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getCompanyIndustries',
				},
				default: '',
				description: 'The type of business the company performs.',
			},
			{
				displayName: 'Is Public',
				name: 'isPublic',
				type: 'boolean',
				default: false,
				description: 'Indicates that the company is publicly traded.',
			},
			{
				displayName: 'Lead Status',
				name: 'leadStatus',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getCompanyleadStatuses',
				},
				default: '',
				description: `The company's sales, prospecting or outreach status`,
			},
			{
				displayName: 'Lifecycle Stage',
				name: 'lifecycleStatus',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getCompanylifecycleStages',
				},
				default: '',
				description: 'The most advanced lifecycle stage across all contacts associated with this company or organization',
			},
			{
				displayName: 'LinkedIn Bio',
				name: 'linkedinBio',
				type: 'string',
				default: '',
				description: 'The LinkedIn bio for the company or organization',
			},
			{
				displayName: 'LinkedIn Company Page',
				name: 'linkedInCompanyPage',
				type: 'string',
				default: '',
				description: 'The URL of the LinkedIn company page for the company or organization',
			},
			{
				displayName: 'Number Of Employees',
				name: 'numberOfEmployees',
				type: 'number',
				typeOptions: {
					minValue: 0,
				},
				default: 0,
				description: 'The total number of employees who work for the company or organization',
			},
			{
				displayName: 'Original Source Type',
				name: 'originalSourceType',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getCompanySourceTypes',
				},
				default: '',
				description: 'Original source for the contact with the earliest activity for this company or organization',
			},
			{
				displayName: 'Phone Number',
				name: 'phoneNumber',
				type: 'string',
				default: '',
				description: `A company's primary phone number. Powered by HubSpot Insights.`,
			},
			{
				displayName: 'Postal Code',
				name: 'postalCode',
				type: 'string',
				default: '',
				description: 'The postal or zip code of the company or organization. Powered by HubSpot Insights.',
			},
			{
				displayName: 'State/Region',
				name: 'stateRegion',
				type: 'string',
				default: '',
				description: 'The state or region in which the company or organization is located. Powered by HubSpot Insights.',
			},
			{
				displayName: 'Street Address',
				name: 'streetAddress',
				type: 'string',
				default: '',
				description: 'The street address of the company or organization, including unit number. Powered by HubSpot Insights.',
			},
			{
				displayName: 'Street Address 2',
				name: 'streetAddress2',
				type: 'string',
				default: '',
				description: 'The additional address of the company or organization. Powered by HubSpot Insights.',
			},

			{
				displayName: 'Target Account',
				name: 'targetAccount',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getCompanyTargetAccounts',
				},
				default: '',
				description: 'The Target Account property is a means to flag high priority companies if you are following an account based strategy',
			},
			{
				displayName: 'Timezone',
				name: 'timezone',
				type: 'string',
				default: '',
				description: 'The time zone where the company or organization is located. Powered by HubSpot Insights.',
			},
			{
				displayName: 'Total Money Raised',
				name: 'totalMoneyRaised',
				type: 'number',
				typeOptions: {
					minValue: 0,
				},
				default: 0,
				description: 'The total amount of money raised by the company. Powered by HubSpot Insights.',
			},
			{
				displayName: 'Twitter Bio',
				name: 'twitterBio',
				type: 'string',
				typeOptions: {
					alwaysOpenEditWindow: true,
				},
				default: '',
				description: 'The Twitter bio of the company or organization',
			},
			{
				displayName: 'Twitter Followers',
				name: 'twitterFollowers',
				type: 'number',
				typeOptions: {
					minValue: 0,
				},
				default: 0,
				description: 'The number of Twitter followers of the company or organization',
			},
			{
				displayName: 'Twitter Handle',
				name: 'twitterHandle',
				type: 'string',
				default: '',
				description: 'The main twitter account of the company or organization',
			},
			{
				displayName: 'Type',
				name: 'type',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getCompanyTypes',
				},
				default: '',
				description: 'The optional classification of this company record - prospect, partner, etc.',
			},
			{
				displayName: 'Web Technologies',
				name: 'webTechnologies',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getCompanyWebTechnologies',
				},
				default: '',
				description: 'The web technologies used by the company or organization. Powered by HubSpot Insights.',
			},
			{
				displayName: 'Website URL',
				name: 'websiteUrl',
				type: 'string',
				default: '',
				description: 'The main website of the company or organization. This property is used to identify unique companies. Powered by HubSpot Insights.',
			},
			{
				displayName: 'Year Founded',
				name: 'yearFounded',
				type: 'string',
				default: '',
				description: 'The year the company was created. Powered by HubSpot Insights.',
			},
		],
	},

	/* -------------------------------------------------------------------------- */
	/*                                 company:update                             */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Company ID',
		name: 'companyId',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				resource: [
					'company',
				],
				operation: [
					'update',
				],
			},
		},
		default: '',
		description: 'Unique identifier for a particular company',
	},
	{
		displayName: 'Update Fields',
		name: 'updateFields',
		type: 'collection',
		placeholder: 'Add Field',
		default: {},
		displayOptions: {
			show: {
				resource: [
					'company',
				],
				operation: [
					'update',
				],
			},
		},
		options: [
			{
				displayName: 'About Us',
				name: 'aboutUs',
				type: 'string',
				typeOptions: {
					alwaysOpenEditWindow: true,
				},
				default: '',
			},
			{
				displayName: 'Annual Revenue',
				name: 'annualRevenue',
				type: 'number',
				typeOptions: {
					minValue: 0,
				},
				default: 0,
				description: 'The actual or estimated annual revenue of the company',
			},
			{
				displayName: 'City',
				name: 'city',
				type: 'string',
				default: '',
				description: 'The city where the company is located.',
			},
			{
				displayName: 'Close Date',
				name: 'closeDate',
				type: 'dateTime',
				default: '',
				description: 'The date the company or organization was closed as a customer',
			},
			{
				displayName: 'Company Domain Name',
				name: 'companyDomainName',
				type: 'string',
				default: '',
				description: 'The domain name of the company or organization',
			},
			{
				displayName: 'Company Owmer',
				name: 'companyOwner',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getOwners',
				},
				default: '',
				description: 'The owner of the company',
			},
			{
				displayName: 'Country/Region',
				name: 'countryRegion',
				type: 'string',
				default: '',
				description: 'The country/region in which the company or organization is located.',
			},
			{
				displayName: 'Custom Properties',
				name: 'customPropertiesUi',
				placeholder: 'Add Custom Property',
				type: 'fixedCollection',
				typeOptions: {
					multipleValues: true,
				},
				default: {},
				options: [
					{
						name: 'customPropertiesValues',
						displayName: 'Custom Property',
						values: [
							{
								displayName: 'Property',
								name: 'property',
								type: 'options',
								typeOptions: {
									loadOptionsMethod: 'getCompanyCustomProperties',
								},
								default: '',
								description: 'Name of the property.',
							},
							{
								displayName: 'Value',
								name: 'value',
								type: 'string',
								default: '',
								description: 'Value of the property',
							},
						],
					},
				],
			},
			{
				displayName: 'Description',
				name: 'description',
				type: 'string',
				default: '',
				description: `A short statement about the company's mission and goals.`,
			},
			{
				displayName: 'Facebook Fans',
				name: 'facebookFans',
				type: 'number',
				typeOptions: {
					minValue: 0,
				},
				default: 0,
				description: 'Number of facebook fans',
			},
			{
				displayName: 'Google Plus Page',
				name: 'googlePlusPage',
				type: 'string',
				default: '',
				description: 'The URL of the Google Plus page for the company or organization',
			},
			{
				displayName: 'Industry',
				name: 'industry',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getCompanyIndustries',
				},
				default: '',
				description: 'The type of business the company performs.',
			},
			{
				displayName: 'Is Public',
				name: 'isPublic',
				type: 'boolean',
				default: false,
				description: 'Indicates that the company is publicly traded.',
			},
			{
				displayName: 'Lead Status',
				name: 'leadStatus',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getCompanyleadStatuses',
				},
				default: '',
				description: `The company's sales, prospecting or outreach status`,
			},
			{
				displayName: 'Lifecycle Stage',
				name: 'lifecycleStatus',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getCompanylifecycleStages',
				},
				default: '',
				description: 'The most advanced lifecycle stage across all contacts associated with this company or organization',
			},
			{
				displayName: 'Linkedin Bio',
				name: 'linkedinBio',
				type: 'string',
				default: '',
				description: 'The LinkedIn bio for the company or organization',
			},
			{
				displayName: 'LinkedIn Company Page',
				name: 'linkedInCompanyPage',
				type: 'string',
				default: '',
				description: 'The URL of the LinkedIn company page for the company or organization',
			},
			{
				displayName: 'Name',
				name: 'name',
				type: 'string',
				default: '',
			},
			{
				displayName: 'Number Of Employees',
				name: 'numberOfEmployees',
				type: 'number',
				typeOptions: {
					minValue: 0,
				},
				default: 0,
				description: 'The total number of employees who work for the company or organization',
			},
			{
				displayName: 'Original Source Type',
				name: 'originalSourceType',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getCompanySourceTypes',
				},
				default: '',
				description: 'Original source for the contact with the earliest activity for this company or organization',
			},
			{
				displayName: 'Phone Number',
				name: 'phoneNumber',
				type: 'string',
				default: '',
				description: `A company's primary phone number. Powered by HubSpot Insights.`,
			},
			{
				displayName: 'Postal Code',
				name: 'postalCode',
				type: 'string',
				default: '',
				description: 'The postal or zip code of the company or organization. Powered by HubSpot Insights.',
			},
			{
				displayName: 'State/Region',
				name: 'stateRegion',
				type: 'string',
				default: '',
				description: 'The state or region in which the company or organization is located. Powered by HubSpot Insights.',
			},
			{
				displayName: 'Street Address',
				name: 'streetAddress',
				type: 'string',
				default: '',
				description: 'The street address of the company or organization, including unit number. Powered by HubSpot Insights.',
			},
			{
				displayName: 'Street Address 2',
				name: 'streetAddress2',
				type: 'string',
				default: '',
				description: 'The additional address of the company or organization. Powered by HubSpot Insights.',
			},

			{
				displayName: 'Target Account',
				name: 'targetAccount',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getCompanyTargetAccounts',
				},
				default: '',
				description: 'The Target Account property is a means to flag high priority companies if you are following an account based strategy',
			},
			{
				displayName: 'Timezone',
				name: 'timezone',
				type: 'string',
				default: '',
				description: 'The time zone where the company or organization is located. Powered by HubSpot Insights.',
			},
			{
				displayName: 'Total Money Raised',
				name: 'totalMoneyRaised',
				type: 'number',
				typeOptions: {
					minValue: 0,
				},
				default: 0,
				description: 'The total amount of money raised by the company. Powered by HubSpot Insights.',
			},
			{
				displayName: 'Twitter Bio',
				name: 'twitterBio',
				type: 'string',
				typeOptions: {
					alwaysOpenEditWindow: true,
				},
				default: '',
				description: 'The Twitter bio of the company or organization',
			},
			{
				displayName: 'Twitter Followers',
				name: 'twitterFollowers',
				type: 'number',
				typeOptions: {
					minValue: 0,
				},
				default: 0,
				description: 'The number of Twitter followers of the company or organization',
			},
			{
				displayName: 'Twitter Handle',
				name: 'twitterHandle',
				type: 'string',
				default: '',
				description: 'The main twitter account of the company or organization',
			},
			{
				displayName: 'Type',
				name: 'type',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getCompanyTypes',
				},
				default: '',
				description: 'The optional classification of this company record - prospect, partner, etc.',
			},
			{
				displayName: 'Web Technologies',
				name: 'webTechnologies',
				type: 'options',
				typeOptions: {
					loadOptionsMethod: 'getCompanyWebTechnologies',
				},
				default: '',
				description: 'The web technologies used by the company or organization. Powered by HubSpot Insights.',
			},
			{
				displayName: 'Website URL',
				name: 'websiteUrl',
				type: 'string',
				default: '',
				description: 'The main website of the company or organization. This property is used to identify unique companies. Powered by HubSpot Insights.',
			},
			{
				displayName: 'Year Founded',
				name: 'yearFounded',
				type: 'string',
				default: '',
				description: 'The year the company was created. Powered by HubSpot Insights.',
			},
		],
	},

	/* -------------------------------------------------------------------------- */
	/*                                  company:get                               */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Company ID',
		name: 'companyId',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				resource: [
					'company',
				],
				operation: [
					'get',
				],
			},
		},
		default: '',
		description: 'Unique identifier for a particular company',
	},
	{
		displayName: 'Additional Fields',
		name: 'additionalFields',
		type: 'collection',
		placeholder: 'Add Field',
		default: {},
		displayOptions: {
			show: {
				resource: [
					'company',
				],
				operation: [
					'get',
				],
			},
		},
		options: [
			{
				displayName: 'Include Merge Audits',
				name: 'includeMergeAudits',
				type: 'boolean',
				default: false,
				description: `Returns any merge history if the company has been previously merged with another company record. Defaults to false.`,
			},
		],
	},

	/* -------------------------------------------------------------------------- */
	/*                                 company:getAll                             */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Return All',
		name: 'returnAll',
		type: 'boolean',
		displayOptions: {
			show: {
				resource: [
					'company',
				],
				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: [
					'company',
				],
				operation: [
					'getAll',
				],
				returnAll: [
					false,
				],
			},
		},
		typeOptions: {
			minValue: 1,
			maxValue: 250,
		},
		default: 100,
		description: 'How many results to return.',
	},
	{
		displayName: 'Options',
		name: 'options',
		type: 'collection',
		placeholder: 'Add Field',
		default: {},
		displayOptions: {
			show: {
				resource: [
					'company',
				],
				operation: [
					'getAll',
				],
			},
		},
		options: [
			{
				displayName: 'Include Merge Audits',
				name: 'includeMergeAudits',
				type: 'boolean',
				default: false,
				description: `Returns any merge history if a company has been previously merged with another company record. Defaults to false.`,
			},
			{
				displayName: 'Properties',
				name: 'properties',
				type: 'multiOptions',
				typeOptions: {
					loadOptionsMethod: 'getCompanyProperties',
				},
				default: '',
				description: `Used to include specific company properties in the results.<br/>
				By default, the results will only include company ID and will not include the values for any properties for your companys.<br/>
				Including this parameter will include the data for the specified property in the results.<br/>
				You can include this parameter multiple times to request multiple properties separed by ,.`,
			},
			{
				displayName: 'Properties With History',
				name: 'propertiesWithHistory',
				type: 'string',
				default: '',
				description: `Works similarly to properties=, but this parameter will include the history for the specified property,<br/>
				instead of just including the current value. Use this parameter when you need the full history of changes to a property's value.`,
			},
		],
	},

	/* -------------------------------------------------------------------------- */
	/*                                 company:delete                             */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Company ID',
		name: 'companyId',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				resource: [
					'company',
				],
				operation: [
					'delete',
				],
			},
		},
		default: '',
		description: 'Unique identifier for a particular company',
	},

	/* -------------------------------------------------------------------------- */
	/*               company:getRecentlyCreated company:getRecentlyModifie        */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Return All',
		name: 'returnAll',
		type: 'boolean',
		displayOptions: {
			show: {
				resource: [
					'company',
				],
				operation: [
					'getRecentlyCreated',
					'getRecentlyModified',
				],
			},
		},
		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: [
					'company',
				],
				operation: [
					'getRecentlyCreated',
					'getRecentlyModified',
				],
				returnAll: [
					false,
				],
			},
		},
		typeOptions: {
			minValue: 1,
			maxValue: 250,
		},
		default: 100,
		description: 'How many results to return.',
	},
	{
		displayName: 'Filters',
		name: 'filters',
		type: 'collection',
		placeholder: 'Add Filter',
		default: {},
		displayOptions: {
			show: {
				resource: [
					'company',
				],
				operation: [
					'getRecentlyModified',
				],
			},
		},
		options: [
			{
				displayName: 'Since',
				name: 'since',
				type: 'dateTime',
				default: '',
				description: `Only return companys created after timestamp x`,
			},
			{
				displayName: 'Include Property Versions',
				name: 'includePropertyVersions',
				type: 'boolean',
				default: false,
				description: `By default, you will only get data for the most recent version of a property in the "versions" data.<br/>
				If you include this parameter, you will get data for all previous versions.`,
			},
		],
	},

	/* -------------------------------------------------------------------------- */
	/*                            company:searchByDomain                          */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Domain',
		name: 'domain',
		type: 'string',
		displayOptions: {
			show: {
				resource: [
					'company',
				],
				operation: [
					'searchByDomain',
				],
			},
		},
		required: true,
		default: '',
	},
	{
		displayName: 'Return All',
		name: 'returnAll',
		type: 'boolean',
		displayOptions: {
			show: {
				resource: [
					'company',
				],
				operation: [
					'searchByDomain',
				],
			},
		},
		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: [
					'company',
				],
				operation: [
					'searchByDomain',
				],
				returnAll: [
					false,
				],
			},
		},
		typeOptions: {
			minValue: 1,
			maxValue: 250,
		},
		default: 100,
		description: 'How many results to return.',
	},
	{
		displayName: 'Options',
		name: 'options',
		type: 'collection',
		placeholder: 'Add Field',
		default: {},
		displayOptions: {
			show: {
				resource: [
					'company',
				],
				operation: [
					'searchByDomain',
				],
			},
		},
		options: [
			{
				displayName: 'Properties',
				name: 'properties',
				type: 'multiOptions',
				typeOptions: {
					loadOptionsMethod: 'getCompanyProperties',
				},
				default: '',
				description: `Used to include specific company properties in the results.<br/>
				By default, the results will only include company ID and will not include the values for any properties for your companys.<br/>
				Including this parameter will include the data for the specified property in the results.<br/>
				You can include this parameter multiple times to request multiple properties separed by ,.`,
			},
		],
	},
] as INodeProperties[];


import {
	INodeProperties,
} from 'n8n-workflow';

export const channelOperations = [
	{
		displayName: 'Operation',
		name: 'operation',
		type: 'options',
		displayOptions: {
			show: {
				resource: [
					'channel',
				],
			},
		},
		options: [
			{
				name: 'Create',
				value: 'create',
				description: 'Create a channel',
			},
			{
				name: 'Delete',
				value: 'delete',
				description: 'Delete a channel',
			},
			{
				name: 'Get',
				value: 'get',
				description: 'Get a channel',
			},
			{
				name: 'Get All',
				value: 'getAll',
				description: 'Get all channels',
			},
			{
				name: 'Update',
				value: 'update',
				description: 'Update a channel',
			},
		],
		default: 'create',
		description: 'The operation to perform.',
	},
] as INodeProperties[];

export const channelFields = [

	/* -------------------------------------------------------------------------- */
	/*                                 channel:create                             */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Team ID',
		name: 'teamId',
		required: true,
		type: 'options',
		typeOptions: {
			loadOptionsMethod: 'getTeams',
		},
		displayOptions: {
			show: {
				operation: [
					'create',
				],
				resource: [
					'channel',
				],
			},
		},
		default: '',
		description: 'Team ID',
	},
	{
		displayName: 'Name',
		name: 'name',
		required: true,
		type: 'string',
		displayOptions: {
			show: {
				operation: [
					'create',
				],
				resource: [
					'channel',
				],
			},
		},
		default: '',
		description: 'Channel name as it will appear to the user in Microsoft Teams.',
	},
	{
		displayName: 'Options',
		name: 'options',
		type: 'collection',
		displayOptions: {
			show: {
				operation: [
					'create',
				],
				resource: [
					'channel',
				],
			},
		},
		default: {},
		placeholder: 'Add Field',
		options: [
			{
				displayName: 'Description',
				name: 'description',
				type: 'string',
				typeOptions: {
					alwaysOpenEditWindow: true,
				},
				default: '',
				description: `channel's description`,
			},
			{
				displayName: 'Type',
				name: 'type',
				type: 'options',
				options: [
					{
						name: 'Private',
						value: 'private',
					},
					{
						name: 'Standard',
						value: 'standard',
					},
				],
				default: 'standard',
				description: 'The type of the channel',
			},
		],
	},

	/* -------------------------------------------------------------------------- */
	/*                                 channel:delete                             */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Team ID',
		name: 'teamId',
		required: true,
		type: 'options',
		typeOptions: {
			loadOptionsMethod: 'getTeams',
		},
		displayOptions: {
			show: {
				operation: [
					'delete',
				],
				resource: [
					'channel',
				],
			},
		},
		default: '',
		description: 'Team ID',
	},
	{
		displayName: 'Channel ID',
		name: 'channelId',
		type: 'options',
		typeOptions: {
			loadOptionsMethod: 'getChannels',
			loadOptionsDependsOn: [
				'teamId',
			],
		},
		displayOptions: {
			show: {
				operation: [
					'delete',
				],
				resource: [
					'channel',
				],
			},
		},
		default: '',
		description: 'channel ID',
	},

	/* -------------------------------------------------------------------------- */
	/*                                 channel:get                                */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Team ID',
		name: 'teamId',
		required: true,
		type: 'options',
		typeOptions: {
			loadOptionsMethod: 'getTeams',
		},
		displayOptions: {
			show: {
				operation: [
					'get',
				],
				resource: [
					'channel',
				],
			},
		},
		default: '',
		description: 'Team ID',
	},
	{
		displayName: 'Channel ID',
		name: 'channelId',
		type: 'options',
		typeOptions: {
			loadOptionsMethod: 'getChannels',
			loadOptionsDependsOn: [
				'teamId',
			],
		},
		displayOptions: {
			show: {
				operation: [
					'get',
				],
				resource: [
					'channel',
				],
			},
		},
		default: '',
		description: 'channel ID',
	},

	/* -------------------------------------------------------------------------- */
	/*                                 channel:getAll                             */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Team ID',
		name: 'teamId',
		required: true,
		type: 'options',
		typeOptions: {
			loadOptionsMethod: 'getTeams',
		},
		displayOptions: {
			show: {
				operation: [
					'getAll',
				],
				resource: [
					'channel',
				],
			},
		},
		default: '',
		description: 'Team ID',
	},
	{
		displayName: 'Return All',
		name: 'returnAll',
		type: 'boolean',
		displayOptions: {
			show: {
				operation: [
					'getAll',
				],
				resource: [
					'channel',
				],
			},
		},
		default: false,
		description: 'If all results should be returned or only up to a given limit.',
	},
	{
		displayName: 'Limit',
		name: 'limit',
		type: 'number',
		displayOptions: {
			show: {
				operation: [
					'getAll',
				],
				resource: [
					'channel',
				],
				returnAll: [
					false,
				],
			},
		},
		typeOptions: {
			minValue: 1,
			maxValue: 500,
		},
		default: 100,
		description: 'How many results to return.',
	},

	/* -------------------------------------------------------------------------- */
	/*                                 channel:update                             */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Team ID',
		name: 'teamId',
		required: true,
		type: 'options',
		typeOptions: {
			loadOptionsMethod: 'getTeams',
		},
		displayOptions: {
			show: {
				operation: [
					'update',
				],
				resource: [
					'channel',
				],
			},
		},
		default: '',
		description: 'Team ID',
	},
	{
		displayName: 'Channel ID',
		name: 'channelId',
		type: 'options',
		typeOptions: {
			loadOptionsMethod: 'getChannels',
			loadOptionsDependsOn: [
				'teamId',
			],
		},
		displayOptions: {
			show: {
				operation: [
					'update',
				],
				resource: [
					'channel',
				],
			},
		},
		default: '',
		description: 'Channel ID',
	},
	{
		displayName: 'Update Fields',
		name: 'updateFields',
		type: 'collection',
		displayOptions: {
			show: {
				operation: [
					'update',
				],
				resource: [
					'channel',
				],
			},
		},
		default: {},
		placeholder: 'Add Field',
		options: [
			{
				displayName: 'Name',
				name: 'name',
				type: 'string',
				default: '',
				description: 'Channel name as it will appear to the user in Microsoft Teams.',
			},
			{
				displayName: 'Description',
				name: 'description',
				type: 'string',
				typeOptions: {
					alwaysOpenEditWindow: true,
				},
				default: '',
				description: `channel's description`,
			},
		],
	},
] as INodeProperties[];


import { INodeProperties } from 'n8n-workflow';

export const clientOperations = [
	{
		displayName: 'Operation',
		name: 'operation',
		type: 'options',
		displayOptions: {
			show: {
				resource: [
					'client',
				],
			},
		},
		options: [
			{
				name: 'Create',
				value: 'create',
				description: 'Create a new client',
			},
			{
				name: 'Delete',
				value: 'delete',
				description: 'Delete a client',
			},
			{
				name: 'Get',
				value: 'get',
				description: 'Get data of a client',
			},
			{
				name: 'Get All',
				value: 'getAll',
				description: 'Get data of all clients',
			},
		],
		default: 'create',
		description: 'The operation to perform.',
	},
] as INodeProperties[];

export const clientFields = [
/* -------------------------------------------------------------------------- */
/*                                 client:create                              */
/* -------------------------------------------------------------------------- */
	{
		displayName: 'Additional Fields',
		name: 'additionalFields',
		type: 'collection',
		placeholder: 'Add Field',
		default: {},
		displayOptions: {
			show: {
				operation: [
					'create',
				],
				resource: [
					'client',
				],
			},
		},
		options: [
			{
				displayName: 'Client Name',
				name: 'clientName',
				type: 'string',
				default: '',
			},
			{
				displayName: 'ID Number',
				name: 'idNumber',
				type: 'string',
				default: '',
			},
			{
				displayName: 'Private Notes',
				name: 'privateNotes',
				type: 'string',
				typeOptions: {
					alwaysOpenEditWindow: true,
				},
				default: '',
			},
			{
				displayName: 'VAT Number',
				name: 'vatNumber',
				type: 'string',
				default: '',
			},
			{
				displayName: 'Work Phone',
				name: 'workPhone',
				type: 'string',
				default: '',
			},
			{
				displayName: 'Website',
				name: 'website',
				type: 'string',
				default: '',
			},
		],
	},
	{
		displayName: 'Billing Address',
		name: 'billingAddressUi',
		placeholder: 'Add Billing Address',
		type: 'fixedCollection',
		typeOptions: {
			multipleValues: false,
		},
		displayOptions: {
			show: {
				resource: [
					'client',
				],
				operation: [
					'create',
				],
			},
		},
		default: {},
		options: [
			{
				name: 'billingAddressValue',
				displayName: 'Billing Address',
				values: [
					{
						displayName: 'Street Address',
						name: 'streetAddress',
						type: 'string',
						default: '',
					},
					{
						displayName: 'Apt/Suite',
						name: 'aptSuite',
						type: 'string',
						default: '',
					},
					{
						displayName: 'City',
						name: 'city',
						type: 'string',
						default: '',
					},
					{
						displayName: 'State',
						name: 'state',
						type: 'string',
						default: '',
					},
					{
						displayName: 'Postal Code',
						name: 'postalCode',
						type: 'string',
						default: '',
					},
					{
						displayName: 'Country Code',
						name: 'countryCode',
						type: 'options',
						typeOptions: {
							loadOptionsMethod: 'getCountryCodes',
						},
						default: '',
					},
				],
			},
		],
	},
	{
		displayName: 'Contacts',
		name: 'contactsUi',
		placeholder: 'Add Contact',
		type: 'fixedCollection',
		typeOptions: {
			multipleValues: true,
		},
		displayOptions: {
			show: {
				resource: [
					'client',
				],
				operation: [
					'create',
				],
			},
		},
		default: {},
		options: [
			{
				name: 'contacstValues',
				displayName: 'Contact',
				values: [
					{
						displayName: 'First Name',
						name: 'firstName',
						type: 'string',
						default: '',
					},
					{
						displayName: 'Last Name',
						name: 'lastName',
						type: 'string',
						default: '',
					},
					{
						displayName: 'Email',
						name: 'email',
						type: 'string',
						default: '',
					},
					{
						displayName: 'Phone',
						name: 'phone',
						type: 'string',
						default: '',
					},
				],
			},
		],
	},
	{
		displayName: 'Shipping Address',
		name: 'shippingAddressUi',
		placeholder: 'Add Shipping Address',
		type: 'fixedCollection',
		typeOptions: {
			multipleValues: false,
		},
		displayOptions: {
			show: {
				resource: [
					'client',
				],
				operation: [
					'create',
				],
			},
		},
		default: {},
		options: [
			{
				name: 'shippingAddressValue',
				displayName: 'Shipping Address',
				values: [
					{
						displayName: 'Street Address',
						name: 'streetAddress',
						type: 'string',
						default: '',
					},
					{
						displayName: 'Apt/Suite',
						name: 'aptSuite',
						type: 'string',
						default: '',
					},
					{
						displayName: 'City',
						name: 'city',
						type: 'string',
						default: '',
					},
					{
						displayName: 'State',
						name: 'state',
						type: 'string',
						default: '',
					},
					{
						displayName: 'Postal Code',
						name: 'postalCode',
						type: 'string',
						default: '',
					},
					{
						displayName: 'Country Code',
						name: 'countryCode',
						type: 'options',
						typeOptions: {
							loadOptionsMethod: 'getCountryCodes',
						},
						default: '',
					},
				],
			},
		],
	},
/* -------------------------------------------------------------------------- */
/*                                 client:delete                              */
/* -------------------------------------------------------------------------- */
	{
		displayName: 'Client ID',
		name: 'clientId',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				resource: [
					'client',
				],
				operation: [
					'delete',
				],
			},
		},
	},
/* -------------------------------------------------------------------------- */
/*                                  client:get                                */
/* -------------------------------------------------------------------------- */
	{
		displayName: 'Client ID',
		name: 'clientId',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				resource: [
					'client',
				],
				operation: [
					'get',
				],
			},
		},
	},
	{
		displayName: 'Options',
		name: 'options',
		type: 'collection',
		placeholder: 'Add Field',
		default: {},
		displayOptions: {
			show: {
				operation: [
					'get',
				],
				resource: [
					'client',
				],
			},
		},
		options: [
			{
				displayName: 'Include',
				name: 'include',
				type: 'options',
				options: [
					{
						name: 'Invoices',
						value: 'invoices',
					},
				],
				default: 'invoices',
			},
		],
	},
/* -------------------------------------------------------------------------- */
/*                                  client:getAll                             */
/* -------------------------------------------------------------------------- */
	{
		displayName: 'Return All',
		name: 'returnAll',
		type: 'boolean',
		displayOptions: {
			show: {
				resource: [
					'client',
				],
				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: [
					'client',
				],
				operation: [
					'getAll',
				],
				returnAll: [
					false,
				],
			},
		},
		typeOptions: {
			minValue: 1,
			maxValue: 60,
		},
		default: 50,
		description: 'How many results to return.',
	},
	{
		displayName: 'Options',
		name: 'options',
		type: 'collection',
		placeholder: 'Add Field',
		default: {},
		displayOptions: {
			show: {
				operation: [
					'getAll',
				],
				resource: [
					'client',
				],
			},
		},
		options: [
			{
				displayName: 'Include',
				name: 'include',
				type: 'options',
				options: [
					{
						name: 'Invoices',
						value: 'invoices',
					},
				],
				default: 'invoices',
			},
		],
	},
] as INodeProperties[];


showSelectBox (event: MouseEvent) {
// @ts-ignore

this.selectBox = Object.assign(this.selectBox, this.getMousePositionWithinNodeView(event));


import {
	IHookFunctions,
	IWebhookFunctions,
} from 'n8n-core';

import {
	IDataObject,
	ILoadOptionsFunctions,
	INodePropertyOptions,
	INodeType,
	INodeTypeDescription,
	IWebhookResponseData,
} from 'n8n-workflow';

import {
	companyFields,
	contactFields,
	dealFields,
	hubspotApiRequest,
	propertyEvents,
} from './GenericFunctions';

import {
	createHash,
} from 'crypto';

import {
	capitalCase,
} from 'change-case';

export class HubspotTrigger implements INodeType {
	description: INodeTypeDescription = {
		displayName: 'HubSpot Trigger',
		name: 'hubspotTrigger',
		icon: 'file:hubspot.svg',
		group: ['trigger'],
		version: 1,
		description: 'Starts the workflow when HubSpot events occur.',
		defaults: {
			name: 'Hubspot Trigger',
			color: '#ff7f64',
		},
		inputs: [],
		outputs: ['main'],
		credentials: [
			{
				name: 'hubspotDeveloperApi',
				required: true,
			},
		],
		webhooks: [
			{
				name: 'default',
				httpMethod: 'POST',
				responseMode: 'onReceived',
				path: 'webhook',
			},
			{
				name: 'setup',
				httpMethod: 'GET',
				responseMode: 'onReceived',
				path: 'webhook',
			},
		],
		properties: [
			{
				displayName: 'Events',
				name: 'eventsUi',
				type: 'fixedCollection',
				typeOptions: {
					multipleValues: true,
				},
				placeholder: 'Add Event',
				default: {},
				options: [
					{
						displayName: 'Event',
						name: 'eventValues',
						values: [
							{
								displayName: 'Name',
								name: 'name',
								type: 'options',
								options: [
									{
										name: 'Contact Created',
										value: 'contact.creation',
										description: `To get notified if any contact is created in a customer's account.`,
									},
									{
										name: 'Contact Deleted',
										value: 'contact.deletion',
										description: `To get notified if any contact is deleted in a customer's account.`,
									},
									{
										name: 'Contact Privacy Deleted',
										value: 'contact.privacyDeletion',
										description: `To get notified if a contact is deleted for privacy compliance reasons. `,
									},
									{
										name: 'Contact Property Changed',
										value: 'contact.propertyChange',
										description: `to get notified if a specified property is changed for any contact in a customer's account. `,
									},
									{
										name: 'Company Created',
										value: 'company.creation',
										description: `To get notified if any company is created in a customer's account.`,
									},
									{
										name: 'Company Deleted',
										value: 'company.deletion',
										description: `To get notified if any company is deleted in a customer's account.`,
									},
									{
										name: 'Company Property Changed',
										value: 'company.propertyChange',
										description: `To get notified if a specified property is changed for any company in a customer's account.`,
									},
									{
										name: 'Deal Created',
										value: 'deal.creation',
										description: `To get notified if any deal is created in a customer's account.`,
									},
									{
										name: 'Deal Deleted',
										value: 'deal.deletion',
										description: `To get notified if any deal is deleted in a customer's account.`,
									},
									{
										name: 'Deal Property Changed',
										value: 'deal.propertyChange',
										description: `To get notified if a specified property is changed for any deal in a customer's account.`,
									},
								],
								default: 'contact.creation',
								required: true,
							},
							{
								displayName: 'Property',
								name: 'property',
								type: 'options',
								typeOptions: {
									loadOptionsMethod: 'getContactProperties',
								},
								displayOptions: {
									show: {
										name: [
											'contact.propertyChange',
										],
									},
								},
								default: '',
								required: true,
							},
							{
								displayName: 'Property',
								name: 'property',
								type: 'options',
								typeOptions: {
									loadOptionsMethod: 'getCompanyProperties',
								},
								displayOptions: {
									show: {
										name: [
											'company.propertyChange',
										],
									},
								},
								default: '',
								required: true,
							},
							{
								displayName: 'Property',
								name: 'property',
								type: 'options',
								typeOptions: {
									loadOptionsMethod: 'getDealProperties',
								},
								displayOptions: {
									show: {
										name: [
											'deal.propertyChange',
										],
									},
								},
								default: '',
								required: true,
							},
						],
					},
				],
			},
			{
				displayName: 'Additional Fields',
				name: 'additionalFields',
				type: 'collection',
				placeholder: 'Add Field',
				default: {},
				options: [
					{
						displayName: 'Max Concurrent Requests',
						name: 'maxConcurrentRequests',
						type: 'number',
						typeOptions: {
							minValue: 5,
						},
						default: 5,
					},
				],
			},
		],
	};

	methods = {
		loadOptions: {
			// Get all the available contacts to display them to user so that he can
			// select them easily
			async getContactProperties(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
				const returnData: INodePropertyOptions[] = [];
				for (const field of contactFields) {
					returnData.push({
						name: capitalCase(field.label),
						value: field.id,
					});
				}
				returnData.sort((a, b) => {
					if (a.name < b.name) { return -1; }
					if (a.name > b.name) { return 1; }
					return 0;
				});
				return returnData;
			},
			// Get all the available companies to display them to user so that he can
			// select them easily
			async getCompanyProperties(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
				const returnData: INodePropertyOptions[] = [];
				for (const field of companyFields) {
					returnData.push({
						name: capitalCase(field.label),
						value: field.id,
					});
				}
				returnData.sort((a, b) => {
					if (a.name < b.name) { return -1; }
					if (a.name > b.name) { return 1; }
					return 0;
				});
				return returnData;
			},
			// Get all the available deals to display them to user so that he can
			// select them easily
			async getDealProperties(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
				const returnData: INodePropertyOptions[] = [];
				for (const field of dealFields) {
					returnData.push({
						name: capitalCase(field.label),
						value: field.id,
					});
				}
				returnData.sort((a, b) => {
					if (a.name < b.name) { return -1; }
					if (a.name > b.name) { return 1; }
					return 0;
				});
				return returnData;
			},
		},
	};

	// @ts-ignore (because of request)
	webhookMethods = {
		default: {
			async checkExists(this: IHookFunctions): Promise<boolean> {
				// Check all the webhooks which exist already if it is identical to the
				// one that is supposed to get created.
				const currentWebhookUrl = this.getNodeWebhookUrl('default') as string;
				const { appId } = this.getCredentials('hubspotDeveloperApi') as IDataObject;

				try {
					const { targetUrl } = await hubspotApiRequest.call(this, 'GET', `/webhooks/v3/${appId}/settings`, {});
					if (targetUrl !== currentWebhookUrl) {
						throw new Error(`The APP ID ${appId} already has a target url ${targetUrl}. Delete it or use another APP ID before executing the trigger. Due to Hubspot API limitations, you can have just one trigger per APP.`);
					}
				} catch (error) {
					if (error.statusCode === 404) {
						return false;
					}
				}
				// if the app is using the current webhook url. Delete everything and create it again with the current events

				const { results: subscriptions } = await hubspotApiRequest.call(this, 'GET', `/webhooks/v3/${appId}/subscriptions`, {});

				// delete all subscriptions
				for (const subscription of subscriptions) {
					await hubspotApiRequest.call(this, 'DELETE', `/webhooks/v3/${appId}/subscriptions/${subscription.id}`, {});
				}

				await hubspotApiRequest.call(this, 'DELETE', `/webhooks/v3/${appId}/settings`, {});

				return false;
			},
			async create(this: IHookFunctions): Promise<boolean> {
				const webhookUrl = this.getNodeWebhookUrl('default');
				const { appId } = this.getCredentials('hubspotDeveloperApi') as IDataObject;
				const events = (this.getNodeParameter('eventsUi') as IDataObject || {}).eventValues as IDataObject[] || [];
				const additionalFields = this.getNodeParameter('additionalFields') as IDataObject;
				let endpoint = `/webhooks/v3/${appId}/settings`;
				let body: IDataObject = {
					targetUrl: webhookUrl,
					maxConcurrentRequests: additionalFields.maxConcurrentRequests || 5,
				};

				await hubspotApiRequest.call(this, 'PUT', endpoint, body);

				endpoint = `/webhooks/v3/${appId}/subscriptions`;

				if (Array.isArray(events) && events.length === 0) {
					throw new Error(`You must define at least one event`);
				}

				for (const event of events) {
					body = {
						eventType: event.name,
						active: true,
					};
					if (propertyEvents.includes(event.name as string)) {
						const property = event.property;
						body.propertyName = property;
					}
					await hubspotApiRequest.call(this, 'POST', endpoint, body);
				}

				return true;
			},
			async delete(this: IHookFunctions): Promise<boolean> {
				const { appId } = this.getCredentials('hubspotDeveloperApi') as IDataObject;

				const { results: subscriptions } = await hubspotApiRequest.call(this, 'GET', `/webhooks/v3/${appId}/subscriptions`, {});

				for (const subscription of subscriptions) {
					await hubspotApiRequest.call(this, 'DELETE', `/webhooks/v3/${appId}/subscriptions/${subscription.id}`, {});
				}

				try {
					await hubspotApiRequest.call(this, 'DELETE', `/webhooks/v3/${appId}/settings`, {});
				} catch (e) {
					return false;
				}
				return true;
			},
		},
	};

	async webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> {

		const credentials = this.getCredentials('hubspotDeveloperApi') as IDataObject;

		if (credentials === undefined) {
			throw new Error('No credentials found!');
		}

		const req = this.getRequestObject();
		const bodyData = req.body;
		const headerData = this.getHeaderData();
		//@ts-ignore
		if (headerData['x-hubspot-signature'] === undefined) {
			return {};
		}

		// check signare if client secret is defined

		if (credentials.clientSecret !== '') {
			const hash = `${credentials!.clientSecret}${JSON.stringify(bodyData)}`;
			const signature = createHash('sha256').update(hash).digest('hex');
			//@ts-ignore
			if (signature !== headerData['x-hubspot-signature']) {
				return {};
			}
		}

		for (let i = 0; i < bodyData.length; i++) {
			const subscriptionType = bodyData[i].subscriptionType as string;
			if (subscriptionType.includes('contact')) {
				bodyData[i].contactId = bodyData[i].objectId;
			}
			if (subscriptionType.includes('company')) {
				bodyData[i].companyId = bodyData[i].objectId;
			}
			if (subscriptionType.includes('deal')) {
				bodyData[i].dealId = bodyData[i].objectId;
			}
			delete bodyData[i].objectId;
		}
		return {
			workflowData: [
				this.helpers.returnJsonArray(bodyData),
			],
		};
	}
}


// @ts-ignore
this.selectBox.x = event.pageX;
// @ts-ignore

this.selectBox.style.left = this.selectBox.x + 'px';


import { IExecuteFunctions } from 'n8n-core';
import {
	INodeExecutionData,
	INodeType,
	INodeTypeDescription,
} from 'n8n-workflow';

const { NodeVM } = require('vm2');

export class Function implements INodeType {
	description: INodeTypeDescription = {
		displayName: 'Function',
		name: 'function',
		icon: 'fa:code',
		group: ['transform'],
		version: 1,
		description: 'Run custom function code which gets executed once and allows to add, remove, change and replace items.',
		defaults: {
			name: 'Function',
			color: '#FF9922',
		},
		inputs: ['main'],
		outputs: ['main'],
		properties: [
			{
				displayName: 'JavaScript Code',
				name: 'functionCode',
				typeOptions: {
					alwaysOpenEditWindow: true,
					editor: 'code',
					rows: 10,
				},
				type: 'string',
				default: 'items[0].json.myVariable = 1;\nreturn items;',
				description: 'The JavaScript code to execute.',
				noDataExpression: true,
			},
		],
	};

	async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
		// const item = this.getInputData();
		let items = this.getInputData();

		// Copy the items as they may get changed in the functions
		items = JSON.parse(JSON.stringify(items));

		// Define the global objects for the custom function
		const sandbox = {
			getNodeParameter: this.getNodeParameter,
			getWorkflowStaticData: this.getWorkflowStaticData,
			helpers: this.helpers,
			items,
			// To be able to access data of other items
			$item: (index: number) => this.getWorkflowDataProxy(index),
		};

		// Make it possible to access data via $node, $parameter, ...
		// By default use data from first item
		Object.assign(sandbox, sandbox.$item(0));

		const options = {
			console: 'inherit',
			sandbox,
			require: {
				external: false as boolean | { modules: string[] },
				builtin: [] as string[],
			},
		};

		if (process.env.NODE_FUNCTION_ALLOW_BUILTIN) {
			options.require.builtin = process.env.NODE_FUNCTION_ALLOW_BUILTIN.split(',');
		}

		if (process.env.NODE_FUNCTION_ALLOW_EXTERNAL) {
			options.require.external = { modules: process.env.NODE_FUNCTION_ALLOW_EXTERNAL.split(',') };
		}

		const vm = new NodeVM(options);

		// Get the code to execute
		const functionCode = this.getNodeParameter('functionCode', 0) as string;

		try {
			// Execute the function code
			items = (await vm.run(`module.exports = async function() {${functionCode}}()`, __dirname));
		} catch (e) {
			return Promise.reject(e);
		}

		// Do very basic validation of the data
		if (items === undefined) {
			throw new Error('No data got returned. Always return an Array of items!');
		}
		if (!Array.isArray(items)) {
			throw new Error('Always an Array of items has to be returned!');
		}
		for (const item of items) {
			if (item.json === undefined) {
				throw new Error('All returned items have to contain a property named "json"!');
			}
			if (typeof item.json !== 'object') {
				throw new Error('The json-property has to be an object!');
			}
			if (item.binary !== undefined) {
				if (Array.isArray(item.binary) || typeof item.binary !== 'object') {
					throw new Error('The binary-property has to be an object!');
				}
			}
		}

		return this.prepareOutputData(items);
	}
}


import {
	IConnections,
	IDataObject,
	INode,
	IWorkflowSettings,
} from 'n8n-workflow';

import {
	IWorkflowDb,
} from '../../';

import {
	Column,
	Entity,
	PrimaryGeneratedColumn,
} from 'typeorm';

@Entity()
export class WorkflowEntity implements IWorkflowDb {

	@PrimaryGeneratedColumn()
	id: number;

	@Column({
		length: 128,
	})
	name: string;

	@Column()
	active: boolean;

	@Column('json')
	nodes: INode[];

	@Column('json')
	connections: IConnections;

	@Column('datetime')
	createdAt: Date;

	@Column('datetime')
	updatedAt: Date;

	@Column({
		type: 'json',
		nullable: true,
	})
	settings?: IWorkflowSettings;

	@Column({
		type: 'json',
		nullable: true,
	})
	staticData?: IDataObject;
}


import {
	ICredentialType,
	NodePropertyTypes,
} from 'n8n-workflow';

const scopes = [
	'https://www.googleapis.com/auth/calendar',
	'https://www.googleapis.com/auth/calendar.events',
];

export class GoogleCalendarOAuth2Api implements ICredentialType {
	name = 'googleCalendarOAuth2Api';
	extends = [
		'googleOAuth2Api',
	];
	displayName = 'Google Calendar OAuth2 API';
	documentationUrl = 'google';
	properties = [
		{
			displayName: 'Scope',
			name: 'scope',
			type: 'hidden' as NodePropertyTypes,
			default: scopes.join(' '),
		},
	];
}


this.selectBox.style.left = event.pageX + 'px';

this.selectBox.style.top = event.pageY + 'px';

keep replace replace replace replace keep keep keep keep keep

this.selectBox.style.top = this.selectBox.y + 'px';


import {
	ICredentialType,
	NodePropertyTypes,
} from 'n8n-workflow';

export class BitlyApi implements ICredentialType {
	name = 'bitlyApi';
	displayName = 'Bitly API';
	documentationUrl = 'bitly';
	properties = [
		{
			displayName: 'Access Token',
			name: 'accessToken',
			type: 'string' as NodePropertyTypes,
			default: '',
		},
	];
}


import {
	INodeProperties,
} from 'n8n-workflow';

export const issueAttachmentOperations = [
	{
		displayName: 'Operation',
		name: 'operation',
		type: 'options',
		displayOptions: {
			show: {
				resource: [
					'issueAttachment',
				],
			},
		},
		options: [
			{
				name: 'Add',
				value: 'add',
				description: 'Add attachment to issue',
			},
			{
				name: 'Get',
				value: 'get',
				description: 'Get an attachment',
			},
			{
				name: 'Get All',
				value: 'getAll',
				description: 'Get all attachments',
			},
			{
				name: 'Remove',
				value: 'remove',
				description: 'Remove an attachment',
			},
		],
		default: 'add',
		description: 'The operation to perform.',
	},
] as INodeProperties[];

export const issueAttachmentFields = [

	/* -------------------------------------------------------------------------- */
	/*                                issueAttachment:add                         */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Issue Key',
		name: 'issueKey',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				resource: [
					'issueAttachment',
				],
				operation: [
					'add',
				],
			},
		},
		default: '',
		description: 'Issue Key',
	},
	{
		displayName: 'Binary Property',
		displayOptions: {
			show: {
				resource: [
					'issueAttachment',
				],
				operation: [
					'add',
				],
			},
		},
		name: 'binaryPropertyName',
		type: 'string',
		default: 'data',
		description: 'Object property name which holds binary data.',
		required: true,
	},

	/* -------------------------------------------------------------------------- */
	/*                                issueAttachment:get                         */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Attachment ID',
		name: 'attachmentId',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				resource: [
					'issueAttachment',
				],
				operation: [
					'get',
				],
			},
		},
		default: '',
		description: 'The ID of the attachment.',
	},
	{
		displayName: 'Download',
		name: 'download',
		type: 'boolean',
		default: false,
		required: true,
		displayOptions: {
			show: {
				resource: [
					'issueAttachment',
				],
				operation: [
					'get',
				],
			},
		},
	},
	{
		displayName: 'Binary Property',
		name: 'binaryProperty',
		type: 'string',
		default: 'data',
		displayOptions: {
			show: {
				resource: [
					'issueAttachment',
				],
				operation: [
					'get',
				],
				download: [
					true,
				],
			},
		},
		description: 'Object property name which holds binary data.',
		required: true,
	},
	/* -------------------------------------------------------------------------- */
	/*                                issueAttachment:getAll                      */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Issue Key',
		name: 'issueKey',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				resource: [
					'issueAttachment',
				],
				operation: [
					'getAll',
				],
			},
		},
		default: '',
		description: 'Issue Key',
	},
	{
		displayName: 'Return All',
		name: 'returnAll',
		type: 'boolean',
		displayOptions: {
			show: {
				resource: [
					'issueAttachment',
				],
				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: [
					'issueAttachment',
				],
				operation: [
					'getAll',
				],
				returnAll: [
					false,
				],
			},
		},
		typeOptions: {
			minValue: 1,
			maxValue: 100,
		},
		default: 50,
		description: 'How many results to return.',
	},
	{
		displayName: 'Download',
		name: 'download',
		type: 'boolean',
		default: false,
		required: true,
		displayOptions: {
			show: {
				resource: [
					'issueAttachment',
				],
				operation: [
					'getAll',
				],
			},
		},
	},
	{
		displayName: 'Binary Property',
		name: 'binaryProperty',
		type: 'string',
		default: 'data',
		displayOptions: {
			show: {
				resource: [
					'issueAttachment',
				],
				operation: [
					'getAll',
				],
				download: [
					true,
				],
			},
		},
		description: 'Object property name which holds binary data.',
		required: true,
	},
	/* -------------------------------------------------------------------------- */
	/*                                issueAttachment:remove                      */
	/* -------------------------------------------------------------------------- */
	{
		displayName: 'Attachment ID',
		name: 'attachmentId',
		type: 'string',
		required: true,
		displayOptions: {
			show: {
				resource: [
					'issueAttachment',
				],
				operation: [
					'remove',
				],
			},
		},
		default: '',
		description: 'The ID of the attachment.',
	},
] as INodeProperties[];


import { MigrationInterface, QueryRunner } from "typeorm";

import * as config from '../../../../config';

export class CreateIndexStoppedAt1594902918301 implements MigrationInterface {
	name = 'CreateIndexStoppedAt1594902918301';

	async up(queryRunner: QueryRunner): Promise<void> {
		const tablePrefix = config.get('database.tablePrefix');

		await queryRunner.query('CREATE INDEX `IDX_' + tablePrefix + 'cefb067df2402f6aed0638a6c1` ON `' + tablePrefix + 'execution_entity` (`stoppedAt`)');
	}

	async down(queryRunner: QueryRunner): Promise<void> {
		const tablePrefix = config.get('database.tablePrefix');

		await queryRunner.query('DROP INDEX `IDX_' + tablePrefix + 'cefb067df2402f6aed0638a6c1` ON `' + tablePrefix + 'execution_entity`');
	}

}


const {x, y} = this.getMousePositionWithinNodeView(event);


import {
	OptionsWithUri,
 } from 'request';

import {
	IExecuteFunctions,
	IExecuteSingleFunctions,
	ILoadOptionsFunctions,
} from 'n8n-core';

import {
	IDataObject,
} from 'n8n-workflow';

export async function xeroApiRequest(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, resource: string, body: any = {}, qs: IDataObject = {}, uri?: string, headers: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any
	const options: OptionsWithUri = {
		headers: {
			'Content-Type': 'application/json',
		},
		method,
		body,
		qs,
		uri: uri || `https://api.xero.com/api.xro/2.0${resource}`,
		json: true,
	};
	try {
		if (body.organizationId) {
			options.headers = { ...options.headers, 'Xero-tenant-id': body.organizationId };
			delete body.organizationId;
		}
		if (Object.keys(headers).length !== 0) {
			options.headers = Object.assign({}, options.headers, headers);
		}
		if (Object.keys(body).length === 0) {
			delete options.body;
		}
		//@ts-ignore
		return await this.helpers.requestOAuth2.call(this, 'xeroOAuth2Api', options);
	} catch (error) {
		let errorMessage;

		if (error.response && error.response.body && error.response.body.Message) {

			errorMessage = error.response.body.Message;

			if (error.response.body.Elements) {
				const elementErrors = [];
				for (const element of error.response.body.Elements) {
					elementErrors.push(element.ValidationErrors.map((error: IDataObject) =>  error.Message).join('|'));
				}
				errorMessage = elementErrors.join('-');
			}
			// Try to return the error prettier
			throw new Error(`Xero error response [${error.statusCode}]: ${errorMessage}`);
		}
		throw error;
	}
}

export async function xeroApiRequestAllItems(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;
	query.page = 1;

	do {
		responseData = await xeroApiRequest.call(this, method, endpoint, body, query);
		query.page++;
		returnData.push.apply(returnData, responseData[propertyName]);
	} while (
		responseData[propertyName].length !== 0
	);

	return returnData;
}


import {
	INodeProperties,
 } from 'n8n-workflow';

export const checklistOperations = [
	{
		displayName: 'Operation',
		name: 'operation',
		type: 'options',
		displayOptions: {
			show: {
				resource: [
					'checklist',
				],
			},
		},
		options: [
			{
				name: 'Create',
				value: 'create',
				description: 'Create a checklist',
			},
			{
				name: 'Delete',
				value: 'delete',
				description: 'Delete a checklist',
			},
			{
				name: 'Update',
				value: 'update',
				description: 'Update a checklist',
			},
		],
		default: 'create',
		description: 'The operation to perform.',
	},
] as INodeProperties[];

export const checklistFields = [

/* -------------------------------------------------------------------------- */
/*                                checklist:create                            */
/* -------------------------------------------------------------------------- */
	{
		displayName: 'Task ID',
		name: 'task',
		type: 'string',
		default: '',
		displayOptions: {
			show: {
				resource: [
					'checklist',
				],
				operation: [
					'create',
				],
			},
		},
		required: true,
	},
	{
		displayName: 'Name',
		name: 'name',
		type: 'string',
		default: '',
		displayOptions: {
			show: {
				resource: [
					'checklist',
				],
				operation: [
					'create',
				],
			},
		},
		required: true,
	},
/* -------------------------------------------------------------------------- */
/*                                checklist:delete                            */
/* -------------------------------------------------------------------------- */
	{
		displayName: 'Checklist ID',
		name: 'checklist',
		type: 'string',
		default: '',
		displayOptions: {
			show: {
				resource: [
					'checklist',
				],
				operation: [
					'delete',
				],
			},
		},
		required: true,
	},
/* -------------------------------------------------------------------------- */
/*                                checklist:update                            */
/* -------------------------------------------------------------------------- */
	{
		displayName: 'Checklist ID',
		name: 'checklist',
		type: 'string',
		default: '',
		displayOptions: {
			show: {
				resource: [
					'checklist',
				],
				operation: [
					'update',
				],
			},
		},
		required: true,
	},
	{
		displayName: 'Update Fields',
		name: 'updateFields',
		type: 'collection',
		placeholder: 'Add Field',
		default: {},
		displayOptions: {
			show: {
				resource: [
					'checklist',
				],
				operation: [
					'update',
				],
			},
		},
		options: [
			{
				displayName: 'Name',
				name: 'name',
				type: 'string',
				default: '',
			},
			{
				displayName: 'Position',
				name: 'position',
				type: 'number',
				typeOptions: {
					minValue: 0,
				},
				default: 0,
			},
		],
	},
] as INodeProperties[];


#!/usr/bin/env node

var path = require('path'); // tslint:disable-line:no-var-keyword

// Make sure that it also find the config folder when it
// did get started from another folder that the root one.
process.env.NODE_CONFIG_DIR = process.env.NODE_CONFIG_DIR || path.join(__dirname, 'config');

// Check if version should be displayed
var versionFlags = [ // tslint:disable-line:no-var-keyword
	'-v',
	'-V',
	'--version',
];
if (versionFlags.includes(process.argv.slice(-1)[0])) {
	console.log(require('../package').version);
	process.exit(0);
}

if (process.argv.length === 2) {
	// When no command is given choose by default start
	process.argv.push('start');
}

var nodeVersion = process.versions.node.split('.');

if (parseInt(nodeVersion[0], 10) < 12 || parseInt(nodeVersion[0], 10) === 12 && parseInt(nodeVersion[1], 10) < 9) {
	console.log(`\nYour Node.js version (${process.versions.node}) is too old to run n8n.\nPlease update to version 12.9 or later!\n`);
	process.exit(0);
}

require('@oclif/command').run()
.then(require('@oclif/command/flush'))
.catch(require('@oclif/errors/handle'));


import {
	OptionsWithUri,
} from 'request';

import {
	IExecuteFunctions,
	IExecuteSingleFunctions,
	ILoadOptionsFunctions,
} from 'n8n-core';

import {
	IDataObject,
} from 'n8n-workflow';

import * as moment from 'moment-timezone';

import * as jwt from 'jsonwebtoken';

export async function googleApiRequest(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, resource: string, body: any = {}, qs: IDataObject = {}, uri?: string, headers: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any
	const authenticationMethod = this.getNodeParameter('authentication', 0, 'serviceAccount') as string;
	const options: OptionsWithUri = {
		headers: {
			'Content-Type': 'application/json',
		},
		method,
		body,
		qs,
		uri: uri || `https://translation.googleapis.com${resource}`,
		json: true,
	};
	try {
		if (Object.keys(headers).length !== 0) {
			options.headers = Object.assign({}, options.headers, headers);
		}
		if (Object.keys(body).length === 0) {
			delete options.body;
		}

		if (authenticationMethod === 'serviceAccount') {
			const credentials = this.getCredentials('googleApi');

			if (credentials === undefined) {
				throw new Error('No credentials got returned!');
			}

			const { access_token } = await getAccessToken.call(this, credentials as IDataObject);

			options.headers!.Authorization = `Bearer ${access_token}`;
			//@ts-ignore
			return await this.helpers.request(options);
		} else {
			//@ts-ignore
			return await this.helpers.requestOAuth2.call(this, 'googleTranslateOAuth2Api', options);
		}
	} catch (error) {
		if (error.response && error.response.body && error.response.body.message) {
			// Try to return the error prettier
			throw new Error(`Google Translate error response [${error.statusCode}]: ${error.response.body.message}`);
		}
		throw error;
	}
}

export async function googleApiRequestAllItems(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;
	query.maxResults = 100;

	do {
		responseData = await googleApiRequest.call(this, method, endpoint, body, query);
		query.pageToken = responseData['nextPageToken'];
		returnData.push.apply(returnData, responseData[propertyName]);
	} while (
		responseData['nextPageToken'] !== undefined &&
		responseData['nextPageToken'] !== ''
	);

	return returnData;
}

function getAccessToken(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, credentials: IDataObject): Promise<IDataObject> {
	//https://developers.google.com/identity/protocols/oauth2/service-account#httprest

	const scopes = [
		'https://www.googleapis.com/auth/cloud-translation',
		'https://www.googleapis.com/auth/cloud-platform',
	];

	const now = moment().unix();

	const signature = jwt.sign(
		{
			'iss': credentials.email as string,
			'sub': credentials.email as string,
			'scope': scopes.join(' '),
			'aud': `https://oauth2.googleapis.com/token`,
			'iat': now,
			'exp': now + 3600,
		},
		credentials.privateKey as string,
		{
			algorithm: 'RS256',
			header: {
				'kid': credentials.privateKey as string,
				'typ': 'JWT',
				'alg': 'RS256',
			},
		},
	);

	const options: OptionsWithUri = {
		headers: {
			'Content-Type': 'application/x-www-form-urlencoded',
		},
		method: 'POST',
		form: {
			grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
			assertion: signature,
		},
		uri: 'https://oauth2.googleapis.com/token',
		json: true,
	};

	//@ts-ignore
	return this.helpers.request(options);
}


import {
	OptionsWithUri,
} from 'request';

import {
	IExecuteFunctions,
	IExecuteSingleFunctions,
	IHookFunctions,
	ILoadOptionsFunctions,
} from 'n8n-core';

import {
	IDataObject,
} from 'n8n-workflow';

export async function sendGridApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, endpoint: string, method: string, body: any = {}, qs: IDataObject = {}, uri?: string | undefined): Promise<any> { // tslint:disable-line:no-any
	const credentials = this.getCredentials('sendGridApi') as IDataObject;

	const host = 'api.sendgrid.com/v3';

	const options: OptionsWithUri = {
		headers: {
			Authorization: `Bearer ${credentials.apiKey}`,
		},
		method,
		qs,
		body,
		uri: uri || `https://${host}${endpoint}`,
		json: true,
	};

	if (Object.keys(body).length === 0) {
		delete options.body;
	}

	try {
		//@ts-ignore
		return await this.helpers.request!(options);
	} catch (error) {
		if (error.response && error.response.body && error.response.body.errors) {

			let errors = error.response.body.errors;

			errors = errors.map((e: IDataObject) => e.message);
			// Try to return the error prettier
			throw new Error(
				`SendGrid error response [${error.statusCode}]: ${errors.join('|')}`,
			);
		}
		throw error;
	}
}

export async function sendGridApiRequestAllItems(this: IExecuteFunctions | ILoadOptionsFunctions, endpoint: string, method: string, propertyName: string, body: any = {}, query: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any

	const returnData: IDataObject[] = [];

	let responseData;

	let uri;

	do {
		responseData = await sendGridApiRequest.call(this, endpoint, method, body, query, uri);
		uri = responseData._metadata.next;
		returnData.push.apply(returnData, responseData[propertyName]);
		if (query.limit && returnData.length >= query.limit) {
			return returnData;
		}
	} while (
		responseData._metadata.next !== undefined
	);

	return returnData;
}


import {
	INodeProperties,
 } from 'n8n-workflow';

export const goalKeyResultOperations = [
	{
		displayName: 'Operation',
		name: 'operation',
		type: 'options',
		displayOptions: {
			show: {
				resource: [
					'goalKeyResult',
				],
			},
		},
		options: [
			{
				name: 'Create',
				value: 'create',
				description: 'Create a key result',
			},
			{
				name: 'Delete',
				value: 'delete',
				description: 'Delete a key result',
			},
			{
				name: 'Update',
				value: 'update',
				description: 'Update a key result',
			},
		],
		default: 'create',
		description: 'The operation to perform.',
	},
] as INodeProperties[];

export const goalKeyResultFields = [

/* -------------------------------------------------------------------------- */
/*                                goalKeyResult:create                        */
/* -------------------------------------------------------------------------- */
	{
		displayName: 'Goal ID',
		name: 'goal',
		type: 'string',
		default: '',
		displayOptions: {
			show: {
				resource: [
					'goalKeyResult',
				],
				operation: [
					'create',
				],
			},
		},
		required: true,
	},
	{
		displayName: 'Name',
		name: 'name',
		type: 'string',
		default: '',
		displayOptions: {
			show: {
				resource: [
					'goalKeyResult',
				],
				operation: [
					'create',
				],
			},
		},
		required: true,
	},
	{
		displayName: 'Type',
		name: 'type',
		type: 'options',
		options: [
			{
				name: 'Automatic',
				value: 'automatic',
			},
			{
				name: 'Boolean',
				value: 'boolean',
			},
			{
				name: 'Currency',
				value: 'currency',
			},
			{
				name: 'Number',
				value: 'number',
			},
			{
				name: 'Percentage',
				value: 'percentage',
			},
		],
		default: '',
		displayOptions: {
			show: {
				resource: [
					'goalKeyResult',
				],
				operation: [
					'create',
				],
			},
		},
		required: true,
	},
	{
		displayName: 'Additional Fields',
		name: 'additionalFields',
		type: 'collection',
		placeholder: 'Add Field',
		default: {},
		displayOptions: {
			show: {
				resource: [
					'goalKeyResult',
				],
				operation: [
					'create',
				],
			},
		},
		options: [
			{
				displayName: 'List IDs',
				name: 'listIds',
				type: 'string',
				default: '',
			},
			{
				displayName: 'Owners',
				name: 'owners',
				type: 'string',
				default: '',
			},
			{
				displayName: 'Steps Start',
				name: 'stepsStart',
				type: 'number',
				typeOptions: {
					minValue: 0,
				},
				default: 0,
				description: 'Required for Percentage, Automatic, Number and Currency',
			},
			{
				displayName: 'Steps End',
				name: 'stepsEnd',
				type: 'number',
				typeOptions: {
					minValue: 0,
				},
				default: 0,
				description: 'Required for Percentage, Automatic, Number and Currency',
			},
			{
				displayName: 'Task IDs',
				name: 'taskIds',
				type: 'string',
				default: '',
			},
			{
				displayName: 'Unit',
				name: 'unit',
				type: 'string',
				default: '',
				description: `Only matters for type Number and Currency. For Currency the unit must be a valid currency code.`,
			},
		],
	},
/* -------------------------------------------------------------------------- */
/*                                goalKeyResult:delete                        */
/* -------------------------------------------------------------------------- */
	{
		displayName: 'Key Result ID',
		name: 'keyResult',
		type: 'string',
		default: '',
		displayOptions: {
			show: {
				resource: [
					'goalKeyResult',
				],
				operation: [
					'delete',
				],
			},
		},
		required: true,
	},
/* -------------------------------------------------------------------------- */
/*                                goalKeyResult:update                        */
/* -------------------------------------------------------------------------- */
	{
		displayName: 'Key Result ID',
		name: 'keyResult',
		type: 'string',
		default: '',
		displayOptions: {
			show: {
				resource: [
					'goalKeyResult',
				],
				operation: [
					'update',
				],
			},
		},
		required: true,
	},
	{
		displayName: 'Update Fields',
		name: 'updateFields',
		type: 'collection',
		placeholder: 'Add Field',
		default: {},
		displayOptions: {
			show: {
				resource: [
					'goalKeyResult',
				],
				operation: [
					'update',
				],
			},
		},
		options: [
			{
				displayName: 'Name',
				name: 'name',
				type: 'string',
				default: '',
			},
			{
				displayName: 'Note',
				name: 'note',
				type: 'string',
				typeOptions: {
					alwaysOpenEditWindow: true,
				},
				default: '',
			},
			{
				displayName: 'Steps Current',
				name: 'stepsCurrent',
				type: 'number',
				typeOptions: {
					minValue: 0,
				},
				default: 1,
			},
			{
				displayName: 'Steps End',
				name: 'stepsEnd',
				type: 'number',
				typeOptions: {
					minValue: 0,
				},
				default: 0,
			},
			{
				displayName: 'Steps Start',
				name: 'stepsStart',
				type: 'number',
				typeOptions: {
					minValue: 0,
				},
				default: 0,
			},
			{
				displayName: 'Unit',
				name: 'unit',
				type: 'string',
				default: '',
				description: `Only matters for type Number and Currency. For Currency the unit must be a valid currency code.`,
			},
		],
	},
] as INodeProperties[];