From ea8d9921cd5ab5686005797ac7592558f66fba2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milorad=20Filipovi=C4=87?= Date: Wed, 4 May 2022 11:42:50 +0200 Subject: [PATCH 01/11] =?UTF-8?q?=F0=9F=9A=A7=20Initial=20progress=20on=20?= =?UTF-8?q?PostBin=20node.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nodes/PostBin/BinDescription.ts | 79 +++++++++++++++++++ .../nodes-base/nodes/PostBin/PostBin.node.ts | 63 +++++++++++++++ .../nodes/PostBin/RequestDescription.ts | 52 ++++++++++++ packages/nodes-base/nodes/PostBin/postbin.svg | 3 + 4 files changed, 197 insertions(+) create mode 100644 packages/nodes-base/nodes/PostBin/BinDescription.ts create mode 100644 packages/nodes-base/nodes/PostBin/PostBin.node.ts create mode 100644 packages/nodes-base/nodes/PostBin/RequestDescription.ts create mode 100644 packages/nodes-base/nodes/PostBin/postbin.svg diff --git a/packages/nodes-base/nodes/PostBin/BinDescription.ts b/packages/nodes-base/nodes/PostBin/BinDescription.ts new file mode 100644 index 0000000000000..559d9c4fa9899 --- /dev/null +++ b/packages/nodes-base/nodes/PostBin/BinDescription.ts @@ -0,0 +1,79 @@ +import { + INodeProperties +} from 'n8n-workflow'; + +export const binOperations: INodeProperties[] = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'bin', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create new bin', + }, + { + name: 'Get', + value: 'get', + description: 'Returns information based on the binId you provide.', + }, + { + name: 'Delete', + value: 'delete', + description: `Deletes this bin and all of it's posts.`, + }, + ], + default: 'create', + description: 'The operation to perform.', + }, +] + +export const binFields: INodeProperties[] = [ + { + displayName: 'Bin ID', + name: 'binId', + type: 'string', + default: '', + displayOptions: { + show: { + resource: [ + 'bin', + 'request' + ], + operation: [ + 'get', + 'delete', + 'shift', + ] + }, + }, + description: 'Unique identifier for each bin.', + }, + { + displayName: 'Bin content', + name: 'binContent', + type: 'string', + default: '', + typeOptions: { + rows: 5, + }, + displayOptions: { + show: { + resource: [ + 'bin', + ], + operation: [ + 'get', + ] + } + } + } +] diff --git a/packages/nodes-base/nodes/PostBin/PostBin.node.ts b/packages/nodes-base/nodes/PostBin/PostBin.node.ts new file mode 100644 index 0000000000000..99757f60fdbe7 --- /dev/null +++ b/packages/nodes-base/nodes/PostBin/PostBin.node.ts @@ -0,0 +1,63 @@ +import { IExecuteFunctions } from 'n8n-core'; +import { + INodeExecutionData, + INodeType, + INodeTypeDescription +} from 'n8n-workflow'; + +import { + binOperations, + binFields +} from './BinDescription'; + +import { + requestOperations, + requestFields +} from './RequestDescription'; + +export class PostBin implements INodeType { + description: INodeTypeDescription = { + displayName: 'PostBin', + name: 'postBin', + icon: 'file:postbin.svg', + group: ['transform'], + version: 1, + subtitle: '={{ $parameter["operation"] + ": " + $parameter["resource"] }}', + description: 'Consume PostBin API', + defaults: { + name: 'PostBin', + color: '#4dc0b5' + }, + inputs: ['main'], + outputs: ['main'], + credentials: [], + properties: [ + { + displayName: 'Resource', + name: 'resource', + type: 'options', + options: [ + { + name: 'Bin', + value: 'bin' + }, + { + name: 'Request', + value: 'request' + } + ], + default: 'bin', + required: true, + description: 'Bin to work with' + }, + ...binOperations, + ...requestOperations, + ...binFields, + ...requestFields, + ] + }; + + async execute(this: IExecuteFunctions): Promise { + return [[]]; + } +} diff --git a/packages/nodes-base/nodes/PostBin/RequestDescription.ts b/packages/nodes-base/nodes/PostBin/RequestDescription.ts new file mode 100644 index 0000000000000..713aecbcdf41f --- /dev/null +++ b/packages/nodes-base/nodes/PostBin/RequestDescription.ts @@ -0,0 +1,52 @@ +import { + INodeProperties +} from 'n8n-workflow'; + +export const requestOperations: INodeProperties[] = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'request' + ], + }, + }, + options: [ + { + name: 'Get', + value: 'get', + description: 'Returns information based on the binId and reqId you provide.', + }, + { + name: 'Shift', + value: 'shift', + description: 'Removes the first request form the bin.' + } + ], + default: 'get', + description: 'The operation to perform' + } +] + +export const requestFields: INodeProperties[] = [ + { + displayName: 'Request ID', + name: 'requestId', + type: 'string', + default: '', + displayOptions: { + show: { + resource: [ + 'request' + ], + operation: [ + 'get', + ] + } + }, + description: 'Unique identifier for each request.', + } +] diff --git a/packages/nodes-base/nodes/PostBin/postbin.svg b/packages/nodes-base/nodes/PostBin/postbin.svg new file mode 100644 index 0000000000000..daea1576f6077 --- /dev/null +++ b/packages/nodes-base/nodes/PostBin/postbin.svg @@ -0,0 +1,3 @@ + + + From 7bb154c5da589847e08a83d0dd42fa869ac2ac10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milorad=20Filipovi=C4=87?= Date: Wed, 4 May 2022 17:27:28 +0200 Subject: [PATCH 02/11] =?UTF-8?q?=E2=9C=A8=20Implemented=20Bin=20and=20Req?= =?UTF-8?q?uest=20operations=20for=20PostBin=20node.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nodes/PostBin/BinDescription.ts | 87 +++++++----- .../nodes/PostBin/GenericFunctions.ts | 131 ++++++++++++++++++ .../nodes-base/nodes/PostBin/NodeConstants.ts | 78 +++++++++++ .../nodes-base/nodes/PostBin/PostBin.node.ts | 110 +++++++++++++-- .../nodes/PostBin/RequestDescription.ts | 33 +++-- 5 files changed, 380 insertions(+), 59 deletions(-) create mode 100644 packages/nodes-base/nodes/PostBin/GenericFunctions.ts create mode 100644 packages/nodes-base/nodes/PostBin/NodeConstants.ts diff --git a/packages/nodes-base/nodes/PostBin/BinDescription.ts b/packages/nodes-base/nodes/PostBin/BinDescription.ts index 559d9c4fa9899..8a4d0ded08fbf 100644 --- a/packages/nodes-base/nodes/PostBin/BinDescription.ts +++ b/packages/nodes-base/nodes/PostBin/BinDescription.ts @@ -2,7 +2,15 @@ import { INodeProperties } from 'n8n-workflow'; +import { + RESOURCES, + BIN_OPERATIONS, + BIN_FIELDS, + REQUEST_OPERATIONS +} from './NodeConstants'; + export const binOperations: INodeProperties[] = [ + // eslint-disable-next-line n8n-nodes-base/node-param-default-missing { displayName: 'Operation', name: 'operation', @@ -10,70 +18,77 @@ export const binOperations: INodeProperties[] = [ displayOptions: { show: { resource: [ - 'bin', + RESOURCES.BIN.value, ], }, }, options: [ { - name: 'Create', - value: 'create', - description: 'Create new bin', + name: BIN_OPERATIONS.CREATE.name, + value: BIN_OPERATIONS.CREATE.value, + description: BIN_OPERATIONS.CREATE.description, + }, + { + name: BIN_OPERATIONS.GET.name, + value: BIN_OPERATIONS.GET.value, + description: BIN_OPERATIONS.GET.description, }, { - name: 'Get', - value: 'get', - description: 'Returns information based on the binId you provide.', + name: BIN_OPERATIONS.DELETE.name, + value: BIN_OPERATIONS.DELETE.value, + description: BIN_OPERATIONS.DELETE.description, }, { - name: 'Delete', - value: 'delete', - description: `Deletes this bin and all of it's posts.`, + name: BIN_OPERATIONS.TEST.name, + value: BIN_OPERATIONS.TEST.value, + description: BIN_OPERATIONS.TEST.description, }, ], - default: 'create', + default: BIN_OPERATIONS.CREATE.value, description: 'The operation to perform.', }, ] export const binFields: INodeProperties[] = [ { - displayName: 'Bin ID', - name: 'binId', + name: BIN_FIELDS.BIN_ID.name, + displayName: BIN_FIELDS.BIN_ID.displayName, type: 'string', default: '', + required: true, displayOptions: { show: { resource: [ - 'bin', - 'request' + RESOURCES.BIN.value, + RESOURCES.REQUEST.value ], operation: [ - 'get', - 'delete', - 'shift', + BIN_OPERATIONS.GET.value, + BIN_OPERATIONS.DELETE.value, + BIN_OPERATIONS.TEST.value, + REQUEST_OPERATIONS.SHIFT.value, ] }, }, description: 'Unique identifier for each bin.', }, { - displayName: 'Bin content', - name: 'binContent', - type: 'string', - default: '', - typeOptions: { - rows: 5, - }, - displayOptions: { - show: { - resource: [ - 'bin', - ], - operation: [ - 'get', - ] - } - } - } + name: BIN_FIELDS.BIN_CONTENT.name, + displayName: BIN_FIELDS.BIN_CONTENT.displayName, + type: 'string', + default: '', + typeOptions: { + rows: 5, + }, + displayOptions: { + show: { + resource: [ + RESOURCES.BIN.value, + ], + operation: [ + BIN_OPERATIONS.TEST.value, + ] + } + } + }, ] diff --git a/packages/nodes-base/nodes/PostBin/GenericFunctions.ts b/packages/nodes-base/nodes/PostBin/GenericFunctions.ts new file mode 100644 index 0000000000000..0688c255a81a9 --- /dev/null +++ b/packages/nodes-base/nodes/PostBin/GenericFunctions.ts @@ -0,0 +1,131 @@ +import { IExecuteFunctions, IExecuteSingleFunctions, ILoadOptionsFunctions } from "n8n-core"; +import { IDataObject, IHookFunctions, NodeApiError } from "n8n-workflow"; +import { OptionsWithUri } from "request"; +import { + NODE_SETTINGS +} from './NodeConstants' + +const BIN_STRING_REGEX = /Bin '(\d+-\d+)'/g +const BIN_URL_REGEX = /https:\/\/www\.toptal\.com\/developers\/postbin\/b\/(\d+-\d+)/g + +export async function createBinRequest( + this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, +) { + let options: OptionsWithUri = { + method: 'POST', + uri: `${NODE_SETTINGS.BASE_URL}${NODE_SETTINGS.CREATE_BIN_URL}`, + json: true, + } + + try { + return await this.helpers.request!(options); + } catch (error) { + throw new NodeApiError(this.getNode(), error); + } +} + +export async function getBinRequest( + this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, + binId: string +) { + let options: OptionsWithUri = { + method: 'GET', + uri: `${NODE_SETTINGS.BASE_URL}${NODE_SETTINGS.GET_BIN_URL}${binId}`, + json: true, + } + + try { + return await this.helpers.request!(options); + } catch (error) { + throw new NodeApiError(this.getNode(), error); + } +} + +export async function deleteBinRequest( + this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, + binId: string +) { + let options: OptionsWithUri = { + method: 'DELETE', + uri: `${NODE_SETTINGS.BASE_URL}${NODE_SETTINGS.DELETE_BIN_URL}${binId}`, + json: true, + } + + try { + return await this.helpers.request!(options); + } catch (error) { + throw new NodeApiError(this.getNode(), error); + } +} + +export async function testBinRequest( + this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, + method: string, + binId: string, + body: IDataObject, +) { + let options: OptionsWithUri = { + uri: `${NODE_SETTINGS.BASE_URL}${NODE_SETTINGS.TEST_BIN_URL}${binId}`, + method, + body, + json: true, + } + + if (!Object.keys(body).length) { + delete options.body; + } + + try { + return await this.helpers.request!(options); + } catch (error) { + throw new NodeApiError(this.getNode(), error); + } +} + +export async function getRequestRequest( + this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, + binId: string, + reqId: string +) { + let options: OptionsWithUri = { + uri: `${NODE_SETTINGS.BASE_URL}/developers/postbin/api/bin/${binId}/req/${reqId}`, + json: true, + } + + try { + return await this.helpers.request!(options); + } catch (error) { + throw new NodeApiError(this.getNode(), error); + } +} + +// /developers/postbin/api/bin/:binId/req/shift +export async function shiftRequestRequest( + this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, + binId: string, +) { + let options: OptionsWithUri = { + uri: `${NODE_SETTINGS.BASE_URL}/developers/postbin/api/bin/${binId}/req/shift`, + json: true, + } + + try { + return await this.helpers.request!(options); + } catch (error) { + throw new NodeApiError(this.getNode(), error); + } +} + +export function parseBinId(binId: string) { + let string_match = BIN_STRING_REGEX.exec(binId) + let url_match = BIN_URL_REGEX.exec(binId); + + if (string_match) { + return string_match[1]; + } + + if(url_match) { + return url_match[1]; + } + return binId; +} diff --git a/packages/nodes-base/nodes/PostBin/NodeConstants.ts b/packages/nodes-base/nodes/PostBin/NodeConstants.ts new file mode 100644 index 0000000000000..7694eedd6b9bf --- /dev/null +++ b/packages/nodes-base/nodes/PostBin/NodeConstants.ts @@ -0,0 +1,78 @@ +export const NODE_SETTINGS = Object.freeze({ + DESCRIPTION: 'Consume PostBin API', + BASE_URL: 'https://www.toptal.com', + TEST_BIN_URL: '/developers/postbin/', + CREATE_BIN_URL: '/developers/postbin/api/bin', + GET_BIN_URL: '/developers/postbin/api/bin/', + DELETE_BIN_URL: '/developers/postbin/api/bin/' +}); + +export const POSTBIN_VALUES = Object.freeze({ + DISPLAY_NAME: 'PostBin', + BRAND_COLOR: '#4dc0b5' +}); + +export const RESOURCES = Object.freeze({ + BIN: { + name: 'Bin', + value: 'bin', + }, + REQUEST: { + name: 'Request', + value: 'request', + } +}); + +export const BIN_OPERATIONS = Object.freeze({ + CREATE: { + name: 'Create', + value: 'create', + description: 'Create new bin', + }, + GET: { + name: 'Get', + value: 'get', + description: 'Returns information based on the binId you provide.', + }, + DELETE: { + name: 'Delete', + value: 'delete', + description: `Deletes this bin and all of it's posts.`, + }, + TEST: { + name: 'Test', + value: 'test', + description: 'Test your API by sending a request to the bin.' + } +}); + +export const BIN_FIELDS = Object.freeze({ + BIN_ID: { + displayName: 'Bin ID', + name: 'binId' + }, + BIN_CONTENT: { + displayName: 'Bin content', + name: 'binContent' + }, +}); + +export const REQUEST_OPERATIONS = Object.freeze({ + GET: { + name: 'Get', + value: 'get', + description: 'Returns information based on the binId and reqId you provide.', + }, + SHIFT: { + name: 'Shift', + value: 'shift', + description: 'Removes the first request form the bin.' + }, +}); + +export const REQUEST_FIELDS = Object.freeze({ + REQ_ID: { + displayName: 'Request ID', + name: 'requestId' + }, +}) diff --git a/packages/nodes-base/nodes/PostBin/PostBin.node.ts b/packages/nodes-base/nodes/PostBin/PostBin.node.ts index 99757f60fdbe7..25e120d1de345 100644 --- a/packages/nodes-base/nodes/PostBin/PostBin.node.ts +++ b/packages/nodes-base/nodes/PostBin/PostBin.node.ts @@ -1,23 +1,43 @@ import { IExecuteFunctions } from 'n8n-core'; import { + IDataObject, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow'; +import { + POSTBIN_VALUES, + RESOURCES, + BIN_OPERATIONS, + BIN_FIELDS, + REQUEST_OPERATIONS, + REQUEST_FIELDS +} from './NodeConstants' + import { binOperations, - binFields + binFields, } from './BinDescription'; import { requestOperations, - requestFields + requestFields, } from './RequestDescription'; +import { + createBinRequest, + deleteBinRequest, + getBinRequest, + getRequestRequest, + parseBinId, + shiftRequestRequest, + testBinRequest, +} from './GenericFunctions' + export class PostBin implements INodeType { description: INodeTypeDescription = { - displayName: 'PostBin', + displayName: POSTBIN_VALUES.DISPLAY_NAME, name: 'postBin', icon: 'file:postbin.svg', group: ['transform'], @@ -25,28 +45,29 @@ export class PostBin implements INodeType { subtitle: '={{ $parameter["operation"] + ": " + $parameter["resource"] }}', description: 'Consume PostBin API', defaults: { - name: 'PostBin', - color: '#4dc0b5' + name: POSTBIN_VALUES.DISPLAY_NAME, + color: POSTBIN_VALUES.BRAND_COLOR }, inputs: ['main'], outputs: ['main'], credentials: [], properties: [ + // eslint-disable-next-line n8n-nodes-base/node-param-default-missing { displayName: 'Resource', name: 'resource', type: 'options', options: [ { - name: 'Bin', - value: 'bin' + name: RESOURCES.BIN.name, + value: RESOURCES.BIN.value }, { - name: 'Request', - value: 'request' + name: RESOURCES.REQUEST.name, + value: RESOURCES.REQUEST.value } ], - default: 'bin', + default: RESOURCES.BIN.value, required: true, description: 'Bin to work with' }, @@ -58,6 +79,73 @@ export class PostBin implements INodeType { }; async execute(this: IExecuteFunctions): Promise { - return [[]]; + const items = this.getInputData(); + const resource = this.getNodeParameter('resource', 0) as string; + const operation = this.getNodeParameter('operation', 0) as string; + + let responseData; + const returnData: IDataObject[] = []; + + for (let i = 0; i < items.length; i++) { + // --- BIN OPERATIONS: + if (resource === RESOURCES.BIN.value) { + // ------ CREATE NEW BIN: + if (operation === BIN_OPERATIONS.CREATE.value) { + responseData = await createBinRequest.call(this); + responseData = { + [BIN_FIELDS.BIN_ID.name]: responseData[BIN_FIELDS.BIN_ID.name] + }; + // ------ GET BIN INFO: + } else if (operation === BIN_OPERATIONS.GET.value) { + let binId = this.getNodeParameter(BIN_FIELDS.BIN_ID.name, 0) as string; + + binId = parseBinId(binId); + responseData = await getBinRequest.call(this, binId); + // ------ DELETE BIN: + } else if (operation === BIN_OPERATIONS.DELETE.value) { + let binId = this.getNodeParameter(BIN_FIELDS.BIN_ID.name, 0) as string; + + binId = parseBinId(binId); + responseData = await deleteBinRequest.call(this, binId); + } else if (operation === BIN_OPERATIONS.TEST.value) { + let binId = this.getNodeParameter(BIN_FIELDS.BIN_ID.name, 0) as string; + let content = this.getNodeParameter(BIN_FIELDS.BIN_CONTENT.name, 0) as string; + + binId = parseBinId(binId); + const body: IDataObject = {} + if(content !== '') { + body.content = content; + } + let response = await testBinRequest.call(this, 'POST', binId, body); + responseData = { + 'Status': 'Sent', + 'Request ID': response, + 'Bin ID': binId + } + } + } + // --- REQUEST OPERATIONS: + else if (resource === RESOURCES.REQUEST.value) { + // ------ GET REQUEST INFO: + if (operation === REQUEST_OPERATIONS.GET.value) { + let binId = this.getNodeParameter(BIN_FIELDS.BIN_ID.name, 0) as string; + binId = parseBinId(binId); + let reqId = this.getNodeParameter(REQUEST_FIELDS.REQ_ID.name, 0) as string; + + responseData = await getRequestRequest.call(this, binId, reqId); + } + else if (operation === REQUEST_OPERATIONS.SHIFT.value) { + let binId = this.getNodeParameter(BIN_FIELDS.BIN_ID.name, 0) as string; + binId = parseBinId(binId); + responseData = await shiftRequestRequest.call(this, binId); + } + } + + Array.isArray(responseData) + ? returnData.push(...responseData) + : returnData.push(responseData); + } + + return [this.helpers.returnJsonArray(returnData)]; } } diff --git a/packages/nodes-base/nodes/PostBin/RequestDescription.ts b/packages/nodes-base/nodes/PostBin/RequestDescription.ts index 713aecbcdf41f..eff3904aa3864 100644 --- a/packages/nodes-base/nodes/PostBin/RequestDescription.ts +++ b/packages/nodes-base/nodes/PostBin/RequestDescription.ts @@ -2,7 +2,15 @@ import { INodeProperties } from 'n8n-workflow'; +import { + RESOURCES, + REQUEST_OPERATIONS, + REQUEST_FIELDS +} from './NodeConstants' + + export const requestOperations: INodeProperties[] = [ + // eslint-disable-next-line n8n-nodes-base/node-param-default-missing { displayName: 'Operation', name: 'operation', @@ -10,40 +18,41 @@ export const requestOperations: INodeProperties[] = [ displayOptions: { show: { resource: [ - 'request' + RESOURCES.REQUEST.value, ], }, }, options: [ { - name: 'Get', - value: 'get', - description: 'Returns information based on the binId and reqId you provide.', + name: REQUEST_OPERATIONS.GET.name, + value: REQUEST_OPERATIONS.GET.value, + description: REQUEST_OPERATIONS.GET.description, }, { - name: 'Shift', - value: 'shift', - description: 'Removes the first request form the bin.' + name: REQUEST_OPERATIONS.SHIFT.name, + value: REQUEST_OPERATIONS.SHIFT.value, + description: REQUEST_OPERATIONS.SHIFT.description } ], - default: 'get', + default: REQUEST_OPERATIONS.GET.value, description: 'The operation to perform' } ] export const requestFields: INodeProperties[] = [ { - displayName: 'Request ID', - name: 'requestId', + name: REQUEST_FIELDS.REQ_ID.name, + displayName: REQUEST_FIELDS.REQ_ID.displayName, type: 'string', default: '', + required: true, displayOptions: { show: { resource: [ - 'request' + RESOURCES.REQUEST.value ], operation: [ - 'get', + REQUEST_OPERATIONS.GET.value, ] } }, From 2a59134f07900b0c99445eacd786241d9e248bf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milorad=20Filipovi=C4=87?= Date: Thu, 5 May 2022 13:21:21 +0200 Subject: [PATCH 03/11] =?UTF-8?q?=F0=9F=9A=A7=20Reworked=20the=20node=20in?= =?UTF-8?q?=20the=20declarative=20way.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nodes/PostBin/BinDescription.ts | 33 ++++- .../nodes/PostBin/GenericFunctions.ts | 114 ------------------ .../nodes-base/nodes/PostBin/NodeConstants.ts | 6 +- .../nodes/PostBin/PostBin.node.json | 16 +++ .../nodes-base/nodes/PostBin/PostBin.node.ts | 92 +------------- .../nodes/PostBin/RequestDescription.ts | 18 ++- 6 files changed, 70 insertions(+), 209 deletions(-) create mode 100644 packages/nodes-base/nodes/PostBin/PostBin.node.json diff --git a/packages/nodes-base/nodes/PostBin/BinDescription.ts b/packages/nodes-base/nodes/PostBin/BinDescription.ts index 8a4d0ded08fbf..75fc1ddaaf817 100644 --- a/packages/nodes-base/nodes/PostBin/BinDescription.ts +++ b/packages/nodes-base/nodes/PostBin/BinDescription.ts @@ -1,12 +1,14 @@ import { INodeProperties } from 'n8n-workflow'; +import { parseBinId } from './GenericFunctions'; import { RESOURCES, BIN_OPERATIONS, BIN_FIELDS, - REQUEST_OPERATIONS + REQUEST_OPERATIONS, + NODE_SETTINGS } from './NodeConstants'; export const binOperations: INodeProperties[] = [ @@ -27,21 +29,50 @@ export const binOperations: INodeProperties[] = [ name: BIN_OPERATIONS.CREATE.name, value: BIN_OPERATIONS.CREATE.value, description: BIN_OPERATIONS.CREATE.description, + routing: { + request: { + method: 'POST', + url: NODE_SETTINGS.API_URL + }, + } }, { name: BIN_OPERATIONS.GET.name, value: BIN_OPERATIONS.GET.value, description: BIN_OPERATIONS.GET.description, + routing: { + request: { + method: 'GET', + url: `=${NODE_SETTINGS.API_URL}/{{$parameter["${BIN_FIELDS.BIN_ID.name}"]}}` + }, + } }, { name: BIN_OPERATIONS.DELETE.name, value: BIN_OPERATIONS.DELETE.value, description: BIN_OPERATIONS.DELETE.description, + routing: { + request: { + method: 'DELETE', + url: `=${NODE_SETTINGS.API_URL}/{{$parameter["${BIN_FIELDS.BIN_ID.name}"]}}` + }, + } }, { name: BIN_OPERATIONS.TEST.name, value: BIN_OPERATIONS.TEST.value, description: BIN_OPERATIONS.TEST.description, + routing: { + request: { + method: 'POST', + url: `=${NODE_SETTINGS.BIN_URL}/{{$parameter["${BIN_FIELDS.BIN_ID.name}"]}}` + }, + send: { + type: 'body', + property: 'content', + value: `={{$parameter["${BIN_FIELDS.BIN_CONTENT.name}"]}}` + } + } }, ], default: BIN_OPERATIONS.CREATE.value, diff --git a/packages/nodes-base/nodes/PostBin/GenericFunctions.ts b/packages/nodes-base/nodes/PostBin/GenericFunctions.ts index 0688c255a81a9..c22701c9dbc72 100644 --- a/packages/nodes-base/nodes/PostBin/GenericFunctions.ts +++ b/packages/nodes-base/nodes/PostBin/GenericFunctions.ts @@ -1,121 +1,7 @@ import { IExecuteFunctions, IExecuteSingleFunctions, ILoadOptionsFunctions } from "n8n-core"; -import { IDataObject, IHookFunctions, NodeApiError } from "n8n-workflow"; -import { OptionsWithUri } from "request"; -import { - NODE_SETTINGS -} from './NodeConstants' - const BIN_STRING_REGEX = /Bin '(\d+-\d+)'/g const BIN_URL_REGEX = /https:\/\/www\.toptal\.com\/developers\/postbin\/b\/(\d+-\d+)/g -export async function createBinRequest( - this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, -) { - let options: OptionsWithUri = { - method: 'POST', - uri: `${NODE_SETTINGS.BASE_URL}${NODE_SETTINGS.CREATE_BIN_URL}`, - json: true, - } - - try { - return await this.helpers.request!(options); - } catch (error) { - throw new NodeApiError(this.getNode(), error); - } -} - -export async function getBinRequest( - this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, - binId: string -) { - let options: OptionsWithUri = { - method: 'GET', - uri: `${NODE_SETTINGS.BASE_URL}${NODE_SETTINGS.GET_BIN_URL}${binId}`, - json: true, - } - - try { - return await this.helpers.request!(options); - } catch (error) { - throw new NodeApiError(this.getNode(), error); - } -} - -export async function deleteBinRequest( - this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, - binId: string -) { - let options: OptionsWithUri = { - method: 'DELETE', - uri: `${NODE_SETTINGS.BASE_URL}${NODE_SETTINGS.DELETE_BIN_URL}${binId}`, - json: true, - } - - try { - return await this.helpers.request!(options); - } catch (error) { - throw new NodeApiError(this.getNode(), error); - } -} - -export async function testBinRequest( - this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, - method: string, - binId: string, - body: IDataObject, -) { - let options: OptionsWithUri = { - uri: `${NODE_SETTINGS.BASE_URL}${NODE_SETTINGS.TEST_BIN_URL}${binId}`, - method, - body, - json: true, - } - - if (!Object.keys(body).length) { - delete options.body; - } - - try { - return await this.helpers.request!(options); - } catch (error) { - throw new NodeApiError(this.getNode(), error); - } -} - -export async function getRequestRequest( - this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, - binId: string, - reqId: string -) { - let options: OptionsWithUri = { - uri: `${NODE_SETTINGS.BASE_URL}/developers/postbin/api/bin/${binId}/req/${reqId}`, - json: true, - } - - try { - return await this.helpers.request!(options); - } catch (error) { - throw new NodeApiError(this.getNode(), error); - } -} - -// /developers/postbin/api/bin/:binId/req/shift -export async function shiftRequestRequest( - this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, - binId: string, -) { - let options: OptionsWithUri = { - uri: `${NODE_SETTINGS.BASE_URL}/developers/postbin/api/bin/${binId}/req/shift`, - json: true, - } - - try { - return await this.helpers.request!(options); - } catch (error) { - throw new NodeApiError(this.getNode(), error); - } -} - export function parseBinId(binId: string) { let string_match = BIN_STRING_REGEX.exec(binId) let url_match = BIN_URL_REGEX.exec(binId); diff --git a/packages/nodes-base/nodes/PostBin/NodeConstants.ts b/packages/nodes-base/nodes/PostBin/NodeConstants.ts index 7694eedd6b9bf..556107013794e 100644 --- a/packages/nodes-base/nodes/PostBin/NodeConstants.ts +++ b/packages/nodes-base/nodes/PostBin/NodeConstants.ts @@ -1,10 +1,8 @@ export const NODE_SETTINGS = Object.freeze({ DESCRIPTION: 'Consume PostBin API', BASE_URL: 'https://www.toptal.com', - TEST_BIN_URL: '/developers/postbin/', - CREATE_BIN_URL: '/developers/postbin/api/bin', - GET_BIN_URL: '/developers/postbin/api/bin/', - DELETE_BIN_URL: '/developers/postbin/api/bin/' + BIN_URL: 'developers/postbin', + API_URL: 'developers/postbin/api/bin', }); export const POSTBIN_VALUES = Object.freeze({ diff --git a/packages/nodes-base/nodes/PostBin/PostBin.node.json b/packages/nodes-base/nodes/PostBin/PostBin.node.json new file mode 100644 index 0000000000000..1e46a63e04921 --- /dev/null +++ b/packages/nodes-base/nodes/PostBin/PostBin.node.json @@ -0,0 +1,16 @@ +{ + "node": "n8n-nodes-base.postbin", + "nodeVersion": "1.0", + "codexVersion": "1.0", + "categories": [ + "Development", + "Data & Storage" + ], + "resources": { + "primaryDocumentation": [ + { + "url": "https://docs.n8n.io/nodes/n8n-nodes-base.postbin/" + } + ] + } +} diff --git a/packages/nodes-base/nodes/PostBin/PostBin.node.ts b/packages/nodes-base/nodes/PostBin/PostBin.node.ts index 25e120d1de345..2176e6acbdabc 100644 --- a/packages/nodes-base/nodes/PostBin/PostBin.node.ts +++ b/packages/nodes-base/nodes/PostBin/PostBin.node.ts @@ -1,18 +1,12 @@ -import { IExecuteFunctions } from 'n8n-core'; import { - IDataObject, - INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow'; import { + NODE_SETTINGS, POSTBIN_VALUES, RESOURCES, - BIN_OPERATIONS, - BIN_FIELDS, - REQUEST_OPERATIONS, - REQUEST_FIELDS } from './NodeConstants' import { @@ -25,16 +19,6 @@ import { requestFields, } from './RequestDescription'; -import { - createBinRequest, - deleteBinRequest, - getBinRequest, - getRequestRequest, - parseBinId, - shiftRequestRequest, - testBinRequest, -} from './GenericFunctions' - export class PostBin implements INodeType { description: INodeTypeDescription = { displayName: POSTBIN_VALUES.DISPLAY_NAME, @@ -51,6 +35,9 @@ export class PostBin implements INodeType { inputs: ['main'], outputs: ['main'], credentials: [], + requestDefaults: { + baseURL: NODE_SETTINGS.BASE_URL + }, properties: [ // eslint-disable-next-line n8n-nodes-base/node-param-default-missing { @@ -77,75 +64,4 @@ export class PostBin implements INodeType { ...requestFields, ] }; - - async execute(this: IExecuteFunctions): Promise { - const items = this.getInputData(); - const resource = this.getNodeParameter('resource', 0) as string; - const operation = this.getNodeParameter('operation', 0) as string; - - let responseData; - const returnData: IDataObject[] = []; - - for (let i = 0; i < items.length; i++) { - // --- BIN OPERATIONS: - if (resource === RESOURCES.BIN.value) { - // ------ CREATE NEW BIN: - if (operation === BIN_OPERATIONS.CREATE.value) { - responseData = await createBinRequest.call(this); - responseData = { - [BIN_FIELDS.BIN_ID.name]: responseData[BIN_FIELDS.BIN_ID.name] - }; - // ------ GET BIN INFO: - } else if (operation === BIN_OPERATIONS.GET.value) { - let binId = this.getNodeParameter(BIN_FIELDS.BIN_ID.name, 0) as string; - - binId = parseBinId(binId); - responseData = await getBinRequest.call(this, binId); - // ------ DELETE BIN: - } else if (operation === BIN_OPERATIONS.DELETE.value) { - let binId = this.getNodeParameter(BIN_FIELDS.BIN_ID.name, 0) as string; - - binId = parseBinId(binId); - responseData = await deleteBinRequest.call(this, binId); - } else if (operation === BIN_OPERATIONS.TEST.value) { - let binId = this.getNodeParameter(BIN_FIELDS.BIN_ID.name, 0) as string; - let content = this.getNodeParameter(BIN_FIELDS.BIN_CONTENT.name, 0) as string; - - binId = parseBinId(binId); - const body: IDataObject = {} - if(content !== '') { - body.content = content; - } - let response = await testBinRequest.call(this, 'POST', binId, body); - responseData = { - 'Status': 'Sent', - 'Request ID': response, - 'Bin ID': binId - } - } - } - // --- REQUEST OPERATIONS: - else if (resource === RESOURCES.REQUEST.value) { - // ------ GET REQUEST INFO: - if (operation === REQUEST_OPERATIONS.GET.value) { - let binId = this.getNodeParameter(BIN_FIELDS.BIN_ID.name, 0) as string; - binId = parseBinId(binId); - let reqId = this.getNodeParameter(REQUEST_FIELDS.REQ_ID.name, 0) as string; - - responseData = await getRequestRequest.call(this, binId, reqId); - } - else if (operation === REQUEST_OPERATIONS.SHIFT.value) { - let binId = this.getNodeParameter(BIN_FIELDS.BIN_ID.name, 0) as string; - binId = parseBinId(binId); - responseData = await shiftRequestRequest.call(this, binId); - } - } - - Array.isArray(responseData) - ? returnData.push(...responseData) - : returnData.push(responseData); - } - - return [this.helpers.returnJsonArray(returnData)]; - } } diff --git a/packages/nodes-base/nodes/PostBin/RequestDescription.ts b/packages/nodes-base/nodes/PostBin/RequestDescription.ts index eff3904aa3864..93dc979835e5e 100644 --- a/packages/nodes-base/nodes/PostBin/RequestDescription.ts +++ b/packages/nodes-base/nodes/PostBin/RequestDescription.ts @@ -5,7 +5,9 @@ import { import { RESOURCES, REQUEST_OPERATIONS, - REQUEST_FIELDS + REQUEST_FIELDS, + NODE_SETTINGS, + BIN_FIELDS } from './NodeConstants' @@ -27,11 +29,23 @@ export const requestOperations: INodeProperties[] = [ name: REQUEST_OPERATIONS.GET.name, value: REQUEST_OPERATIONS.GET.value, description: REQUEST_OPERATIONS.GET.description, + routing: { + request: { + method: 'GET', + url: `=${NODE_SETTINGS.API_URL}/{{$parameter["${BIN_FIELDS.BIN_ID.name}"]}}/req/{{$parameter["${REQUEST_FIELDS.REQ_ID.name}"]}}` + }, + }, }, { name: REQUEST_OPERATIONS.SHIFT.name, value: REQUEST_OPERATIONS.SHIFT.value, - description: REQUEST_OPERATIONS.SHIFT.description + description: REQUEST_OPERATIONS.SHIFT.description, + routing: { + request: { + method: 'GET', + url: `=${NODE_SETTINGS.API_URL}/{{$parameter["${BIN_FIELDS.BIN_ID.name}"]}}/req/shift` + }, + } } ], default: REQUEST_OPERATIONS.GET.value, From b378968816a8ebc0ae61a069e13490de831f5abf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milorad=20Filipovi=C4=87?= Date: Thu, 5 May 2022 17:47:00 +0200 Subject: [PATCH 04/11] =?UTF-8?q?=F0=9F=9A=A7=20PosBin=20node=20refactorin?= =?UTF-8?q?g=20after=20reworking=20it.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nodes/PostBin/BinDescription.ts | 94 ++++++++++--------- .../nodes-base/nodes/PostBin/NodeConstants.ts | 76 --------------- .../nodes-base/nodes/PostBin/PostBin.node.ts | 24 ++--- .../nodes/PostBin/RequestDescription.ts | 41 ++++---- 4 files changed, 76 insertions(+), 159 deletions(-) delete mode 100644 packages/nodes-base/nodes/PostBin/NodeConstants.ts diff --git a/packages/nodes-base/nodes/PostBin/BinDescription.ts b/packages/nodes-base/nodes/PostBin/BinDescription.ts index 75fc1ddaaf817..6869c26206054 100644 --- a/packages/nodes-base/nodes/PostBin/BinDescription.ts +++ b/packages/nodes-base/nodes/PostBin/BinDescription.ts @@ -1,18 +1,13 @@ import { + IDataObject, + IExecuteSingleFunctions, + IHttpRequestOptions, + IN8nHttpFullResponse, + INodeExecutionData, INodeProperties } from 'n8n-workflow'; -import { parseBinId } from './GenericFunctions'; - -import { - RESOURCES, - BIN_OPERATIONS, - BIN_FIELDS, - REQUEST_OPERATIONS, - NODE_SETTINGS -} from './NodeConstants'; export const binOperations: INodeProperties[] = [ - // eslint-disable-next-line n8n-nodes-base/node-param-default-missing { displayName: 'Operation', name: 'operation', @@ -20,92 +15,97 @@ export const binOperations: INodeProperties[] = [ displayOptions: { show: { resource: [ - RESOURCES.BIN.value, + 'bin', ], }, }, options: [ { - name: BIN_OPERATIONS.CREATE.name, - value: BIN_OPERATIONS.CREATE.value, - description: BIN_OPERATIONS.CREATE.description, + name: 'Create', + value: 'create', + description: 'Create new bin', routing: { request: { method: 'POST', - url: NODE_SETTINGS.API_URL + url: '/developers/postbin/api/bin', }, } }, { - name: BIN_OPERATIONS.GET.name, - value: BIN_OPERATIONS.GET.value, - description: BIN_OPERATIONS.GET.description, + name: 'Get', + value: 'get', + description: 'Returns information based on the binId you provide.', routing: { request: { method: 'GET', - url: `=${NODE_SETTINGS.API_URL}/{{$parameter["${BIN_FIELDS.BIN_ID.name}"]}}` + url: '=/developers/postbin/api/bin/{{$parameter["binId"]}}', }, } }, { - name: BIN_OPERATIONS.DELETE.name, - value: BIN_OPERATIONS.DELETE.value, - description: BIN_OPERATIONS.DELETE.description, + name: 'Delete', + value: 'delete', + description: 'Deletes this bin and all of it\'s posts.', routing: { request: { method: 'DELETE', - url: `=${NODE_SETTINGS.API_URL}/{{$parameter["${BIN_FIELDS.BIN_ID.name}"]}}` + url: '=/developers/postbin/api/bin/{{$parameter["binId"]}}' }, } }, { - name: BIN_OPERATIONS.TEST.name, - value: BIN_OPERATIONS.TEST.value, - description: BIN_OPERATIONS.TEST.description, + name: 'Test', + value: 'test', + description: 'Test your API by sending a request to the bin.', routing: { request: { method: 'POST', - url: `=${NODE_SETTINGS.BIN_URL}/{{$parameter["${BIN_FIELDS.BIN_ID.name}"]}}` + url: '=/developers/postbin/{{$parameter["binId"]}}' }, - send: { - type: 'body', - property: 'content', - value: `={{$parameter["${BIN_FIELDS.BIN_CONTENT.name}"]}}` + output: { + postReceive: [ + { + type: 'set', + properties: { + value: '={{ { "status": "Sent" } }}', + }, + } + ] } } }, ], - default: BIN_OPERATIONS.CREATE.value, + default: 'create', description: 'The operation to perform.', }, ] export const binFields: INodeProperties[] = [ { - name: BIN_FIELDS.BIN_ID.name, - displayName: BIN_FIELDS.BIN_ID.displayName, + name: 'binId', + displayName: 'Bin ID', type: 'string', default: '', required: true, displayOptions: { show: { resource: [ - RESOURCES.BIN.value, - RESOURCES.REQUEST.value + 'bin', + 'request' ], operation: [ - BIN_OPERATIONS.GET.value, - BIN_OPERATIONS.DELETE.value, - BIN_OPERATIONS.TEST.value, - REQUEST_OPERATIONS.SHIFT.value, + 'get', + 'delete', + 'test', + 'shift', ] }, }, description: 'Unique identifier for each bin.', }, { - name: BIN_FIELDS.BIN_CONTENT.name, - displayName: BIN_FIELDS.BIN_CONTENT.displayName, + name: 'binContent', + displayName: 'Bin Content', type: 'string', default: '', typeOptions: { @@ -114,12 +114,18 @@ export const binFields: INodeProperties[] = [ displayOptions: { show: { resource: [ - RESOURCES.BIN.value, + 'bin', ], operation: [ - BIN_OPERATIONS.TEST.value, + 'test', ] } + }, + routing: { + send: { + property: 'content', + type: 'body' + } } }, ] diff --git a/packages/nodes-base/nodes/PostBin/NodeConstants.ts b/packages/nodes-base/nodes/PostBin/NodeConstants.ts deleted file mode 100644 index 556107013794e..0000000000000 --- a/packages/nodes-base/nodes/PostBin/NodeConstants.ts +++ /dev/null @@ -1,76 +0,0 @@ -export const NODE_SETTINGS = Object.freeze({ - DESCRIPTION: 'Consume PostBin API', - BASE_URL: 'https://www.toptal.com', - BIN_URL: 'developers/postbin', - API_URL: 'developers/postbin/api/bin', -}); - -export const POSTBIN_VALUES = Object.freeze({ - DISPLAY_NAME: 'PostBin', - BRAND_COLOR: '#4dc0b5' -}); - -export const RESOURCES = Object.freeze({ - BIN: { - name: 'Bin', - value: 'bin', - }, - REQUEST: { - name: 'Request', - value: 'request', - } -}); - -export const BIN_OPERATIONS = Object.freeze({ - CREATE: { - name: 'Create', - value: 'create', - description: 'Create new bin', - }, - GET: { - name: 'Get', - value: 'get', - description: 'Returns information based on the binId you provide.', - }, - DELETE: { - name: 'Delete', - value: 'delete', - description: `Deletes this bin and all of it's posts.`, - }, - TEST: { - name: 'Test', - value: 'test', - description: 'Test your API by sending a request to the bin.' - } -}); - -export const BIN_FIELDS = Object.freeze({ - BIN_ID: { - displayName: 'Bin ID', - name: 'binId' - }, - BIN_CONTENT: { - displayName: 'Bin content', - name: 'binContent' - }, -}); - -export const REQUEST_OPERATIONS = Object.freeze({ - GET: { - name: 'Get', - value: 'get', - description: 'Returns information based on the binId and reqId you provide.', - }, - SHIFT: { - name: 'Shift', - value: 'shift', - description: 'Removes the first request form the bin.' - }, -}); - -export const REQUEST_FIELDS = Object.freeze({ - REQ_ID: { - displayName: 'Request ID', - name: 'requestId' - }, -}) diff --git a/packages/nodes-base/nodes/PostBin/PostBin.node.ts b/packages/nodes-base/nodes/PostBin/PostBin.node.ts index 2176e6acbdabc..3bdc63228d71b 100644 --- a/packages/nodes-base/nodes/PostBin/PostBin.node.ts +++ b/packages/nodes-base/nodes/PostBin/PostBin.node.ts @@ -3,12 +3,6 @@ import { INodeTypeDescription } from 'n8n-workflow'; -import { - NODE_SETTINGS, - POSTBIN_VALUES, - RESOURCES, -} from './NodeConstants' - import { binOperations, binFields, @@ -21,7 +15,7 @@ import { export class PostBin implements INodeType { description: INodeTypeDescription = { - displayName: POSTBIN_VALUES.DISPLAY_NAME, + displayName: 'PostBin', name: 'postBin', icon: 'file:postbin.svg', group: ['transform'], @@ -29,14 +23,14 @@ export class PostBin implements INodeType { subtitle: '={{ $parameter["operation"] + ": " + $parameter["resource"] }}', description: 'Consume PostBin API', defaults: { - name: POSTBIN_VALUES.DISPLAY_NAME, - color: POSTBIN_VALUES.BRAND_COLOR + name: 'PostBin', + color: '#4dc0b5' }, inputs: ['main'], outputs: ['main'], credentials: [], requestDefaults: { - baseURL: NODE_SETTINGS.BASE_URL + baseURL: 'https://www.toptal.com', }, properties: [ // eslint-disable-next-line n8n-nodes-base/node-param-default-missing @@ -46,15 +40,15 @@ export class PostBin implements INodeType { type: 'options', options: [ { - name: RESOURCES.BIN.name, - value: RESOURCES.BIN.value + name: 'Bin', + value: 'bin' }, { - name: RESOURCES.REQUEST.name, - value: RESOURCES.REQUEST.value + name: 'Request', + value: 'request' } ], - default: RESOURCES.BIN.value, + default: 'bin', required: true, description: 'Bin to work with' }, diff --git a/packages/nodes-base/nodes/PostBin/RequestDescription.ts b/packages/nodes-base/nodes/PostBin/RequestDescription.ts index 93dc979835e5e..531348c1daa2b 100644 --- a/packages/nodes-base/nodes/PostBin/RequestDescription.ts +++ b/packages/nodes-base/nodes/PostBin/RequestDescription.ts @@ -1,18 +1,11 @@ import { + IDataObject, + IExecuteSingleFunctions, + IHttpRequestOptions, INodeProperties } from 'n8n-workflow'; -import { - RESOURCES, - REQUEST_OPERATIONS, - REQUEST_FIELDS, - NODE_SETTINGS, - BIN_FIELDS -} from './NodeConstants' - - export const requestOperations: INodeProperties[] = [ - // eslint-disable-next-line n8n-nodes-base/node-param-default-missing { displayName: 'Operation', name: 'operation', @@ -20,53 +13,53 @@ export const requestOperations: INodeProperties[] = [ displayOptions: { show: { resource: [ - RESOURCES.REQUEST.value, + 'request', ], }, }, options: [ { - name: REQUEST_OPERATIONS.GET.name, - value: REQUEST_OPERATIONS.GET.value, - description: REQUEST_OPERATIONS.GET.description, + name: 'Get', + value: 'get', + description: 'Returns information based on the binId and reqId you provide.', routing: { request: { method: 'GET', - url: `=${NODE_SETTINGS.API_URL}/{{$parameter["${BIN_FIELDS.BIN_ID.name}"]}}/req/{{$parameter["${REQUEST_FIELDS.REQ_ID.name}"]}}` + url: '=/developers/postbin/api/bin/{{$parameter["binId"]}}/req/{{$parameter["requestId"]}}' }, }, }, { - name: REQUEST_OPERATIONS.SHIFT.name, - value: REQUEST_OPERATIONS.SHIFT.value, - description: REQUEST_OPERATIONS.SHIFT.description, + name: 'Shift', + value: 'shift', + description: 'Removes the first request form the bin.', routing: { request: { method: 'GET', - url: `=${NODE_SETTINGS.API_URL}/{{$parameter["${BIN_FIELDS.BIN_ID.name}"]}}/req/shift` + url: '=/developers/postbin/api/bin/{{$parameter["binId"]}}/req/shift' }, } } ], - default: REQUEST_OPERATIONS.GET.value, + default: 'get', description: 'The operation to perform' } ] export const requestFields: INodeProperties[] = [ { - name: REQUEST_FIELDS.REQ_ID.name, - displayName: REQUEST_FIELDS.REQ_ID.displayName, + name: 'requestId', + displayName: 'Request ID', type: 'string', default: '', required: true, displayOptions: { show: { resource: [ - RESOURCES.REQUEST.value + 'request' ], operation: [ - REQUEST_OPERATIONS.GET.value, + 'get', ] } }, From a15c377ae84b7ff3a9779fed77dace0f6d907589 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milorad=20Filipovi=C4=87?= Date: Fri, 6 May 2022 12:00:04 +0200 Subject: [PATCH 05/11] =?UTF-8?q?=E2=9C=A8=20Implemented=20Bin=20id=20pars?= =?UTF-8?q?ing=20in=20PostBin=20node.=20Done=20some=20final=20refactoring?= =?UTF-8?q?=20and=20documentation.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nodes/PostBin/BinDescription.ts | 98 ++++++++++++------- .../nodes/PostBin/GenericFunctions.ts | 94 ++++++++++++++++-- .../nodes-base/nodes/PostBin/PostBin.node.ts | 17 ++-- .../nodes/PostBin/RequestDescription.ts | 45 ++++++--- 4 files changed, 182 insertions(+), 72 deletions(-) diff --git a/packages/nodes-base/nodes/PostBin/BinDescription.ts b/packages/nodes-base/nodes/PostBin/BinDescription.ts index 6869c26206054..35692a5c16a6d 100644 --- a/packages/nodes-base/nodes/PostBin/BinDescription.ts +++ b/packages/nodes-base/nodes/PostBin/BinDescription.ts @@ -1,12 +1,14 @@ import { - IDataObject, - IExecuteSingleFunctions, - IHttpRequestOptions, - IN8nHttpFullResponse, - INodeExecutionData, INodeProperties } from 'n8n-workflow'; +import { + buildBinAPIURL, + buildBinTestURL +} from './GenericFunctions'; + + +// Operations for the `Bin` resource: export const binOperations: INodeProperties[] = [ { displayName: 'Operation', @@ -21,15 +23,15 @@ export const binOperations: INodeProperties[] = [ }, options: [ { - name: 'Create', - value: 'create', - description: 'Create new bin', - routing: { - request: { - method: 'POST', - url: '/developers/postbin/api/bin', - }, - } + name: 'Create', + value: 'create', + description: 'Create new bin', + routing: { + request: { + method: 'POST', + url: '/developers/postbin/api/bin', + }, + }, }, { name: 'Get', @@ -40,7 +42,13 @@ export const binOperations: INodeProperties[] = [ method: 'GET', url: '=/developers/postbin/api/bin/{{$parameter["binId"]}}', }, - } + send: { + preSend: [ + // Parse binId before sending to make sure it's in the right format + buildBinAPIURL, + ], + }, + }, }, { name: 'Delete', @@ -49,9 +57,15 @@ export const binOperations: INodeProperties[] = [ routing: { request: { method: 'DELETE', - url: '=/developers/postbin/api/bin/{{$parameter["binId"]}}' + url: '=/developers/postbin/api/bin/{{$parameter["binId"]}}', }, - } + send: { + preSend: [ + // Parse binId before sending to make sure it's in the right format + buildBinAPIURL, + ], + }, + }, }, { name: 'Test', @@ -60,7 +74,13 @@ export const binOperations: INodeProperties[] = [ routing: { request: { method: 'POST', - url: '=/developers/postbin/{{$parameter["binId"]}}' + url: '=/developers/postbin/{{$parameter["binId"]}}', + }, + send: { + preSend: [ + // Parse binId before sending to make sure it's in the right format + buildBinTestURL, + ], }, output: { postReceive: [ @@ -69,17 +89,18 @@ export const binOperations: INodeProperties[] = [ properties: { value: '={{ { "status": "Sent" } }}', }, - } - ] - } - } + }, + ], + }, + }, }, ], default: 'create', description: 'The operation to perform.', }, -] +]; +// Properties of the `Bin` resource export const binFields: INodeProperties[] = [ { name: 'binId', @@ -91,14 +112,14 @@ export const binFields: INodeProperties[] = [ show: { resource: [ 'bin', - 'request' + 'request', ], operation: [ 'get', 'delete', 'test', 'shift', - ] + ], }, }, description: 'Unique identifier for each bin.', @@ -109,23 +130,24 @@ export const binFields: INodeProperties[] = [ type: 'string', default: '', typeOptions: { - rows: 5, + rows: 5, }, displayOptions: { - show: { - resource: [ - 'bin', - ], - operation: [ - 'test', - ] - } + show: { + resource: [ + 'bin', + ], + operation: [ + 'test', + ], + }, }, + // Content is sent is the body of POST requests routing: { send: { property: 'content', - type: 'body' - } - } + type: 'body', + }, + }, }, -] +]; diff --git a/packages/nodes-base/nodes/PostBin/GenericFunctions.ts b/packages/nodes-base/nodes/PostBin/GenericFunctions.ts index c22701c9dbc72..e77e057cd1a77 100644 --- a/packages/nodes-base/nodes/PostBin/GenericFunctions.ts +++ b/packages/nodes-base/nodes/PostBin/GenericFunctions.ts @@ -1,17 +1,91 @@ -import { IExecuteFunctions, IExecuteSingleFunctions, ILoadOptionsFunctions } from "n8n-core"; -const BIN_STRING_REGEX = /Bin '(\d+-\d+)'/g -const BIN_URL_REGEX = /https:\/\/www\.toptal\.com\/developers\/postbin\/b\/(\d+-\d+)/g +import { IExecuteSingleFunctions, IHttpRequestOptions } from 'n8n-workflow'; -export function parseBinId(binId: string) { - let string_match = BIN_STRING_REGEX.exec(binId) - let url_match = BIN_URL_REGEX.exec(binId); +// Regular expressions used to extract binId from parameter value +const BIN_STRING_REGEX = /Bin '(\d+-\d+)'/g; +const BIN_URL_REGEX = /https:\/\/www\.toptal\.com\/developers\/postbin\/b\/(\d+-\d+)/g; - if (string_match) { - return string_match[1]; +/** + * Creates correctly-formatted PostBin API URL based on the entered binId. + * This function makes sure binId is in the expected format by parsing it + * from current node parameter value. + * + * @export + * @param {IExecuteSingleFunctions} this + * @param {IHttpRequestOptions} requestOptions + * @returns {Promise} requestOptions + */ +export async function buildBinAPIURL(this: IExecuteSingleFunctions, requestOptions: IHttpRequestOptions): Promise { + let binId = this.getNodeParameter('binId') as string; + // Parse binId from parameter value + binId = parseBinId(binId); + // Assemble the PostBin API URL and put it back to requestOptions + requestOptions.url = `/developers/postbin/api/bin/${binId}`; + return requestOptions; +} + +/** + * Creates correctly-formatted PostBin Bin test URL based on the entered binId. + * This function makes sure binId is in the expected format by parsing it + * from current node parameter value. + * + * @export + * @param {IExecuteSingleFunctions} this + * @param {IHttpRequestOptions} requestOptions + * @returns {Promise} requestOptions + */ +export async function buildBinTestURL(this: IExecuteSingleFunctions, requestOptions: IHttpRequestOptions): Promise { + let binId = this.getNodeParameter('binId') as string; + // Parse binId from parameter value + binId = parseBinId(binId); + // Assemble the PostBin API URL and put it back to requestOptions + requestOptions.url = `/developers/postbin/${binId}`; + return requestOptions; +} + +/** + * Creates correctly-formatted PostBin API URL based on the entered binId and reqId. + * This function makes sure binId is in the expected format by parsing it + * from current node parameter value. + * + * @export + * @param {IExecuteSingleFunctions} this + * @param {IHttpRequestOptions} requestOptions + * @returns {Promise} requestOptions + */ +export async function buildRequestURL(this: IExecuteSingleFunctions, requestOptions: IHttpRequestOptions): Promise { + const reqId = this.getNodeParameter('requestId', 'shift') as string; + + let binId = this.getNodeParameter('binId') as string; + binId = parseBinId(binId); + + requestOptions.url = `/developers/postbin/api/bin/${binId}/req/${reqId}`; + return requestOptions; +} + +/** + * Extracts the PostBin Bin Id from the specified string. + * This method should be able to extract bin Id from the + * PostBin URL or from the string in the following format: + * `Bin ''.` + * + * @param {IExecuteSingleFunctions} this + * @param {IHttpRequestOptions} requestOptions + * @returns {Promise} requestOptions + */ +function parseBinId(binId: string) { + // Test if bin id has been copied from website in the format `Bin ''` + const stringMatch = BIN_STRING_REGEX.exec(binId); + // Test if bin URL has been pasted instead if bin id + const urlMatch = BIN_URL_REGEX.exec(binId); + + // Return what is matched + if (stringMatch) { + return stringMatch[1]; } - if(url_match) { - return url_match[1]; + if(urlMatch) { + return urlMatch[1]; } + // Fall back to returning whatever is passed in the first place return binId; } diff --git a/packages/nodes-base/nodes/PostBin/PostBin.node.ts b/packages/nodes-base/nodes/PostBin/PostBin.node.ts index 3bdc63228d71b..1e45eeba44aa8 100644 --- a/packages/nodes-base/nodes/PostBin/PostBin.node.ts +++ b/packages/nodes-base/nodes/PostBin/PostBin.node.ts @@ -4,13 +4,13 @@ import { } from 'n8n-workflow'; import { - binOperations, binFields, + binOperations, } from './BinDescription'; import { - requestOperations, requestFields, + requestOperations, } from './RequestDescription'; export class PostBin implements INodeType { @@ -24,7 +24,7 @@ export class PostBin implements INodeType { description: 'Consume PostBin API', defaults: { name: 'PostBin', - color: '#4dc0b5' + color: '#4dc0b5', }, inputs: ['main'], outputs: ['main'], @@ -33,7 +33,6 @@ export class PostBin implements INodeType { baseURL: 'https://www.toptal.com', }, properties: [ - // eslint-disable-next-line n8n-nodes-base/node-param-default-missing { displayName: 'Resource', name: 'resource', @@ -41,21 +40,21 @@ export class PostBin implements INodeType { options: [ { name: 'Bin', - value: 'bin' + value: 'bin', }, { name: 'Request', - value: 'request' - } + value: 'request', + }, ], default: 'bin', required: true, - description: 'Bin to work with' + description: 'Bin to work with', }, ...binOperations, ...requestOperations, ...binFields, ...requestFields, - ] + ], }; } diff --git a/packages/nodes-base/nodes/PostBin/RequestDescription.ts b/packages/nodes-base/nodes/PostBin/RequestDescription.ts index 531348c1daa2b..b6f849586e569 100644 --- a/packages/nodes-base/nodes/PostBin/RequestDescription.ts +++ b/packages/nodes-base/nodes/PostBin/RequestDescription.ts @@ -1,10 +1,12 @@ import { - IDataObject, - IExecuteSingleFunctions, - IHttpRequestOptions, INodeProperties } from 'n8n-workflow'; +import { + buildRequestURL +} from './GenericFunctions'; + +// Operations for the `Request` resource export const requestOperations: INodeProperties[] = [ { displayName: 'Operation', @@ -25,7 +27,13 @@ export const requestOperations: INodeProperties[] = [ routing: { request: { method: 'GET', - url: '=/developers/postbin/api/bin/{{$parameter["binId"]}}/req/{{$parameter["requestId"]}}' + url: '=/developers/postbin/api/bin/{{$parameter["binId"]}}/req/{{$parameter["requestId"]}}', + }, + send: { + preSend: [ + // Parse binId before sending to make sure it's in the right format + buildRequestURL, + ], }, }, }, @@ -36,16 +44,23 @@ export const requestOperations: INodeProperties[] = [ routing: { request: { method: 'GET', - url: '=/developers/postbin/api/bin/{{$parameter["binId"]}}/req/shift' + url: '=/developers/postbin/api/bin/{{$parameter["binId"]}}/req/shift', }, - } - } + send: { + preSend: [ + // Parse binId before sending to make sure it's in the right format + buildRequestURL, + ], + }, + }, + }, ], default: 'get', - description: 'The operation to perform' - } -] + description: 'The operation to perform', + }, +]; +// Properties of the `Request` resource export const requestFields: INodeProperties[] = [ { name: 'requestId', @@ -56,13 +71,13 @@ export const requestFields: INodeProperties[] = [ displayOptions: { show: { resource: [ - 'request' + 'request', ], operation: [ 'get', - ] - } + ], + }, }, description: 'Unique identifier for each request.', - } -] + }, +]; From cece563d37281c77ed1fb48eb8d4269418fcbead Mon Sep 17 00:00:00 2001 From: ricardo Date: Fri, 13 May 2022 16:22:51 -0400 Subject: [PATCH 06/11] :zap: Improvements --- packages/core/src/NodeExecuteFunctions.ts | 2 +- .../nodes/PostBin/BinDescription.ts | 7 +------ .../nodes/PostBin/GenericFunctions.ts | 10 ++++++++-- .../nodes-base/nodes/PostBin/PostBin.node.ts | 2 +- .../nodes/PostBin/RequestDescription.ts | 19 +++++++++++++++++++ packages/nodes-base/package.json | 1 + 6 files changed, 31 insertions(+), 10 deletions(-) diff --git a/packages/core/src/NodeExecuteFunctions.ts b/packages/core/src/NodeExecuteFunctions.ts index e8038b757255c..927a21f378cbc 100644 --- a/packages/core/src/NodeExecuteFunctions.ts +++ b/packages/core/src/NodeExecuteFunctions.ts @@ -708,7 +708,7 @@ function convertN8nRequestToAxios(n8nRequest: IHttpRequestOptions): AxiosRequest }; } - if (n8nRequest.body) { + if (n8nRequest.body && Object.keys(n8nRequest.body).length) { axiosRequest.data = n8nRequest.body; // Let's add some useful header standards here. const existingContentTypeHeaderKey = searchForHeader(axiosRequest.headers, 'content-type'); diff --git a/packages/nodes-base/nodes/PostBin/BinDescription.ts b/packages/nodes-base/nodes/PostBin/BinDescription.ts index 35692a5c16a6d..1d8c50d658b32 100644 --- a/packages/nodes-base/nodes/PostBin/BinDescription.ts +++ b/packages/nodes-base/nodes/PostBin/BinDescription.ts @@ -40,7 +40,6 @@ export const binOperations: INodeProperties[] = [ routing: { request: { method: 'GET', - url: '=/developers/postbin/api/bin/{{$parameter["binId"]}}', }, send: { preSend: [ @@ -57,7 +56,6 @@ export const binOperations: INodeProperties[] = [ routing: { request: { method: 'DELETE', - url: '=/developers/postbin/api/bin/{{$parameter["binId"]}}', }, send: { preSend: [ @@ -74,7 +72,6 @@ export const binOperations: INodeProperties[] = [ routing: { request: { method: 'POST', - url: '=/developers/postbin/{{$parameter["binId"]}}', }, send: { preSend: [ @@ -112,13 +109,11 @@ export const binFields: INodeProperties[] = [ show: { resource: [ 'bin', - 'request', ], operation: [ 'get', 'delete', 'test', - 'shift', ], }, }, @@ -142,7 +137,7 @@ export const binFields: INodeProperties[] = [ ], }, }, - // Content is sent is the body of POST requests + // Content is sent in the body of POST requests routing: { send: { property: 'content', diff --git a/packages/nodes-base/nodes/PostBin/GenericFunctions.ts b/packages/nodes-base/nodes/PostBin/GenericFunctions.ts index e77e057cd1a77..627429f1c2151 100644 --- a/packages/nodes-base/nodes/PostBin/GenericFunctions.ts +++ b/packages/nodes-base/nodes/PostBin/GenericFunctions.ts @@ -1,4 +1,7 @@ -import { IExecuteSingleFunctions, IHttpRequestOptions } from 'n8n-workflow'; +import { + IExecuteSingleFunctions, + IHttpRequestOptions, +} from 'n8n-workflow'; // Regular expressions used to extract binId from parameter value const BIN_STRING_REGEX = /Bin '(\d+-\d+)'/g; @@ -14,7 +17,10 @@ const BIN_URL_REGEX = /https:\/\/www\.toptal\.com\/developers\/postbin\/b\/(\d+- * @param {IHttpRequestOptions} requestOptions * @returns {Promise} requestOptions */ -export async function buildBinAPIURL(this: IExecuteSingleFunctions, requestOptions: IHttpRequestOptions): Promise { +export async function buildBinAPIURL( + this: IExecuteSingleFunctions, + requestOptions: IHttpRequestOptions, + ): Promise { let binId = this.getNodeParameter('binId') as string; // Parse binId from parameter value binId = parseBinId(binId); diff --git a/packages/nodes-base/nodes/PostBin/PostBin.node.ts b/packages/nodes-base/nodes/PostBin/PostBin.node.ts index 1e45eeba44aa8..1404c7d73e8af 100644 --- a/packages/nodes-base/nodes/PostBin/PostBin.node.ts +++ b/packages/nodes-base/nodes/PostBin/PostBin.node.ts @@ -52,8 +52,8 @@ export class PostBin implements INodeType { description: 'Bin to work with', }, ...binOperations, - ...requestOperations, ...binFields, + ...requestOperations, ...requestFields, ], }; diff --git a/packages/nodes-base/nodes/PostBin/RequestDescription.ts b/packages/nodes-base/nodes/PostBin/RequestDescription.ts index b6f849586e569..5817587cdbe83 100644 --- a/packages/nodes-base/nodes/PostBin/RequestDescription.ts +++ b/packages/nodes-base/nodes/PostBin/RequestDescription.ts @@ -62,6 +62,25 @@ export const requestOperations: INodeProperties[] = [ // Properties of the `Request` resource export const requestFields: INodeProperties[] = [ + { + name: 'binId', + displayName: 'Bin ID', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + resource: [ + 'request', + ], + operation: [ + 'get', + 'shift', + ], + }, + }, + description: 'Unique identifier for each bin.', + }, { name: 'requestId', displayName: 'Request ID', diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index e72ab19efb82b..13efe69b70864 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -570,6 +570,7 @@ "dist/nodes/Pipedrive/Pipedrive.node.js", "dist/nodes/Pipedrive/PipedriveTrigger.node.js", "dist/nodes/Plivo/Plivo.node.js", + "dist/nodes/PostBin/PostBin.node.js", "dist/nodes/Postgres/Postgres.node.js", "dist/nodes/PostHog/PostHog.node.js", "dist/nodes/Postmark/PostmarkTrigger.node.js", From 9944d9839197423531bd0b7517b68a8917db1801 Mon Sep 17 00:00:00 2001 From: ricardo Date: Fri, 13 May 2022 17:41:43 -0400 Subject: [PATCH 07/11] :zap: Add comments --- packages/core/src/NodeExecuteFunctions.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/core/src/NodeExecuteFunctions.ts b/packages/core/src/NodeExecuteFunctions.ts index 927a21f378cbc..7c39a84d2307d 100644 --- a/packages/core/src/NodeExecuteFunctions.ts +++ b/packages/core/src/NodeExecuteFunctions.ts @@ -708,6 +708,9 @@ function convertN8nRequestToAxios(n8nRequest: IHttpRequestOptions): AxiosRequest }; } + // if there is a body and it's empty (does not have properties), + // make sure not to send anything in it as some services fail when + // sending GET request with empty body. if (n8nRequest.body && Object.keys(n8nRequest.body).length) { axiosRequest.data = n8nRequest.body; // Let's add some useful header standards here. From 7ec1755e79dfb06619f94aa748e95b425244febd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milorad=20Filipovi=C4=87?= Date: Wed, 18 May 2022 17:23:54 +0200 Subject: [PATCH 08/11] =?UTF-8?q?=F0=9F=91=8CUpdating=20the=20PostBin=20no?= =?UTF-8?q?de=20based=20on=20the=20product=20review?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nodes/PostBin/BinDescription.ts | 79 ++++++------------- .../nodes-base/nodes/PostBin/PostBin.node.ts | 1 - .../nodes/PostBin/RequestDescription.ts | 69 ++++++++++++++-- 3 files changed, 83 insertions(+), 66 deletions(-) diff --git a/packages/nodes-base/nodes/PostBin/BinDescription.ts b/packages/nodes-base/nodes/PostBin/BinDescription.ts index 1d8c50d658b32..752fd7d61777f 100644 --- a/packages/nodes-base/nodes/PostBin/BinDescription.ts +++ b/packages/nodes-base/nodes/PostBin/BinDescription.ts @@ -1,4 +1,8 @@ import { + IDataObject, + IExecuteSingleFunctions, + IN8nHttpFullResponse, + INodeExecutionData, INodeProperties } from 'n8n-workflow'; @@ -31,12 +35,27 @@ export const binOperations: INodeProperties[] = [ method: 'POST', url: '/developers/postbin/api/bin', }, + output: { + postReceive: [ + async function (this: IExecuteSingleFunctions, items: INodeExecutionData[], response: IN8nHttpFullResponse,): Promise { + items.forEach(item => item.json = { + 'binId': item.json.binId, + 'now_timestamp': item.json.now, + 'now_iso': new Date(item.json.now as string).toISOString(), + 'expires_timestamp': item.json.expires, + 'expires_iso': new Date(item.json.expires as string).toISOString(), + }); + + return items; + }, + ], + }, }, }, { name: 'Get', value: 'get', - description: 'Returns information based on the binId you provide.', + description: 'Return information based on bin ID', routing: { request: { method: 'GET', @@ -52,7 +71,7 @@ export const binOperations: INodeProperties[] = [ { name: 'Delete', value: 'delete', - description: 'Deletes this bin and all of it\'s posts.', + description: 'Delete a bin and all of its posts', routing: { request: { method: 'DELETE', @@ -65,35 +84,8 @@ export const binOperations: INodeProperties[] = [ }, }, }, - { - name: 'Test', - value: 'test', - description: 'Test your API by sending a request to the bin.', - routing: { - request: { - method: 'POST', - }, - send: { - preSend: [ - // Parse binId before sending to make sure it's in the right format - buildBinTestURL, - ], - }, - output: { - postReceive: [ - { - type: 'set', - properties: { - value: '={{ { "status": "Sent" } }}', - }, - }, - ], - }, - }, - }, ], default: 'create', - description: 'The operation to perform.', }, ]; @@ -113,36 +105,9 @@ export const binFields: INodeProperties[] = [ operation: [ 'get', 'delete', - 'test', ], }, }, - description: 'Unique identifier for each bin.', - }, - { - name: 'binContent', - displayName: 'Bin Content', - type: 'string', - default: '', - typeOptions: { - rows: 5, - }, - displayOptions: { - show: { - resource: [ - 'bin', - ], - operation: [ - 'test', - ], - }, - }, - // Content is sent in the body of POST requests - routing: { - send: { - property: 'content', - type: 'body', - }, - }, + description: 'Unique identifier for each bin', }, ]; diff --git a/packages/nodes-base/nodes/PostBin/PostBin.node.ts b/packages/nodes-base/nodes/PostBin/PostBin.node.ts index 1404c7d73e8af..f6da2476ed0ff 100644 --- a/packages/nodes-base/nodes/PostBin/PostBin.node.ts +++ b/packages/nodes-base/nodes/PostBin/PostBin.node.ts @@ -49,7 +49,6 @@ export class PostBin implements INodeType { ], default: 'bin', required: true, - description: 'Bin to work with', }, ...binOperations, ...binFields, diff --git a/packages/nodes-base/nodes/PostBin/RequestDescription.ts b/packages/nodes-base/nodes/PostBin/RequestDescription.ts index 5817587cdbe83..d120685379f78 100644 --- a/packages/nodes-base/nodes/PostBin/RequestDescription.ts +++ b/packages/nodes-base/nodes/PostBin/RequestDescription.ts @@ -3,6 +3,7 @@ import { } from 'n8n-workflow'; import { + buildBinTestURL, buildRequestURL } from './GenericFunctions'; @@ -23,7 +24,7 @@ export const requestOperations: INodeProperties[] = [ { name: 'Get', value: 'get', - description: 'Returns information based on the binId and reqId you provide.', + description: 'Return data based on request ID and bin ID', routing: { request: { method: 'GET', @@ -38,9 +39,9 @@ export const requestOperations: INodeProperties[] = [ }, }, { - name: 'Shift', - value: 'shift', - description: 'Removes the first request form the bin.', + name: 'Remove First', + value: 'removeFirst', + description: 'Remove the first request from the bin', routing: { request: { method: 'GET', @@ -54,9 +55,34 @@ export const requestOperations: INodeProperties[] = [ }, }, }, + { + name: 'Send', + value: 'send', + description: 'Test your API by sending the bin a request', + routing: { + request: { + method: 'POST', + }, + send: { + preSend: [ + // Parse binId before sending to make sure it's in the right format + buildBinTestURL, + ], + }, + output: { + postReceive: [ + { + type: 'set', + properties: { + value: '={{ { "status": "Sent" } }}', + }, + }, + ], + }, + }, + }, ], default: 'get', - description: 'The operation to perform', }, ]; @@ -75,12 +101,39 @@ export const requestFields: INodeProperties[] = [ ], operation: [ 'get', - 'shift', + 'removeFirst', + 'send', ], }, }, - description: 'Unique identifier for each bin.', + description: 'Unique identifier for each bin', }, + { + name: 'binContent', + displayName: 'Bin Content', + type: 'string', + default: '', + typeOptions: { + rows: 5, + }, + displayOptions: { + show: { + resource: [ + 'request', + ], + operation: [ + 'send', + ], + }, + }, + // Content is sent in the body of POST requests + routing: { + send: { + property: 'content', + type: 'body', + }, + }, + }, { name: 'requestId', displayName: 'Request ID', @@ -97,6 +150,6 @@ export const requestFields: INodeProperties[] = [ ], }, }, - description: 'Unique identifier for each request.', + description: 'Unique identifier for each request', }, ]; From e2b9ad1f9977a6117f5be69090de6983538480b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milorad=20Filipovi=C4=87?= Date: Tue, 24 May 2022 16:15:44 +0200 Subject: [PATCH 09/11] =?UTF-8?q?=F0=9F=92=84Updating=20PostBin=20node=20B?= =?UTF-8?q?in=20ID=20validation=20logic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nodes/PostBin/BinDescription.ts | 1 - .../nodes/PostBin/GenericFunctions.ts | 47 ++++++++----------- 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/packages/nodes-base/nodes/PostBin/BinDescription.ts b/packages/nodes-base/nodes/PostBin/BinDescription.ts index 752fd7d61777f..88aa9dcfd4335 100644 --- a/packages/nodes-base/nodes/PostBin/BinDescription.ts +++ b/packages/nodes-base/nodes/PostBin/BinDescription.ts @@ -8,7 +8,6 @@ import { import { buildBinAPIURL, - buildBinTestURL } from './GenericFunctions'; diff --git a/packages/nodes-base/nodes/PostBin/GenericFunctions.ts b/packages/nodes-base/nodes/PostBin/GenericFunctions.ts index 627429f1c2151..a785701010a53 100644 --- a/packages/nodes-base/nodes/PostBin/GenericFunctions.ts +++ b/packages/nodes-base/nodes/PostBin/GenericFunctions.ts @@ -1,11 +1,11 @@ import { IExecuteSingleFunctions, IHttpRequestOptions, + NodeApiError, } from 'n8n-workflow'; // Regular expressions used to extract binId from parameter value -const BIN_STRING_REGEX = /Bin '(\d+-\d+)'/g; -const BIN_URL_REGEX = /https:\/\/www\.toptal\.com\/developers\/postbin\/b\/(\d+-\d+)/g; +const BIN_ID_REGEX = /\b\d{13}-\d{13}\b/g; /** * Creates correctly-formatted PostBin API URL based on the entered binId. @@ -17,15 +17,11 @@ const BIN_URL_REGEX = /https:\/\/www\.toptal\.com\/developers\/postbin\/b\/(\d+- * @param {IHttpRequestOptions} requestOptions * @returns {Promise} requestOptions */ -export async function buildBinAPIURL( - this: IExecuteSingleFunctions, - requestOptions: IHttpRequestOptions, - ): Promise { - let binId = this.getNodeParameter('binId') as string; - // Parse binId from parameter value - binId = parseBinId(binId); +export async function buildBinAPIURL(this: IExecuteSingleFunctions, requestOptions: IHttpRequestOptions): Promise { + const binId = parseBinId(this); // Assemble the PostBin API URL and put it back to requestOptions requestOptions.url = `/developers/postbin/api/bin/${binId}`; + return requestOptions; } @@ -40,9 +36,8 @@ export async function buildBinAPIURL( * @returns {Promise} requestOptions */ export async function buildBinTestURL(this: IExecuteSingleFunctions, requestOptions: IHttpRequestOptions): Promise { - let binId = this.getNodeParameter('binId') as string; - // Parse binId from parameter value - binId = parseBinId(binId); + const binId = parseBinId(this); + // Assemble the PostBin API URL and put it back to requestOptions requestOptions.url = `/developers/postbin/${binId}`; return requestOptions; @@ -60,9 +55,7 @@ export async function buildBinTestURL(this: IExecuteSingleFunctions, requestOpti */ export async function buildRequestURL(this: IExecuteSingleFunctions, requestOptions: IHttpRequestOptions): Promise { const reqId = this.getNodeParameter('requestId', 'shift') as string; - - let binId = this.getNodeParameter('binId') as string; - binId = parseBinId(binId); + const binId = parseBinId(this); requestOptions.url = `/developers/postbin/api/bin/${binId}/req/${reqId}`; return requestOptions; @@ -78,20 +71,20 @@ export async function buildRequestURL(this: IExecuteSingleFunctions, requestOpti * @param {IHttpRequestOptions} requestOptions * @returns {Promise} requestOptions */ -function parseBinId(binId: string) { - // Test if bin id has been copied from website in the format `Bin ''` - const stringMatch = BIN_STRING_REGEX.exec(binId); - // Test if bin URL has been pasted instead if bin id - const urlMatch = BIN_URL_REGEX.exec(binId); +function parseBinId(context: IExecuteSingleFunctions) { + const binId = context.getNodeParameter('binId') as string; + // Test if the Bin id is in the expected format + const idMatch = BIN_ID_REGEX.exec(binId); // Return what is matched - if (stringMatch) { - return stringMatch[1]; + if(idMatch) { + return idMatch[0]; } - if(urlMatch) { - return urlMatch[1]; - } - // Fall back to returning whatever is passed in the first place - return binId; + // If it's not recognized, error out + throw new NodeApiError(context.getNode(), {}, { + message: 'Bin ID format is not valid', + description: 'Please check the provided Bin ID and try again.', + parseXml: false, + }); } From e758af8b80772fb3c7b9f9d149905b9dcc1b270b Mon Sep 17 00:00:00 2001 From: ricardo Date: Wed, 25 May 2022 12:37:25 -0400 Subject: [PATCH 10/11] :zap: Small improvements --- packages/nodes-base/nodes/PostBin/BinDescription.ts | 8 +++----- packages/nodes-base/nodes/PostBin/RequestDescription.ts | 8 ++++---- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/nodes-base/nodes/PostBin/BinDescription.ts b/packages/nodes-base/nodes/PostBin/BinDescription.ts index 88aa9dcfd4335..0ef9e6541f423 100644 --- a/packages/nodes-base/nodes/PostBin/BinDescription.ts +++ b/packages/nodes-base/nodes/PostBin/BinDescription.ts @@ -1,5 +1,4 @@ import { - IDataObject, IExecuteSingleFunctions, IN8nHttpFullResponse, INodeExecutionData, @@ -28,7 +27,7 @@ export const binOperations: INodeProperties[] = [ { name: 'Create', value: 'create', - description: 'Create new bin', + description: 'Create bin', routing: { request: { method: 'POST', @@ -44,7 +43,6 @@ export const binOperations: INodeProperties[] = [ 'expires_timestamp': item.json.expires, 'expires_iso': new Date(item.json.expires as string).toISOString(), }); - return items; }, ], @@ -54,7 +52,7 @@ export const binOperations: INodeProperties[] = [ { name: 'Get', value: 'get', - description: 'Return information based on bin ID', + description: 'Get a bin', routing: { request: { method: 'GET', @@ -70,7 +68,7 @@ export const binOperations: INodeProperties[] = [ { name: 'Delete', value: 'delete', - description: 'Delete a bin and all of its posts', + description: 'Delete a bin', routing: { request: { method: 'DELETE', diff --git a/packages/nodes-base/nodes/PostBin/RequestDescription.ts b/packages/nodes-base/nodes/PostBin/RequestDescription.ts index d120685379f78..6ed545263d09d 100644 --- a/packages/nodes-base/nodes/PostBin/RequestDescription.ts +++ b/packages/nodes-base/nodes/PostBin/RequestDescription.ts @@ -24,7 +24,7 @@ export const requestOperations: INodeProperties[] = [ { name: 'Get', value: 'get', - description: 'Return data based on request ID and bin ID', + description: 'Get a request', routing: { request: { method: 'GET', @@ -41,7 +41,7 @@ export const requestOperations: INodeProperties[] = [ { name: 'Remove First', value: 'removeFirst', - description: 'Remove the first request from the bin', + description: 'Remove the first request from bin', routing: { request: { method: 'GET', @@ -58,7 +58,7 @@ export const requestOperations: INodeProperties[] = [ { name: 'Send', value: 'send', - description: 'Test your API by sending the bin a request', + description: 'Send a test request to the bin', routing: { request: { method: 'POST', @@ -74,7 +74,7 @@ export const requestOperations: INodeProperties[] = [ { type: 'set', properties: { - value: '={{ { "status": "Sent" } }}', + value: '={{ { "requestId": $response.body } }}', }, }, ], From 597c8467e65bfcf11869154790114527ed7f0c8f Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Fri, 27 May 2022 18:03:02 +0200 Subject: [PATCH 11/11] :zap: Transform the bin requests and add additional properties --- .../nodes/PostBin/BinDescription.ts | 20 ++++++---------- .../nodes/PostBin/GenericFunctions.ts | 23 +++++++++++++++++++ 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/packages/nodes-base/nodes/PostBin/BinDescription.ts b/packages/nodes-base/nodes/PostBin/BinDescription.ts index 0ef9e6541f423..91dd007f6c03f 100644 --- a/packages/nodes-base/nodes/PostBin/BinDescription.ts +++ b/packages/nodes-base/nodes/PostBin/BinDescription.ts @@ -1,12 +1,10 @@ import { - IExecuteSingleFunctions, - IN8nHttpFullResponse, - INodeExecutionData, INodeProperties } from 'n8n-workflow'; import { buildBinAPIURL, + transformBinReponse, } from './GenericFunctions'; @@ -35,16 +33,7 @@ export const binOperations: INodeProperties[] = [ }, output: { postReceive: [ - async function (this: IExecuteSingleFunctions, items: INodeExecutionData[], response: IN8nHttpFullResponse,): Promise { - items.forEach(item => item.json = { - 'binId': item.json.binId, - 'now_timestamp': item.json.now, - 'now_iso': new Date(item.json.now as string).toISOString(), - 'expires_timestamp': item.json.expires, - 'expires_iso': new Date(item.json.expires as string).toISOString(), - }); - return items; - }, + transformBinReponse, ], }, }, @@ -57,6 +46,11 @@ export const binOperations: INodeProperties[] = [ request: { method: 'GET', }, + output: { + postReceive: [ + transformBinReponse, + ], + }, send: { preSend: [ // Parse binId before sending to make sure it's in the right format diff --git a/packages/nodes-base/nodes/PostBin/GenericFunctions.ts b/packages/nodes-base/nodes/PostBin/GenericFunctions.ts index a785701010a53..3a07ae776872f 100644 --- a/packages/nodes-base/nodes/PostBin/GenericFunctions.ts +++ b/packages/nodes-base/nodes/PostBin/GenericFunctions.ts @@ -1,6 +1,8 @@ import { IExecuteSingleFunctions, IHttpRequestOptions, + IN8nHttpFullResponse, + INodeExecutionData, NodeApiError, } from 'n8n-workflow'; @@ -88,3 +90,24 @@ function parseBinId(context: IExecuteSingleFunctions) { parseXml: false, }); } + +/** + * Converts the bin response data and adds additional properties + * + * @param {IExecuteSingleFunctions} this + * @param {INodeExecutionData} items[] + * @param {IN8nHttpFullResponse} response + * @returns {Promise} + */ + export async function transformBinReponse(this: IExecuteSingleFunctions, items: INodeExecutionData[], response: IN8nHttpFullResponse): Promise { + items.forEach(item => item.json = { + 'binId': item.json.binId, + 'nowTimestamp': item.json.now, + 'nowIso': new Date(item.json.now as string).toISOString(), + 'expiresTimestamp': item.json.expires, + 'expiresIso': new Date(item.json.expires as string).toISOString(), + 'requestUrl': 'https://www.toptal.com/developers/postbin/' + item.json.binId, + 'viewUrl': 'https://www.toptal.com/developers/postbin/b/' + item.json.binId, + }); + return items; +}