mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-25 20:54:07 -08:00
✨ Add resource "files" to Pipedrive-Node
This commit is contained in:
parent
014972a0c0
commit
a24918021c
|
@ -7,6 +7,8 @@ import {
|
||||||
IDataObject,
|
IDataObject,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
import { OptionsWithUri } from 'request';
|
||||||
|
|
||||||
|
|
||||||
export interface ICustomInterface {
|
export interface ICustomInterface {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -25,7 +27,7 @@ export interface ICustomInterface {
|
||||||
* @param {object} body
|
* @param {object} body
|
||||||
* @returns {Promise<any>}
|
* @returns {Promise<any>}
|
||||||
*/
|
*/
|
||||||
export async function pipedriveApiRequest(this: IHookFunctions | IExecuteFunctions, method: string, endpoint: string, body: IDataObject, query?: IDataObject): Promise<any> { // tslint:disable-line:no-any
|
export async function pipedriveApiRequest(this: IHookFunctions | IExecuteFunctions, method: string, endpoint: string, body: IDataObject, query?: IDataObject, formData?: IDataObject, downloadFile?: boolean): Promise<any> { // tslint:disable-line:no-any
|
||||||
const credentials = this.getCredentials('pipedriveApi');
|
const credentials = this.getCredentials('pipedriveApi');
|
||||||
if (credentials === undefined) {
|
if (credentials === undefined) {
|
||||||
throw new Error('No credentials got returned!');
|
throw new Error('No credentials got returned!');
|
||||||
|
@ -37,17 +39,35 @@ export async function pipedriveApiRequest(this: IHookFunctions | IExecuteFunctio
|
||||||
|
|
||||||
query.api_token = credentials.apiToken;
|
query.api_token = credentials.apiToken;
|
||||||
|
|
||||||
const options = {
|
const options: OptionsWithUri = {
|
||||||
method,
|
method,
|
||||||
body,
|
|
||||||
qs: query,
|
qs: query,
|
||||||
uri: `https://api.pipedrive.com/v1${endpoint}`,
|
uri: `https://api.pipedrive.com/v1${endpoint}`,
|
||||||
json: true
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (downloadFile === true) {
|
||||||
|
options.encoding = null;
|
||||||
|
} else {
|
||||||
|
options.json = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(body).length !== 0) {
|
||||||
|
options.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formData !== undefined && Object.keys(formData).length !== 0) {
|
||||||
|
options.formData = formData;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const responseData = await this.helpers.request(options);
|
const responseData = await this.helpers.request(options);
|
||||||
|
|
||||||
|
if (downloadFile === true) {
|
||||||
|
return {
|
||||||
|
data: responseData,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (responseData.success === false) {
|
if (responseData.success === false) {
|
||||||
throw new Error(`Pipedrive error response: ${responseData.error} (${responseData.error_info})`);
|
throw new Error(`Pipedrive error response: ${responseData.error} (${responseData.error_info})`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import {
|
import {
|
||||||
|
BINARY_ENCODING,
|
||||||
IExecuteFunctions,
|
IExecuteFunctions,
|
||||||
} from 'n8n-core';
|
} from 'n8n-core';
|
||||||
import {
|
import {
|
||||||
|
@ -73,6 +74,10 @@ export class Pipedrive implements INodeType {
|
||||||
name: 'Deal',
|
name: 'Deal',
|
||||||
value: 'deal',
|
value: 'deal',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'File',
|
||||||
|
value: 'file',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Note',
|
name: 'Note',
|
||||||
value: 'note',
|
value: 'note',
|
||||||
|
@ -183,6 +188,53 @@ export class Pipedrive implements INodeType {
|
||||||
description: 'The operation to perform.',
|
description: 'The operation to perform.',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
displayName: 'Operation',
|
||||||
|
name: 'operation',
|
||||||
|
type: 'options',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'file',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Create',
|
||||||
|
value: 'create',
|
||||||
|
description: 'Create a file',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Delete',
|
||||||
|
value: 'delete',
|
||||||
|
description: 'Delete a file',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Download',
|
||||||
|
value: 'download',
|
||||||
|
description: 'Download a file',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Get',
|
||||||
|
value: 'get',
|
||||||
|
description: 'Get data of a file',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// name: 'Get All',
|
||||||
|
// value: 'getAll',
|
||||||
|
// description: 'Get data of all file',
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: 'Update',
|
||||||
|
// value: 'update',
|
||||||
|
// description: 'Update a file',
|
||||||
|
// },
|
||||||
|
],
|
||||||
|
default: 'create',
|
||||||
|
description: 'The operation to perform.',
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
displayName: 'Operation',
|
displayName: 'Operation',
|
||||||
name: 'operation',
|
name: 'operation',
|
||||||
|
@ -1092,6 +1144,174 @@ export class Pipedrive implements INodeType {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// file
|
||||||
|
// ----------------------------------
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// file:create
|
||||||
|
// ----------------------------------
|
||||||
|
{
|
||||||
|
displayName: 'Binary Property',
|
||||||
|
name: 'binaryPropertyName',
|
||||||
|
type: 'string',
|
||||||
|
default: 'data',
|
||||||
|
required: true,
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: [
|
||||||
|
'create'
|
||||||
|
],
|
||||||
|
resource: [
|
||||||
|
'file',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
placeholder: '',
|
||||||
|
description: 'Name of the binary property which contains<br />the data for the file to be created.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Additional Fields',
|
||||||
|
name: 'additionalFields',
|
||||||
|
type: 'collection',
|
||||||
|
placeholder: 'Add Field',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: [
|
||||||
|
'create',
|
||||||
|
],
|
||||||
|
resource: [
|
||||||
|
'file',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: {},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
displayName: 'Activity ID',
|
||||||
|
name: 'activity_id',
|
||||||
|
type: 'number',
|
||||||
|
default: 0,
|
||||||
|
description: 'ID of the activite this file will be associated with.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Deal ID',
|
||||||
|
name: 'deal_id',
|
||||||
|
type: 'number',
|
||||||
|
default: 0,
|
||||||
|
description: 'ID of the deal this file will be associated with',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Organization ID',
|
||||||
|
name: 'org_id',
|
||||||
|
type: 'number',
|
||||||
|
default: 0,
|
||||||
|
description: 'ID of the organization this file will be associated with.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Person ID',
|
||||||
|
name: 'person_id',
|
||||||
|
type: 'number',
|
||||||
|
default: 0,
|
||||||
|
description: 'ID of the person this file will be associated with.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Product ID',
|
||||||
|
name: 'product_id',
|
||||||
|
type: 'number',
|
||||||
|
default: 0,
|
||||||
|
description: 'ID of the person this file will be associated with.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// file:delete
|
||||||
|
// ----------------------------------
|
||||||
|
{
|
||||||
|
displayName: 'File ID',
|
||||||
|
name: 'fileId',
|
||||||
|
type: 'number',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: [
|
||||||
|
'delete',
|
||||||
|
],
|
||||||
|
resource: [
|
||||||
|
'file',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: 0,
|
||||||
|
required: true,
|
||||||
|
description: 'ID of the file to delete.',
|
||||||
|
},
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// file:download
|
||||||
|
// ----------------------------------
|
||||||
|
{
|
||||||
|
displayName: 'File ID',
|
||||||
|
name: 'fileId',
|
||||||
|
type: 'number',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: [
|
||||||
|
'download',
|
||||||
|
],
|
||||||
|
resource: [
|
||||||
|
'file',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: 0,
|
||||||
|
required: true,
|
||||||
|
description: 'ID of the file to download.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Binary Property',
|
||||||
|
name: 'binaryPropertyName',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
default: 'data',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: [
|
||||||
|
'download'
|
||||||
|
],
|
||||||
|
resource: [
|
||||||
|
'file',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
description: 'Name of the binary property to which to<br />write the data of the downloaded file.',
|
||||||
|
},
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// file:get
|
||||||
|
// ----------------------------------
|
||||||
|
{
|
||||||
|
displayName: 'File ID',
|
||||||
|
name: 'fileId',
|
||||||
|
type: 'number',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: [
|
||||||
|
'get'
|
||||||
|
],
|
||||||
|
resource: [
|
||||||
|
'file',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: 0,
|
||||||
|
required: true,
|
||||||
|
description: 'ID of the file to get.',
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------
|
// ----------------------------------
|
||||||
// note
|
// note
|
||||||
// ----------------------------------
|
// ----------------------------------
|
||||||
|
@ -1786,9 +2006,13 @@ export class Pipedrive implements INodeType {
|
||||||
|
|
||||||
// For Post
|
// For Post
|
||||||
let body: IDataObject;
|
let body: IDataObject;
|
||||||
|
// For FormData
|
||||||
|
let formData: IDataObject;
|
||||||
// For Query string
|
// For Query string
|
||||||
let qs: IDataObject;
|
let qs: IDataObject;
|
||||||
|
|
||||||
|
let downloadFile: boolean;
|
||||||
|
|
||||||
let requestMethod: string;
|
let requestMethod: string;
|
||||||
let endpoint: string;
|
let endpoint: string;
|
||||||
let returnAll = false;
|
let returnAll = false;
|
||||||
|
@ -1800,7 +2024,9 @@ export class Pipedrive implements INodeType {
|
||||||
|
|
||||||
requestMethod = 'GET';
|
requestMethod = 'GET';
|
||||||
endpoint = '';
|
endpoint = '';
|
||||||
|
downloadFile = false;
|
||||||
body = {};
|
body = {};
|
||||||
|
formData = {};
|
||||||
qs = {};
|
qs = {};
|
||||||
|
|
||||||
if (resource === 'activity') {
|
if (resource === 'activity') {
|
||||||
|
@ -1928,6 +2154,73 @@ export class Pipedrive implements INodeType {
|
||||||
addAdditionalFields(body, updateFields);
|
addAdditionalFields(body, updateFields);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (resource === 'file') {
|
||||||
|
if (operation === 'create') {
|
||||||
|
// ----------------------------------
|
||||||
|
// file:create
|
||||||
|
// ----------------------------------
|
||||||
|
|
||||||
|
requestMethod = 'POST';
|
||||||
|
endpoint = '/files';
|
||||||
|
|
||||||
|
const item = items[i];
|
||||||
|
|
||||||
|
if (item.binary === undefined) {
|
||||||
|
throw new Error('No binary data exists on item!');
|
||||||
|
}
|
||||||
|
|
||||||
|
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i) as string;
|
||||||
|
|
||||||
|
if (item.binary[binaryPropertyName] === undefined) {
|
||||||
|
throw new Error(`No binary data property "${binaryPropertyName}" does not exists on item!`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileBufferData = Buffer.from(item.binary[binaryPropertyName].data, BINARY_ENCODING);
|
||||||
|
|
||||||
|
formData.file = {
|
||||||
|
value: fileBufferData,
|
||||||
|
options: {
|
||||||
|
contentType: item.binary[binaryPropertyName].mimeType,
|
||||||
|
filename: item.binary[binaryPropertyName].fileName,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
|
||||||
|
addAdditionalFields(formData, additionalFields);
|
||||||
|
|
||||||
|
} else if (operation === 'delete') {
|
||||||
|
// ----------------------------------
|
||||||
|
// file:delete
|
||||||
|
// ----------------------------------
|
||||||
|
|
||||||
|
requestMethod = 'DELETE';
|
||||||
|
|
||||||
|
const fileId = this.getNodeParameter('fileId', i) as number;
|
||||||
|
endpoint = `/files/${fileId}`;
|
||||||
|
|
||||||
|
} else if (operation === 'download') {
|
||||||
|
// ----------------------------------
|
||||||
|
// file:download
|
||||||
|
// ----------------------------------
|
||||||
|
|
||||||
|
requestMethod = 'GET';
|
||||||
|
downloadFile = true;
|
||||||
|
|
||||||
|
const fileId = this.getNodeParameter('fileId', i) as number;
|
||||||
|
endpoint = `/files/${fileId}/download`;
|
||||||
|
|
||||||
|
} else if (operation === 'get') {
|
||||||
|
// ----------------------------------
|
||||||
|
// file:get
|
||||||
|
// ----------------------------------
|
||||||
|
|
||||||
|
requestMethod = 'GET';
|
||||||
|
|
||||||
|
const fileId = this.getNodeParameter('fileId', i) as number;
|
||||||
|
endpoint = `/files/${fileId}`;
|
||||||
|
|
||||||
|
}
|
||||||
} else if (resource === 'note') {
|
} else if (resource === 'note') {
|
||||||
if (operation === 'create') {
|
if (operation === 'create') {
|
||||||
// ----------------------------------
|
// ----------------------------------
|
||||||
|
@ -1989,8 +2282,6 @@ export class Pipedrive implements INodeType {
|
||||||
addAdditionalFields(body, updateFields);
|
addAdditionalFields(body, updateFields);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} else if (resource === 'organization') {
|
} else if (resource === 'organization') {
|
||||||
if (operation === 'create') {
|
if (operation === 'create') {
|
||||||
// ----------------------------------
|
// ----------------------------------
|
||||||
|
@ -2013,6 +2304,7 @@ export class Pipedrive implements INodeType {
|
||||||
|
|
||||||
const organizationId = this.getNodeParameter('organizationId', i) as number;
|
const organizationId = this.getNodeParameter('organizationId', i) as number;
|
||||||
endpoint = `/organizations/${organizationId}`;
|
endpoint = `/organizations/${organizationId}`;
|
||||||
|
|
||||||
} else if (operation === 'get') {
|
} else if (operation === 'get') {
|
||||||
// ----------------------------------
|
// ----------------------------------
|
||||||
// organization:get
|
// organization:get
|
||||||
|
@ -2123,17 +2415,37 @@ export class Pipedrive implements INodeType {
|
||||||
if (returnAll === true) {
|
if (returnAll === true) {
|
||||||
responseData = await pipedriveApiRequestAllItems.call(this, requestMethod, endpoint, body, qs);
|
responseData = await pipedriveApiRequestAllItems.call(this, requestMethod, endpoint, body, qs);
|
||||||
} else {
|
} else {
|
||||||
responseData = await pipedriveApiRequest.call(this, requestMethod, endpoint, body, qs);
|
responseData = await pipedriveApiRequest.call(this, requestMethod, endpoint, body, qs, formData, downloadFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(responseData.data)) {
|
if (resource === 'file' && operation === 'download') {
|
||||||
returnData.push.apply(returnData, responseData.data as IDataObject[]);
|
const newItem: INodeExecutionData = {
|
||||||
|
json: items[i].json,
|
||||||
|
binary: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (items[i].binary !== undefined) {
|
||||||
|
// Create a shallow copy of the binary data so that the old
|
||||||
|
// data references which do not get changed still stay behind
|
||||||
|
// but the incoming data does not get changed.
|
||||||
|
Object.assign(newItem.binary, items[i].binary);
|
||||||
|
}
|
||||||
|
|
||||||
|
items[i] = newItem;
|
||||||
|
|
||||||
|
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i) as string;
|
||||||
|
|
||||||
|
items[i].binary![binaryPropertyName] = await this.helpers.prepareBinaryData(responseData.data);
|
||||||
} else {
|
} else {
|
||||||
returnData.push(responseData.data as IDataObject);
|
if (Array.isArray(responseData.data)) {
|
||||||
|
returnData.push.apply(returnData, responseData.data as IDataObject[]);
|
||||||
|
} else {
|
||||||
|
returnData.push(responseData.data as IDataObject);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (['get', 'getAll'].includes(operation) && resource !== 'note') {
|
if (['get', 'getAll'].includes(operation) && ['activity', 'deal', 'organization', 'person', 'product'].includes(resource)) {
|
||||||
const resolveProperties = this.getNodeParameter('resolveProperties', 0) as boolean;
|
const resolveProperties = this.getNodeParameter('resolveProperties', 0) as boolean;
|
||||||
|
|
||||||
if (resolveProperties === true) {
|
if (resolveProperties === true) {
|
||||||
|
@ -2141,6 +2453,12 @@ export class Pipedrive implements INodeType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return [this.helpers.returnJsonArray(returnData)];
|
if (resource === 'file' && operation === 'download') {
|
||||||
|
// For file downloads the files get attached to the existing items
|
||||||
|
return this.prepareOutputData(items);
|
||||||
|
} else {
|
||||||
|
// For all other ones does the output items get replaced
|
||||||
|
return [this.helpers.returnJsonArray(returnData)];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue