From 1bb7f88a6e15758da5793a9315cc57c1ea2827fc Mon Sep 17 00:00:00 2001 From: brianinoa Date: Tue, 14 Jun 2022 15:35:59 +0200 Subject: [PATCH 01/20] :arrow_up: Update n8n core and workflow --- package.json | 134 ++++++++++++++++++++++++++------------------------- 1 file changed, 68 insertions(+), 66 deletions(-) diff --git a/package.json b/package.json index 4c83043..342debe 100644 --- a/package.json +++ b/package.json @@ -1,70 +1,72 @@ { - "name": "n8n-nodes-starter", - "version": "0.1.0", - "description": "Example starter module for custom n8n nodes.", - "keywords": ["n8n-community-node-package"], - "license": "SEE LICENSE IN LICENSE.md", - "homepage": "https://n8n.io", - "author": { - "name": "Jan Oberhauser", - "email": "jan@n8n.io" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/n8n-io/n8n-nodes-starter.git" - }, - "main": "index.js", - "scripts": { - "dev": "npm run watch", - "build": "tsc && gulp", - "lint": "tslint -p tsconfig.json -c tslint.json", - "lintfix": "tslint --fix -p tsconfig.json -c tslint.json", - "nodelinter": "nodelinter", - "watch": "tsc --watch", - "test": "jest" - }, - "files": [ - "dist" + "name": "n8n-nodes-starter", + "version": "0.1.0", + "description": "Example starter module for custom n8n nodes.", + "keywords": [ + "n8n-community-node-package" + ], + "license": "SEE LICENSE IN LICENSE.md", + "homepage": "https://n8n.io", + "author": { + "name": "Jan Oberhauser", + "email": "jan@n8n.io" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/n8n-io/n8n-nodes-starter.git" + }, + "main": "index.js", + "scripts": { + "dev": "npm run watch", + "build": "tsc && gulp", + "lint": "tslint -p tsconfig.json -c tslint.json", + "lintfix": "tslint --fix -p tsconfig.json -c tslint.json", + "nodelinter": "nodelinter", + "watch": "tsc --watch", + "test": "jest" + }, + "files": [ + "dist" + ], + "n8n": { + "credentials": [ + "dist/credentials/ExampleCredentials.credentials.js" ], - "n8n": { - "credentials": [ - "dist/credentials/ExampleCredentials.credentials.js" - ], - "nodes": [ - "dist/nodes/ExampleNode/ExampleNode.node.js" - ] + "nodes": [ + "dist/nodes/ExampleNode/ExampleNode.node.js" + ] + }, + "devDependencies": { + "@types/express": "^4.17.6", + "@types/jest": "^26.0.13", + "@types/node": "^14.17.27", + "@types/request-promise-native": "~1.0.15", + "gulp": "^4.0.0", + "jest": "^26.4.2", + "n8n-workflow": "~0.103.0", + "nodelinter": "^0.1.9", + "ts-jest": "^26.3.0", + "tslint": "^6.1.2", + "typescript": "~4.3.5" + }, + "dependencies": { + "n8n-core": "~0.121.3" + }, + "jest": { + "transform": { + "^.+\\.tsx?$": "ts-jest" }, - "devDependencies": { - "@types/express": "^4.17.6", - "@types/jest": "^26.0.13", - "@types/node": "^14.17.27", - "@types/request-promise-native": "~1.0.15", - "gulp": "^4.0.0", - "jest": "^26.4.2", - "n8n-workflow": "~0.83.0", - "nodelinter": "^0.1.9", - "ts-jest": "^26.3.0", - "tslint": "^6.1.2", - "typescript": "~4.3.5" - }, - "dependencies": { - "n8n-core": "~0.101.0" - }, - "jest": { - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testURL": "http://localhost/", - "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "testPathIgnorePatterns": [ - "/dist/", - "/node_modules/" - ], - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "json" - ] - } + "testURL": "http://localhost/", + "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", + "testPathIgnorePatterns": [ + "/dist/", + "/node_modules/" + ], + "moduleFileExtensions": [ + "ts", + "tsx", + "js", + "json" + ] + } } From 380b617a5f1505a6a74b0723f51a16f27795d253 Mon Sep 17 00:00:00 2001 From: brianinoa Date: Tue, 14 Jun 2022 16:31:05 +0200 Subject: [PATCH 02/20] :zap: Create New HttpBin Declarative Node --- nodes/HttpBin/HttpBin.credentials.ts | 39 ++++++++++++++++++++++++++++ nodes/HttpBin/HttpBin.node.json | 21 +++++++++++++++ nodes/HttpBin/HttpBin.node.ts | 34 ++++++++++++++++++++++++ nodes/HttpBin/httpbin.svg | 18 +++++++++++++ 4 files changed, 112 insertions(+) create mode 100644 nodes/HttpBin/HttpBin.credentials.ts create mode 100644 nodes/HttpBin/HttpBin.node.json create mode 100644 nodes/HttpBin/HttpBin.node.ts create mode 100644 nodes/HttpBin/httpbin.svg diff --git a/nodes/HttpBin/HttpBin.credentials.ts b/nodes/HttpBin/HttpBin.credentials.ts new file mode 100644 index 0000000..b6bbab1 --- /dev/null +++ b/nodes/HttpBin/HttpBin.credentials.ts @@ -0,0 +1,39 @@ +import { + IAuthenticateHeaderAuth, + ICredentialTestRequest, + ICredentialType, + INodeProperties, +} from "n8n-workflow"; + +export class HttpBinApi implements ICredentialType { + name = "HttpBinApi"; + displayName = "HttpBin API"; + documentationUrl = "httpbin"; + properties: INodeProperties[] = [ + { + displayName: "API Key", + name: "apiKey", + type: "string", + default: "", + }, + { + displayName: "Domain", + name: "domain", + type: "string", + default: "https://httpbin.org", + }, + ]; + authenticate = { + type: "headerAuth", + properties: { + name: "api-key", + value: "={{$credentials.apiKey}}", + }, + } as IAuthenticateHeaderAuth; + test: ICredentialTestRequest = { + request: { + baseURL: "={{$credentials?.domain}}/v3", + url: "/account", + }, + }; +} diff --git a/nodes/HttpBin/HttpBin.node.json b/nodes/HttpBin/HttpBin.node.json new file mode 100644 index 0000000..5f3ed05 --- /dev/null +++ b/nodes/HttpBin/HttpBin.node.json @@ -0,0 +1,21 @@ +{ + "node": "n8n-nodes-base.httpbin", + "nodeVersion": "1.0", + "codexVersion": "1.0", + "categories": [ + "HTTP Request & Response Service", + "Developer Tools" + ], + "resources": { + "credentialDocumentation": [ + { + "url": "https://docs.n8n.io/credentials/httpbin" + } + ], + "primaryDocumentation": [ + { + "url": "https://docs.n8n.io/nodes/n8n-nodes-base.httpbin/" + } + ] + } +} diff --git a/nodes/HttpBin/HttpBin.node.ts b/nodes/HttpBin/HttpBin.node.ts new file mode 100644 index 0000000..161c44b --- /dev/null +++ b/nodes/HttpBin/HttpBin.node.ts @@ -0,0 +1,34 @@ +import { INodeType, INodeTypeDescription } from "n8n-workflow"; + +export class HttpBin implements INodeType { + description: INodeTypeDescription = { + displayName: "HttpBin", + name: "httpbin", + icon: "file:httpbin.svg", + group: ["transform"], + version: 1, + subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', + description: "Interact with HttpBin API", + defaults: { + name: "Sendinblue", + color: "#044a75", + }, + inputs: ["main"], + outputs: ["main"], + credentials: [ + { + name: "sendinblueApi", + required: true, + }, + ], + requestDefaults: { + baseURL: "={{$credentials.domain}}", + url: "", + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + }, + properties: [], + }; +} diff --git a/nodes/HttpBin/httpbin.svg b/nodes/HttpBin/httpbin.svg new file mode 100644 index 0000000..aee1de1 --- /dev/null +++ b/nodes/HttpBin/httpbin.svg @@ -0,0 +1,18 @@ + + + + From 2496f9bef7892cb9bda8aa9c0139c01594aea0af Mon Sep 17 00:00:00 2001 From: brianinoa Date: Tue, 14 Jun 2022 16:44:04 +0200 Subject: [PATCH 03/20] :wrench: Enable ES Module Interop --- tsconfig.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 6456490..48efe0b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,7 +18,8 @@ "declaration": true, "outDir": "./dist/", "target": "es2017", - "sourceMap": true + "sourceMap": true, + "esModuleInterop": true }, "include": [ "credentials/**/*", @@ -30,4 +31,4 @@ "exclude": [ "**/*.spec.ts" ] -} \ No newline at end of file +} From 1f0e9fc3e64198bff2ab4ea2d644b7292245e4d0 Mon Sep 17 00:00:00 2001 From: brianinoa Date: Tue, 14 Jun 2022 17:01:15 +0200 Subject: [PATCH 04/20] Move credentials to correct directory --- {nodes/HttpBin => credentials}/HttpBin.credentials.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename {nodes/HttpBin => credentials}/HttpBin.credentials.ts (97%) diff --git a/nodes/HttpBin/HttpBin.credentials.ts b/credentials/HttpBin.credentials.ts similarity index 97% rename from nodes/HttpBin/HttpBin.credentials.ts rename to credentials/HttpBin.credentials.ts index b6bbab1..0b74def 100644 --- a/nodes/HttpBin/HttpBin.credentials.ts +++ b/credentials/HttpBin.credentials.ts @@ -6,7 +6,7 @@ import { } from "n8n-workflow"; export class HttpBinApi implements ICredentialType { - name = "HttpBinApi"; + name = "httpbinApi"; displayName = "HttpBin API"; documentationUrl = "httpbin"; properties: INodeProperties[] = [ From 71978520bac111a56a54a591d16dacf7565fd2b1 Mon Sep 17 00:00:00 2001 From: brianinoa Date: Tue, 14 Jun 2022 17:02:04 +0200 Subject: [PATCH 05/20] :zap: Fix node name and color :zap: Add initial Resource and Operation --- nodes/HttpBin/HttpBin.node.ts | 53 +++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/nodes/HttpBin/HttpBin.node.ts b/nodes/HttpBin/HttpBin.node.ts index 161c44b..e4e7f6c 100644 --- a/nodes/HttpBin/HttpBin.node.ts +++ b/nodes/HttpBin/HttpBin.node.ts @@ -1,5 +1,6 @@ import { INodeType, INodeTypeDescription } from "n8n-workflow"; +// Description of our Node export class HttpBin implements INodeType { description: INodeTypeDescription = { displayName: "HttpBin", @@ -10,15 +11,15 @@ export class HttpBin implements INodeType { subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', description: "Interact with HttpBin API", defaults: { - name: "Sendinblue", - color: "#044a75", + name: "HttpBin", + color: "#3b4151", }, inputs: ["main"], outputs: ["main"], credentials: [ { - name: "sendinblueApi", - required: true, + name: "httpbinApi", + required: false, }, ], requestDefaults: { @@ -29,6 +30,48 @@ export class HttpBin implements INodeType { "Content-Type": "application/json", }, }, - properties: [], + /** + * In the properties array we have two mandatory options objects required + * + * Resource & Operation + * + */ + properties: [ + { + displayName: "Resource", + name: "resource", + type: "options", + noDataExpression: true, + options: [ + { + name: "Http Verbs", + value: "httpverbs", + }, + { + name: "Auth Methods", + value: "authmethods", + }, + ], + default: "httpverbs", + }, + { + displayName: "Operation", + name: "operation", + type: "options", + noDataExpression: true, + displayOptions: { + show: { + resource: ["httpverbs"], + }, + }, + options: [ + { + name: "GET", + value: "getMethod", + }, + ], + default: "getMethod", + }, + ], }; } From d753dc9dbf68c151e4829613ce56f13fdf8b5ddc Mon Sep 17 00:00:00 2001 From: brianinoa Date: Tue, 14 Jun 2022 19:52:28 +0200 Subject: [PATCH 06/20] Add new node to n8n credentials and nodes list --- package.json | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 342debe..e42fd39 100644 --- a/package.json +++ b/package.json @@ -30,10 +30,12 @@ ], "n8n": { "credentials": [ - "dist/credentials/ExampleCredentials.credentials.js" + "dist/credentials/ExampleCredentials.credentials.js", + "dist/credentials/HttpBin.credentials.js" ], "nodes": [ - "dist/nodes/ExampleNode/ExampleNode.node.js" + "dist/nodes/ExampleNode/ExampleNode.node.js", + "dist/nodes/HttpBin/HttpBin.node.js" ] }, "devDependencies": { @@ -41,7 +43,7 @@ "@types/jest": "^26.0.13", "@types/node": "^14.17.27", "@types/request-promise-native": "~1.0.15", - "gulp": "^4.0.0", + "gulp": "^4.0.2", "jest": "^26.4.2", "n8n-workflow": "~0.103.0", "nodelinter": "^0.1.9", From 0623f030e61ecf722fca95515afbaba69508de17 Mon Sep 17 00:00:00 2001 From: brianinoa Date: Tue, 14 Jun 2022 19:52:39 +0200 Subject: [PATCH 07/20] Add relevant category --- nodes/HttpBin/HttpBin.node.json | 1 + 1 file changed, 1 insertion(+) diff --git a/nodes/HttpBin/HttpBin.node.json b/nodes/HttpBin/HttpBin.node.json index 5f3ed05..1b0235c 100644 --- a/nodes/HttpBin/HttpBin.node.json +++ b/nodes/HttpBin/HttpBin.node.json @@ -3,6 +3,7 @@ "nodeVersion": "1.0", "codexVersion": "1.0", "categories": [ + "Development", "HTTP Request & Response Service", "Developer Tools" ], From f528f995a26980d31f57dd905af8d39137578f6e Mon Sep 17 00:00:00 2001 From: brianinoa Date: Tue, 14 Jun 2022 21:29:18 +0200 Subject: [PATCH 08/20] Fix credentials naming to match class name --- .../{HttpBin.credentials.ts => HttpBinApi.credentials.ts} | 0 package.json | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename credentials/{HttpBin.credentials.ts => HttpBinApi.credentials.ts} (100%) diff --git a/credentials/HttpBin.credentials.ts b/credentials/HttpBinApi.credentials.ts similarity index 100% rename from credentials/HttpBin.credentials.ts rename to credentials/HttpBinApi.credentials.ts diff --git a/package.json b/package.json index e42fd39..b786fc9 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "n8n": { "credentials": [ "dist/credentials/ExampleCredentials.credentials.js", - "dist/credentials/HttpBin.credentials.js" + "dist/credentials/HttpBinApi.credentials.js" ], "nodes": [ "dist/nodes/ExampleNode/ExampleNode.node.js", From 35b1808ce045c15a52662a03ae6c1ee94cfeae33 Mon Sep 17 00:00:00 2001 From: brianinoa Date: Thu, 16 Jun 2022 11:53:57 +0200 Subject: [PATCH 09/20] :recycle: Add Bearer Token authentication section --- credentials/HttpBinApi.credentials.ts | 45 ++++++++++++++++++++------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/credentials/HttpBinApi.credentials.ts b/credentials/HttpBinApi.credentials.ts index 0b74def..efd8639 100644 --- a/credentials/HttpBinApi.credentials.ts +++ b/credentials/HttpBinApi.credentials.ts @@ -1,7 +1,8 @@ import { - IAuthenticateHeaderAuth, + ICredentialDataDecryptedObject, ICredentialTestRequest, ICredentialType, + IHttpRequestOptions, INodeProperties, } from "n8n-workflow"; @@ -11,11 +12,17 @@ export class HttpBinApi implements ICredentialType { documentationUrl = "httpbin"; properties: INodeProperties[] = [ { - displayName: "API Key", - name: "apiKey", + displayName: "Token", + name: "token", type: "string", default: "", }, + // { + // displayName: "API Key", + // name: "apiKey", + // type: "string", + // default: "", + // }, { displayName: "Domain", name: "domain", @@ -23,17 +30,31 @@ export class HttpBinApi implements ICredentialType { default: "https://httpbin.org", }, ]; - authenticate = { - type: "headerAuth", - properties: { - name: "api-key", - value: "={{$credentials.apiKey}}", - }, - } as IAuthenticateHeaderAuth; + + // authenticate = { + // type: "headerAuth", + // properties: { + // name: "api-key", + // value: "={{$credentials.apiKey}}", + // }, + // } as IAuthenticateHeaderAuth; + + authenticate = async ( + credentials: ICredentialDataDecryptedObject, + requestOptions: IHttpRequestOptions + ): Promise => { + const headers = requestOptions.headers || {}; + const authentication = { Authorization: `Bearer ${credentials.token}` }; + Object.assign(requestOptions, { + headers: { ...authentication, ...headers }, + }); + return requestOptions; + }; + test: ICredentialTestRequest = { request: { - baseURL: "={{$credentials?.domain}}/v3", - url: "/account", + baseURL: "={{$credentials?.domain}}", + url: "/bearer", }, }; } From e123f16c42a07ca2cd855da193fc5b3657acccd6 Mon Sep 17 00:00:00 2001 From: brianinoa Date: Thu, 16 Jun 2022 11:59:25 +0200 Subject: [PATCH 10/20] :recycle: Separate HTTP Verbs functionality to it's own file --- nodes/HttpBin/HttpVerbDescriptions.ts | 245 ++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 nodes/HttpBin/HttpVerbDescriptions.ts diff --git a/nodes/HttpBin/HttpVerbDescriptions.ts b/nodes/HttpBin/HttpVerbDescriptions.ts new file mode 100644 index 0000000..e0f74c7 --- /dev/null +++ b/nodes/HttpBin/HttpVerbDescriptions.ts @@ -0,0 +1,245 @@ +import { INodeProperties } from "n8n-workflow"; + +/** + * This maps the operations to when the resource HTTP Verbs is selected + */ +export const httpVerbOperations: Array = [ + { + displayName: "Operation", + name: "operation", + type: "options", + noDataExpression: true, + displayOptions: { + show: { + resource: ["httpverbs"], + }, + }, + options: [ + { + name: "GET", + value: "get", + routing: { + request: { + method: "GET", + url: "/get", + }, + }, + }, + { + name: "DELETE", + value: "delete", + routing: { + request: { + method: "DELETE", + url: "/delete", + }, + }, + }, + ], + default: "get", + }, +]; + +const getOperation: Array = [ + { + name: "typeofData", + default: "queryParameterOption", + description: + "Select type of data to send [Query Parameter Arguments, JSON-Body]", + displayName: "Type of Data", + displayOptions: { + show: { + resource: ["httpverbs"], + operation: ["get"], + }, + }, + type: "options", + options: [ + { + name: "Query", + value: "queryParameter", + }, + ], + required: true, + }, + { + name: "arguments", + default: {}, + description: "The request's query parameters", + displayName: "GET Query Parameters", + displayOptions: { + show: { + resource: ["httpverbs"], + operation: ["get"], + }, + }, + options: [ + { + name: "keyvalue", + displayName: "Key:Value", + values: [ + { + displayName: "Key", + name: "key", + type: "string", + default: "", + required: true, + description: "Key of query parameter", + }, + { + displayName: "Value", + name: "value", + type: "string", + default: "", + routing: { + send: { + property: "={{$parent.key}}", + type: "query", + }, + }, + required: true, + description: "Value of query parameter", + }, + ], + }, + ], + type: "fixedCollection", + typeOptions: { + multipleValues: true, + }, + }, +]; + +const deleteOperation: Array = [ + { + name: "typeofData", + default: "queryParameterOption", + description: + "Select type of data to send [Query Parameter Arguments, Form-Data, Body, JSON]", + displayName: "Type of Data", + displayOptions: { + show: { + resource: ["httpverbs"], + operation: ["delete"], + }, + }, + options: [ + { + name: "Query", + value: "queryParameter", + }, + { + name: "JSON", + value: "jsonData", + }, + ], + required: true, + type: "options", + }, + { + name: "arguments", + default: {}, + description: "The request's query parameters", + displayName: "DELETE Query Parameters", + displayOptions: { + show: { + resource: ["httpverbs"], + operation: ["delete"], + typeofData: ["queryParameter"], + }, + }, + options: [ + { + name: "keyvalue", + displayName: "Key:Value", + values: [ + { + displayName: "Key", + name: "key", + type: "string", + default: "", + required: true, + description: "Key of query parameter", + }, + { + displayName: "Value", + name: "value", + type: "string", + default: "", + routing: { + send: { + property: "={{$parent.key}}", + type: "query", + }, + }, + required: true, + description: "Value of query parameter", + }, + ], + }, + ], + type: "fixedCollection", + typeOptions: { + multipleValues: true, + }, + }, + { + name: "arguments", + default: {}, + description: "The request's query parameters", + displayName: "DELETE JSON Object", + displayOptions: { + show: { + resource: ["httpverbs"], + operation: ["delete"], + typeofData: ["jsonData"], + }, + }, + options: [ + { + name: "keyvalue", + displayName: "Key:Value", + values: [ + { + displayName: "Key", + name: "key", + type: "string", + default: "", + required: true, + description: "Key of json property", + }, + { + displayName: "Value", + name: "value", + type: "string", + default: "", + routing: { + send: { + property: "={{$parent.key}}", + type: "body", + }, + }, + required: true, + description: "Value of json property", + }, + ], + }, + ], + type: "fixedCollection", + typeOptions: { + multipleValues: true, + }, + }, +]; + +export const httpVerbFields: Array = [ + /* -------------------------------------------------------------------------- */ + /* Http Verbs:Get */ + /* -------------------------------------------------------------------------- */ + ...getOperation, + + /* -------------------------------------------------------------------------- */ + /* Http Verbs:Delete */ + /* -------------------------------------------------------------------------- */ + ...deleteOperation, +]; From 5909f4d124856667860d82645045a22e09a5fbe7 Mon Sep 17 00:00:00 2001 From: brianinoa Date: Thu, 16 Jun 2022 12:00:05 +0200 Subject: [PATCH 11/20] :recycle: Import HTTP Verbs operations and fields --- nodes/HttpBin/HttpBin.node.ts | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/nodes/HttpBin/HttpBin.node.ts b/nodes/HttpBin/HttpBin.node.ts index e4e7f6c..2bb9502 100644 --- a/nodes/HttpBin/HttpBin.node.ts +++ b/nodes/HttpBin/HttpBin.node.ts @@ -1,6 +1,6 @@ import { INodeType, INodeTypeDescription } from "n8n-workflow"; +import { httpVerbOperations, httpVerbFields } from "./HttpVerbDescriptions"; -// Description of our Node export class HttpBin implements INodeType { description: INodeTypeDescription = { displayName: "HttpBin", @@ -23,7 +23,7 @@ export class HttpBin implements INodeType { }, ], requestDefaults: { - baseURL: "={{$credentials.domain}}", + baseURL: "https://httpbin.org", url: "", headers: { Accept: "application/json", @@ -44,7 +44,7 @@ export class HttpBin implements INodeType { noDataExpression: true, options: [ { - name: "Http Verbs", + name: "HTTP Verbs", value: "httpverbs", }, { @@ -54,24 +54,8 @@ export class HttpBin implements INodeType { ], default: "httpverbs", }, - { - displayName: "Operation", - name: "operation", - type: "options", - noDataExpression: true, - displayOptions: { - show: { - resource: ["httpverbs"], - }, - }, - options: [ - { - name: "GET", - value: "getMethod", - }, - ], - default: "getMethod", - }, + ...httpVerbOperations, + ...httpVerbFields, ], }; } From e37148b6e60a699d7ca4939b0589d8500e8dd71b Mon Sep 17 00:00:00 2001 From: brianinoa Date: Thu, 16 Jun 2022 12:18:05 +0200 Subject: [PATCH 12/20] :recycle: fix descriptions --- nodes/HttpBin/HttpVerbDescriptions.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nodes/HttpBin/HttpVerbDescriptions.ts b/nodes/HttpBin/HttpVerbDescriptions.ts index e0f74c7..4a47ed7 100644 --- a/nodes/HttpBin/HttpVerbDescriptions.ts +++ b/nodes/HttpBin/HttpVerbDescriptions.ts @@ -66,7 +66,7 @@ const getOperation: Array = [ name: "arguments", default: {}, description: "The request's query parameters", - displayName: "GET Query Parameters", + displayName: "Query Parameters", displayOptions: { show: { resource: ["httpverbs"], @@ -140,7 +140,7 @@ const deleteOperation: Array = [ name: "arguments", default: {}, description: "The request's query parameters", - displayName: "DELETE Query Parameters", + displayName: "Query Parameters", displayOptions: { show: { resource: ["httpverbs"], @@ -186,8 +186,8 @@ const deleteOperation: Array = [ { name: "arguments", default: {}, - description: "The request's query parameters", - displayName: "DELETE JSON Object", + description: "The request's JSON properties", + displayName: "JSON Object", displayOptions: { show: { resource: ["httpverbs"], From 1c53ac9f8522f126dbbf6441d802d36d0bd065f4 Mon Sep 17 00:00:00 2001 From: brianinoa Date: Thu, 16 Jun 2022 15:03:56 +0200 Subject: [PATCH 13/20] :zap: Improve descriptions --- nodes/HttpBin/HttpBin.node.json | 1 - nodes/HttpBin/HttpBin.node.ts | 9 ++++++++- nodes/HttpBin/HttpVerbDescriptions.ts | 19 +++++++++++++++---- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/nodes/HttpBin/HttpBin.node.json b/nodes/HttpBin/HttpBin.node.json index 1b0235c..cc9eb82 100644 --- a/nodes/HttpBin/HttpBin.node.json +++ b/nodes/HttpBin/HttpBin.node.json @@ -4,7 +4,6 @@ "codexVersion": "1.0", "categories": [ "Development", - "HTTP Request & Response Service", "Developer Tools" ], "resources": { diff --git a/nodes/HttpBin/HttpBin.node.ts b/nodes/HttpBin/HttpBin.node.ts index 2bb9502..7737f7c 100644 --- a/nodes/HttpBin/HttpBin.node.ts +++ b/nodes/HttpBin/HttpBin.node.ts @@ -33,7 +33,13 @@ export class HttpBin implements INodeType { /** * In the properties array we have two mandatory options objects required * - * Resource & Operation + * [Resource & Operation] + * + * + * https://docs.n8n.io/integrations/creating-nodes/code/create-first-node/#resources-and-operations + * + * In our example, the operations are separated into their own file (HTTPVerbDescription) + * to keep this class easy to read * */ properties: [ @@ -54,6 +60,7 @@ export class HttpBin implements INodeType { ], default: "httpverbs", }, + ...httpVerbOperations, ...httpVerbFields, ], diff --git a/nodes/HttpBin/HttpVerbDescriptions.ts b/nodes/HttpBin/HttpVerbDescriptions.ts index 4a47ed7..9609101 100644 --- a/nodes/HttpBin/HttpVerbDescriptions.ts +++ b/nodes/HttpBin/HttpVerbDescriptions.ts @@ -1,7 +1,7 @@ import { INodeProperties } from "n8n-workflow"; /** - * This maps the operations to when the resource HTTP Verbs is selected + * This maps the operations to when the Resource option HTTP Verbs is selected */ export const httpVerbOperations: Array = [ { @@ -40,12 +40,17 @@ export const httpVerbOperations: Array = [ }, ]; +/** + * + * Here we define what to show when the GET Operation is selected + * + * We do that by adding operation: ["get"], to "displayOptions.show" + */ const getOperation: Array = [ { name: "typeofData", default: "queryParameterOption", - description: - "Select type of data to send [Query Parameter Arguments, JSON-Body]", + description: "Select type of data to send [Query Parameters]", displayName: "Type of Data", displayOptions: { show: { @@ -110,12 +115,18 @@ const getOperation: Array = [ }, ]; +/** + * + * Here we define what to show when the DELETE Operation is selected + * + * We do that by adding operation: ["delete"], to "displayOptions.show" + */ const deleteOperation: Array = [ { name: "typeofData", default: "queryParameterOption", description: - "Select type of data to send [Query Parameter Arguments, Form-Data, Body, JSON]", + "Select type of data to send [Query Parameter Arguments, JSON-Body]", displayName: "Type of Data", displayOptions: { show: { From cdeb92e57e6d7ee39271925b5d1c01cbfc589460 Mon Sep 17 00:00:00 2001 From: brianinoa Date: Mon, 20 Jun 2022 08:18:15 +0200 Subject: [PATCH 14/20] :see_no_evil: Add launch.json to gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ffb419d..a80c4ec 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ tmp dist npm-debug.log* package-lock.json -yarn.lock \ No newline at end of file +yarn.lock +.vscode/launch.json From b61ff785f0eb34b45ee4aba2466316eac5728f42 Mon Sep 17 00:00:00 2001 From: Brian Inoa Date: Mon, 20 Jun 2022 14:21:52 +0200 Subject: [PATCH 15/20] :zap: Fix incorrect defaults :zap: Remove Auth resource --- nodes/HttpBin/HttpBin.node.ts | 6 +----- nodes/HttpBin/HttpVerbDescriptions.ts | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/nodes/HttpBin/HttpBin.node.ts b/nodes/HttpBin/HttpBin.node.ts index 7737f7c..3f6fa51 100644 --- a/nodes/HttpBin/HttpBin.node.ts +++ b/nodes/HttpBin/HttpBin.node.ts @@ -52,11 +52,7 @@ export class HttpBin implements INodeType { { name: "HTTP Verbs", value: "httpverbs", - }, - { - name: "Auth Methods", - value: "authmethods", - }, + } ], default: "httpverbs", }, diff --git a/nodes/HttpBin/HttpVerbDescriptions.ts b/nodes/HttpBin/HttpVerbDescriptions.ts index 9609101..03f2df9 100644 --- a/nodes/HttpBin/HttpVerbDescriptions.ts +++ b/nodes/HttpBin/HttpVerbDescriptions.ts @@ -49,7 +49,7 @@ export const httpVerbOperations: Array = [ const getOperation: Array = [ { name: "typeofData", - default: "queryParameterOption", + default: "queryParameter", description: "Select type of data to send [Query Parameters]", displayName: "Type of Data", displayOptions: { @@ -124,7 +124,7 @@ const getOperation: Array = [ const deleteOperation: Array = [ { name: "typeofData", - default: "queryParameterOption", + default: "queryParameter", description: "Select type of data to send [Query Parameter Arguments, JSON-Body]", displayName: "Type of Data", From ff96b5988fecfde2c697f4aabaaa12e95c43777f Mon Sep 17 00:00:00 2001 From: brianinoa Date: Mon, 20 Jun 2022 15:17:10 +0200 Subject: [PATCH 16/20] :heavy_plus_sign: Add eslint-plugin-n8n dependency --- package.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2f9feb8..31d337b 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "lintfix": "tslint --fix -p tsconfig.json -c tslint.json", "nodelinter": "nodelinter", "watch": "tsc --watch", - "test": "jest" + "test": "jest", + "lintfix-plugin": "cd ../.. && node_modules/eslint/bin/eslint.js packages/nodes-base/nodes --fix" }, "files": [ "dist" @@ -49,7 +50,8 @@ "nodelinter": "^0.1.9", "ts-jest": "^26.3.0", "tslint": "^6.1.2", - "typescript": "~4.3.5" + "typescript": "~4.3.5", + "eslint-plugin-n8n-nodes-base": "^1.0.43" }, "dependencies": { "n8n-core": "~0.122.1" From b15212d300105a13ab0cda45c9c292a7ecf9d5e5 Mon Sep 17 00:00:00 2001 From: brianinoa Date: Mon, 20 Jun 2022 15:17:28 +0200 Subject: [PATCH 17/20] :rotating_light: Add linting rules --- .eslintignore | 2 + .eslintrc.js | 429 ++++++++++++++++++++++++++++++++++++++++++++++++++ tslint.json | 33 ++-- 3 files changed, 451 insertions(+), 13 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc.js diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..2bbcd4d --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +packages/editor-ui +packages/design-system diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..6a008e0 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,429 @@ +module.exports = { + root: true, + + env: { + browser: true, + es6: true, + node: true, + }, + + parser: '@typescript-eslint/parser', + parserOptions: { + project: ['./packages/*/tsconfig.json'], + sourceType: 'module', + }, + ignorePatterns: [ + '.eslintrc.js', + '**/*.js', + '**/node_modules/**', + '**/dist/**', + '**/test/**', + '**/templates/**', + '**/ormconfig.ts', + '**/migrations/**', + ], + + overrides: [ + { + files: './packages/*(cli|core|workflow|node-dev)/**/*.ts', + plugins: [ + /** + * Plugin with lint rules for import/export syntax + * https://github.com/import-js/eslint-plugin-import + */ + 'eslint-plugin-import', + + /** + * @typescript-eslint/eslint-plugin is required by eslint-config-airbnb-typescript + * See step 2: https://github.com/iamturns/eslint-config-airbnb-typescript#2-install-eslint-plugins + */ + '@typescript-eslint', + + /** + * Plugin to report formatting violations as lint violations + * https://github.com/prettier/eslint-plugin-prettier + */ + 'eslint-plugin-prettier', + ], + extends: [ + /** + * Config for typescript-eslint recommended ruleset (without type checking) + * + * https://github.com/typescript-eslint/typescript-eslint/blob/1c1b572c3000d72cfe665b7afbada0ec415e7855/packages/eslint-plugin/src/configs/recommended.ts + */ + 'plugin:@typescript-eslint/recommended', + + /** + * Config for typescript-eslint recommended ruleset (with type checking) + * + * https://github.com/typescript-eslint/typescript-eslint/blob/1c1b572c3000d72cfe665b7afbada0ec415e7855/packages/eslint-plugin/src/configs/recommended-requiring-type-checking.ts + */ + 'plugin:@typescript-eslint/recommended-requiring-type-checking', + + /** + * Config for Airbnb style guide for TS, /base to remove React rules + * + * https://github.com/iamturns/eslint-config-airbnb-typescript + * https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb-base/rules + */ + 'eslint-config-airbnb-typescript/base', + + /** + * Config to disable ESLint rules covered by Prettier + * + * https://github.com/prettier/eslint-config-prettier + */ + 'eslint-config-prettier', + ], + rules: { + // ****************************************************************** + // required by prettier plugin + // ****************************************************************** + + // The following rule enables eslint-plugin-prettier + // See: https://github.com/prettier/eslint-plugin-prettier#recommended-configuration + + 'prettier/prettier': 'error', + + // The following two rules must be disabled when using eslint-plugin-prettier: + // See: https://github.com/prettier/eslint-plugin-prettier#arrow-body-style-and-prefer-arrow-callback-issue + + /** + * https://eslint.org/docs/rules/arrow-body-style + */ + 'arrow-body-style': 'off', + + /** + * https://eslint.org/docs/rules/prefer-arrow-callback + */ + 'prefer-arrow-callback': 'off', + + // ****************************************************************** + // additions to base ruleset + // ****************************************************************** + + // ---------------------------------- + // ESLint + // ---------------------------------- + + /** + * https://eslint.org/docs/rules/id-denylist + */ + 'id-denylist': [ + 'error', + 'err', + 'cb', + 'callback', + 'any', + 'Number', + 'number', + 'String', + 'string', + 'Boolean', + 'boolean', + 'Undefined', + 'undefined', + ], + + 'no-void': ['error', { allowAsStatement: true }], + + // ---------------------------------- + // @typescript-eslint + // ---------------------------------- + + /** + * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/array-type.md + */ + '@typescript-eslint/array-type': ['error', { default: 'array-simple' }], + + /** + * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/ban-ts-comment.md + */ + '@typescript-eslint/ban-ts-comment': 'off', + + /** + * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/ban-types.md + */ + '@typescript-eslint/ban-types': [ + 'error', + { + types: { + Object: { + message: 'Use object instead', + fixWith: 'object', + }, + String: { + message: 'Use string instead', + fixWith: 'string', + }, + Boolean: { + message: 'Use boolean instead', + fixWith: 'boolean', + }, + Number: { + message: 'Use number instead', + fixWith: 'number', + }, + Symbol: { + message: 'Use symbol instead', + fixWith: 'symbol', + }, + Function: { + message: [ + 'The `Function` type accepts any function-like value.', + 'It provides no type safety when calling the function, which can be a common source of bugs.', + 'It also accepts things like class declarations, which will throw at runtime as they will not be called with `new`.', + 'If you are expecting the function to accept certain arguments, you should explicitly define the function shape.', + ].join('\n'), + }, + }, + extendDefaults: false, + }, + ], + + /** + * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/consistent-type-assertions.md + */ + '@typescript-eslint/consistent-type-assertions': 'error', + + /** + * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/explicit-member-accessibility.md + */ + '@typescript-eslint/explicit-member-accessibility': [ + 'error', + { accessibility: 'no-public' }, + ], + + /** + * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/member-delimiter-style.md + */ + '@typescript-eslint/member-delimiter-style': [ + 'error', + { + multiline: { + delimiter: 'semi', + requireLast: true, + }, + singleline: { + delimiter: 'semi', + requireLast: false, + }, + }, + ], + + /** + * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/naming-convention.md + */ + '@typescript-eslint/naming-convention': [ + 'error', + { + selector: 'default', + format: ['camelCase'], + }, + { + selector: 'variable', + format: ['camelCase', 'snake_case', 'UPPER_CASE'], + leadingUnderscore: 'allowSingleOrDouble', + trailingUnderscore: 'allowSingleOrDouble', + }, + { + selector: 'property', + format: ['camelCase', 'snake_case'], + leadingUnderscore: 'allowSingleOrDouble', + trailingUnderscore: 'allowSingleOrDouble', + }, + { + selector: 'typeLike', + format: ['PascalCase'], + }, + { + selector: ['method', 'function'], + format: ['camelCase'], + leadingUnderscore: 'allowSingleOrDouble', + }, + ], + + /** + * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-duplicate-imports.md + */ + '@typescript-eslint/no-duplicate-imports': 'error', + + /** + * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-invalid-void-type.md + */ + '@typescript-eslint/no-invalid-void-type': 'error', + + /** + * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-misused-promises.md + */ + '@typescript-eslint/no-misused-promises': ['error', { checksVoidReturn: false }], + + /** + * https://github.com/typescript-eslint/typescript-eslint/blob/v4.30.0/packages/eslint-plugin/docs/rules/no-floating-promises.md + */ + '@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: true }], + + /** + * https://github.com/typescript-eslint/typescript-eslint/blob/v4.33.0/packages/eslint-plugin/docs/rules/no-namespace.md + */ + '@typescript-eslint/no-namespace': 'off', + + /** + * https://eslint.org/docs/1.0.0/rules/no-throw-literal + */ + '@typescript-eslint/no-throw-literal': 'error', + + /** + * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unnecessary-boolean-literal-compare.md + */ + '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error', + + /** + * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unnecessary-qualifier.md + */ + '@typescript-eslint/no-unnecessary-qualifier': 'error', + + /** + * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unused-expressions.md + */ + '@typescript-eslint/no-unused-expressions': 'error', + + /** + * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unused-vars.md + */ + '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '_' }], + + /** + * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/prefer-nullish-coalescing.md + */ + '@typescript-eslint/prefer-nullish-coalescing': 'error', + + /** + * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/prefer-optional-chain.md + */ + '@typescript-eslint/prefer-optional-chain': 'error', + + /** + * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/promise-function-async.md + */ + '@typescript-eslint/promise-function-async': 'error', + + // ---------------------------------- + // eslint-plugin-import + // ---------------------------------- + + /** + * https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-default-export.md + */ + 'import/no-default-export': 'error', + + /** + * https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/order.md + */ + 'import/order': 'error', + + // ****************************************************************** + // overrides to base ruleset + // ****************************************************************** + + // ---------------------------------- + // ESLint + // ---------------------------------- + + /** + * https://eslint.org/docs/rules/class-methods-use-this + */ + 'class-methods-use-this': 'off', + + /** + * https://eslint.org/docs/rules/eqeqeq + */ + eqeqeq: 'error', + + /** + * https://eslint.org/docs/rules/no-plusplus + */ + 'no-plusplus': 'off', + + /** + * https://eslint.org/docs/rules/object-shorthand + */ + 'object-shorthand': 'error', + + /** + * https://eslint.org/docs/rules/prefer-const + */ + 'prefer-const': 'error', + + /** + * https://eslint.org/docs/rules/prefer-spread + */ + 'prefer-spread': 'error', + + // ---------------------------------- + // import + // ---------------------------------- + + /** + * https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/prefer-default-export.md + */ + 'import/prefer-default-export': 'off', + }, + }, + { + files: ['./packages/nodes-base/nodes/**/*.ts'], + plugins: ['eslint-plugin-n8n-nodes-base'], + rules: { + 'n8n-nodes-base/node-class-description-inputs-wrong-regular-node': 'error', + 'n8n-nodes-base/node-class-description-inputs-wrong-trigger-node': 'error', + 'n8n-nodes-base/node-class-description-missing-subtitle': 'error', + 'n8n-nodes-base/node-class-description-outputs-wrong': 'error', + 'n8n-nodes-base/node-execute-block-double-assertion-for-items': 'error', + 'n8n-nodes-base/node-param-collection-type-unsorted-items': 'error', + 'n8n-nodes-base/node-param-default-missing': 'error', + 'n8n-nodes-base/node-param-default-wrong-for-boolean': 'error', + 'n8n-nodes-base/node-param-default-wrong-for-collection': 'error', + 'n8n-nodes-base/node-param-default-wrong-for-fixed-collection': 'error', + 'n8n-nodes-base/node-param-default-wrong-for-multi-options': 'error', + 'n8n-nodes-base/node-param-default-wrong-for-simplify': 'error', + 'n8n-nodes-base/node-param-description-comma-separated-hyphen': 'error', + 'n8n-nodes-base/node-param-description-empty-string': 'error', + 'n8n-nodes-base/node-param-description-excess-final-period': 'error', + 'n8n-nodes-base/node-param-description-excess-inner-whitespace': 'error', + 'n8n-nodes-base/node-param-description-identical-to-display-name': 'error', + 'n8n-nodes-base/node-param-description-miscased-id': 'error', + 'n8n-nodes-base/node-param-description-miscased-json': 'error', + 'n8n-nodes-base/node-param-description-missing-final-period': 'error', + 'n8n-nodes-base/node-param-description-missing-for-ignore-ssl-issues': 'error', + 'n8n-nodes-base/node-param-description-missing-for-return-all': 'error', + 'n8n-nodes-base/node-param-description-missing-for-simplify': 'error', + 'n8n-nodes-base/node-param-description-missing-from-limit': 'error', + 'n8n-nodes-base/node-param-description-unencoded-angle-brackets': 'error', + 'n8n-nodes-base/node-param-description-unneeded-backticks': 'error', + 'n8n-nodes-base/node-param-description-untrimmed': 'error', + 'n8n-nodes-base/node-param-description-url-missing-protocol': 'error', + 'n8n-nodes-base/node-param-description-weak': 'error', + 'n8n-nodes-base/node-param-description-wrong-for-ignore-ssl-issues': 'error', + 'n8n-nodes-base/node-param-description-wrong-for-limit': 'error', + 'n8n-nodes-base/node-param-description-wrong-for-return-all': 'error', + 'n8n-nodes-base/node-param-description-wrong-for-simplify': 'error', + 'n8n-nodes-base/node-param-description-wrong-for-upsert': 'error', + 'n8n-nodes-base/node-param-display-name-excess-inner-whitespace': 'error', + 'n8n-nodes-base/node-param-display-name-miscased-id': 'error', + 'n8n-nodes-base/node-param-display-name-untrimmed': 'error', + 'n8n-nodes-base/node-param-display-name-wrong-for-simplify': 'error', + 'n8n-nodes-base/node-param-display-name-wrong-for-update-fields': 'error', + 'n8n-nodes-base/node-param-operation-without-no-data-expression': 'error', + 'n8n-nodes-base/node-param-option-description-identical-to-name': 'error', + 'n8n-nodes-base/node-param-option-name-containing-star': 'error', + 'n8n-nodes-base/node-param-option-name-duplicate': 'error', + 'n8n-nodes-base/node-param-option-name-wrong-for-get-all': 'error', + 'n8n-nodes-base/node-param-option-value-duplicate': 'error', + 'n8n-nodes-base/node-param-required-false': 'error', + 'n8n-nodes-base/node-param-resource-with-plural-option': 'error', + 'n8n-nodes-base/node-param-resource-without-no-data-expression': 'error', + 'n8n-nodes-base/node-param-type-options-missing-from-limit': 'error', + }, + }, + ], +}; diff --git a/tslint.json b/tslint.json index 859893d..d8dc7ad 100644 --- a/tslint.json +++ b/tslint.json @@ -46,7 +46,11 @@ "forin": true, "jsdoc-format": true, "label-position": true, - "indent": [true, "tabs", 2], + "indent": [ + true, + "tabs", + 2 + ], "member-access": [ true, "no-public" @@ -61,10 +65,13 @@ "no-default-export": true, "no-duplicate-variable": true, "no-inferrable-types": true, - "ordered-imports": [true, { - "import-sources-order": "any", - "named-imports-order": "case-insensitive" - }], + "ordered-imports": [ + true, + { + "import-sources-order": "any", + "named-imports-order": "case-insensitive" + } + ], "no-namespace": [ true, "allow-declarations" @@ -90,13 +97,13 @@ "trailing-comma": [ true, { - "multiline": { - "objects": "always", - "arrays": "always", - "functions": "always", - "typeLiterals": "ignore" - }, - "esSpecCompliant": true + "multiline": { + "objects": "always", + "arrays": "always", + "functions": "always", + "typeLiterals": "ignore" + }, + "esSpecCompliant": true } ], "triple-equals": [ @@ -121,4 +128,4 @@ ] }, "rulesDirectory": [] -} \ No newline at end of file +} From b2b5a971885ab663823043ab127575f84d6a78f4 Mon Sep 17 00:00:00 2001 From: brianinoa Date: Mon, 20 Jun 2022 15:22:10 +0200 Subject: [PATCH 18/20] :rotating_light: Autofix node linting --- credentials/HttpBinApi.credentials.ts | 30 ++-- nodes/HttpBin/HttpBin.node.ts | 46 +++--- nodes/HttpBin/HttpVerbDescriptions.ts | 220 ++++++++++++-------------- 3 files changed, 143 insertions(+), 153 deletions(-) diff --git a/credentials/HttpBinApi.credentials.ts b/credentials/HttpBinApi.credentials.ts index efd8639..8ccd44f 100644 --- a/credentials/HttpBinApi.credentials.ts +++ b/credentials/HttpBinApi.credentials.ts @@ -4,18 +4,18 @@ import { ICredentialType, IHttpRequestOptions, INodeProperties, -} from "n8n-workflow"; +} from 'n8n-workflow'; export class HttpBinApi implements ICredentialType { - name = "httpbinApi"; - displayName = "HttpBin API"; - documentationUrl = "httpbin"; + name = 'httpbinApi'; + displayName = 'HttpBin API'; + documentationUrl = 'httpbin'; properties: INodeProperties[] = [ { - displayName: "Token", - name: "token", - type: "string", - default: "", + displayName: 'Token', + name: 'token', + type: 'string', + default: '', }, // { // displayName: "API Key", @@ -24,10 +24,10 @@ export class HttpBinApi implements ICredentialType { // default: "", // }, { - displayName: "Domain", - name: "domain", - type: "string", - default: "https://httpbin.org", + displayName: 'Domain', + name: 'domain', + type: 'string', + default: 'https://httpbin.org', }, ]; @@ -41,7 +41,7 @@ export class HttpBinApi implements ICredentialType { authenticate = async ( credentials: ICredentialDataDecryptedObject, - requestOptions: IHttpRequestOptions + requestOptions: IHttpRequestOptions, ): Promise => { const headers = requestOptions.headers || {}; const authentication = { Authorization: `Bearer ${credentials.token}` }; @@ -53,8 +53,8 @@ export class HttpBinApi implements ICredentialType { test: ICredentialTestRequest = { request: { - baseURL: "={{$credentials?.domain}}", - url: "/bearer", + baseURL: '={{$credentials?.domain}}', + url: '/bearer', }, }; } diff --git a/nodes/HttpBin/HttpBin.node.ts b/nodes/HttpBin/HttpBin.node.ts index 3f6fa51..b4454d4 100644 --- a/nodes/HttpBin/HttpBin.node.ts +++ b/nodes/HttpBin/HttpBin.node.ts @@ -1,33 +1,33 @@ -import { INodeType, INodeTypeDescription } from "n8n-workflow"; -import { httpVerbOperations, httpVerbFields } from "./HttpVerbDescriptions"; +import { INodeType, INodeTypeDescription } from 'n8n-workflow'; +import { httpVerbFields, httpVerbOperations } from './HttpVerbDescriptions'; export class HttpBin implements INodeType { description: INodeTypeDescription = { - displayName: "HttpBin", - name: "httpbin", - icon: "file:httpbin.svg", - group: ["transform"], + displayName: 'HttpBin', + name: 'httpbin', + icon: 'file:httpbin.svg', + group: ['transform'], version: 1, subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', - description: "Interact with HttpBin API", + description: 'Interact with HttpBin API', defaults: { - name: "HttpBin", - color: "#3b4151", + name: 'HttpBin', + color: '#3b4151', }, - inputs: ["main"], - outputs: ["main"], + inputs: ['main'], + outputs: ['main'], credentials: [ { - name: "httpbinApi", + name: 'httpbinApi', required: false, }, ], requestDefaults: { - baseURL: "https://httpbin.org", - url: "", + baseURL: 'https://httpbin.org', + url: '', headers: { - Accept: "application/json", - "Content-Type": "application/json", + Accept: 'application/json', + 'Content-Type': 'application/json', }, }, /** @@ -44,17 +44,17 @@ export class HttpBin implements INodeType { */ properties: [ { - displayName: "Resource", - name: "resource", - type: "options", + displayName: 'Resource', + name: 'resource', + type: 'options', noDataExpression: true, options: [ { - name: "HTTP Verbs", - value: "httpverbs", - } + name: 'HTTP Verbs', + value: 'httpverbs', + }, ], - default: "httpverbs", + default: 'httpverbs', }, ...httpVerbOperations, diff --git a/nodes/HttpBin/HttpVerbDescriptions.ts b/nodes/HttpBin/HttpVerbDescriptions.ts index 03f2df9..df0b8ac 100644 --- a/nodes/HttpBin/HttpVerbDescriptions.ts +++ b/nodes/HttpBin/HttpVerbDescriptions.ts @@ -1,249 +1,239 @@ -import { INodeProperties } from "n8n-workflow"; +import { INodeProperties } from 'n8n-workflow'; -/** - * This maps the operations to when the Resource option HTTP Verbs is selected - */ -export const httpVerbOperations: Array = [ +// This maps the operations to when the Resource option HTTP Verbs is selected +export const httpVerbOperations: INodeProperties[] = [ { - displayName: "Operation", - name: "operation", - type: "options", + displayName: 'Operation', + name: 'operation', + type: 'options', noDataExpression: true, displayOptions: { show: { - resource: ["httpverbs"], + resource: ['httpverbs'], }, }, options: [ { - name: "GET", - value: "get", + name: 'GET', + value: 'get', routing: { request: { - method: "GET", - url: "/get", + method: 'GET', + url: '/get', }, }, }, { - name: "DELETE", - value: "delete", + name: 'DELETE', + value: 'delete', routing: { request: { - method: "DELETE", - url: "/delete", + method: 'DELETE', + url: '/delete', }, }, }, ], - default: "get", + default: 'get', }, ]; -/** - * - * Here we define what to show when the GET Operation is selected - * - * We do that by adding operation: ["get"], to "displayOptions.show" - */ -const getOperation: Array = [ +// Here we define what to show when the GET Operation is selected +// We do that by adding operation: ["get"], to "displayOptions.show" +const getOperation: INodeProperties[] = [ { - name: "typeofData", - default: "queryParameter", - description: "Select type of data to send [Query Parameters]", - displayName: "Type of Data", + name: 'typeofData', + default: 'queryParameter', + description: 'Select type of data to send [Query Parameters]', + displayName: 'Type of Data', displayOptions: { show: { - resource: ["httpverbs"], - operation: ["get"], + resource: ['httpverbs'], + operation: ['get'], }, }, - type: "options", + type: 'options', options: [ { - name: "Query", - value: "queryParameter", + name: 'Query', + value: 'queryParameter', }, ], required: true, }, { - name: "arguments", + name: 'arguments', default: {}, - description: "The request's query parameters", - displayName: "Query Parameters", + description: 'The request\'s query parameters', + displayName: 'Query Parameters', displayOptions: { show: { - resource: ["httpverbs"], - operation: ["get"], + resource: ['httpverbs'], + operation: ['get'], }, }, options: [ { - name: "keyvalue", - displayName: "Key:Value", + name: 'keyvalue', + displayName: 'Key:Value', values: [ { - displayName: "Key", - name: "key", - type: "string", - default: "", + displayName: 'Key', + name: 'key', + type: 'string', + default: '', required: true, - description: "Key of query parameter", + description: 'Key of query parameter', }, { - displayName: "Value", - name: "value", - type: "string", - default: "", + displayName: 'Value', + name: 'value', + type: 'string', + default: '', routing: { send: { - property: "={{$parent.key}}", - type: "query", + property: '={{$parent.key}}', + type: 'query', }, }, required: true, - description: "Value of query parameter", + description: 'Value of query parameter', }, ], }, ], - type: "fixedCollection", + type: 'fixedCollection', typeOptions: { multipleValues: true, }, }, ]; -/** - * - * Here we define what to show when the DELETE Operation is selected - * - * We do that by adding operation: ["delete"], to "displayOptions.show" - */ -const deleteOperation: Array = [ +// Here we define what to show when the DELETE Operation is selected +// We do that by adding operation: ["delete"], to "displayOptions.show" +const deleteOperation: INodeProperties[] = [ { - name: "typeofData", - default: "queryParameter", + name: 'typeofData', + default: 'queryParameter', description: - "Select type of data to send [Query Parameter Arguments, JSON-Body]", - displayName: "Type of Data", + 'Select type of data to send [Query Parameter Arguments, JSON-Body]', + displayName: 'Type of Data', displayOptions: { show: { - resource: ["httpverbs"], - operation: ["delete"], + resource: ['httpverbs'], + operation: ['delete'], }, }, options: [ { - name: "Query", - value: "queryParameter", + name: 'Query', + value: 'queryParameter', }, { - name: "JSON", - value: "jsonData", + name: 'JSON', + value: 'jsonData', }, ], required: true, - type: "options", + type: 'options', }, { - name: "arguments", + name: 'arguments', default: {}, - description: "The request's query parameters", - displayName: "Query Parameters", + description: 'The request\'s query parameters', + displayName: 'Query Parameters', displayOptions: { show: { - resource: ["httpverbs"], - operation: ["delete"], - typeofData: ["queryParameter"], + resource: ['httpverbs'], + operation: ['delete'], + typeofData: ['queryParameter'], }, }, options: [ { - name: "keyvalue", - displayName: "Key:Value", + name: 'keyvalue', + displayName: 'Key:Value', values: [ { - displayName: "Key", - name: "key", - type: "string", - default: "", + displayName: 'Key', + name: 'key', + type: 'string', + default: '', required: true, - description: "Key of query parameter", + description: 'Key of query parameter', }, { - displayName: "Value", - name: "value", - type: "string", - default: "", + displayName: 'Value', + name: 'value', + type: 'string', + default: '', routing: { send: { - property: "={{$parent.key}}", - type: "query", + property: '={{$parent.key}}', + type: 'query', }, }, required: true, - description: "Value of query parameter", + description: 'Value of query parameter', }, ], }, ], - type: "fixedCollection", + type: 'fixedCollection', typeOptions: { multipleValues: true, }, }, { - name: "arguments", + name: 'arguments', default: {}, - description: "The request's JSON properties", - displayName: "JSON Object", + description: 'The request\'s JSON properties', + displayName: 'JSON Object', displayOptions: { show: { - resource: ["httpverbs"], - operation: ["delete"], - typeofData: ["jsonData"], + resource: ['httpverbs'], + operation: ['delete'], + typeofData: ['jsonData'], }, }, options: [ { - name: "keyvalue", - displayName: "Key:Value", + name: 'keyvalue', + displayName: 'Key:Value', values: [ { - displayName: "Key", - name: "key", - type: "string", - default: "", + displayName: 'Key', + name: 'key', + type: 'string', + default: '', required: true, - description: "Key of json property", + description: 'Key of json property', }, { - displayName: "Value", - name: "value", - type: "string", - default: "", + displayName: 'Value', + name: 'value', + type: 'string', + default: '', routing: { send: { - property: "={{$parent.key}}", - type: "body", + property: '={{$parent.key}}', + type: 'body', }, }, required: true, - description: "Value of json property", + description: 'Value of json property', }, ], }, ], - type: "fixedCollection", + type: 'fixedCollection', typeOptions: { multipleValues: true, }, }, ]; -export const httpVerbFields: Array = [ +export const httpVerbFields: INodeProperties[] = [ /* -------------------------------------------------------------------------- */ /* Http Verbs:Get */ /* -------------------------------------------------------------------------- */ From 583e5302bc8c1e500c9cd4e1bdd663b2207e77e2 Mon Sep 17 00:00:00 2001 From: Omar Ajoue Date: Tue, 21 Jun 2022 11:23:10 +0200 Subject: [PATCH 19/20] Added necessary plugins and fixed configs for linting --- .eslintrc.js | 375 ++------------------------ nodes/HttpBin/HttpBin.node.ts | 3 +- nodes/HttpBin/HttpVerbDescriptions.ts | 4 +- package.json | 14 +- tsconfig.json | 2 +- 5 files changed, 37 insertions(+), 361 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 6a008e0..a4fe925 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -9,7 +9,7 @@ module.exports = { parser: '@typescript-eslint/parser', parserOptions: { - project: ['./packages/*/tsconfig.json'], + project: ['./tsconfig.json'], sourceType: 'module', }, ignorePatterns: [ @@ -25,356 +25,13 @@ module.exports = { overrides: [ { - files: './packages/*(cli|core|workflow|node-dev)/**/*.ts', - plugins: [ - /** - * Plugin with lint rules for import/export syntax - * https://github.com/import-js/eslint-plugin-import - */ - 'eslint-plugin-import', - - /** - * @typescript-eslint/eslint-plugin is required by eslint-config-airbnb-typescript - * See step 2: https://github.com/iamturns/eslint-config-airbnb-typescript#2-install-eslint-plugins - */ - '@typescript-eslint', - - /** - * Plugin to report formatting violations as lint violations - * https://github.com/prettier/eslint-plugin-prettier - */ - 'eslint-plugin-prettier', - ], - extends: [ - /** - * Config for typescript-eslint recommended ruleset (without type checking) - * - * https://github.com/typescript-eslint/typescript-eslint/blob/1c1b572c3000d72cfe665b7afbada0ec415e7855/packages/eslint-plugin/src/configs/recommended.ts - */ - 'plugin:@typescript-eslint/recommended', - - /** - * Config for typescript-eslint recommended ruleset (with type checking) - * - * https://github.com/typescript-eslint/typescript-eslint/blob/1c1b572c3000d72cfe665b7afbada0ec415e7855/packages/eslint-plugin/src/configs/recommended-requiring-type-checking.ts - */ - 'plugin:@typescript-eslint/recommended-requiring-type-checking', - - /** - * Config for Airbnb style guide for TS, /base to remove React rules - * - * https://github.com/iamturns/eslint-config-airbnb-typescript - * https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb-base/rules - */ - 'eslint-config-airbnb-typescript/base', - - /** - * Config to disable ESLint rules covered by Prettier - * - * https://github.com/prettier/eslint-config-prettier - */ - 'eslint-config-prettier', - ], - rules: { - // ****************************************************************** - // required by prettier plugin - // ****************************************************************** - - // The following rule enables eslint-plugin-prettier - // See: https://github.com/prettier/eslint-plugin-prettier#recommended-configuration - - 'prettier/prettier': 'error', - - // The following two rules must be disabled when using eslint-plugin-prettier: - // See: https://github.com/prettier/eslint-plugin-prettier#arrow-body-style-and-prefer-arrow-callback-issue - - /** - * https://eslint.org/docs/rules/arrow-body-style - */ - 'arrow-body-style': 'off', - - /** - * https://eslint.org/docs/rules/prefer-arrow-callback - */ - 'prefer-arrow-callback': 'off', - - // ****************************************************************** - // additions to base ruleset - // ****************************************************************** - - // ---------------------------------- - // ESLint - // ---------------------------------- - - /** - * https://eslint.org/docs/rules/id-denylist - */ - 'id-denylist': [ - 'error', - 'err', - 'cb', - 'callback', - 'any', - 'Number', - 'number', - 'String', - 'string', - 'Boolean', - 'boolean', - 'Undefined', - 'undefined', - ], - - 'no-void': ['error', { allowAsStatement: true }], - - // ---------------------------------- - // @typescript-eslint - // ---------------------------------- - - /** - * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/array-type.md - */ - '@typescript-eslint/array-type': ['error', { default: 'array-simple' }], - - /** - * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/ban-ts-comment.md - */ - '@typescript-eslint/ban-ts-comment': 'off', - - /** - * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/ban-types.md - */ - '@typescript-eslint/ban-types': [ - 'error', - { - types: { - Object: { - message: 'Use object instead', - fixWith: 'object', - }, - String: { - message: 'Use string instead', - fixWith: 'string', - }, - Boolean: { - message: 'Use boolean instead', - fixWith: 'boolean', - }, - Number: { - message: 'Use number instead', - fixWith: 'number', - }, - Symbol: { - message: 'Use symbol instead', - fixWith: 'symbol', - }, - Function: { - message: [ - 'The `Function` type accepts any function-like value.', - 'It provides no type safety when calling the function, which can be a common source of bugs.', - 'It also accepts things like class declarations, which will throw at runtime as they will not be called with `new`.', - 'If you are expecting the function to accept certain arguments, you should explicitly define the function shape.', - ].join('\n'), - }, - }, - extendDefaults: false, - }, - ], - - /** - * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/consistent-type-assertions.md - */ - '@typescript-eslint/consistent-type-assertions': 'error', - - /** - * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/explicit-member-accessibility.md - */ - '@typescript-eslint/explicit-member-accessibility': [ - 'error', - { accessibility: 'no-public' }, - ], - - /** - * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/member-delimiter-style.md - */ - '@typescript-eslint/member-delimiter-style': [ - 'error', - { - multiline: { - delimiter: 'semi', - requireLast: true, - }, - singleline: { - delimiter: 'semi', - requireLast: false, - }, - }, - ], - - /** - * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/naming-convention.md - */ - '@typescript-eslint/naming-convention': [ - 'error', - { - selector: 'default', - format: ['camelCase'], - }, - { - selector: 'variable', - format: ['camelCase', 'snake_case', 'UPPER_CASE'], - leadingUnderscore: 'allowSingleOrDouble', - trailingUnderscore: 'allowSingleOrDouble', - }, - { - selector: 'property', - format: ['camelCase', 'snake_case'], - leadingUnderscore: 'allowSingleOrDouble', - trailingUnderscore: 'allowSingleOrDouble', - }, - { - selector: 'typeLike', - format: ['PascalCase'], - }, - { - selector: ['method', 'function'], - format: ['camelCase'], - leadingUnderscore: 'allowSingleOrDouble', - }, - ], - - /** - * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-duplicate-imports.md - */ - '@typescript-eslint/no-duplicate-imports': 'error', - - /** - * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-invalid-void-type.md - */ - '@typescript-eslint/no-invalid-void-type': 'error', - - /** - * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-misused-promises.md - */ - '@typescript-eslint/no-misused-promises': ['error', { checksVoidReturn: false }], - - /** - * https://github.com/typescript-eslint/typescript-eslint/blob/v4.30.0/packages/eslint-plugin/docs/rules/no-floating-promises.md - */ - '@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: true }], - - /** - * https://github.com/typescript-eslint/typescript-eslint/blob/v4.33.0/packages/eslint-plugin/docs/rules/no-namespace.md - */ - '@typescript-eslint/no-namespace': 'off', - - /** - * https://eslint.org/docs/1.0.0/rules/no-throw-literal - */ - '@typescript-eslint/no-throw-literal': 'error', - - /** - * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unnecessary-boolean-literal-compare.md - */ - '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error', - - /** - * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unnecessary-qualifier.md - */ - '@typescript-eslint/no-unnecessary-qualifier': 'error', - - /** - * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unused-expressions.md - */ - '@typescript-eslint/no-unused-expressions': 'error', - - /** - * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unused-vars.md - */ - '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '_' }], - - /** - * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/prefer-nullish-coalescing.md - */ - '@typescript-eslint/prefer-nullish-coalescing': 'error', - - /** - * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/prefer-optional-chain.md - */ - '@typescript-eslint/prefer-optional-chain': 'error', - - /** - * https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/promise-function-async.md - */ - '@typescript-eslint/promise-function-async': 'error', - - // ---------------------------------- - // eslint-plugin-import - // ---------------------------------- - - /** - * https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-default-export.md - */ - 'import/no-default-export': 'error', - - /** - * https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/order.md - */ - 'import/order': 'error', - - // ****************************************************************** - // overrides to base ruleset - // ****************************************************************** - - // ---------------------------------- - // ESLint - // ---------------------------------- - - /** - * https://eslint.org/docs/rules/class-methods-use-this - */ - 'class-methods-use-this': 'off', - - /** - * https://eslint.org/docs/rules/eqeqeq - */ - eqeqeq: 'error', - - /** - * https://eslint.org/docs/rules/no-plusplus - */ - 'no-plusplus': 'off', - - /** - * https://eslint.org/docs/rules/object-shorthand - */ - 'object-shorthand': 'error', - - /** - * https://eslint.org/docs/rules/prefer-const - */ - 'prefer-const': 'error', - - /** - * https://eslint.org/docs/rules/prefer-spread - */ - 'prefer-spread': 'error', - - // ---------------------------------- - // import - // ---------------------------------- - - /** - * https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/prefer-default-export.md - */ - 'import/prefer-default-export': 'off', - }, - }, - { - files: ['./packages/nodes-base/nodes/**/*.ts'], + files: [ './**/*.ts' ], plugins: ['eslint-plugin-n8n-nodes-base'], rules: { - 'n8n-nodes-base/node-class-description-inputs-wrong-regular-node': 'error', + 'n8n-nodes-base/filesystem-wrong-cred-filename': 'error', + 'n8n-nodes-base/filesystem-wrong-node-filename': 'error', + 'n8n-nodes-base/node-class-description-empty-string': 'error', + 'n8n-nodes-base/node-class-description-icon-not-svg': 'error', 'n8n-nodes-base/node-class-description-inputs-wrong-trigger-node': 'error', 'n8n-nodes-base/node-class-description-missing-subtitle': 'error', 'n8n-nodes-base/node-class-description-outputs-wrong': 'error', @@ -384,45 +41,65 @@ module.exports = { 'n8n-nodes-base/node-param-default-wrong-for-boolean': 'error', 'n8n-nodes-base/node-param-default-wrong-for-collection': 'error', 'n8n-nodes-base/node-param-default-wrong-for-fixed-collection': 'error', + 'n8n-nodes-base/node-param-default-wrong-for-fixed-collection': 'error', 'n8n-nodes-base/node-param-default-wrong-for-multi-options': 'error', + 'n8n-nodes-base/node-param-default-wrong-for-number': 'error', 'n8n-nodes-base/node-param-default-wrong-for-simplify': 'error', + 'n8n-nodes-base/node-param-default-wrong-for-string': 'error', + 'n8n-nodes-base/node-param-description-boolean-without-whether': 'error', 'n8n-nodes-base/node-param-description-comma-separated-hyphen': 'error', 'n8n-nodes-base/node-param-description-empty-string': 'error', 'n8n-nodes-base/node-param-description-excess-final-period': 'error', 'n8n-nodes-base/node-param-description-excess-inner-whitespace': 'error', 'n8n-nodes-base/node-param-description-identical-to-display-name': 'error', + 'n8n-nodes-base/node-param-description-line-break-html-tag': 'error', + 'n8n-nodes-base/node-param-description-lowercase-first-char': 'error', 'n8n-nodes-base/node-param-description-miscased-id': 'error', 'n8n-nodes-base/node-param-description-miscased-json': 'error', + 'n8n-nodes-base/node-param-description-miscased-url': 'error', 'n8n-nodes-base/node-param-description-missing-final-period': 'error', 'n8n-nodes-base/node-param-description-missing-for-ignore-ssl-issues': 'error', 'n8n-nodes-base/node-param-description-missing-for-return-all': 'error', 'n8n-nodes-base/node-param-description-missing-for-simplify': 'error', + 'n8n-nodes-base/node-param-description-missing-from-dynamic-options': 'error', 'n8n-nodes-base/node-param-description-missing-from-limit': 'error', 'n8n-nodes-base/node-param-description-unencoded-angle-brackets': 'error', 'n8n-nodes-base/node-param-description-unneeded-backticks': 'error', 'n8n-nodes-base/node-param-description-untrimmed': 'error', 'n8n-nodes-base/node-param-description-url-missing-protocol': 'error', 'n8n-nodes-base/node-param-description-weak': 'error', + 'n8n-nodes-base/node-param-description-wrong-for-dynamic-multi-options': 'error', + 'n8n-nodes-base/node-param-description-wrong-for-dynamic-options': 'error', 'n8n-nodes-base/node-param-description-wrong-for-ignore-ssl-issues': 'error', 'n8n-nodes-base/node-param-description-wrong-for-limit': 'error', 'n8n-nodes-base/node-param-description-wrong-for-return-all': 'error', 'n8n-nodes-base/node-param-description-wrong-for-simplify': 'error', 'n8n-nodes-base/node-param-description-wrong-for-upsert': 'error', 'n8n-nodes-base/node-param-display-name-excess-inner-whitespace': 'error', + 'n8n-nodes-base/node-param-display-name-miscased': 'error', 'n8n-nodes-base/node-param-display-name-miscased-id': 'error', 'n8n-nodes-base/node-param-display-name-untrimmed': 'error', + 'n8n-nodes-base/node-param-display-name-wrong-for-dynamic-multi-options': 'error', + 'n8n-nodes-base/node-param-display-name-wrong-for-dynamic-options': 'error', 'n8n-nodes-base/node-param-display-name-wrong-for-simplify': 'error', 'n8n-nodes-base/node-param-display-name-wrong-for-update-fields': 'error', + 'n8n-nodes-base/node-param-min-value-wrong-for-limit': 'error', + 'n8n-nodes-base/node-param-multi-options-type-unsorted-items': 'error', 'n8n-nodes-base/node-param-operation-without-no-data-expression': 'error', 'n8n-nodes-base/node-param-option-description-identical-to-name': 'error', 'n8n-nodes-base/node-param-option-name-containing-star': 'error', 'n8n-nodes-base/node-param-option-name-duplicate': 'error', 'n8n-nodes-base/node-param-option-name-wrong-for-get-all': 'error', + 'n8n-nodes-base/node-param-option-name-wrong-for-upsert': 'error', 'n8n-nodes-base/node-param-option-value-duplicate': 'error', + 'n8n-nodes-base/node-param-options-type-unsorted-items': 'error', + 'n8n-nodes-base/node-param-placeholder-miscased-id': 'error', + 'n8n-nodes-base/node-param-placeholder-missing-email': 'error', 'n8n-nodes-base/node-param-required-false': 'error', 'n8n-nodes-base/node-param-resource-with-plural-option': 'error', 'n8n-nodes-base/node-param-resource-without-no-data-expression': 'error', 'n8n-nodes-base/node-param-type-options-missing-from-limit': 'error', + 'n8n-nodes-base/node-class-description-inputs-wrong-regular-node': 'error', }, }, ], diff --git a/nodes/HttpBin/HttpBin.node.ts b/nodes/HttpBin/HttpBin.node.ts index b4454d4..00eaee7 100644 --- a/nodes/HttpBin/HttpBin.node.ts +++ b/nodes/HttpBin/HttpBin.node.ts @@ -1,3 +1,4 @@ +/* eslint-disable n8n-nodes-base/filesystem-wrong-node-filename */ import { INodeType, INodeTypeDescription } from 'n8n-workflow'; import { httpVerbFields, httpVerbOperations } from './HttpVerbDescriptions'; @@ -50,7 +51,7 @@ export class HttpBin implements INodeType { noDataExpression: true, options: [ { - name: 'HTTP Verbs', + name: 'HTTP Verb', value: 'httpverbs', }, ], diff --git a/nodes/HttpBin/HttpVerbDescriptions.ts b/nodes/HttpBin/HttpVerbDescriptions.ts index df0b8ac..265d131 100644 --- a/nodes/HttpBin/HttpVerbDescriptions.ts +++ b/nodes/HttpBin/HttpVerbDescriptions.ts @@ -207,7 +207,7 @@ const deleteOperation: INodeProperties[] = [ type: 'string', default: '', required: true, - description: 'Key of json property', + description: 'Key of JSON property', }, { displayName: 'Value', @@ -221,7 +221,7 @@ const deleteOperation: INodeProperties[] = [ }, }, required: true, - description: 'Value of json property', + description: 'Value of JSON property', }, ], }, diff --git a/package.json b/package.json index 31d337b..f02b545 100644 --- a/package.json +++ b/package.json @@ -19,12 +19,10 @@ "scripts": { "dev": "npm run watch", "build": "tsc && gulp", - "lint": "tslint -p tsconfig.json -c tslint.json", - "lintfix": "tslint --fix -p tsconfig.json -c tslint.json", - "nodelinter": "nodelinter", + "lint": "tslint -p tsconfig.json -c tslint.json && node_modules/eslint/bin/eslint.js ./nodes", + "lintfix": "tslint --fix -p tsconfig.json -c tslint.json && node_modules/eslint/bin/eslint.js --fix ./nodes", "watch": "tsc --watch", - "test": "jest", - "lintfix-plugin": "cd ../.. && node_modules/eslint/bin/eslint.js packages/nodes-base/nodes --fix" + "test": "jest" }, "files": [ "dist" @@ -44,14 +42,14 @@ "@types/jest": "^26.0.13", "@types/node": "^14.17.27", "@types/request-promise-native": "~1.0.15", + "@typescript-eslint/parser": "^5.29.0", + "eslint-plugin-n8n-nodes-base": "^1.0.43", "gulp": "^4.0.2", "jest": "^26.4.2", "n8n-workflow": "~0.104.0", - "nodelinter": "^0.1.9", "ts-jest": "^26.3.0", "tslint": "^6.1.2", - "typescript": "~4.3.5", - "eslint-plugin-n8n-nodes-base": "^1.0.43" + "typescript": "~4.3.5" }, "dependencies": { "n8n-core": "~0.122.1" diff --git a/tsconfig.json b/tsconfig.json index 48efe0b..fc72671 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,7 +17,7 @@ "resolveJsonModule": true, "declaration": true, "outDir": "./dist/", - "target": "es2017", + "target": "es2019", "sourceMap": true, "esModuleInterop": true }, From 4bc4f1e336c58082324526316008b8275b4cf805 Mon Sep 17 00:00:00 2001 From: Omar Ajoue Date: Tue, 21 Jun 2022 11:26:00 +0200 Subject: [PATCH 20/20] Added minor info to readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 52ca22c..2943e58 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ All nodes are npm packages. To make your custom node available to the community, 2. Open the project in your editor. 3. Browse the examples in `/nodes`. Modify the examples, or replace them with your own nodes. 4. Update the `package.json` to match your details. +5. Run `npm run lint` to check for errors or `npm run lintfix` to automatically fix errors when possible. +6. Publish your package to npm. More information on the links below. ## More information