Merge branch 'master' into update-readme

This commit is contained in:
Deborah 2022-08-11 10:20:22 +01:00 committed by GitHub
commit d8174322fd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 13510 additions and 164 deletions

View file

@ -18,118 +18,36 @@ module.exports = {
'**/*.js',
'**/node_modules/**',
'**/dist/**',
'**/test/**',
'**/templates/**',
'**/ormconfig.ts',
'**/migrations/**',
],
overrides: [
{
files: ['package.json'],
plugins: ['eslint-plugin-n8n-nodes-base'],
extends: ['plugin:n8n-nodes-base/community'],
rules: {
'n8n-nodes-base/community-package-json-author-email-still-default': 'error',
'n8n-nodes-base/community-package-json-author-missing': 'error',
'n8n-nodes-base/community-package-json-author-name-missing': 'error',
'n8n-nodes-base/community-package-json-author-name-still-default': 'error',
'n8n-nodes-base/community-package-json-description-missing': 'error',
'n8n-nodes-base/community-package-json-description-still-default': 'error',
'n8n-nodes-base/community-package-json-keywords-missing': 'error',
'n8n-nodes-base/community-package-json-keywords-without-official-tag': 'error',
'n8n-nodes-base/community-package-json-license-missing': 'error',
'n8n-nodes-base/community-package-json-license-not-default': 'error',
'n8n-nodes-base/community-package-json-n8n-missing': 'error',
'n8n-nodes-base/community-package-json-n8n-nodes-empty': 'error',
'n8n-nodes-base/community-package-json-n8n-nodes-missing': 'error',
'n8n-nodes-base/community-package-json-name-missing': 'error',
'n8n-nodes-base/community-package-json-name-still-default': 'error',
'n8n-nodes-base/community-package-json-repository-url-still-default': 'error',
'n8n-nodes-base/community-package-json-version-missing': 'error',
},
'n8n-nodes-base/community-package-json-name-still-default': 'off',
}
},
{
files: ['./credentials/**/*.ts'],
plugins: ['eslint-plugin-n8n-nodes-base'],
extends: ['plugin:n8n-nodes-base/credentials'],
rules: {
'n8n-nodes-base/filesystem-wrong-cred-filename': 'error',
'n8n-nodes-base/cred-class-field-documentation-url-missing': 'off',
'n8n-nodes-base/cred-class-field-documentation-url-miscased': 'off',
},
},
{
files: ['./nodes/**/*.ts'],
plugins: ['eslint-plugin-n8n-nodes-base'],
extends: ['plugin:n8n-nodes-base/nodes'],
rules: {
'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',
'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-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',
'n8n-nodes-base/node-execute-block-missing-continue-on-fail': 'off',
'n8n-nodes-base/node-resource-description-filename-against-convention': 'off',
'n8n-nodes-base/node-param-fixed-collection-type-unsorted-items': 'off',
'n8n-nodes-base/node-execute-block-operation-missing-singular-pairing': 'off',
'n8n-nodes-base/node-execute-block-operation-missing-plural-pairing': 'off',
},
},
],

12
.eslintrc.prepublish.js Normal file
View file

@ -0,0 +1,12 @@
module.exports = {
extends: "./.eslintrc.js",
overrides: [
{
files: ['package.json'],
plugins: ['eslint-plugin-n8n-nodes-base'],
rules: {
'n8n-nodes-base/community-package-json-name-still-default': 'error',
},
},
],
};

1
.gitignore vendored
View file

@ -4,6 +4,5 @@ node_modules
tmp
dist
npm-debug.log*
package-lock.json
yarn.lock
.vscode/launch.json

7
.vscode/extensions.json vendored Normal file
View file

@ -0,0 +1,7 @@
{
"recommendations": [
"dbaeumer.vscode-eslint",
"EditorConfig.EditorConfig",
"esbenp.prettier-vscode",
]
}

View file

@ -1,5 +0,0 @@
# n8n Contributor License Agreement
I give n8n permission to license my contributions on any terms they like. I am giving them this license in order to make it possible for them to accept my contributions into their project.
***As far as the law allows, my contributions come as is, without any warranty or condition, and I will not be liable to anyone for any damages related to this software or this license, under any kind of legal claim.***

