From fa127df73646ef53125e9d249b746aae65a557ff Mon Sep 17 00:00:00 2001 From: Deborah Barnard Date: Tue, 24 May 2022 12:47:46 +0100 Subject: [PATCH 01/18] start drafting community nodes --- .../integrations/community-nodes/blocklist.md | 11 ++++ docs/integrations/community-nodes/index.md | 6 +++ .../community-nodes/installation.md | 51 +++++++++++++++++++ docs/integrations/community-nodes/risks.md | 9 ++++ .../community-nodes/submit-nodes.md | 9 ++++ docs/integrations/community-nodes/usage.md | 12 +++++ mkdocs.yml | 7 +++ styles/Vocab/default/accept.txt | 1 + styles/Vocab/default/reject.txt | 5 +- 9 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 docs/integrations/community-nodes/blocklist.md create mode 100644 docs/integrations/community-nodes/index.md create mode 100644 docs/integrations/community-nodes/installation.md create mode 100644 docs/integrations/community-nodes/risks.md create mode 100644 docs/integrations/community-nodes/submit-nodes.md create mode 100644 docs/integrations/community-nodes/usage.md diff --git a/docs/integrations/community-nodes/blocklist.md b/docs/integrations/community-nodes/blocklist.md new file mode 100644 index 000000000..e72ed9610 --- /dev/null +++ b/docs/integrations/community-nodes/blocklist.md @@ -0,0 +1,11 @@ +# n8n Community Node blocklist + +n8n maintains a blocklist of Community Nodes. You can't install any node on this list. + +n8n may add Community Nodes to the blocklist for a range of reasons, including: + +* The node is intentionally malicious +* It's of very low quality (low enough to be harmful) + + +If you are a Community Node creator whose node is on the blocklist, and you believe this is a mistake, contact [hello@n8n.io](mailto: hello@n8n.io). \ No newline at end of file diff --git a/docs/integrations/community-nodes/index.md b/docs/integrations/community-nodes/index.md new file mode 100644 index 000000000..29eff5469 --- /dev/null +++ b/docs/integrations/community-nodes/index.md @@ -0,0 +1,6 @@ +# Overview + +The Community Nodes repository allows n8n users to publish and install custom nodes. + +n8n provides hundreds of built-in nodes. It also supports users [creating their own nodes](/integrations/creating-nodes/){:target=_blank}. The Community Nodes repository allows users who create nodes to publish them to npm. These nodes are then available to install and use in your n8n instance. + diff --git a/docs/integrations/community-nodes/installation.md b/docs/integrations/community-nodes/installation.md new file mode 100644 index 000000000..c79afaf0d --- /dev/null +++ b/docs/integrations/community-nodes/installation.md @@ -0,0 +1,51 @@ +# Install, upgrade, and downgrade Community Nodes + +!!! note "Limited to n8n instance owners" + Only the n8n instance owner can install and manage Community Nodes. The instance owner is the person who sets up and manages user management. If you haven't set up user management, the instance owner is the default user. + +## Install a Community Node + +To install a Community Node: + +1. Go to **Settings** > **Community Nodes**. +2. Select **Install a Community Node**. +3. Find the node you want to install: + 1. Select **Browse**. n8n takes you to an npm search results page, showing all npm packages tagged with the keyword `n8n-community-node-package`. + 2. Browse the list of results. You can filter the results or add more keywords. + 3. Once you find the package you want, make a note of the package name. If you want to install a specific version, make a note of the version number as well. + 4. Return to n8n. +4. Enter the npm package name, and version number if required. For example, consider a Community Node designed to access a weather API called "Stormz." The package is named n8n-node-stormz, and has three major versions. + * To install the latest version of a package called n8n-node-weather: enter `n8n-node-stormz` in **Enter npm package name**. + * Install version 2.3: enter `n8n-node-stormz@2.3` in **Enter npm package name**. +5. Agree to the [risks](/integrations/community-nodes/risks/) of using Community Nodes: select **I understand the risks of installing unverified code from a public source.** +6. Select **Install**. n8n installs the node, and returns to the **Community Nodes** list in **Settings**. + +!!! note "Nodes on the blocklist" + n8n maintains a blocklist of Community Nodes that it prevents you from installing. Refer to [n8n Community Node blocklist](/integrations/community-nodes/blocklist/) for more information. + +## Uninstall a Community Node + +To uninstall a Community Node: + +1. Go to **Settings** > **Community Nodes**. +2. On the node you want to install, select **Options** [TODO: add image of icon]. +3. Select **Uninstall package**. + +## Upgrade a Community Node + +### Upgrade to the latest version + +You can upgrade Community Nodes to the latest version from the node list in **Settings** > **Community Nodes**. + +When a new version of a Community Node is available, n8n displays an **Update** button on the node. Click the button to upgrade to the latest version. + +### Upgrade to a specific version + +To upgrade to a specific version (a version other than the latest), uninstall the node, then reinstall it, making sure to specify the target version. Follow the [Installation](#install-a-community-node) instructions for more guidance. + +## Downgrade a Community Node + +If there is a problem with a particular version of a Community Node, you may want to roll back to a previous version. + +To do this, uninstall the Community Node, then reinstall it, targeting a specific node version. Follow the [Installation](#install-a-community-node) instructions for more guidance. + diff --git a/docs/integrations/community-nodes/risks.md b/docs/integrations/community-nodes/risks.md new file mode 100644 index 000000000..dcbb8d57b --- /dev/null +++ b/docs/integrations/community-nodes/risks.md @@ -0,0 +1,9 @@ +# Risks when using Community Nodes + +Using Community Nodes has some risks. You are installing unverified code from a public source into your n8n instance. + +Risks include: + +* Data security: any Community Node that you use has access to data in your workflows. + +## Report bad Community Nodes \ No newline at end of file diff --git a/docs/integrations/community-nodes/submit-nodes.md b/docs/integrations/community-nodes/submit-nodes.md new file mode 100644 index 000000000..550adfdb6 --- /dev/null +++ b/docs/integrations/community-nodes/submit-nodes.md @@ -0,0 +1,9 @@ +# Submit your node to the Community Node repository + +Community Nodes are npm packages, hosted in the npm registry. + +To make your node available to the n8n Community Node repository, you must: + +* Make sure the package name starts with `n8n-node-`. +* Tag your package with `n8n-community-node-package`. +* Submit the package to the npm registry. Refer to npm's documentation on [Contributing packages to the registry](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry){:target=_blank .external-link} for more information. \ No newline at end of file diff --git a/docs/integrations/community-nodes/usage.md b/docs/integrations/community-nodes/usage.md new file mode 100644 index 000000000..f529ad1c1 --- /dev/null +++ b/docs/integrations/community-nodes/usage.md @@ -0,0 +1,12 @@ +# Using Community Nodes + +To use Community Nodes, you first need to [install](/integrations/community-nodes/installation/){:target=_blank} them. + +## Adding Community Nodes to your workflow + +After installing a Community Node, you can use it like any other node. n8n displays the node in search results in the **Nodes** panel. To show which nodes are Community Nodes and which are built-in, n8n marks Community Nodes with a **Package** icon [TODO: add icon]. + +## Community Nodes with duplicate names + +It's possible for several Community Nodes to have the same name. If you use two nodes with the same name in your workflow, they'll look the same, unless they have different icons. + diff --git a/mkdocs.yml b/mkdocs.yml index ef8c024ed..f39f57ee4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -118,6 +118,13 @@ nav: - Nodes: integrations/nodes/ - Trigger nodes: integrations/trigger-nodes/ - Credentials: integrations/credentials/ + - Community nodes: + - Overview: integrations/community-nodes/index.md + - Installation and management: integrations/community-nodes/installation.md + - Risks: integrations/community-nodes/risks.md + - Blocklist: integrations/community-nodes/blocklist.md + - Using community nodes: integrations/community-nodes/usage.md + - Submit your node: integrations/community-nodes/submit-nodes.md - Creating nodes: - Overview: integrations/creating-nodes/index.md - Code-based node building: diff --git a/styles/Vocab/default/accept.txt b/styles/Vocab/default/accept.txt index 172dfb11f..87332dc7c 100644 --- a/styles/Vocab/default/accept.txt +++ b/styles/Vocab/default/accept.txt @@ -4,5 +4,6 @@ Enum enum n8n namespace +npm onboarding URL \ No newline at end of file diff --git a/styles/Vocab/default/reject.txt b/styles/Vocab/default/reject.txt index d588a387d..37e5746f5 100644 --- a/styles/Vocab/default/reject.txt +++ b/styles/Vocab/default/reject.txt @@ -1,3 +1,6 @@ N8n n8N -N8N \ No newline at end of file +N8N +NPM +nPM +NPm \ No newline at end of file From f975bc7fe5463d36a58b91ef8f2ccc0cf84456bb Mon Sep 17 00:00:00 2001 From: Deborah Barnard Date: Tue, 24 May 2022 14:04:01 +0100 Subject: [PATCH 02/18] wip --- docs/integrations/community-nodes/blocklist.md | 7 +++++-- docs/integrations/community-nodes/installation.md | 8 +++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/integrations/community-nodes/blocklist.md b/docs/integrations/community-nodes/blocklist.md index e72ed9610..266d0f582 100644 --- a/docs/integrations/community-nodes/blocklist.md +++ b/docs/integrations/community-nodes/blocklist.md @@ -5,7 +5,10 @@ n8n maintains a blocklist of Community Nodes. You can't install any node on this n8n may add Community Nodes to the blocklist for a range of reasons, including: * The node is intentionally malicious -* It's of very low quality (low enough to be harmful) +* It's low quality (low enough to be harmful) + -If you are a Community Node creator whose node is on the blocklist, and you believe this is a mistake, contact [hello@n8n.io](mailto: hello@n8n.io). \ No newline at end of file +If you are a Community Node creator whose node is on the blocklist, and you believe this is a mistake, contact [hello@n8n.io](mailto: hello@n8n.io). + + \ No newline at end of file diff --git a/docs/integrations/community-nodes/installation.md b/docs/integrations/community-nodes/installation.md index c79afaf0d..a1a9701dd 100644 --- a/docs/integrations/community-nodes/installation.md +++ b/docs/integrations/community-nodes/installation.md @@ -14,10 +14,12 @@ To install a Community Node: 2. Browse the list of results. You can filter the results or add more keywords. 3. Once you find the package you want, make a note of the package name. If you want to install a specific version, make a note of the version number as well. 4. Return to n8n. -4. Enter the npm package name, and version number if required. For example, consider a Community Node designed to access a weather API called "Stormz." The package is named n8n-node-stormz, and has three major versions. - * To install the latest version of a package called n8n-node-weather: enter `n8n-node-stormz` in **Enter npm package name**. - * Install version 2.3: enter `n8n-node-stormz@2.3` in **Enter npm package name**. +4. Enter the npm package name, and version number if required. For example, consider a Community Node designed to access a weather API called "Storms." The package name is n8n-node-storms, and it has three major versions. + * To install the latest version of a package called n8n-node-weather: enter `n8n-node-storms` in **Enter npm package name**. + * Install version 2.3: enter `n8n-node-storms@2.3` in **Enter npm package name**. + 5. Agree to the [risks](/integrations/community-nodes/risks/) of using Community Nodes: select **I understand the risks of installing unverified code from a public source.** + 6. Select **Install**. n8n installs the node, and returns to the **Community Nodes** list in **Settings**. !!! note "Nodes on the blocklist" From ff0328518e91279bdb4ece2f0842e46ffab0de51 Mon Sep 17 00:00:00 2001 From: Deborah Barnard Date: Tue, 24 May 2022 15:26:09 +0100 Subject: [PATCH 03/18] wip --- docs/integrations/community-nodes/risks.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/integrations/community-nodes/risks.md b/docs/integrations/community-nodes/risks.md index dcbb8d57b..212ba7a6d 100644 --- a/docs/integrations/community-nodes/risks.md +++ b/docs/integrations/community-nodes/risks.md @@ -6,4 +6,10 @@ Risks include: * Data security: any Community Node that you use has access to data in your workflows. -## Report bad Community Nodes \ No newline at end of file +## Report bad Community Nodes + + + +You can report bad Community Nodes to [security@n8n.io](mailto: security@n8n.io) + + \ No newline at end of file From 63bf7b6be52470c5587ac44c5840e665b9dd9af9 Mon Sep 17 00:00:00 2001 From: Deborah Barnard Date: Wed, 25 May 2022 11:16:51 +0100 Subject: [PATCH 04/18] add scope name --- docs/integrations/community-nodes/submit-nodes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/community-nodes/submit-nodes.md b/docs/integrations/community-nodes/submit-nodes.md index 550adfdb6..075abf544 100644 --- a/docs/integrations/community-nodes/submit-nodes.md +++ b/docs/integrations/community-nodes/submit-nodes.md @@ -4,6 +4,6 @@ Community Nodes are npm packages, hosted in the npm registry. To make your node available to the n8n Community Node repository, you must: -* Make sure the package name starts with `n8n-node-`. +* Make sure the package name starts with `n8n-node-` or `@scope/n8n-node-`. * Tag your package with `n8n-community-node-package`. * Submit the package to the npm registry. Refer to npm's documentation on [Contributing packages to the registry](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry){:target=_blank .external-link} for more information. \ No newline at end of file From e28dff4c5fb52ee85e84f17e6d8f8343735ffab0 Mon Sep 17 00:00:00 2001 From: Deborah Barnard Date: Thu, 26 May 2022 10:16:17 +0100 Subject: [PATCH 05/18] edits --- .../integrations/community-nodes/blocklist.md | 8 ++--- docs/integrations/community-nodes/index.md | 4 +-- .../community-nodes/installation.md | 34 +++++++++---------- docs/integrations/community-nodes/risks.md | 10 +++--- .../community-nodes/submit-nodes.md | 11 +++--- docs/integrations/community-nodes/usage.md | 12 +++---- 6 files changed, 41 insertions(+), 38 deletions(-) diff --git a/docs/integrations/community-nodes/blocklist.md b/docs/integrations/community-nodes/blocklist.md index 266d0f582..42d8071e9 100644 --- a/docs/integrations/community-nodes/blocklist.md +++ b/docs/integrations/community-nodes/blocklist.md @@ -1,14 +1,14 @@ -# n8n Community Node blocklist +# n8n community node blocklist -n8n maintains a blocklist of Community Nodes. You can't install any node on this list. +n8n maintains a blocklist of community nodes. You can't install any node on this list. -n8n may add Community Nodes to the blocklist for a range of reasons, including: +n8n may add community nodes to the blocklist for a range of reasons, including: * The node is intentionally malicious * It's low quality (low enough to be harmful) -If you are a Community Node creator whose node is on the blocklist, and you believe this is a mistake, contact [hello@n8n.io](mailto: hello@n8n.io). +If you are a community node creator whose node is on the blocklist, and you believe this is a mistake, contact [hello@n8n.io](mailto: hello@n8n.io). \ No newline at end of file diff --git a/docs/integrations/community-nodes/index.md b/docs/integrations/community-nodes/index.md index 29eff5469..baa68c605 100644 --- a/docs/integrations/community-nodes/index.md +++ b/docs/integrations/community-nodes/index.md @@ -1,6 +1,6 @@ # Overview -The Community Nodes repository allows n8n users to publish and install custom nodes. +The community nodes repository allows n8n users to publish and install custom nodes. -n8n provides hundreds of built-in nodes. It also supports users [creating their own nodes](/integrations/creating-nodes/){:target=_blank}. The Community Nodes repository allows users who create nodes to publish them to npm. These nodes are then available to install and use in your n8n instance. +n8n provides hundreds of built-in nodes. It also supports users [creating their own nodes](/integrations/creating-nodes/){:target=_blank}. The community nodes repository allows users who create nodes to publish them to npm. These nodes are then available to install and use in your n8n instance. diff --git a/docs/integrations/community-nodes/installation.md b/docs/integrations/community-nodes/installation.md index a1a9701dd..96a8ab7d8 100644 --- a/docs/integrations/community-nodes/installation.md +++ b/docs/integrations/community-nodes/installation.md @@ -1,53 +1,53 @@ -# Install, upgrade, and downgrade Community Nodes +# Install, upgrade, and downgrade community nodes !!! note "Limited to n8n instance owners" - Only the n8n instance owner can install and manage Community Nodes. The instance owner is the person who sets up and manages user management. If you haven't set up user management, the instance owner is the default user. + Only the n8n instance owner can install and manage community nodes. The instance owner is the person who sets up and manages user management. If you haven't set up user management, the instance owner is the default user. -## Install a Community Node +## Install a community node -To install a Community Node: +To install a community node: 1. Go to **Settings** > **Community Nodes**. -2. Select **Install a Community Node**. +2. Select **Install a community node**. 3. Find the node you want to install: 1. Select **Browse**. n8n takes you to an npm search results page, showing all npm packages tagged with the keyword `n8n-community-node-package`. 2. Browse the list of results. You can filter the results or add more keywords. 3. Once you find the package you want, make a note of the package name. If you want to install a specific version, make a note of the version number as well. 4. Return to n8n. -4. Enter the npm package name, and version number if required. For example, consider a Community Node designed to access a weather API called "Storms." The package name is n8n-node-storms, and it has three major versions. +4. Enter the npm package name, and version number if required. For example, consider a community node designed to access a weather API called "Storms." The package name is n8n-node-storms, and it has three major versions. * To install the latest version of a package called n8n-node-weather: enter `n8n-node-storms` in **Enter npm package name**. * Install version 2.3: enter `n8n-node-storms@2.3` in **Enter npm package name**. -5. Agree to the [risks](/integrations/community-nodes/risks/) of using Community Nodes: select **I understand the risks of installing unverified code from a public source.** +5. Agree to the [risks](/integrations/community-nodes/risks/) of using community nodes: select **I understand the risks of installing unverified code from a public source.** 6. Select **Install**. n8n installs the node, and returns to the **Community Nodes** list in **Settings**. !!! note "Nodes on the blocklist" - n8n maintains a blocklist of Community Nodes that it prevents you from installing. Refer to [n8n Community Node blocklist](/integrations/community-nodes/blocklist/) for more information. + n8n maintains a blocklist of community nodes that it prevents you from installing. Refer to [n8n community node blocklist](/integrations/community-nodes/blocklist/) for more information. -## Uninstall a Community Node +## Uninstall a community node -To uninstall a Community Node: +To uninstall a community node: -1. Go to **Settings** > **Community Nodes**. +1. Go to **Settings** > **community nodes**. 2. On the node you want to install, select **Options** [TODO: add image of icon]. 3. Select **Uninstall package**. -## Upgrade a Community Node +## Upgrade a community node ### Upgrade to the latest version -You can upgrade Community Nodes to the latest version from the node list in **Settings** > **Community Nodes**. +You can upgrade community nodes to the latest version from the node list in **Settings** > **community nodes**. -When a new version of a Community Node is available, n8n displays an **Update** button on the node. Click the button to upgrade to the latest version. +When a new version of a community node is available, n8n displays an **Update** button on the node. Click the button to upgrade to the latest version. ### Upgrade to a specific version To upgrade to a specific version (a version other than the latest), uninstall the node, then reinstall it, making sure to specify the target version. Follow the [Installation](#install-a-community-node) instructions for more guidance. -## Downgrade a Community Node +## Downgrade a community node -If there is a problem with a particular version of a Community Node, you may want to roll back to a previous version. +If there is a problem with a particular version of a community node, you may want to roll back to a previous version. -To do this, uninstall the Community Node, then reinstall it, targeting a specific node version. Follow the [Installation](#install-a-community-node) instructions for more guidance. +To do this, uninstall the community node, then reinstall it, targeting a specific node version. Follow the [Installation](#install-a-community-node) instructions for more guidance. diff --git a/docs/integrations/community-nodes/risks.md b/docs/integrations/community-nodes/risks.md index 212ba7a6d..fdea6e588 100644 --- a/docs/integrations/community-nodes/risks.md +++ b/docs/integrations/community-nodes/risks.md @@ -1,15 +1,15 @@ -# Risks when using Community Nodes +# Risks when using community nodes -Using Community Nodes has some risks. You are installing unverified code from a public source into your n8n instance. +Using community nodes has some risks. You are installing unverified code from a public source into your n8n instance. Risks include: -* Data security: any Community Node that you use has access to data in your workflows. +* Data security: any community node that you use has access to data in your workflows. -## Report bad Community Nodes +## Report bad community nodes -You can report bad Community Nodes to [security@n8n.io](mailto: security@n8n.io) +You can report bad community nodes to [security@n8n.io](mailto: security@n8n.io) \ No newline at end of file diff --git a/docs/integrations/community-nodes/submit-nodes.md b/docs/integrations/community-nodes/submit-nodes.md index 075abf544..548b52fda 100644 --- a/docs/integrations/community-nodes/submit-nodes.md +++ b/docs/integrations/community-nodes/submit-nodes.md @@ -1,9 +1,12 @@ -# Submit your node to the Community Node repository +# Submit your node to the community node repository -Community Nodes are npm packages, hosted in the npm registry. +!!! note "Subject to change" + The standards described in this document are for the first release of the community nodes repository. These may change in future releases. -To make your node available to the n8n Community Node repository, you must: +Community nodes are npm packages, hosted in the npm registry. -* Make sure the package name starts with `n8n-node-` or `@scope/n8n-node-`. +To make your node available to the n8n community node repository, you must: + +* Make sure the package name starts with `n8n-node-` or `@/n8n-node-`. For example, `n8n-node-weather` or `@weatherPlugins/n8n-node-weather`. * Tag your package with `n8n-community-node-package`. * Submit the package to the npm registry. Refer to npm's documentation on [Contributing packages to the registry](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry){:target=_blank .external-link} for more information. \ No newline at end of file diff --git a/docs/integrations/community-nodes/usage.md b/docs/integrations/community-nodes/usage.md index f529ad1c1..40c78adfe 100644 --- a/docs/integrations/community-nodes/usage.md +++ b/docs/integrations/community-nodes/usage.md @@ -1,12 +1,12 @@ -# Using Community Nodes +# Using community nodes -To use Community Nodes, you first need to [install](/integrations/community-nodes/installation/){:target=_blank} them. +To use community nodes, you first need to [install](/integrations/community-nodes/installation/){:target=_blank} them. -## Adding Community Nodes to your workflow +## Adding community nodes to your workflow -After installing a Community Node, you can use it like any other node. n8n displays the node in search results in the **Nodes** panel. To show which nodes are Community Nodes and which are built-in, n8n marks Community Nodes with a **Package** icon [TODO: add icon]. +After installing a community node, you can use it like any other node. n8n displays the node in search results in the **Nodes** panel. To show which nodes are community nodes and which are built-in, n8n marks community nodes with a **Package** icon [TODO: add icon]. -## Community Nodes with duplicate names +## Community nodes with duplicate names -It's possible for several Community Nodes to have the same name. If you use two nodes with the same name in your workflow, they'll look the same, unless they have different icons. +It's possible for several community nodes to have the same name. If you use two nodes with the same name in your workflow, they'll look the same, unless they have different icons. From 6cdef645349448442f42b19223b8eb909cf41119 Mon Sep 17 00:00:00 2001 From: Deborah Barnard Date: Thu, 26 May 2022 14:09:13 +0100 Subject: [PATCH 06/18] edited the editor UI page --- .../creating-nodes/code/ui-elements.md | 95 +++++++------------ 1 file changed, 34 insertions(+), 61 deletions(-) diff --git a/docs/integrations/creating-nodes/code/ui-elements.md b/docs/integrations/creating-nodes/code/ui-elements.md index e28f400dc..2b00fbcc8 100644 --- a/docs/integrations/creating-nodes/code/ui-elements.md +++ b/docs/integrations/creating-nodes/code/ui-elements.md @@ -1,32 +1,25 @@ -# Node UI Elements +# Node user interface elements n8n provides a set of predefined UI components (based on a JSON file) that allows users to input all sorts of data types. The following UI elements are available in n8n. - - ## String -The `string` type is used to input string values. - -Basic configuration +Basic configuration: ```typescript { - displayName: Name, // The value the user would see in the UI - name: name, // The name use to reference the element UI within the code + displayName: Name, // The value the user sees in the UI + name: name, // The name used to reference the element UI within the code type: string, required: true, // Whether the field is required or not - default: 'n8n', // Value that would be set by default + default: 'n8n', description: 'The name of the user', -}, +} ``` - - ![String](/_images/integrations/creating-nodes/code/string.png) - -Variation for inputting passwords +String field for inputting passwords: ```typescript { @@ -39,14 +32,13 @@ Variation for inputting passwords }, default: '', description: `User's password`, - -}, +} ``` ![Password](/_images/integrations/creating-nodes/code/password.png) -Variation with multiple rows +String field with more than one row: ```typescript { @@ -59,18 +51,14 @@ Variation with multiple rows }, default: '', description: 'Description', -}, +} ``` ![Multiple rows](/_images/integrations/creating-nodes/code/multiple-rows.png) - - ## Number -The `number` type is used to input numbers. - -Basic configuration +Basic configuration: ```typescript { @@ -85,13 +73,12 @@ Basic configuration }, default: 10, description: 'Your current age', -}, +} ``` ![Number](/_images/integrations/creating-nodes/code/number.png) - -Variation with decimal points +Number field with decimal points: ```typescript { @@ -104,16 +91,14 @@ Variation with decimal points }, default: 10.00, description: 'Your current amount', -}, +} ``` ![Decimal](/_images/integrations/creating-nodes/code/decimal.png) - - ## Collection -The `collection` type is used to input a collection of fields. For example, additional fields (or optional fields). +Use the `collection` type when you need to display optional fields. ```typescript { @@ -144,16 +129,15 @@ The `collection` type is used to input a collection of fields. For example, addi default: '', }, ], -}, +} ``` ![Collection](/_images/integrations/creating-nodes/code/collection.png) +## DateTime -## Datetime - -The `dateTime` type provides a calendar from which you can pick a specific date and time. +The `dateTime` type provides a date picker. ```typescript { @@ -162,16 +146,14 @@ The `dateTime` type provides a calendar from which you can pick a specific date type: 'dateTime', default: '', description: 'The date and time when the file was last modified', -}, +} ``` -![Datetime](/_images/integrations/creating-nodes/code/datetime.png) - - +![DateTime](/_images/integrations/creating-nodes/code/datetime.png) ## Boolean -The `boolean` type is used to input a value that is either true or false. It is shown as a toggle that can be either on or off. +The `boolean` type adds a toggle for entering true or false. ```typescript { @@ -180,15 +162,14 @@ The `boolean` type is used to input a value that is either true or false. It is type: 'boolean', default: true, // Initial state of the toggle description: 'Whether to wait for the image or not', -}, +} ``` ![Boolean](/_images/integrations/creating-nodes/code/boolean.png) - ## Color -The `color` type provides a color palette from which a specific color can be selected. +The `color` type provides a color selector. ```typescript { @@ -196,16 +177,14 @@ The `color` type provides a color palette from which a specific color can be sel name: 'backgroundColor', type: 'color', default: '', // Initially selected color -}, +} ``` ![Color](/_images/integrations/creating-nodes/code/color.png) - - ## Options -The `options` type is used to provide options from which a single one has to be selected. +The `options` type adds an options list. Users can select a single value. ```typescript { @@ -224,15 +203,14 @@ The `options` type is used to provide options from which a single one has to be ], default: 'image', // The initially selected option description: 'Resource to consume', -}, +} ``` ![Options](/_images/integrations/creating-nodes/code/options.png) +## Multi options -## Multi Options - -The `multiOptions` type is used to provide options from which many can be selected. +The `multiOptions` type adds an options list. Users can select more than one value. ```typescript { @@ -251,15 +229,15 @@ The `multiOptions` type is used to provide options from which many can be select ], default: [], // Initially selected options description: 'The events to be monitored', -}, +} ``` -![Multioptions](/_images/integrations/creating-nodes/code/multioptions.png) +![Multi-options](/_images/integrations/creating-nodes/code/multioptions.png) -## Fixed Collection +## Fixed collection -The `fixedCollection? type is used to present groups of fields that are semantically related. +Use the `fixedCollection` type to group fields that are semantically related. ```typescript { @@ -293,18 +271,13 @@ The `fixedCollection? type is used to present groups of fields that are semantic ], }, ], -}, +} ``` ![Fixed collection](/_images/integrations/creating-nodes/code/fixed-collection.png) - - - ## JSON -The `json` type is used to input data formatted as JSON. - ```typescript { displayName: 'Content (JSON)', @@ -312,7 +285,7 @@ The `json` type is used to input data formatted as JSON. type: 'json', default: '', description: '', -}, +} ``` ![JSON](/_images/integrations/creating-nodes/code/json.png) From 9e5f12598d6c7d86b7e06a96aeab8dfcd5fb51e2 Mon Sep 17 00:00:00 2001 From: Omar Ajoue Date: Tue, 31 May 2022 17:52:05 +0200 Subject: [PATCH 07/18] Adding more detailed instructions about how to use the example repo and how to convert a pr to package --- .../community-nodes/submit-nodes.md | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/docs/integrations/community-nodes/submit-nodes.md b/docs/integrations/community-nodes/submit-nodes.md index 548b52fda..b4923d5a4 100644 --- a/docs/integrations/community-nodes/submit-nodes.md +++ b/docs/integrations/community-nodes/submit-nodes.md @@ -5,8 +5,29 @@ Community nodes are npm packages, hosted in the npm registry. +## How to start + +n8n provides an example of how your repository should look like when you submit it to npm. You can find our example repository [here](https://github.com/n8n-io/n8n-nodes-starter). + +### Instructions + +1) Browse the repository page above and check the documentation on how to customize and build your own nodes +2) Clone the repository locally +3) Open the `package.json` file and change it according to your data, changing the package name, author information, etc. +4) Upload your repository to your own Github account +5) Submit your package to npm according to the information below following the naming and keyword guidelines + +### Important notes + To make your node available to the n8n community node repository, you must: * Make sure the package name starts with `n8n-node-` or `@/n8n-node-`. For example, `n8n-node-weather` or `@weatherPlugins/n8n-node-weather`. * Tag your package with `n8n-community-node-package`. -* Submit the package to the npm registry. Refer to npm's documentation on [Contributing packages to the registry](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry){:target=_blank .external-link} for more information. \ No newline at end of file +* Submit the package to the npm registry. Refer to npm's documentation on [Contributing packages to the registry](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry){:target=_blank .external-link} for more information. +* Make sure that you add your nodes and credentials to the `package.json` file inside the `n8n` attribute. + +## Migrating Pull Requests to npm packages + +If you have submitted a PR you may be requested to release it as a package instead. + +In this case, you should follow the above processes, cloning the starter repository and replacing the existing nodes and credentials with your own, while also making sure that you update the `package.json` file to reflect those changes and publish it to npm. From 7c40be66c848081b68cf8feb3d7101556087006d Mon Sep 17 00:00:00 2001 From: Deborah Barnard Date: Mon, 6 Jun 2022 09:58:43 +0100 Subject: [PATCH 08/18] update node submission guide --- .../community-nodes/submit-nodes.md | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/docs/integrations/community-nodes/submit-nodes.md b/docs/integrations/community-nodes/submit-nodes.md index b4923d5a4..4c816352b 100644 --- a/docs/integrations/community-nodes/submit-nodes.md +++ b/docs/integrations/community-nodes/submit-nodes.md @@ -5,29 +5,26 @@ Community nodes are npm packages, hosted in the npm registry. -## How to start +When building a node to submit to the community node repository, use the following resources to make sure your node setup is correct: -n8n provides an example of how your repository should look like when you submit it to npm. You can find our example repository [here](https://github.com/n8n-io/n8n-nodes-starter). + * View the [starter node](https://github.com/n8n-io/n8n-nodes-starter). + * Refer to the documentation on [building your own nodes](/integrations/creating-nodes/). + * Make sure your node follows the [standards](#standards) for community nodes. -### Instructions - -1) Browse the repository page above and check the documentation on how to customize and build your own nodes -2) Clone the repository locally -3) Open the `package.json` file and change it according to your data, changing the package name, author information, etc. -4) Upload your repository to your own Github account -5) Submit your package to npm according to the information below following the naming and keyword guidelines - -### Important notes +## Standards To make your node available to the n8n community node repository, you must: * Make sure the package name starts with `n8n-node-` or `@/n8n-node-`. For example, `n8n-node-weather` or `@weatherPlugins/n8n-node-weather`. * Tag your package with `n8n-community-node-package`. * Submit the package to the npm registry. Refer to npm's documentation on [Contributing packages to the registry](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry){:target=_blank .external-link} for more information. -* Make sure that you add your nodes and credentials to the `package.json` file inside the `n8n` attribute. +* Make sure that you add your nodes and credentials to the `package.json` file inside the `n8n` attribute. Refer to the [package.json in the starter node](https://github.com/n8n-io/n8n-nodes-starter/blob/master/package.json) for an example. -## Migrating Pull Requests to npm packages +## Migrating pull requests to npm packages -If you have submitted a PR you may be requested to release it as a package instead. +If you have submitted a pull request to n8n with a new node, you may need to release it as a community node instead. -In this case, you should follow the above processes, cloning the starter repository and replacing the existing nodes and credentials with your own, while also making sure that you update the `package.json` file to reflect those changes and publish it to npm. +1. Clone the [starter repository](https://github.com/n8n-io/n8n-nodes-starter). +2. Replace the example node and credentials with your own +3. Update the `package.json` file to reflect your changes. +4. Publish the package to npm. From 4297286569938dea1b7bf01fe79724242bb5b9b8 Mon Sep 17 00:00:00 2001 From: Deborah Barnard Date: Tue, 7 Jun 2022 10:11:10 +0100 Subject: [PATCH 09/18] formatting --- docs/integrations/community-nodes/submit-nodes.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/integrations/community-nodes/submit-nodes.md b/docs/integrations/community-nodes/submit-nodes.md index 4c816352b..117275e40 100644 --- a/docs/integrations/community-nodes/submit-nodes.md +++ b/docs/integrations/community-nodes/submit-nodes.md @@ -7,9 +7,9 @@ Community nodes are npm packages, hosted in the npm registry. When building a node to submit to the community node repository, use the following resources to make sure your node setup is correct: - * View the [starter node](https://github.com/n8n-io/n8n-nodes-starter). - * Refer to the documentation on [building your own nodes](/integrations/creating-nodes/). - * Make sure your node follows the [standards](#standards) for community nodes. +* View the [starter node](https://github.com/n8n-io/n8n-nodes-starter). +* Refer to the documentation on [building your own nodes](/integrations/creating-nodes/). +* Make sure your node follows the [standards](#standards) for community nodes. ## Standards From 4f1859a5b260295ffa4a484990f29b8a21def5a5 Mon Sep 17 00:00:00 2001 From: Deborah Barnard Date: Mon, 13 Jun 2022 14:24:50 +0100 Subject: [PATCH 10/18] merge main --- docs/integrations/community-nodes/submit-nodes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/community-nodes/submit-nodes.md b/docs/integrations/community-nodes/submit-nodes.md index 117275e40..ec88ffeff 100644 --- a/docs/integrations/community-nodes/submit-nodes.md +++ b/docs/integrations/community-nodes/submit-nodes.md @@ -25,6 +25,6 @@ To make your node available to the n8n community node repository, you must: If you have submitted a pull request to n8n with a new node, you may need to release it as a community node instead. 1. Clone the [starter repository](https://github.com/n8n-io/n8n-nodes-starter). -2. Replace the example node and credentials with your own +2. Replace the example nodes and credentials with your own 3. Update the `package.json` file to reflect your changes. 4. Publish the package to npm. From a36194763bcf02fe24e633820dfa2b9852c58b58 Mon Sep 17 00:00:00 2001 From: Deborah Barnard Date: Mon, 13 Jun 2022 16:32:41 +0100 Subject: [PATCH 11/18] start moving embed content over --- .../create_new_credentials.png | Bin 0 -> 21944 bytes .../create_new_credentials2.png | Bin 0 -> 24698 bytes .../managing-workflows/duplicate_workflow.png | Bin 0 -> 32696 bytes docs/embed/configuration.md | 242 +++++++++++ docs/embed/deployment.md | 17 + docs/embed/index.md | 13 + docs/embed/managing-workflows.md | 388 ++++++++++++++++++ docs/embed/prerequisites.md | 36 ++ docs/embed/workflow-templates.md | 30 ++ mkdocs.yml | 7 + 10 files changed, 733 insertions(+) create mode 100644 docs/_images/embed/managing-workflows/create_new_credentials.png create mode 100644 docs/_images/embed/managing-workflows/create_new_credentials2.png create mode 100644 docs/_images/embed/managing-workflows/duplicate_workflow.png create mode 100644 docs/embed/configuration.md create mode 100644 docs/embed/deployment.md create mode 100644 docs/embed/index.md create mode 100644 docs/embed/managing-workflows.md create mode 100644 docs/embed/prerequisites.md create mode 100644 docs/embed/workflow-templates.md diff --git a/docs/_images/embed/managing-workflows/create_new_credentials.png b/docs/_images/embed/managing-workflows/create_new_credentials.png new file mode 100644 index 0000000000000000000000000000000000000000..d07f9567acf324ee673e620b8f9f73eb21cf5212 GIT binary patch literal 21944 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 av2EJS1WR9SBJ@XAn7OI7NtMyr_`d_}9}aE+ literal 0 HcmV?d00001 diff --git a/docs/_images/embed/managing-workflows/create_new_credentials2.png b/docs/_images/embed/managing-workflows/create_new_credentials2.png new file mode 100644 index 0000000000000000000000000000000000000000..e1a6707631a4a01720b4e99f0858ac5c9ad44d99 GIT binary patch literal 24698 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 B4Uzx= literal 0 HcmV?d00001 diff --git a/docs/_images/embed/managing-workflows/duplicate_workflow.png b/docs/_images/embed/managing-workflows/duplicate_workflow.png new file mode 100644 index 0000000000000000000000000000000000000000..1afa61c09748d228a3db625f0ba833bca2a092da GIT binary patch literal 32696 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 literal 0 HcmV?d00001 diff --git a/docs/embed/configuration.md b/docs/embed/configuration.md new file mode 100644 index 000000000..b8b95bd96 --- /dev/null +++ b/docs/embed/configuration.md @@ -0,0 +1,242 @@ +# Configuration + +## Authentication + +n8n can be secured via Basic Authentication by setting the following environment variables: + +```sh +export N8N_BASIC_AUTH_ACTIVE=true +export N8N_BASIC_AUTH_USER= +export N8N_BASIC_AUTH_PASSWORD= +``` + +### Credential overwrites + +To offer easy OAuth login to users, it is possible to overwrite credentials on a global basis. This credential data will not be visible to users but is used automatically by the backend. + +In the Editor UI, all overwritten fields are hidden by default. So users are able to authenticate via OAuth by pressing the “connect” button on the credentials. + +Credential overwrites can be applied in two different ways: via Environment Variable and via REST API. + +#### Using environment variables + +Credential overwrites can be set via environment variable by setting the `CREDENTIALS_OVERWRITE_DATA` to `{ CREDENTIAL_NAME: { PARAMETER: VALUE }}`. + +!!! warning + Even though this is possible, it is not recommended. Environment variables can be easily read in n8n, so the data would leak to users. + + +#### Using REST APIs + +The recommended way is to load the data via a custom REST endpoint. This endpoint can be made available by setting the `CREDENTIALS_OVERWRITE_ENDPOINT` to a path under which this endpoint should be made available. + +!!! note + The endpoints can be called just one at a time for security reasons. + + +For example: + +1. Activate the endpoint by setting the environment variable in the environment n8n runs under: + + ```sh + export CREDENTIALS_OVERWRITE_ENDPOINT=send-credentials + ``` + +2. A JSON file with the credentials to overwrite is then needed. For example, a `oauth-credentials.json` file to overwrite credentials for Asana and GitHub could look like this: + + ```json + { + "asanaOAuth2Api": { + "clientId": "", + "clientSecret": "" + }, + "githubOAuth2Api": { + "clientId": "", + "clientSecret": "" + } + } + ``` + +3. Then apply it to the instance by sending it via curl: + + ```sh + curl -H "Content-Type: application/json" --data @oauth-credentials.json http://localhost:5678/send-credentials + ``` + +!!! note + There are cases when credentials are based on others. For example, the `googleSheetsOAuth2Api` extends the `googleOAuth2Api`. + In this case, you can set parameters on the parent credentials (`googleOAuth2Api`) which will be used by all child-credentials (`googleSheetsOAuth2Api`). + + +## Environment variables + +There are many [environment variables configurable in n8n](https://docs.n8n.io/reference/environment-variables.html). The following are most relevant for your hosted solution: + +| Variable | Values | Description | +| :------- | :----- | :---------- | +| `EXECUTIONS_TIMEOUT` | `number` | The maximum amount of time (in seconds) a workflow is allowed to run. | +| `EXECUTIONS_PROCESS` | `'main', 'own'` | If workflow executions should run in the main process or in their own process. The `main` setting requires fewer resources. | +| `EXECUTIONS_DATA_PRUNE` | `boolean` | If data of past executions should be deleted automatically. | +| `EXECUTIONS_DATA_MAX_AGE` | `number` | Number of hours after which old executions are deleted. | +| `NODES_EXCLUDE` | `Array` | Specific nodes that should not be made available. | +| `NODES_INCLUDE` | `Array` | Specific nodes that should be included. | +| `N8N_TEMPLATES_ENABLED` | `boolean` | Whether workflow templates should be enabled (true) or disabled (false) | +| `N8N_TEMPLATES_HOST` | `string` | Defaults to https://api.n8n.io. Change this if creating your own workflow template library. Note that to use your own workflow templates library, your API must provide the same endpoints and response structure as n8n's. Refer to [Workflow templates](workflow-templates.md) for more information. | + +## Backend hooks + +It is possible to define external hooks that are executed by n8n whenever a specific operation is performed. They can be used, for example, to log data, change data, or forbid an action by throwing an error. + +### Available hooks + +| Hook | Arguments | Description | +| :------- | :---------| :---------- | +| `credentials.create` | `[credentialData: ICredentialsDb]` | Called before new credentials get created. Can be used to restrict the number of credentials. | +| `credentials.delete` | `[id: credentialId]` | Called before credentials get deleted. | +| `credentials.update` | `[credentialData: ICredentialsDb]` | Called before existing credentials are saved. | +| `frontend.settings` | `[frontendSettings: IN8nUISettings]` | Gets called on n8n startup. Allows you to, for example, overwrite frontend data like the displayed OAuth URL. | +| `n8n.ready` | `[app: App]` | Called once n8n is ready. Can be used to, for example, register custom API endpoints. | +| `n8n.step` | | Called when an n8n process gets stopped. Allows you to save some process data. | +| `oauth1.authenticate` | `[oAuthOptions: clientOAuth1.Options, oauthRequestData: {oauth_callback: string}]` | Called before an OAuth1 authentication. Can be used to overwrite an OAuth callback URL. | +| `oauth2.callback` | `[oAuth2Parameters: {clientId: string, clientSecret: string \| undefined, accessTokenUri: string, authorizationUri: string, redirectUri: string, scopes: string[]}]` | Called in an OAuth2 callback. Can be used to overwrite an OAuth callback URL. | +| `workflow.activate` | `[workflowData: IWorkflowDb]` | Called before a workflow gets activated. Can be used to restrict the number of active workflows. | +| `workflow.afterDelete` | `[workflowId: string]` | Called after a workflow gets deleted. | +| `workflow.afterUpdate` | `[workflowData: IWorkflowBase]` | Called after an existing workflow gets saved. | +| `workflow.create` | `[workflowData: IWorkflowBase]` | Called before a workflow gets created. Can be used to restrict the number of saved workflows. | +| `workflow.delete` | `[workflowId: string]` | Called before a workflow gets delete. | +| `workflow.postExecute` | `[run: IRun, workflowData: IWorkflowBase]` | Called after a workflow gets executed. | +| `workflow.preExecute` | `[workflow: Workflow: mode: WorkflowExecuteMode]` | Called before a workflow gets executed. Allows you to count or limit the number of workflow executions. | +| `workflow.update` | `[workflowData: IWorkflowBase]` | Called before an existing workflow gets saved. | + +### Registering hooks + +Hooks are set by registering a hook file that contains the hook functions. +Hook registration is done via the environment variable `EXTERNAL_HOOK_FILES`. + +The variable can be set to a single file: + +`EXTERNAL_HOOK_FILES=/data/hook.js` + +Or to contain multiple files separated by a semicolon: + +`EXTERNAL_HOOK_FILES=/data/hook1.js;/data/hook2.js` + +### Hook files + +Hook files are regular JavaScript files that have the following format: + +```js +module.exports = { + "frontend": { + "settings": [ + async function (settings) { + settings.oauthCallbackUrls.oauth1 = 'https://n8n.example.com/oauth1/callback'; + settings.oauthCallbackUrls.oauth2 = 'https://n8n.example.com/oauth2/callback'; + } + ] + }, + "workflow": { + "activate": [ + async function (workflowData) { + const activeWorkflows = await this.dbCollections.Workflow.count({ active: true }); + + if (activeWorkflows > 1) { + throw new Error( + 'Active workflow limit reached.' + ); + } + } + ] + } +} +``` + +### Hook functions + +A hook or a hook file can contain multiple hook functions, with all functions executed one after another. +If the parameters of the hook function are objects, it is possible to change the data of that parameter to change the behavior of n8n. +Additionally, the database can also be accessed in any hook function via `this.dbCollections` (see above). + +## Frontend external hooks + +Like backend external hooks, it is possible to define external hooks in the frontend code that get executed by n8n whenever a specific operation is performed. They can be used, for example, to log data and change data. + +### Available hooks + +| Hook | Description | +| :------- | :---------- | +| `credentialsEdit.credentialTypeChanged` | Called when an existing credential's type is changed. | +| `credentials.create` | Called when a new credential is created. | +| `credentialsList.dialogVisibleChanged` | | +| `dataDisplay.nodeTypeChanged` | | +| `dataDisplay.onDocumentationUrlClick` | Called when the help documentation link is selected. | +| `execution.open` | Called when an existing execution is opened. | +| `executionsList.openDialog` | Called when the an execution is selected from existing Workflow Executions. | +| `expressionEdit.itemSelected` | | +| `expressionEdit.dialogVisibleChanged` | | +| `nodeCreateList.filteredNodeTypesComputed` | | +| `nodeCreateList.nodeFilterChanged` | Called when a new entry has been made in the node panel filter. | +| `nodeCreateList.selectedTypeChanged` | | +| `nodeCreateList.mounted` | | +| `nodeCreateList.destroyed` | | +| `nodeSettings.credentialSelected` | | +| `nodeSettings.valueChanged` | | +| `nodeView.createNodeActiveChanged` | | +| `nodeView.addNodeButton` | | +| `nodeView.createNodeActiveChanged` | | +| `nodeView.mount` | | +| `pushConnection.executionFinished` | | +| `showMessage.showError` | | +| `runData.displayModeChanged` | | +| `workflow.activeChange` | | +| `workflow.activeChangeCurrent` | | +| `workflow.afterUpdate` | Called when an existing workflow is updated. | +| `workflow.open` | | +| `workflowRun.runError` | | +| `workflowRun.runWorkflow` | Called when a workflow is executed. | +| `workflowSettings.dialogVisibleChanged` | | +| `workflowSettings.saveSettings` | Called when the settings of a workflow are saved. | + +### Registering hooks + +Hooks can be set by loading the hooks script on the page. One way to do this is by creating a hooks file in the project and adding a script tag in your `editor-ui/public/index.html` file: + +```html + +``` + +### Hook files + +Hook files are regular JavaScript files which have the following format: + +```js +window.n8nExternalHooks = { + nodeView: { + mount: [ + function (store, meta) { + // do something + }, + ], + createNodeActiveChanged: [ + function (store, meta) { + // do something + }, + function (store, meta) { + // do something else + }, + ], + addNodeButton: [ + function (store, meta) { + // do something + }, + ], + }, +}; +``` + +### Hook functions + +Multiple hook functions can be defined per hook. Each hook function is invoked with the following arguments arguments: + +* `store`: The vuex store object. Can be used to modify/get data from the store. +* `metadata`: Object that contains any data provided by the hook. To see exactly what is passed, search for the hook in the `editor-ui` package. diff --git a/docs/embed/deployment.md b/docs/embed/deployment.md new file mode 100644 index 000000000..6d3ac49f3 --- /dev/null +++ b/docs/embed/deployment.md @@ -0,0 +1,17 @@ +# Deployment + +See the [official n8n documentation](https://docs.n8n.io/reference/server-setup.html) for detailed setup options. + +## User data + +It is recommended that you follow the same or similar practices we use internally for n8n.cloud: User data is saved using [Rook](https://rook.io/) and, if an n8n server goes down, a new instance is started on another machine using the same data. + +In this manner, backups only need to be used in case of a catastrophic failure, or when a user wants to reactivate their account within your prescribed retention period (2 weeks for n8n.cloud). + +## Backups + +We recommend creating nightly backups by attaching another container, and copying all data to this second container. In this manner, RAM usage is negligible, and so does not impact the amount of users you can place on the server. + +## Restarting + +If your instance is down or restarting, missed executions (e.g. Cron or Webhook nodes) during this time are not recoverable. If it is important for you, you would have to build another proxy in front of it which caches the data. diff --git a/docs/embed/index.md b/docs/embed/index.md new file mode 100644 index 000000000..04d5ba95a --- /dev/null +++ b/docs/embed/index.md @@ -0,0 +1,13 @@ +# Introduction + +n8n Embed is part of n8n's paid offering. Using Embed, you can white label n8n, or incorporate it in your software as part of your commercial product. + +For more information about when to use Embed, as well as costs and licensing processes, contact [TODO]. + +## Support + +The [community forum](https://community.n8n.io/) can help with many issues. If you are a current Embed customer, you can also contact n8n support, using the email provided when you bought the license. + +## Russia and Belarus + +n8n Embed is not available in Russia and Belarus. Refer to our blog post [Update on n8n cloud accounts in Russia and Belarus](https://n8n.io/blog/update-on-n8n-cloud-accounts-in-russia-and-belarus/) for more information. \ No newline at end of file diff --git a/docs/embed/managing-workflows.md b/docs/embed/managing-workflows.md new file mode 100644 index 000000000..c12d66c3b --- /dev/null +++ b/docs/embed/managing-workflows.md @@ -0,0 +1,388 @@ +# Workflow management + +When managing an embedded n8n deployment, spanning across teams or organizations, you will likely need to run the same (or similar) workflows for multiple users. There are two available options for doing so: + +| Solution | Pros | Cons | +| -------- | ---- | ---- | +| Create a workflow for each user | No limitation on how workflow is started (can use any trigger) | Requires managing multiple workflows. | +| Create a single workflow, and pass it user credentials when executing | Simplified workflow management (i.e. only need to change one workflow). | To run the workflow, your product must call it | + +Below we cover the steps for both approaches. + +!!! warning + The APIs referenced in this document are subject to change at any time. Be sure the check for continued functionality with each version upgrade. + + +## Workflow per user + +There are three general steps to follow: + +* Obtain the credentials for each user, and any additional parameters that may be required based on the workflow. +* Create the n8n credentials for this user. +* Create the workflow. + +### 1. Obtain user credentials + +Here you need to capture all credentials for any node/service this user must authenticate with, along with any additional parameters required for the particular workflow. The credentials and any parameters needed will depend on your workflow and what you are trying to do. + +### 2. Create user credentials + +After all relevant credential details have been obtained, you can proceed to create the relevant service credentials in n8n. This can be done via the Editor UI or API call. + + +#### Via Editor UI + +1. From the menu select **Credentials** > **New**. +1. Use the drop-down to select the **Credential type** to create, for example *Airtable*. + ![Create New Credentials drop-down](/_images/embed/managing-workflows/create_new_credentials.png) +1. In the **Create New Credentials** modal, enter the corresponding credentials details for the user, and select the nodes that will have access to these credentials. + ![Create New Credentials modal](/_images/embed/managing-workflows/create_new_credentials2.png) +1. Click **Create** to finish and save. + +#### Via API + +The frontend API used by the Editor UI can also be called to achieve the same result. The API endpoint is in the format: `https:///rest/credentials`. + +For example, to create the credentials in the Editor UI example above, the request would be: +``` +POST https:///rest/credentials +``` + +With the request body: +```json +{ + "name":"MyAirtable", + "type":"airtableApi", + "nodesAccess":[ + { + "nodeType":"n8n-nodes-base.airtable" + } + ], + "data":{ + "apiKey":"q12we34r5t67yu" + } +} +``` + +The response will contain the ID of the new credentials, which you will use when creating the workflow for this user: +```json +{ + "data":{ + "name":"MyAirtable", + "type":"airtableApi", + "data":{ + "apiKey":"q12we34r5t67yu" + }, + "nodesAccess":[ + { + "nodeType":"n8n-nodes-base.airtable", + "date":"2021-09-10T07:41:27.770Z" + } + ], + "id":"29", + "createdAt":"2021-09-10T07:41:27.777Z", + "updatedAt":"2021-09-10T07:41:27.777Z" + } +} +``` + +### 3. Create the workflow + +Best practice is to have a “base” workflow that you then duplicate and customize for each new user with their credentials (and any other details). + +You can duplicate and customize your template workflow using either the Editor UI or API call. + +#### Via Editor UI + +1. From the menu select **Workflows** > **Open** to open the template workflow to be duplicated. + +1. Select **Workflows** > **Duplicate**, then enter a name for this new workflow and click **Save**. + ![Duplicate workflow](/_images/embed/managing-workflows/duplicate_workflow.png) + +1. Update all relevant nodes to use the credentials for this user (created above). + +1. **Save** this workflow set it to **Active** using the toggle in the top-right corner. + +#### Via API + +1. Fetch the JSON of the template workflow using the endpoint: `https:///rest/workflows/` +``` +GET https:///rest/workflows/1012 +``` + +The response will contain the JSON data of the selected workflow: +```json +{ + "data": { + "id": "1012", + "name": "Nathan's Workflow", + "active": false, + "nodes": [ + { + "parameters": {}, + "name": "Start", + "type": "n8n-nodes-base.start", + "typeVersion": 1, + "position": [ + 130, + 640 + ] + }, + { + "parameters": { + "authentication": "headerAuth", + "url": "https://internal.users.n8n.cloud/webhook/custom-erp", + "options": { + "splitIntoItems": true + }, + "headerParametersUi": { + "parameter": [ + { + "name": "unique_id", + "value": "recLhLYQbzNSFtHNq" + } + ] + } + }, + "name": "HTTP Request", + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 1, + "position": [ + 430, + 300 + ], + "credentials": { + "httpHeaderAuth": "beginner_course" + } + }, + { + "parameters": { + "operation": "append", + "application": "appKBGQfbm6NfW6bv", + "table": "processingOrders", + "options": {} + }, + "name": "Airtable", + "type": "n8n-nodes-base.airtable", + "typeVersion": 1, + "position": [ + 990, + 210 + ], + "credentials": { + "airtableApi": "Airtable" + } + }, + { + "parameters": { + "conditions": { + "string": [ + { + "value1": "={{$json[\"orderStatus\"]}}", + "value2": "processing" + } + ] + } + }, + "name": "IF", + "type": "n8n-nodes-base.if", + "typeVersion": 1, + "position": [ + 630, + 300 + ] + }, + { + "parameters": { + "keepOnlySet": true, + "values": { + "number": [ + { + "name": "=orderId", + "value": "={{$json[\"orderID\"]}}" + } + ], + "string": [ + { + "name": "employeeName", + "value": "={{$json[\"employeeName\"]}}" + } + ] + }, + "options": {} + }, + "name": "Set", + "type": "n8n-nodes-base.set", + "typeVersion": 1, + "position": [ + 800, + 210 + ] + }, + { + "parameters": { + "functionCode": "let totalBooked = items.length;\nlet bookedSum = 0;\n\nfor(let i=0; i < items.length; i++) {\n bookedSum = bookedSum + items[i].json.orderPrice;\n}\nreturn [{json:{totalBooked, bookedSum}}]\n" + }, + "name": "Function", + "type": "n8n-nodes-base.function", + "typeVersion": 1, + "position": [ + 800, + 400 + ] + }, + { + "parameters": { + "webhookUri": "https://discord.com/api/webhooks/865213348202151968/oD5_WPDQwtr22Vjd_82QP3-_4b_lGhAeM7RynQ8Js5DzyXrQEnj0zeAQIA6fki1JLtXE", + "text": "=This week we have {{$json[\"totalBooked\"]}} booked orders with a total value of {{$json[\"bookedSum\"]}}. My Unique ID: {{$node[\"HTTP Request\"].parameter[\"headerParametersUi\"][\"parameter\"][0][\"value\"]}}" + }, + "name": "Discord", + "type": "n8n-nodes-base.discord", + "typeVersion": 1, + "position": [ + 1000, + 400 + ] + }, + { + "parameters": { + "triggerTimes": { + "item": [ + { + "mode": "everyWeek", + "hour": 9 + } + ] + } + }, + "name": "Cron", + "type": "n8n-nodes-base.cron", + "typeVersion": 1, + "position": [ + 220, + 300 + ] + } + ], + "connections": { + "HTTP Request": { + "main": [ + [ + { + "node": "IF", + "type": "main", + "index": 0 + } + ] + ] + }, + "Start": { + "main": [ + [] + ] + }, + "IF": { + "main": [ + [ + { + "node": "Set", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Function", + "type": "main", + "index": 0 + } + ] + ] + }, + "Set": { + "main": [ + [ + { + "node": "Airtable", + "type": "main", + "index": 0 + } + ] + ] + }, + "Function": { + "main": [ + [ + { + "node": "Discord", + "type": "main", + "index": 0 + } + ] + ] + }, + "Cron": { + "main": [ + [ + { + "node": "HTTP Request", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "createdAt": "2021-07-16T11:15:46.066Z", + "updatedAt": "2021-07-16T12:05:44.045Z", + "settings": {}, + "staticData": null, + "tags": [] + } +} +``` + +1. Save the returned JSON data and update any relevant credentials and fields for the new user. + +1. Create a new workflow using the updated JSON as the request body at endpoint: `https:///rest/workflows` +``` +POST https:///rest/workflows/ +``` + +The response will contain the ID of the new workflow, which you will use in the next step. + +1. Lastly, activate the new workflow: +``` +PATCH https:///rest/workflows/1012 +``` + +Passing the additional value `active` in your JSON payload: +```json +// ... +"active":true, +"settings": {}, +"staticData": null, +"tags": [] +``` + +## Single workflow + +There are four steps to follow to implement this method: + +* Obtain the credentials for each user, and any additional parameters that may be required based on the workflow. See [Obtain user credentials](#obtain-user-credentials) above. +* Create the n8n credentials for this user. See [Create user credentials](#create-user-credentials) above. +* Create the workflow. +* Call the workflow as needed. + +### Create the workflow + +The details and scope of this workflow will vary greatly according to the individual use case, however there are a few design implementations to keep in mind: + +* This workflow must be triggered by a [Webhook](https://docs.n8n.io/nodes/n8n-nodes-base.webhook/#webhook) node. +* The incoming webhook call must contain the user’s credentials and any other workflow parameters required. +* Each node where the user’s credentials are needed should use an [expression](https://docs.n8n.io/nodes/expressions.html) so that the node’s credential field reads the credential provided in the webhook call. +* Save and activate the workflow, ensuring the [Production URL](https://docs.n8n.io/nodes/n8n-nodes-base.webhook/#node-reference) is selected for the Webhook node. + +### Call the workflow + +For each new user, or for any existing user as may be needed, call the webhook defined as the workflow trigger and provide the necessary credentials (and any other workflow parameters). diff --git a/docs/embed/prerequisites.md b/docs/embed/prerequisites.md new file mode 100644 index 000000000..1fd4df809 --- /dev/null +++ b/docs/embed/prerequisites.md @@ -0,0 +1,36 @@ +# Prerequisites + +The requirements provided here are an example based on our n8n.cloud and are for illustrative purposes only. Your requirements may vary depending on the number of users, workflows, and executions. Contact n8n for more information. + +| Component | Sizing | Supported | +| :-------- | :----- | :-------- | +| CPU/vCPU | Minimum 10 CPU cycles, scaling as needed | Any public or private cloud | +| Database | 512 MB - 4 GB SSD | SQLite, PostgreSQL, MySQL, MariaDB | +| Memory | 320 MB - 2 GB | | + +## CPU considerations + +n8n is not CPU intensive so even small instances (of AWS, GCP, etc.) should be sufficient for most use cases. Generally, memory requirements supersede CPU requirements, so focus resources there when planning your infrastructure. + +## Database considerations + +n8n uses its database to store credentials, past executions, and workflows. +A core feature of n8n is the flexibility to choose a database. All of the supported databases have different advantages and disadvantages, which you have to consider individually and pick the one that best suits your needs. **By default n8n creates a SQLite database if none is found at the given location.** + +It is recommended that every n8n instance have a dedicated database. This helps to prevent dependencies and potential performance degradation. If it is not possible to provide an own database to every n8n instance we recommend making use of Postgres’s schema feature. + +For Postgres, MySQL and MariaDB it is required that the database already exists on the DB-instance. The database user for the n8n process needs to have full permissions on all tables that they are using/creating. The database schema is created and maintained by n8n itself, no further actions are required. + +### Best practices + +* SSD storage is recommended. +* In containerized cloud environments, ensure that the volume is persisted and mounted when stopping/starting a container. If not, all data will be lost. +* If using Postgres, do not use the `tablePrefix` configuration option. It will be deprecated in the near future. +* Pay attention to the changelog of new versions and consider reverting migrations before downgrading. +* Implement at least the basic database security and stability mechanisms such as IP-whitelisting and backups. + +## Memory considerations + +An n8n instance does not typically require large amounts of available memory, for example an n8n.cloud instance at idle requires ~100MB. It is the nature of your workflows and the data being processed that will determine your ultimate memory requirements. + +For example, while most nodes just pass data to the next node in the workflow, `Function` nodes create a pre- and post-processing copy of the data. When dealing will large binary files, this can quickly consume all available resources. diff --git a/docs/embed/workflow-templates.md b/docs/embed/workflow-templates.md new file mode 100644 index 000000000..2c0962bd1 --- /dev/null +++ b/docs/embed/workflow-templates.md @@ -0,0 +1,30 @@ +# Workflow templates + +n8n provides a library of workflow templates. When embedding n8n, you can: + +* Continue to use n8n's workflow templates library (this is the default behavior) +* Disable workflow templates +* Create your own workflow templates library + +## Disable workflow templates + +In your environment variables, set `N8N_TEMPLATES_ENABLED` to false. + +## Use your own workflow templates library + +In your environment variables, set `N8N_TEMPLATES_HOST` to the base URL of your API. + +Your API must provide the same endpoints and data structure as n8n's. + +The endpoints are: + +| Method | Path | +| ------ | ---- | +| GET | /templates/workflows/`` | +| GET | /templates/workflows | +| GET | /templates/collections/`` | +| GET | /templates/collections | +| GET | /templates/categories | +| GET | /health | + +To learn about the data structure, try out the endpoints. You can also [contact us](mailto:support@n8n.io) for more support. \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 66de15880..5f43c5869 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -203,4 +203,11 @@ nav: - Pagination: api/pagination.md - Using the API playground: api/using-api-playground.md - API reference: api/api-reference.md + - Embed: + - n8n Embed: embed/index.md + - Prerequisites: embed/prerequisites.md + - Deployment: embed/deployment.md + - Configuration: embed/configuration.md + - Workflow management: embed/managing-workflows.md + - Workflows templates: embed/workflow-templates.md - Contributing: contributing.md From b78ba2bb1a18bde63603926e2c8c0f9198cb72ba Mon Sep 17 00:00:00 2001 From: Deborah Date: Tue, 14 Jun 2022 11:38:54 +0100 Subject: [PATCH 12/18] Update docs/integrations/community-nodes/submit-nodes.md --- docs/integrations/community-nodes/submit-nodes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/community-nodes/submit-nodes.md b/docs/integrations/community-nodes/submit-nodes.md index ec88ffeff..448897d85 100644 --- a/docs/integrations/community-nodes/submit-nodes.md +++ b/docs/integrations/community-nodes/submit-nodes.md @@ -15,7 +15,7 @@ When building a node to submit to the community node repository, use the followi To make your node available to the n8n community node repository, you must: -* Make sure the package name starts with `n8n-node-` or `@/n8n-node-`. For example, `n8n-node-weather` or `@weatherPlugins/n8n-node-weather`. +* Make sure the package name starts with `n8n-nodes-` or `@/n8n-nodes-`. For example, `n8n-nodes-weather` or `@weatherPlugins/n8n-nodes-weather`. * Tag your package with `n8n-community-node-package`. * Submit the package to the npm registry. Refer to npm's documentation on [Contributing packages to the registry](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry){:target=_blank .external-link} for more information. * Make sure that you add your nodes and credentials to the `package.json` file inside the `n8n` attribute. Refer to the [package.json in the starter node](https://github.com/n8n-io/n8n-nodes-starter/blob/master/package.json) for an example. From bf3222c8645e624d3cba03fadfb78e9507016a3c Mon Sep 17 00:00:00 2001 From: Deborah Barnard Date: Wed, 15 Jun 2022 11:05:24 +0100 Subject: [PATCH 13/18] release notes for 0.182.0 plus some style tweaks --- docs/_extra/css/extra.css | 4 +++ .../nodes/n8n-nodes-base.postbin.md | 3 ++ docs/reference/release-notes.md | 34 +++++++++++++++++++ styles/Vocab/default/accept.txt | 3 ++ 4 files changed, 44 insertions(+) create mode 100644 docs/integrations/nodes/n8n-nodes-base.postbin.md diff --git a/docs/_extra/css/extra.css b/docs/_extra/css/extra.css index 41c95de0d..539d2478b 100644 --- a/docs/_extra/css/extra.css +++ b/docs/_extra/css/extra.css @@ -111,6 +111,10 @@ margin-top: 0; } +.n8n-new-features + .n8n-new-features { + margin-top: 1em; +} + /* preserve the logo and site title on page scroll */ .md-header__topic:first-child { diff --git a/docs/integrations/nodes/n8n-nodes-base.postbin.md b/docs/integrations/nodes/n8n-nodes-base.postbin.md new file mode 100644 index 000000000..d04e04ac1 --- /dev/null +++ b/docs/integrations/nodes/n8n-nodes-base.postbin.md @@ -0,0 +1,3 @@ +# Postbin + +[Postbin](https://www.toptal.com/developers/postbin/) is a service that collects all requests to a special URL, which you can use to test your API Clients or your WebHooks. \ No newline at end of file diff --git a/docs/reference/release-notes.md b/docs/reference/release-notes.md index 0875c6065..3e5cb7add 100644 --- a/docs/reference/release-notes.md +++ b/docs/reference/release-notes.md @@ -1,5 +1,39 @@ # Release notes +## n8n@0.182.0 + +View the [commits](https://github.com/n8n-io/n8n/compare/n8n@0.181.2...n8n@0.182.0) for this version.
+**Release date:** 2022-06-14 + +This release contains enhancements to the Twilio and Wise integrations, and adds support for a new grant type for OAuth2. It also includes some bug fixes. + +### New features + +Added support for the client_credentials grant type for OAuth2. + +### Node enhancements + +* [Twilio node](/integrations/nodes/n8n-nodes-base.twilio/): added the ability to make a voice call using TTS. +* [Wise node](/integrations/nodes/n8n-nodes-base.wise/): added support for downloading statements as JSON, CSV, or PDF. + +### Bug fixes + +* Core: fixes an issue that was causing parameters to get lost in some edge cases. +* Core: fixes an issue with combined expressions not resolving if one expression was invalid. +* Core: fixed an issue that was causing the public API to fail to build on Windows. +* Editor: ensure errors display correctly. +* [HTTP Request node](/integrations/core-nodes/n8n-nodes-base.httpRequest/): better handling for requests that return null. +* [Pipedrive node](/integrations/nodes/n8n-nodes-base.pipedrive/): fixes a limits issue with the GetAll operation on the Lead resource. +* [Postbin node](/integrations/nodes/n8n-nodes-base.postbin/): remove a false error. + +### Contributors + +[Albrecht Schmidt](https://github.com/IamDrowsy) +[Erick Friis](https://github.com/efriis) +[JoLo](https://github.com/jolo-dev) +[Shaun](https://github.com/simshaun) +[Valentin Mocanu](https://github.com/rontav) + ## n8n@0.181.2 View the [commits](https://github.com/n8n-io/n8n/compare/n8n@0.181.1...n8n@0.181.2){:target=_blank .external-link} for this version.
diff --git a/styles/Vocab/default/accept.txt b/styles/Vocab/default/accept.txt index 172dfb11f..2c46324ac 100644 --- a/styles/Vocab/default/accept.txt +++ b/styles/Vocab/default/accept.txt @@ -5,4 +5,7 @@ enum n8n namespace onboarding +Pipedrive +Postbin +Twilio URL \ No newline at end of file From 98c9ae2faa47311386435f440811797349a54c82 Mon Sep 17 00:00:00 2001 From: Deborah Barnard Date: Wed, 15 Jun 2022 11:11:17 +0100 Subject: [PATCH 14/18] add some details for postbin --- .../nodes/n8n-nodes-base.postbin.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/integrations/nodes/n8n-nodes-base.postbin.md b/docs/integrations/nodes/n8n-nodes-base.postbin.md index d04e04ac1..e17f3e3b9 100644 --- a/docs/integrations/nodes/n8n-nodes-base.postbin.md +++ b/docs/integrations/nodes/n8n-nodes-base.postbin.md @@ -1,3 +1,20 @@ # Postbin -[Postbin](https://www.toptal.com/developers/postbin/) is a service that collects all requests to a special URL, which you can use to test your API Clients or your WebHooks. \ No newline at end of file +[Postbin](https://www.toptal.com/developers/postbin/) is a service that collects all requests to a URL, which you can use to test your API Clients or your WebHooks. + + +## Send requests + +To send requests to a Postbin bin: + +1. Go to [Postbin](https://www.toptal.com/developers/postbin/) and follow the steps to generate a new bin. Postbin gives you a unique URL, including a bin ID. +2. In the Postbin node, select the **Request** resource. +3. Choose the type of **Operation** you want to perform. +4. Enter your bin ID in **Bin ID**. + +## Create and manage bins + +You can create and manage Postbin bins using the Postbin node. + +1. In **Resource**, select **Bin**. +2. Choose an **Operation**. You can create, delete, or get a bin. \ No newline at end of file From 36878a6c3bf13c42eabc95ab8e6b685c3ff201c8 Mon Sep 17 00:00:00 2001 From: Deborah Barnard Date: Wed, 15 Jun 2022 11:18:44 +0100 Subject: [PATCH 15/18] open links in new tab --- .../nodes/n8n-nodes-base.postbin.md | 4 ++-- docs/reference/release-notes.md | 22 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/integrations/nodes/n8n-nodes-base.postbin.md b/docs/integrations/nodes/n8n-nodes-base.postbin.md index e17f3e3b9..db7819697 100644 --- a/docs/integrations/nodes/n8n-nodes-base.postbin.md +++ b/docs/integrations/nodes/n8n-nodes-base.postbin.md @@ -1,13 +1,13 @@ # Postbin -[Postbin](https://www.toptal.com/developers/postbin/) is a service that collects all requests to a URL, which you can use to test your API Clients or your WebHooks. +[Postbin](https://www.toptal.com/developers/postbin/){:target=_blank .external-link} is a service that collects all requests to a URL, which you can use to test your API Clients or your WebHooks. ## Send requests To send requests to a Postbin bin: -1. Go to [Postbin](https://www.toptal.com/developers/postbin/) and follow the steps to generate a new bin. Postbin gives you a unique URL, including a bin ID. +1. Go to [Postbin](https://www.toptal.com/developers/postbin/){:target=_blank .external-link} and follow the steps to generate a new bin. Postbin gives you a unique URL, including a bin ID. 2. In the Postbin node, select the **Request** resource. 3. Choose the type of **Operation** you want to perform. 4. Enter your bin ID in **Bin ID**. diff --git a/docs/reference/release-notes.md b/docs/reference/release-notes.md index 3e5cb7add..c28853f76 100644 --- a/docs/reference/release-notes.md +++ b/docs/reference/release-notes.md @@ -2,7 +2,7 @@ ## n8n@0.182.0 -View the [commits](https://github.com/n8n-io/n8n/compare/n8n@0.181.2...n8n@0.182.0) for this version.
+View the [commits](https://github.com/n8n-io/n8n/compare/n8n@0.181.2...n8n@0.182.0){:target=_blank .external-link} for this version.
**Release date:** 2022-06-14 This release contains enhancements to the Twilio and Wise integrations, and adds support for a new grant type for OAuth2. It also includes some bug fixes. @@ -13,8 +13,8 @@ Added support for the client_credentials grant type for OAuth2. ### Node enhancements -* [Twilio node](/integrations/nodes/n8n-nodes-base.twilio/): added the ability to make a voice call using TTS. -* [Wise node](/integrations/nodes/n8n-nodes-base.wise/): added support for downloading statements as JSON, CSV, or PDF. +* [Twilio node](/integrations/nodes/n8n-nodes-base.twilio/){:target=_blank}: added the ability to make a voice call using TTS. +* [Wise node](/integrations/nodes/n8n-nodes-base.wise/){:target=_blank}: added support for downloading statements as JSON, CSV, or PDF. ### Bug fixes @@ -22,17 +22,17 @@ Added support for the client_credentials grant type for OAuth2. * Core: fixes an issue with combined expressions not resolving if one expression was invalid. * Core: fixed an issue that was causing the public API to fail to build on Windows. * Editor: ensure errors display correctly. -* [HTTP Request node](/integrations/core-nodes/n8n-nodes-base.httpRequest/): better handling for requests that return null. -* [Pipedrive node](/integrations/nodes/n8n-nodes-base.pipedrive/): fixes a limits issue with the GetAll operation on the Lead resource. -* [Postbin node](/integrations/nodes/n8n-nodes-base.postbin/): remove a false error. +* [HTTP Request node](/integrations/core-nodes/n8n-nodes-base.httpRequest/){:target=_blank}: better handling for requests that return null. +* [Pipedrive node](/integrations/nodes/n8n-nodes-base.pipedrive/){:target=_blank}: fixes a limits issue with the GetAll operation on the Lead resource. +* [Postbin node](/integrations/nodes/n8n-nodes-base.postbin/){:target=_blank}: remove a false error. ### Contributors -[Albrecht Schmidt](https://github.com/IamDrowsy) -[Erick Friis](https://github.com/efriis) -[JoLo](https://github.com/jolo-dev) -[Shaun](https://github.com/simshaun) -[Valentin Mocanu](https://github.com/rontav) +[Albrecht Schmidt](https://github.com/IamDrowsy){:target=_blank .external-link} +[Erick Friis](https://github.com/efriis){:target=_blank .external-link} +[JoLo](https://github.com/jolo-dev){:target=_blank .external-link} +[Shaun](https://github.com/simshaun){:target=_blank .external-link} +[Valentin Mocanu](https://github.com/rontav){:target=_blank .external-link} ## n8n@0.181.2 From 35a9b14e732c3a02c656687b28f27a530d62fd47 Mon Sep 17 00:00:00 2001 From: Deborah Barnard Date: Wed, 15 Jun 2022 14:56:34 +0100 Subject: [PATCH 16/18] wip --- docs/embed/configuration.md | 30 +++++++++++++++--------------- docs/embed/deployment.md | 10 +++++----- docs/embed/index.md | 4 ++-- docs/embed/managing-workflows.md | 16 ++++++++-------- docs/embed/prerequisites.md | 23 ++++++++++++----------- overrides/main.html | 9 ++++++++- styles/Vocab/default/accept.txt | 5 ++++- 7 files changed, 54 insertions(+), 43 deletions(-) diff --git a/docs/embed/configuration.md b/docs/embed/configuration.md index b8b95bd96..ef1ed1e21 100644 --- a/docs/embed/configuration.md +++ b/docs/embed/configuration.md @@ -2,7 +2,7 @@ ## Authentication -n8n can be secured via Basic Authentication by setting the following environment variables: +You can secure n8n using Basic Authentication by setting the following environment variables: ```sh export N8N_BASIC_AUTH_ACTIVE=true @@ -12,23 +12,23 @@ export N8N_BASIC_AUTH_PASSWORD= ### Credential overwrites -To offer easy OAuth login to users, it is possible to overwrite credentials on a global basis. This credential data will not be visible to users but is used automatically by the backend. +To offer OAuth login to users, it's possible to overwrite credentials on a global basis. This credential data isn't visible to users but the backend uses it automatically. -In the Editor UI, all overwritten fields are hidden by default. So users are able to authenticate via OAuth by pressing the “connect” button on the credentials. +In the Editor UI, n8n hides all overwritten fields by default. This means that users are able to authenticate using OAuth by pressing the "connect" button on the credentials. -Credential overwrites can be applied in two different ways: via Environment Variable and via REST API. +n8n offers two ways to apply credential overwrites: using Environment Variable and using the REST API. #### Using environment variables -Credential overwrites can be set via environment variable by setting the `CREDENTIALS_OVERWRITE_DATA` to `{ CREDENTIAL_NAME: { PARAMETER: VALUE }}`. +Credential overwrites can be set using environment variable by setting the `CREDENTIALS_OVERWRITE_DATA` to `{ CREDENTIAL_NAME: { PARAMETER: VALUE }}`. !!! warning - Even though this is possible, it is not recommended. Environment variables can be easily read in n8n, so the data would leak to users. + Even though this is possible, it isn't recommended. Environment variables aren't protected in n8n, so the data can leak to users. #### Using REST APIs -The recommended way is to load the data via a custom REST endpoint. This endpoint can be made available by setting the `CREDENTIALS_OVERWRITE_ENDPOINT` to a path under which this endpoint should be made available. +The recommended way is to load the data using a custom REST endpoint. Set the `CREDENTIALS_OVERWRITE_ENDPOINT` to a path under which this endpoint should be made available. !!! note The endpoints can be called just one at a time for security reasons. @@ -57,7 +57,7 @@ For example: } ``` -3. Then apply it to the instance by sending it via curl: +3. Then apply it to the instance by sending it using curl: ```sh curl -H "Content-Type: application/json" --data @oauth-credentials.json http://localhost:5678/send-credentials @@ -85,7 +85,7 @@ There are many [environment variables configurable in n8n](https://docs.n8n.io/r ## Backend hooks -It is possible to define external hooks that are executed by n8n whenever a specific operation is performed. They can be used, for example, to log data, change data, or forbid an action by throwing an error. +It's possible to define external hooks that n8n executes whenever a specific operation runs. You can use these to, for example, to log data, change data, or forbid an action by throwing an error. ### Available hooks @@ -111,7 +111,7 @@ It is possible to define external hooks that are executed by n8n whenever a spec ### Registering hooks Hooks are set by registering a hook file that contains the hook functions. -Hook registration is done via the environment variable `EXTERNAL_HOOK_FILES`. +Hook registration is done using the environment variable `EXTERNAL_HOOK_FILES`. The variable can be set to a single file: @@ -154,12 +154,12 @@ module.exports = { ### Hook functions A hook or a hook file can contain multiple hook functions, with all functions executed one after another. -If the parameters of the hook function are objects, it is possible to change the data of that parameter to change the behavior of n8n. -Additionally, the database can also be accessed in any hook function via `this.dbCollections` (see above). +If the parameters of the hook function are objects, it's possible to change the data of that parameter to change the behavior of n8n. +Additionally, the database can also be accessed in any hook function using `this.dbCollections` (see above). ## Frontend external hooks -Like backend external hooks, it is possible to define external hooks in the frontend code that get executed by n8n whenever a specific operation is performed. They can be used, for example, to log data and change data. +Like backend external hooks, it's possible to define external hooks in the frontend code that get executed by n8n whenever a specific operation is performed. They can be used, for example, to log data and change data. ### Available hooks @@ -238,5 +238,5 @@ window.n8nExternalHooks = { Multiple hook functions can be defined per hook. Each hook function is invoked with the following arguments arguments: -* `store`: The vuex store object. Can be used to modify/get data from the store. -* `metadata`: Object that contains any data provided by the hook. To see exactly what is passed, search for the hook in the `editor-ui` package. +* `store`: The Vuex store object. Can be used to change or get data from the store. +* `metadata`: Object that contains any data provided by the hook. To see exactly what's passed, search for the hook in the `editor-ui` package. diff --git a/docs/embed/deployment.md b/docs/embed/deployment.md index 6d3ac49f3..b7a75e51c 100644 --- a/docs/embed/deployment.md +++ b/docs/embed/deployment.md @@ -1,17 +1,17 @@ # Deployment -See the [official n8n documentation](https://docs.n8n.io/reference/server-setup.html) for detailed setup options. +See the [hosting documentation](https://docs.n8n.io/reference/server-setup.html) for detailed setup options. ## User data -It is recommended that you follow the same or similar practices we use internally for n8n.cloud: User data is saved using [Rook](https://rook.io/) and, if an n8n server goes down, a new instance is started on another machine using the same data. +n8n recommends that you follow the same or similar practices used internally for n8n Cloud: Save user data using [Rook](https://rook.io/) and, if an n8n server goes down, a new instance starts on another machine using the same data. -In this manner, backups only need to be used in case of a catastrophic failure, or when a user wants to reactivate their account within your prescribed retention period (2 weeks for n8n.cloud). +Due to this, you don't need to use backups except in case of a catastrophic failure, or when a user wants to reactivate their account within your prescribed retention period (two weeks for n8n Cloud). ## Backups -We recommend creating nightly backups by attaching another container, and copying all data to this second container. In this manner, RAM usage is negligible, and so does not impact the amount of users you can place on the server. +n8n recommends creating nightly backups by attaching another container, and copying all data to this second container. In this manner, RAM usage is negligible, and so does'nt impact the amount of users you can place on the server. ## Restarting -If your instance is down or restarting, missed executions (e.g. Cron or Webhook nodes) during this time are not recoverable. If it is important for you, you would have to build another proxy in front of it which caches the data. +If your instance is down or restarting, missed executions (for example, Cron or Webhook nodes) during this time aren't recoverable. If it's important for you to maintain 100% uptime, you need to build another proxy in front of it which caches the data. diff --git a/docs/embed/index.md b/docs/embed/index.md index 04d5ba95a..32e61d43d 100644 --- a/docs/embed/index.md +++ b/docs/embed/index.md @@ -2,7 +2,7 @@ n8n Embed is part of n8n's paid offering. Using Embed, you can white label n8n, or incorporate it in your software as part of your commercial product. -For more information about when to use Embed, as well as costs and licensing processes, contact [TODO]. +For more information about when to use Embed, as well as costs and licensing processes, contact n8n using [this form](https://n8n-community.typeform.com/to/qOBgyWWA){:target=_blank .external-link}. ## Support @@ -10,4 +10,4 @@ The [community forum](https://community.n8n.io/) can help with many issues. If y ## Russia and Belarus -n8n Embed is not available in Russia and Belarus. Refer to our blog post [Update on n8n cloud accounts in Russia and Belarus](https://n8n.io/blog/update-on-n8n-cloud-accounts-in-russia-and-belarus/) for more information. \ No newline at end of file +n8n Embed isn't available in Russia and Belarus. Refer to n8n's blog post [Update on n8n cloud accounts in Russia and Belarus](https://n8n.io/blog/update-on-n8n-cloud-accounts-in-russia-and-belarus/){:target=_blank .external-link} for more information. \ No newline at end of file diff --git a/docs/embed/managing-workflows.md b/docs/embed/managing-workflows.md index c12d66c3b..bdcd6bd43 100644 --- a/docs/embed/managing-workflows.md +++ b/docs/embed/managing-workflows.md @@ -1,13 +1,13 @@ -# Workflow management +# Workflow management in Embed When managing an embedded n8n deployment, spanning across teams or organizations, you will likely need to run the same (or similar) workflows for multiple users. There are two available options for doing so: | Solution | Pros | Cons | | -------- | ---- | ---- | -| Create a workflow for each user | No limitation on how workflow is started (can use any trigger) | Requires managing multiple workflows. | -| Create a single workflow, and pass it user credentials when executing | Simplified workflow management (i.e. only need to change one workflow). | To run the workflow, your product must call it | +| Create a workflow for each user | No limitation on how workflow starts (can use any trigger) | Requires managing multiple workflows. | +| Create a single workflow, and pass it user credentials when executing | Simplified workflow management (only need to change one workflow). | To run the workflow, your product must call it | + -Below we cover the steps for both approaches. !!! warning The APIs referenced in this document are subject to change at any time. Be sure the check for continued functionality with each version upgrade. @@ -30,7 +30,7 @@ Here you need to capture all credentials for any node/service this user must aut After all relevant credential details have been obtained, you can proceed to create the relevant service credentials in n8n. This can be done via the Editor UI or API call. -#### Via Editor UI +#### Using the Editor UI 1. From the menu select **Credentials** > **New**. 1. Use the drop-down to select the **Credential type** to create, for example *Airtable*. @@ -39,7 +39,7 @@ After all relevant credential details have been obtained, you can proceed to cre ![Create New Credentials modal](/_images/embed/managing-workflows/create_new_credentials2.png) 1. Click **Create** to finish and save. -#### Via API +#### Using the API The frontend API used by the Editor UI can also be called to achieve the same result. The API endpoint is in the format: `https:///rest/credentials`. @@ -92,7 +92,7 @@ Best practice is to have a “base” workflow that you then duplicate and custo You can duplicate and customize your template workflow using either the Editor UI or API call. -#### Via Editor UI +#### Using the Editor UI 1. From the menu select **Workflows** > **Open** to open the template workflow to be duplicated. @@ -103,7 +103,7 @@ You can duplicate and customize your template workflow using either the Editor U 1. **Save** this workflow set it to **Active** using the toggle in the top-right corner. -#### Via API +#### Using the API 1. Fetch the JSON of the template workflow using the endpoint: `https:///rest/workflows/` ``` diff --git a/docs/embed/prerequisites.md b/docs/embed/prerequisites.md index 1fd4df809..5c0c7c507 100644 --- a/docs/embed/prerequisites.md +++ b/docs/embed/prerequisites.md @@ -1,6 +1,6 @@ # Prerequisites -The requirements provided here are an example based on our n8n.cloud and are for illustrative purposes only. Your requirements may vary depending on the number of users, workflows, and executions. Contact n8n for more information. +The requirements provided here are an example based on n8n.cloud and are for illustrative purposes only. Your requirements may vary depending on the number of users, workflows, and executions. Contact n8n for more information. | Component | Sizing | Supported | | :-------- | :----- | :-------- | @@ -10,27 +10,28 @@ The requirements provided here are an example based on our n8n.cloud and are for ## CPU considerations -n8n is not CPU intensive so even small instances (of AWS, GCP, etc.) should be sufficient for most use cases. Generally, memory requirements supersede CPU requirements, so focus resources there when planning your infrastructure. +n8n isn't CPU intensive so even small instances (of providers such as AWS and GCP) should be enough for most use cases. Usually, memory requirements supersede CPU requirements, so focus resources there when planning your infrastructure. ## Database considerations n8n uses its database to store credentials, past executions, and workflows. -A core feature of n8n is the flexibility to choose a database. All of the supported databases have different advantages and disadvantages, which you have to consider individually and pick the one that best suits your needs. **By default n8n creates a SQLite database if none is found at the given location.** -It is recommended that every n8n instance have a dedicated database. This helps to prevent dependencies and potential performance degradation. If it is not possible to provide an own database to every n8n instance we recommend making use of Postgres’s schema feature. +A core feature of n8n is the flexibility to choose a database. All the supported databases have different advantages and disadvantages, which you have to consider individually and pick the one that best suits your needs. By default n8n creates an SQLite database if no database exists at the given location. -For Postgres, MySQL and MariaDB it is required that the database already exists on the DB-instance. The database user for the n8n process needs to have full permissions on all tables that they are using/creating. The database schema is created and maintained by n8n itself, no further actions are required. +n8n recommends that every n8n instance have a dedicated database. This helps to prevent dependencies and potential performance degradation. If it isn't possible to provide a dedicated database for every n8n instance, n8n recommends making use of Postgres's schema feature. + +For Postgres, MySQL, and MariaDB, the database must already exist on the DB-instance. The database user for the n8n process needs to have full permissions on all tables that they're using or creating. n8n creates and maintains the database schema. ### Best practices -* SSD storage is recommended. -* In containerized cloud environments, ensure that the volume is persisted and mounted when stopping/starting a container. If not, all data will be lost. -* If using Postgres, do not use the `tablePrefix` configuration option. It will be deprecated in the near future. +* SSD storage. +* In containerized cloud environments, ensure that the volume is persisted and mounted when stopping/starting a container. If not, all data is lost. +* If using Postgres, don't use the `tablePrefix` configuration option. It will be deprecated in the near future. * Pay attention to the changelog of new versions and consider reverting migrations before downgrading. -* Implement at least the basic database security and stability mechanisms such as IP-whitelisting and backups. +* Set up at least the basic database security and stability mechanisms such as IP allow lists and backups. ## Memory considerations -An n8n instance does not typically require large amounts of available memory, for example an n8n.cloud instance at idle requires ~100MB. It is the nature of your workflows and the data being processed that will determine your ultimate memory requirements. +An n8n instance doesn't typically require large amounts of available memory. For example an n8n.cloud instance at idle requires ~100MB. It's the nature of your workflows and the data being processed that determines your memory requirements. -For example, while most nodes just pass data to the next node in the workflow, `Function` nodes create a pre- and post-processing copy of the data. When dealing will large binary files, this can quickly consume all available resources. +For example, while most nodes just pass data to the next node in the workflow, `Function` nodes create a pre-processing and post-processing copy of the data. When dealing will large binary files, this can consume all available resources. diff --git a/overrides/main.html b/overrides/main.html index 82b0a930d..b17177da1 100644 --- a/overrides/main.html +++ b/overrides/main.html @@ -9,4 +9,11 @@ g.async=true; g.src='https://cdn.matomo.cloud/n8n.matomo.cloud/container_V5geRwlT.js'; s.parentNode.insertBefore(g,s); -{% endblock %} \ No newline at end of file +{% endblock %} + + +{% block announce %} + {% if section and section.title == "Embed" %} + Section is {{ section.title }}. n8n Embed requires a license. Contact n8n for more information. + {% endif %} +{% endblock %} diff --git a/styles/Vocab/default/accept.txt b/styles/Vocab/default/accept.txt index 2c46324ac..310856bcc 100644 --- a/styles/Vocab/default/accept.txt +++ b/styles/Vocab/default/accept.txt @@ -1,3 +1,4 @@ +Asana backend Cron Enum @@ -7,5 +8,7 @@ namespace onboarding Pipedrive Postbin +Postgres Twilio -URL \ No newline at end of file +URL +Vuex \ No newline at end of file From 02017b7bfa7ab5fe7ec1bf6b9bf3557c13c43e5b Mon Sep 17 00:00:00 2001 From: Deborah Barnard Date: Wed, 15 Jun 2022 16:44:01 +0100 Subject: [PATCH 17/18] remove banner for now --- overrides/main.html | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/overrides/main.html b/overrides/main.html index b17177da1..e9665851c 100644 --- a/overrides/main.html +++ b/overrides/main.html @@ -11,9 +11,4 @@ {% endblock %} - -{% block announce %} - {% if section and section.title == "Embed" %} - Section is {{ section.title }}. n8n Embed requires a license. Contact n8n for more information. - {% endif %} -{% endblock %} + From ca31563939585ff4cbac1e5b89067726880ce962 Mon Sep 17 00:00:00 2001 From: Deborah Barnard Date: Thu, 16 Jun 2022 14:06:16 +0100 Subject: [PATCH 18/18] add versioning risk and merge main --- .../integrations/submit-community-node.md | 19 ++++++++++++ .../community-nodes/installation.md | 3 ++ docs/integrations/community-nodes/risks.md | 4 ++- .../community-nodes/submit-nodes.md | 29 +------------------ 4 files changed, 26 insertions(+), 29 deletions(-) create mode 100644 _snippets/integrations/submit-community-node.md diff --git a/_snippets/integrations/submit-community-node.md b/_snippets/integrations/submit-community-node.md new file mode 100644 index 000000000..06e8af896 --- /dev/null +++ b/_snippets/integrations/submit-community-node.md @@ -0,0 +1,19 @@ +!!! note "Subject to change" + The standards described in this document are for the first release of the community nodes repository. These may change in future releases. + +Community nodes are npm packages, hosted in the npm registry. + +When building a node to submit to the community node repository, use the following resources to make sure your node setup is correct: + +* View the [starter node](https://github.com/n8n-io/n8n-nodes-starter). +* Refer to the documentation on [building your own nodes](/integrations/creating-nodes/). +* Make sure your node follows the [standards](#standards) for community nodes. + +## Standards + +To make your node available to the n8n community node repository, you must: + +* Make sure the package name starts with `n8n-node-` or `@/n8n-node-`. For example, `n8n-node-weather` or `@weatherPlugins/n8n-node-weather`. +* Tag your package with `n8n-community-node-package`. +* Submit the package to the npm registry. Refer to npm's documentation on [Contributing packages to the registry](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry){:target=_blank .external-link} for more information. +* Make sure that you add your nodes and credentials to the `package.json` file inside the `n8n` attribute. Refer to the [package.json in the starter node](https://github.com/n8n-io/n8n-nodes-starter/blob/master/package.json) for an example. diff --git a/docs/integrations/community-nodes/installation.md b/docs/integrations/community-nodes/installation.md index 96a8ab7d8..d0bab7134 100644 --- a/docs/integrations/community-nodes/installation.md +++ b/docs/integrations/community-nodes/installation.md @@ -35,6 +35,9 @@ To uninstall a community node: ## Upgrade a community node +!!! warning "Breaking changes in versions" + Node developers may introduce breaking changes in new versions of their nodes. A breaking change is an update that breaks previous functionality. Depending on the node versioning approach that a node developer chooses, upgrading to a version with a breaking change could cause all workflows using the node to break. Be careful when upgrading your nodes. + ### Upgrade to the latest version You can upgrade community nodes to the latest version from the node list in **Settings** > **community nodes**. diff --git a/docs/integrations/community-nodes/risks.md b/docs/integrations/community-nodes/risks.md index fdea6e588..707672ba4 100644 --- a/docs/integrations/community-nodes/risks.md +++ b/docs/integrations/community-nodes/risks.md @@ -5,6 +5,7 @@ Using community nodes has some risks. You are installing unverified code from a Risks include: * Data security: any community node that you use has access to data in your workflows. +* Breaking changes: node developers may introduce breaking changes in new versions of their nodes. A breaking change is an update that breaks previous functionality. Depending on the node versioning approach that a node developer chooses, upgrading to a version with a breaking change could cause all workflows using the node to break. Be careful when upgrading your nodes. ## Report bad community nodes @@ -12,4 +13,5 @@ Risks include: You can report bad community nodes to [security@n8n.io](mailto: security@n8n.io) - \ No newline at end of file + + diff --git a/docs/integrations/community-nodes/submit-nodes.md b/docs/integrations/community-nodes/submit-nodes.md index ec88ffeff..fc0607bcc 100644 --- a/docs/integrations/community-nodes/submit-nodes.md +++ b/docs/integrations/community-nodes/submit-nodes.md @@ -1,30 +1,3 @@ # Submit your node to the community node repository -!!! note "Subject to change" - The standards described in this document are for the first release of the community nodes repository. These may change in future releases. - -Community nodes are npm packages, hosted in the npm registry. - -When building a node to submit to the community node repository, use the following resources to make sure your node setup is correct: - -* View the [starter node](https://github.com/n8n-io/n8n-nodes-starter). -* Refer to the documentation on [building your own nodes](/integrations/creating-nodes/). -* Make sure your node follows the [standards](#standards) for community nodes. - -## Standards - -To make your node available to the n8n community node repository, you must: - -* Make sure the package name starts with `n8n-node-` or `@/n8n-node-`. For example, `n8n-node-weather` or `@weatherPlugins/n8n-node-weather`. -* Tag your package with `n8n-community-node-package`. -* Submit the package to the npm registry. Refer to npm's documentation on [Contributing packages to the registry](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry){:target=_blank .external-link} for more information. -* Make sure that you add your nodes and credentials to the `package.json` file inside the `n8n` attribute. Refer to the [package.json in the starter node](https://github.com/n8n-io/n8n-nodes-starter/blob/master/package.json) for an example. - -## Migrating pull requests to npm packages - -If you have submitted a pull request to n8n with a new node, you may need to release it as a community node instead. - -1. Clone the [starter repository](https://github.com/n8n-io/n8n-nodes-starter). -2. Replace the example nodes and credentials with your own -3. Update the `package.json` file to reflect your changes. -4. Publish the package to npm. +--8<-- "_snippets/integrations/submit-community-node.md"