View file

@ -1,4 +1,4 @@
Copyright 2022 n8n GmbH
Copyright <YEAR> <COPYRIGHT HOLDER>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in

View file

@ -2,9 +2,11 @@
# n8n-nodes-starter
This repo contains example nodes to help you get started building your own custom integrations for n8n. It includes the node linter and other dependencies.
All nodes are npm packages. To make your custom node available to the community, you must create it as an npm package, and [submit it to the npm registry](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry).
This repo contains example nodes to help you get started building your own custom integrations for [n8n](n8n.io). It includes the node linter and other dependencies.
To make your custom node available to the community, you must create it as an npm package, and [submit it to the npm registry](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry).
## Prerequisites
@ -22,9 +24,10 @@ You need the following installed on your development machine:
## Using this starter
These are the basic steps for working with the starter. For detailed guidance on creating and publishing nodes, refer to the [documentation](https://docs.n8n.io/integrations/creating-nodes/).
1. Copy the repo by clicking **Use this template** and following the steps on GitHub.
1. [Generate a new repository](https://github.com/n8n-io/n8n-nodes-starter/generate) from this template repository.
2. Clone your new repo:
```
git clone https://github.com/<your organisation>/<your-repo-name>.git
@ -34,7 +37,7 @@ These are the basic steps for working with the starter. For detailed guidance on
5. Browse the examples in `/nodes` and `/credentials`. Modify the examples, or replace them with your own nodes.
6. Update the `package.json` to match your details.
7. Run `npm run lint` to check for errors or `npm run lintfix` to automatically fix errors when possible.
8. Publish your package to npm.
8. [Publish](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry) your package to npm.
## More information

View file

@ -1,22 +1,27 @@
import { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, NodePropertyTypes } from 'n8n-workflow';
import {
IAuthenticateGeneric,
ICredentialTestRequest,
ICredentialType,
INodeProperties,
} from 'n8n-workflow';
export class ExampleCredentials implements ICredentialType {
name = 'exampleCredentials';
displayName = 'Example Credentials';
properties = [
export class ExampleCredentialsApi implements ICredentialType {
name = 'exampleCredentialsApi';
displayName = 'Example Credentials API';
properties: INodeProperties[] = [
// The credentials to get from user and save encrypted.
// Properties can be defined exactly in the same way
// as node properties.
{
displayName: 'User Name',
name: 'username',
type: 'string' as NodePropertyTypes,
type: 'string',
default: '',
},
{
displayName: 'Password',
name: 'password',
type: 'string' as NodePropertyTypes,
type: 'string',
typeOptions: {
password: true,
},
@ -27,7 +32,7 @@ export class ExampleCredentials implements ICredentialType {
// This credential is currently not used by any node directly
// but the HTTP Request node can use it to make requests.
// The credential is also testable due to the `test` property below
authenticate = {
authenticate: IAuthenticateGeneric = {
type: 'generic',
properties: {
auth: {
@ -37,9 +42,9 @@ export class ExampleCredentials implements ICredentialType {
qs: {
// Send this as part of the query string
n8n: 'rocks',
}
},
},
} as IAuthenticateGeneric;
};
// The block below tells how this credential can be tested
test: ICredentialTestRequest = {

View file

@ -8,7 +8,7 @@ import {
export class HttpBinApi implements ICredentialType {
name = 'httpbinApi';
displayName = 'HttpBin API';
documentationUrl = 'httpbin';
documentationUrl = '<your-docs-url>';
properties: INodeProperties[] = [
{
displayName: 'Token',

View file

@ -1,11 +1,16 @@
const path = require('path');
const { task, src, dest } = require('gulp');
task('build:icons', copyIcons);
function copyIcons() {
src('nodes/**/*.{png,svg}').pipe(dest('dist/nodes'));
const nodeSource = path.resolve('nodes', '**', '*.{png,svg}');
const nodeDestination = path.resolve('dist', 'nodes');
return src('credentials/**/*.{png,svg}').pipe(dest('dist/credentials'));
src(nodeSource).pipe(dest(nodeDestination));
const credSource = path.resolve('credentials', '**', '*.{png,svg}');
const credDestination = path.resolve('dist', 'credentials');
return src(credSource).pipe(dest(credDestination));
}
// TODO: Add i18n to pipeline

View file

@ -1,5 +1,10 @@
import { IExecuteFunctions } from 'n8n-core';
import { INodeExecutionData, INodeType, INodeTypeDescription, NodeOperationError } from 'n8n-workflow';
import {
INodeExecutionData,
INodeType,
INodeTypeDescription,
NodeOperationError,
} from 'n8n-workflow';
export class ExampleNode implements INodeType {
description: INodeTypeDescription = {
@ -10,7 +15,6 @@ export class ExampleNode implements INodeType {
description: 'Basic Example Node',
defaults: {
name: 'Example Node',
color: '#772244',
},
inputs: ['main'],
outputs: ['main'],
@ -48,11 +52,10 @@ export class ExampleNode implements INodeType {
item.json['myString'] = myString;
} catch (error) {
// This node should never fail but we want to showcase how
// to handle errors.
if (this.continueOnFail()) {
items.push({json: this.getInputData(itemIndex)[0].json, error});
items.push({ json: this.getInputData(itemIndex)[0].json, error, pairedItem: itemIndex });
} else {
// Adding `itemIndex` allows other workflows to handle this error
if (error.context) {
@ -66,7 +69,6 @@ export class ExampleNode implements INodeType {
});
}
}
}
return this.prepareOutputData(items);

View file

@ -6,12 +6,12 @@
"resources": {
"credentialDocumentation": [
{
"url": "https://docs.n8n.io/credentials/httpbin"
"url": "http://httpbin.org/#/Auth/get_bearer"
}
],
"primaryDocumentation": [
{
"url": "https://docs.n8n.io/nodes/n8n-nodes-base.httpbin/"
"url": "http://httpbin.org/"
}
]
}

View file

@ -1,11 +1,10 @@
/* eslint-disable n8n-nodes-base/filesystem-wrong-node-filename */
import { INodeType, INodeTypeDescription } from 'n8n-workflow';
import { httpVerbFields, httpVerbOperations } from './HttpVerbDescriptions';
import { httpVerbFields, httpVerbOperations } from './HttpVerbDescription';
export class HttpBin implements INodeType {
description: INodeTypeDescription = {
displayName: 'HttpBin',
name: 'httpbin',
name: 'httpBin',
icon: 'file:httpbin.svg',
group: ['transform'],
version: 1,
@ -36,11 +35,10 @@ export class HttpBin implements INodeType {
*
* [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
* In our example, the operations are separated into their own file (HTTPVerbDescription.ts)
* to keep this class easy to read.
*
*/
properties: [
@ -52,10 +50,10 @@ export class HttpBin implements INodeType {
options: [
{
name: 'HTTP Verb',
value: 'httpverbs',
value: 'httpVerb',
},
],
default: 'httpverbs',
default: 'httpVerb',
},
...httpVerbOperations,

View file

@ -1,21 +1,23 @@
import { INodeProperties } from 'n8n-workflow';
// This maps the operations to when the Resource option HTTP Verbs is selected
// When the resource `httpVerb` is selected, this `operation` parameter will be shown.
export const httpVerbOperations: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['httpverbs'],
resource: ['httpVerb'],
},
},
options: [
{
name: 'GET',
value: 'get',
action: 'Perform a GET request',
routing: {
request: {
method: 'GET',
@ -26,6 +28,7 @@ export const httpVerbOperations: INodeProperties[] = [
{
name: 'DELETE',
value: 'delete',
action: 'Perform a DELETE request',
routing: {
request: {
method: 'DELETE',
@ -38,8 +41,8 @@ export const httpVerbOperations: INodeProperties[] = [
},
];
// Here we define what to show when the GET Operation is selected
// We do that by adding operation: ["get"], to "displayOptions.show"
// 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',
@ -48,7 +51,7 @@ const getOperation: INodeProperties[] = [
displayName: 'Type of Data',
displayOptions: {
show: {
resource: ['httpverbs'],
resource: ['httpVerb'],
operation: ['get'],
},
},
@ -68,7 +71,7 @@ const getOperation: INodeProperties[] = [
displayName: 'Query Parameters',
displayOptions: {
show: {
resource: ['httpverbs'],
resource: ['httpVerb'],
operation: ['get'],
},
},
@ -109,8 +112,8 @@ const getOperation: INodeProperties[] = [
},
];
// Here we define what to show when the DELETE Operation is selected
// We do that by adding operation: ["delete"], to "displayOptions.show"
// 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',
@ -119,7 +122,7 @@ const deleteOperation: INodeProperties[] = [
displayName: 'Type of Data',
displayOptions: {
show: {
resource: ['httpverbs'],
resource: ['httpVerb'],
operation: ['delete'],
},
},
@ -143,7 +146,7 @@ const deleteOperation: INodeProperties[] = [
displayName: 'Query Parameters',
displayOptions: {
show: {
resource: ['httpverbs'],
resource: ['httpVerb'],
operation: ['delete'],
typeofData: ['queryParameter'],
},
@ -190,7 +193,7 @@ const deleteOperation: INodeProperties[] = [
displayName: 'JSON Object',
displayOptions: {
show: {
resource: ['httpverbs'],
resource: ['httpVerb'],
operation: ['delete'],
typeofData: ['jsonData'],
},
@ -234,12 +237,12 @@ const deleteOperation: INodeProperties[] = [
export const httpVerbFields: INodeProperties[] = [
/* -------------------------------------------------------------------------- */
/* Http Verbs:Get */
/* httpVerb:get */
/* -------------------------------------------------------------------------- */
...getOperation,
/* -------------------------------------------------------------------------- */
/* Http Verbs:Delete */
/* httpVerb:delete */
/* -------------------------------------------------------------------------- */
...deleteOperation,
];

13401
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,34 +1,36 @@
{
"name": "n8n-nodes-starter",
"name": "n8n-nodes-<...>",
"version": "0.1.0",
"description": "Example starter module for custom n8n nodes.",
"description": "",
"keywords": [
"n8n-community-node-package"
],
"license": "MIT",
"homepage": "https://n8n.io",
"homepage": "",
"author": {
"name": "Jan Oberhauser",
"email": "jan@n8n.io"
"name": "",
"email": ""
},
"repository": {
"type": "git",
"url": "git+https://github.com/n8n-io/n8n-nodes-starter.git"
"url": "https://github.com/<...>/n8n-nodes-<...>.git"
},
"main": "index.js",
"scripts": {
"build": "tsc && gulp build:icons",
"dev": "tsc --watch",
"format": "prettier nodes credentials --write",
"lint": "tslint -p tsconfig.json -c tslint.json; eslint nodes credentials package.json",
"lintfix": "tslint --fix -p tsconfig.json -c tslint.json; eslint nodes credentials package.json --fix"
"lint": "tslint -p tsconfig.json -c tslint.json && eslint nodes credentials package.json",
"lintfix": "tslint --fix -p tsconfig.json -c tslint.json && eslint nodes credentials package.json --fix",
"prepublishOnly": "npm run build && npm run lint -c .eslintrc.prepublish.js nodes credentials package.json"
},
"files": [
"dist"
],
"n8n": {
"n8nNodesApiVersion": 1,
"credentials": [
"dist/credentials/ExampleCredentials.credentials.js",
"dist/credentials/ExampleCredentialsApi.credentials.js",
"dist/credentials/HttpBinApi.credentials.js"
],
"nodes": [
@ -40,10 +42,10 @@
"@types/express": "^4.17.6",
"@types/request-promise-native": "~1.0.15",
"@typescript-eslint/parser": "^5.29.0",
"eslint-plugin-n8n-nodes-base": "~1.1.1",
"eslint-plugin-n8n-nodes-base": "^1.5.4",
"gulp": "^4.0.2",
"n8n-core": "^0.124.0",
"n8n-workflow": "^0.106.0",
"n8n-core": "^0.125.0",
"n8n-workflow": "^0.107.0",
"prettier": "^2.7.1",
"tslint": "^6.1.2",
"typescript": "~4.6.0"

View file

@ -111,10 +111,6 @@
"allow-null-check"
],
"use-isnan": true,
"quotemark": [
true,
"single"
],
"quotes": [
"error",
"single"