mirror of
https://github.com/n8n-io/n8n.git
synced 2026-06-02 09:47:00 +02:00
fix conflicts
This commit is contained in:
commit
54fe874637
|
|
@ -1,3 +1,7 @@
|
|||
**/.env
|
||||
node_modules
|
||||
packages/node-dev
|
||||
packages/*/node_modules
|
||||
packages/*/dist
|
||||
packages/*/.turbo
|
||||
.git
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
packages/editor-ui
|
||||
packages/design-system
|
||||
packages/cli/scripts/build.mjs
|
||||
473
.eslintrc.js
473
.eslintrc.js
|
|
@ -1,473 +0,0 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
|
||||
env: {
|
||||
browser: true,
|
||||
es6: true,
|
||||
node: true,
|
||||
},
|
||||
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: ['./packages/*/tsconfig.json'],
|
||||
sourceType: 'module',
|
||||
},
|
||||
ignorePatterns: [
|
||||
'.eslintrc.js',
|
||||
'**/*.js',
|
||||
'**/node_modules/**',
|
||||
'**/dist/**',
|
||||
'**/test/**',
|
||||
'**/templates/**',
|
||||
'**/ormconfig.ts',
|
||||
'**/migrations/**',
|
||||
],
|
||||
|
||||
overrides: [
|
||||
{
|
||||
files: './packages/*(cli|core|workflow|node-dev)/**/*.ts',
|
||||
plugins: [
|
||||
/**
|
||||
* Plugin with lint rules for import/export syntax
|
||||
* https://github.com/import-js/eslint-plugin-import
|
||||
*/
|
||||
'eslint-plugin-import',
|
||||
|
||||
/**
|
||||
* @typescript-eslint/eslint-plugin is required by eslint-config-airbnb-typescript
|
||||
* See step 2: https://github.com/iamturns/eslint-config-airbnb-typescript#2-install-eslint-plugins
|
||||
*/
|
||||
'@typescript-eslint',
|
||||
|
||||
/**
|
||||
* Plugin to report formatting violations as lint violations
|
||||
* https://github.com/prettier/eslint-plugin-prettier
|
||||
*/
|
||||
'eslint-plugin-prettier',
|
||||
],
|
||||
extends: [
|
||||
/**
|
||||
* Config for typescript-eslint recommended ruleset (without type checking)
|
||||
*
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/1c1b572c3000d72cfe665b7afbada0ec415e7855/packages/eslint-plugin/src/configs/recommended.ts
|
||||
*/
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
|
||||
/**
|
||||
* Config for typescript-eslint recommended ruleset (with type checking)
|
||||
*
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/1c1b572c3000d72cfe665b7afbada0ec415e7855/packages/eslint-plugin/src/configs/recommended-requiring-type-checking.ts
|
||||
*/
|
||||
'plugin:@typescript-eslint/recommended-requiring-type-checking',
|
||||
|
||||
/**
|
||||
* Config for Airbnb style guide for TS, /base to remove React rules
|
||||
*
|
||||
* https://github.com/iamturns/eslint-config-airbnb-typescript
|
||||
* https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb-base/rules
|
||||
*/
|
||||
'eslint-config-airbnb-typescript/base',
|
||||
|
||||
/**
|
||||
* Config to disable ESLint rules covered by Prettier
|
||||
*
|
||||
* https://github.com/prettier/eslint-config-prettier
|
||||
*/
|
||||
'eslint-config-prettier',
|
||||
],
|
||||
rules: {
|
||||
// ******************************************************************
|
||||
// required by prettier plugin
|
||||
// ******************************************************************
|
||||
|
||||
// The following rule enables eslint-plugin-prettier
|
||||
// See: https://github.com/prettier/eslint-plugin-prettier#recommended-configuration
|
||||
|
||||
'prettier/prettier': 'error',
|
||||
|
||||
// The following two rules must be disabled when using eslint-plugin-prettier:
|
||||
// See: https://github.com/prettier/eslint-plugin-prettier#arrow-body-style-and-prefer-arrow-callback-issue
|
||||
|
||||
/**
|
||||
* https://eslint.org/docs/rules/arrow-body-style
|
||||
*/
|
||||
'arrow-body-style': 'off',
|
||||
|
||||
/**
|
||||
* https://eslint.org/docs/rules/prefer-arrow-callback
|
||||
*/
|
||||
'prefer-arrow-callback': 'off',
|
||||
|
||||
// ******************************************************************
|
||||
// additions to base ruleset
|
||||
// ******************************************************************
|
||||
|
||||
// ----------------------------------
|
||||
// ESLint
|
||||
// ----------------------------------
|
||||
|
||||
/**
|
||||
* https://eslint.org/docs/rules/id-denylist
|
||||
*/
|
||||
'id-denylist': [
|
||||
'error',
|
||||
'err',
|
||||
'cb',
|
||||
'callback',
|
||||
'any',
|
||||
'Number',
|
||||
'number',
|
||||
'String',
|
||||
'string',
|
||||
'Boolean',
|
||||
'boolean',
|
||||
'Undefined',
|
||||
'undefined',
|
||||
],
|
||||
|
||||
'no-void': ['error', { allowAsStatement: true }],
|
||||
|
||||
// ----------------------------------
|
||||
// @typescript-eslint
|
||||
// ----------------------------------
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/array-type.md
|
||||
*/
|
||||
'@typescript-eslint/array-type': ['error', { default: 'array-simple' }],
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/ban-ts-comment.md
|
||||
*/
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/ban-types.md
|
||||
*/
|
||||
'@typescript-eslint/ban-types': [
|
||||
'error',
|
||||
{
|
||||
types: {
|
||||
Object: {
|
||||
message: 'Use object instead',
|
||||
fixWith: 'object',
|
||||
},
|
||||
String: {
|
||||
message: 'Use string instead',
|
||||
fixWith: 'string',
|
||||
},
|
||||
Boolean: {
|
||||
message: 'Use boolean instead',
|
||||
fixWith: 'boolean',
|
||||
},
|
||||
Number: {
|
||||
message: 'Use number instead',
|
||||
fixWith: 'number',
|
||||
},
|
||||
Symbol: {
|
||||
message: 'Use symbol instead',
|
||||
fixWith: 'symbol',
|
||||
},
|
||||
Function: {
|
||||
message: [
|
||||
'The `Function` type accepts any function-like value.',
|
||||
'It provides no type safety when calling the function, which can be a common source of bugs.',
|
||||
'It also accepts things like class declarations, which will throw at runtime as they will not be called with `new`.',
|
||||
'If you are expecting the function to accept certain arguments, you should explicitly define the function shape.',
|
||||
].join('\n'),
|
||||
},
|
||||
},
|
||||
extendDefaults: false,
|
||||
},
|
||||
],
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/consistent-type-assertions.md
|
||||
*/
|
||||
'@typescript-eslint/consistent-type-assertions': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/explicit-member-accessibility.md
|
||||
*/
|
||||
'@typescript-eslint/explicit-member-accessibility': [
|
||||
'error',
|
||||
{ accessibility: 'no-public' },
|
||||
],
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/member-delimiter-style.md
|
||||
*/
|
||||
'@typescript-eslint/member-delimiter-style': [
|
||||
'error',
|
||||
{
|
||||
multiline: {
|
||||
delimiter: 'semi',
|
||||
requireLast: true,
|
||||
},
|
||||
singleline: {
|
||||
delimiter: 'semi',
|
||||
requireLast: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/naming-convention.md
|
||||
*/
|
||||
'@typescript-eslint/naming-convention': [
|
||||
'error',
|
||||
{
|
||||
selector: 'default',
|
||||
format: ['camelCase'],
|
||||
},
|
||||
{
|
||||
selector: 'variable',
|
||||
format: ['camelCase', 'snake_case', 'UPPER_CASE'],
|
||||
leadingUnderscore: 'allowSingleOrDouble',
|
||||
trailingUnderscore: 'allowSingleOrDouble',
|
||||
},
|
||||
{
|
||||
selector: 'property',
|
||||
format: ['camelCase', 'snake_case'],
|
||||
leadingUnderscore: 'allowSingleOrDouble',
|
||||
trailingUnderscore: 'allowSingleOrDouble',
|
||||
},
|
||||
{
|
||||
selector: 'typeLike',
|
||||
format: ['PascalCase'],
|
||||
},
|
||||
{
|
||||
selector: ['method', 'function'],
|
||||
format: ['camelCase'],
|
||||
leadingUnderscore: 'allowSingleOrDouble',
|
||||
},
|
||||
],
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-duplicate-imports.md
|
||||
*/
|
||||
'@typescript-eslint/no-duplicate-imports': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-invalid-void-type.md
|
||||
*/
|
||||
'@typescript-eslint/no-invalid-void-type': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-misused-promises.md
|
||||
*/
|
||||
'@typescript-eslint/no-misused-promises': ['error', { checksVoidReturn: false }],
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/v4.30.0/packages/eslint-plugin/docs/rules/no-floating-promises.md
|
||||
*/
|
||||
'@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: true }],
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/v4.33.0/packages/eslint-plugin/docs/rules/no-namespace.md
|
||||
*/
|
||||
'@typescript-eslint/no-namespace': 'off',
|
||||
|
||||
/**
|
||||
* https://eslint.org/docs/1.0.0/rules/no-throw-literal
|
||||
*/
|
||||
'@typescript-eslint/no-throw-literal': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unnecessary-boolean-literal-compare.md
|
||||
*/
|
||||
'@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unnecessary-qualifier.md
|
||||
*/
|
||||
'@typescript-eslint/no-unnecessary-qualifier': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unused-expressions.md
|
||||
*/
|
||||
'@typescript-eslint/no-unused-expressions': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unused-vars.md
|
||||
*/
|
||||
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '_' }],
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/prefer-nullish-coalescing.md
|
||||
*/
|
||||
'@typescript-eslint/prefer-nullish-coalescing': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/prefer-optional-chain.md
|
||||
*/
|
||||
'@typescript-eslint/prefer-optional-chain': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/promise-function-async.md
|
||||
*/
|
||||
'@typescript-eslint/promise-function-async': 'error',
|
||||
|
||||
// ----------------------------------
|
||||
// eslint-plugin-import
|
||||
// ----------------------------------
|
||||
|
||||
/**
|
||||
* https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-default-export.md
|
||||
*/
|
||||
'import/no-default-export': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/order.md
|
||||
*/
|
||||
'import/order': 'error',
|
||||
|
||||
// ******************************************************************
|
||||
// overrides to base ruleset
|
||||
// ******************************************************************
|
||||
|
||||
// ----------------------------------
|
||||
// ESLint
|
||||
// ----------------------------------
|
||||
|
||||
/**
|
||||
* https://eslint.org/docs/rules/class-methods-use-this
|
||||
*/
|
||||
'class-methods-use-this': 'off',
|
||||
|
||||
/**
|
||||
* https://eslint.org/docs/rules/eqeqeq
|
||||
*/
|
||||
eqeqeq: 'error',
|
||||
|
||||
/**
|
||||
* https://eslint.org/docs/rules/no-plusplus
|
||||
*/
|
||||
'no-plusplus': 'off',
|
||||
|
||||
/**
|
||||
* https://eslint.org/docs/rules/object-shorthand
|
||||
*/
|
||||
'object-shorthand': 'error',
|
||||
|
||||
/**
|
||||
* https://eslint.org/docs/rules/prefer-const
|
||||
*/
|
||||
'prefer-const': 'error',
|
||||
|
||||
/**
|
||||
* https://eslint.org/docs/rules/prefer-spread
|
||||
*/
|
||||
'prefer-spread': 'error',
|
||||
|
||||
// ----------------------------------
|
||||
// import
|
||||
// ----------------------------------
|
||||
|
||||
/**
|
||||
* https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/prefer-default-export.md
|
||||
*/
|
||||
'import/prefer-default-export': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['./packages/nodes-base/credentials/*.credentials.ts'],
|
||||
plugins: ['eslint-plugin-n8n-nodes-base'],
|
||||
rules: {
|
||||
'n8n-nodes-base/cred-class-field-display-name-missing-oauth2': 'error',
|
||||
'n8n-nodes-base/cred-class-field-name-missing-oauth2': 'error',
|
||||
'n8n-nodes-base/cred-class-field-name-unsuffixed': 'error',
|
||||
'n8n-nodes-base/cred-class-field-name-uppercase-first-char': 'error',
|
||||
'n8n-nodes-base/cred-class-name-missing-oauth2-suffix': 'error',
|
||||
'n8n-nodes-base/cred-class-name-unsuffixed': 'error',
|
||||
'n8n-nodes-base/cred-filename-against-convention': 'error',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['./packages/nodes-base/nodes/**/*.ts'],
|
||||
plugins: ['eslint-plugin-n8n-nodes-base'],
|
||||
rules: {
|
||||
'n8n-nodes-base/node-class-description-credentials-name-unsuffixed': 'error',
|
||||
'n8n-nodes-base/node-class-description-display-name-unsuffixed-trigger-node': 'error',
|
||||
'n8n-nodes-base/node-class-description-empty-string': 'error',
|
||||
'n8n-nodes-base/node-class-description-icon-not-svg': 'error',
|
||||
'n8n-nodes-base/node-class-description-inputs-wrong-regular-node': 'error',
|
||||
'n8n-nodes-base/node-class-description-inputs-wrong-trigger-node': 'error',
|
||||
'n8n-nodes-base/node-class-description-missing-subtitle': 'error',
|
||||
'n8n-nodes-base/node-class-description-name-unsuffixed-trigger-node': 'error',
|
||||
'n8n-nodes-base/node-class-description-outputs-wrong': 'error',
|
||||
'n8n-nodes-base/node-dirname-against-convention': 'error',
|
||||
'n8n-nodes-base/node-execute-block-double-assertion-for-items': 'error',
|
||||
'n8n-nodes-base/node-execute-block-wrong-error-thrown': 'error',
|
||||
'n8n-nodes-base/node-filename-against-convention': 'error',
|
||||
'n8n-nodes-base/node-param-array-type-assertion': 'error',
|
||||
'n8n-nodes-base/node-param-collection-type-unsorted-items': 'error',
|
||||
'n8n-nodes-base/node-param-color-type-unused': 'error',
|
||||
'n8n-nodes-base/node-param-default-missing': 'error',
|
||||
'n8n-nodes-base/node-param-default-wrong-for-boolean': 'error',
|
||||
'n8n-nodes-base/node-param-default-wrong-for-collection': 'error',
|
||||
'n8n-nodes-base/node-param-default-wrong-for-fixed-collection': 'error',
|
||||
'n8n-nodes-base/node-param-default-wrong-for-fixed-collection': 'error',
|
||||
'n8n-nodes-base/node-param-default-wrong-for-multi-options': 'error',
|
||||
'n8n-nodes-base/node-param-default-wrong-for-number': 'error',
|
||||
'n8n-nodes-base/node-param-default-wrong-for-simplify': 'error',
|
||||
'n8n-nodes-base/node-param-default-wrong-for-string': 'error',
|
||||
'n8n-nodes-base/node-param-description-boolean-without-whether': 'error',
|
||||
'n8n-nodes-base/node-param-description-comma-separated-hyphen': 'error',
|
||||
'n8n-nodes-base/node-param-description-empty-string': 'error',
|
||||
'n8n-nodes-base/node-param-description-excess-final-period': 'error',
|
||||
'n8n-nodes-base/node-param-description-excess-inner-whitespace': 'error',
|
||||
'n8n-nodes-base/node-param-description-identical-to-display-name': 'error',
|
||||
'n8n-nodes-base/node-param-description-line-break-html-tag': 'error',
|
||||
'n8n-nodes-base/node-param-description-lowercase-first-char': 'error',
|
||||
'n8n-nodes-base/node-param-description-miscased-id': 'error',
|
||||
'n8n-nodes-base/node-param-description-miscased-json': 'error',
|
||||
'n8n-nodes-base/node-param-description-miscased-url': 'error',
|
||||
'n8n-nodes-base/node-param-description-missing-final-period': 'error',
|
||||
'n8n-nodes-base/node-param-description-missing-for-ignore-ssl-issues': 'error',
|
||||
'n8n-nodes-base/node-param-description-missing-for-return-all': 'error',
|
||||
'n8n-nodes-base/node-param-description-missing-for-simplify': 'error',
|
||||
'n8n-nodes-base/node-param-description-missing-from-dynamic-multi-options': 'error',
|
||||
'n8n-nodes-base/node-param-description-missing-from-dynamic-options': 'error',
|
||||
'n8n-nodes-base/node-param-description-missing-from-limit': 'error',
|
||||
'n8n-nodes-base/node-param-description-unencoded-angle-brackets': 'error',
|
||||
'n8n-nodes-base/node-param-description-unneeded-backticks': 'error',
|
||||
'n8n-nodes-base/node-param-description-untrimmed': 'error',
|
||||
'n8n-nodes-base/node-param-description-url-missing-protocol': 'error',
|
||||
'n8n-nodes-base/node-param-description-weak': 'error',
|
||||
'n8n-nodes-base/node-param-description-wrong-for-dynamic-multi-options': 'error',
|
||||
'n8n-nodes-base/node-param-description-wrong-for-dynamic-options': 'error',
|
||||
'n8n-nodes-base/node-param-description-wrong-for-ignore-ssl-issues': 'error',
|
||||
'n8n-nodes-base/node-param-description-wrong-for-limit': 'error',
|
||||
'n8n-nodes-base/node-param-description-wrong-for-return-all': 'error',
|
||||
'n8n-nodes-base/node-param-description-wrong-for-simplify': 'error',
|
||||
'n8n-nodes-base/node-param-description-wrong-for-upsert': 'error',
|
||||
'n8n-nodes-base/node-param-display-name-excess-inner-whitespace': 'error',
|
||||
'n8n-nodes-base/node-param-display-name-miscased': 'error',
|
||||
'n8n-nodes-base/node-param-display-name-miscased-id': 'error',
|
||||
'n8n-nodes-base/node-param-display-name-untrimmed': 'error',
|
||||
'n8n-nodes-base/node-param-display-name-wrong-for-dynamic-multi-options': 'error',
|
||||
'n8n-nodes-base/node-param-display-name-wrong-for-dynamic-options': 'error',
|
||||
'n8n-nodes-base/node-param-display-name-wrong-for-simplify': 'error',
|
||||
'n8n-nodes-base/node-param-display-name-wrong-for-update-fields': 'error',
|
||||
'n8n-nodes-base/node-param-min-value-wrong-for-limit': 'error',
|
||||
'n8n-nodes-base/node-param-multi-options-type-unsorted-items': 'error',
|
||||
'n8n-nodes-base/node-param-operation-without-no-data-expression': 'error',
|
||||
'n8n-nodes-base/node-param-operation-option-without-action': 'error',
|
||||
'n8n-nodes-base/node-param-option-description-identical-to-name': 'error',
|
||||
'n8n-nodes-base/node-param-option-name-containing-star': 'error',
|
||||
'n8n-nodes-base/node-param-option-name-duplicate': 'error',
|
||||
'n8n-nodes-base/node-param-option-name-wrong-for-get-all': 'error',
|
||||
'n8n-nodes-base/node-param-option-name-wrong-for-upsert': 'error',
|
||||
'n8n-nodes-base/node-param-option-value-duplicate': 'error',
|
||||
'n8n-nodes-base/node-param-options-type-unsorted-items': 'error',
|
||||
'n8n-nodes-base/node-param-placeholder-miscased-id': 'error',
|
||||
'n8n-nodes-base/node-param-placeholder-missing-email': 'error',
|
||||
'n8n-nodes-base/node-param-required-false': 'error',
|
||||
'n8n-nodes-base/node-param-resource-with-plural-option': 'error',
|
||||
'n8n-nodes-base/node-param-resource-without-no-data-expression': 'error',
|
||||
'n8n-nodes-base/node-param-type-options-missing-from-limit': 'error',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
13
.github/ISSUE_TEMPLATE/bug_report.md
vendored
13
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
|
@ -4,7 +4,6 @@ about: Create a report to help us improve
|
|||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
|
|
@ -12,6 +11,7 @@ A clear and concise description of what the bug is.
|
|||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
|
|
@ -21,11 +21,12 @@ Steps to reproduce the behavior:
|
|||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Environment (please complete the following information):**
|
||||
- OS: [e.g. Ubuntu Linux 18.04]
|
||||
- n8n Version [e.g. 0.119.0]
|
||||
- Node.js Version [e.g. 14.16.0]
|
||||
- Database system [e.g. SQLite; n8n uses SQLite as default otherwise changed]
|
||||
- Operation mode [e.g. own; operation modes are `own`, `main` and `queue`. Default is `own`]
|
||||
|
||||
- OS: [e.g. Ubuntu Linux 18.04]
|
||||
- n8n Version [e.g. 0.119.0]
|
||||
- Node.js Version [e.g. 14.16.0]
|
||||
- Database system [e.g. SQLite; n8n uses SQLite as default otherwise changed]
|
||||
- Operation mode [e.g. own; operation modes are `own`, `main` and `queue`. Default is `own`]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
|
|
|
|||
32
.github/workflows/check-pr-title.yml
vendored
Normal file
32
.github/workflows/check-pr-title.yml
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
name: Test Pull Request Semantics
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- synchronize
|
||||
|
||||
jobs:
|
||||
check-pr-title:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
checks: write
|
||||
pull-requests: read
|
||||
contents: read
|
||||
steps:
|
||||
- uses: amannn/action-semantic-pull-request@v4
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
# https://www.notion.so/n8n/Release-Process-fce65faea3d5403a85210f7e7a60d0f8
|
||||
types: |
|
||||
feat
|
||||
fix
|
||||
perf
|
||||
test
|
||||
docs
|
||||
refactor
|
||||
build
|
||||
ci
|
||||
requireScope: false
|
||||
37
.github/workflows/ci-master.yml
vendored
Normal file
37
.github/workflows/ci-master.yml
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
name: Test Master
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
timeout-minutes: 30
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x, 16.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install npm and dependencies
|
||||
run: npm install -g npm@latest && npm install
|
||||
|
||||
- name: Build
|
||||
run: npm run build --if-present
|
||||
|
||||
- name: Test
|
||||
run: npm run test
|
||||
|
||||
- name: Lint
|
||||
run: npm run lint
|
||||
39
.github/workflows/ci-pull-requests.yml
vendored
Normal file
39
.github/workflows/ci-pull-requests.yml
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
name: Test Pull Requests
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
timeout-minutes: 30
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x, 16.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install npm and dependencies
|
||||
run: npm install -g npm@latest && npm install
|
||||
|
||||
- name: Build
|
||||
run: npm run build --if-present
|
||||
|
||||
- name: Test
|
||||
run: npm run test
|
||||
|
||||
- name: Fetch base branch for `git diff`
|
||||
run: git fetch origin ${{ github.event.pull_request.base.ref }}:${{ github.event.pull_request.base.ref }}
|
||||
|
||||
- name: Run ESLint on changes only
|
||||
env:
|
||||
ESLINT_PLUGIN_DIFF_COMMIT: ${{ github.event.pull_request.base.ref }}
|
||||
run: npm run lint
|
||||
39
.github/workflows/docker-base-image.yml
vendored
Normal file
39
.github/workflows/docker-base-image.yml
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
name: Docker Base Image CI
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
node_version:
|
||||
description: 'Node.js version to build this image with.'
|
||||
type: string
|
||||
required: true
|
||||
default: '16'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: ./docker/images/n8n-base
|
||||
build-args: |
|
||||
NODE_VERSION=${{github.event.inputs.node_version}}
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
push: true
|
||||
tags: |
|
||||
${{ secrets.DOCKER_USERNAME }}/base:${{ github.event.inputs.node_version }}
|
||||
16
.github/workflows/docker-images-nightly.yml
vendored
16
.github/workflows/docker-images-nightly.yml
vendored
|
|
@ -33,23 +33,28 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: ${{ github.event.inputs.repository || 'n8n-io/n8n' }}
|
||||
ref: ${{ github.event.inputs.branch || 'master' }}
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Merge Master - optionally
|
||||
run: |
|
||||
[[ "${{github.event.inputs.merge-master}}" == "true" ]] && git remote add upstream https://github.com/n8n-io/n8n.git -f; git merge upstream/master --allow-unrelated-histories || echo ""
|
||||
shell: bash
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
|
|
@ -57,8 +62,9 @@ jobs:
|
|||
file: ./docker/images/n8n-custom/Dockerfile
|
||||
platforms: linux/amd64
|
||||
push: true
|
||||
tags: n8nio/n8n:${{ github.event.inputs.tag || 'nightly' }}
|
||||
tags: ${{ secrets.DOCKER_USERNAME }}/n8n:${{ github.event.inputs.tag || 'nightly' }}
|
||||
no-cache: true
|
||||
|
||||
- name: Call Success URL - optionally
|
||||
run: |
|
||||
[[ "${{github.event.inputs.success-url}}" != "" ]] && curl -v ${{github.event.inputs.success-url}} || echo ""
|
||||
|
|
|
|||
76
.github/workflows/docker-images.yml
vendored
76
.github/workflows/docker-images.yml
vendored
|
|
@ -9,38 +9,44 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Get the version
|
||||
id: vars
|
||||
run: echo ::set-output name=tag::$(echo ${GITHUB_REF:14})
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: ./docker/images/n8n
|
||||
build-args: |
|
||||
N8N_VERSION=${{steps.vars.outputs.tag}}
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
push: true
|
||||
tags: |
|
||||
${{ secrets.DOCKER_USERNAME }}/n8n:${{ steps.vars.outputs.tag }}
|
||||
${{ secrets.DOCKER_USERNAME }}/n8n:latest
|
||||
- name: Build (debian)
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: ./docker/images/n8n-debian
|
||||
build-args: |
|
||||
N8N_VERSION=${{ steps.vars.outputs.tag }}
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
push: true
|
||||
tags: |
|
||||
${{ secrets.DOCKER_USERNAME }}/n8n:${{ steps.vars.outputs.tag }}-debian
|
||||
${{ secrets.DOCKER_USERNAME }}/n8n:latest-debian
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Get the version
|
||||
id: vars
|
||||
run: echo ::set-output name=tag::$(echo ${GITHUB_REF:14})
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: ./docker/images/n8n
|
||||
build-args: |
|
||||
N8N_VERSION=${{steps.vars.outputs.tag}}
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
push: true
|
||||
tags: |
|
||||
${{ secrets.DOCKER_USERNAME }}/n8n:${{ steps.vars.outputs.tag }}
|
||||
${{ secrets.DOCKER_USERNAME }}/n8n:latest
|
||||
|
||||
- name: Build (debian)
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: ./docker/images/n8n-debian
|
||||
build-args: |
|
||||
N8N_VERSION=${{ steps.vars.outputs.tag }}
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
push: true
|
||||
tags: |
|
||||
${{ secrets.DOCKER_USERNAME }}/n8n:${{ steps.vars.outputs.tag }}-debian
|
||||
${{ secrets.DOCKER_USERNAME }}/n8n:latest-debian
|
||||
|
|
|
|||
53
.github/workflows/test-workflows.yml
vendored
53
.github/workflows/test-workflows.yml
vendored
|
|
@ -2,13 +2,11 @@ name: Run test workflows
|
|||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 2 * * *"
|
||||
- cron: '0 2 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
|
||||
jobs:
|
||||
run-test-workflows:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
timeout-minutes: 30
|
||||
|
|
@ -17,62 +15,61 @@ jobs:
|
|||
matrix:
|
||||
node-version: [16.x]
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: n8n
|
||||
-
|
||||
name: Checkout workflows repo
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Checkout workflows repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: n8n-io/test-workflows
|
||||
path: test-workflows
|
||||
-
|
||||
name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
-
|
||||
name: Install dependencies
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'n8n/package-lock.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update -y
|
||||
echo 'tzdata tzdata/Areas select Europe' | sudo debconf-set-selections
|
||||
echo 'tzdata tzdata/Zones/Europe select Paris' | sudo debconf-set-selections
|
||||
DEBIAN_FRONTEND="noninteractive" sudo apt-get install -y graphicsmagick
|
||||
shell: bash
|
||||
-
|
||||
name: npm install and build
|
||||
|
||||
- name: npm install and build
|
||||
working-directory: n8n
|
||||
run: |
|
||||
cd n8n
|
||||
npm install -g npm@latest
|
||||
npm install
|
||||
npm run bootstrap
|
||||
npm run build --if-present
|
||||
env:
|
||||
CI: true
|
||||
shell: bash
|
||||
-
|
||||
name: Import credentials
|
||||
|
||||
- name: Import credentials
|
||||
run: n8n/packages/cli/bin/n8n import:credentials --input=test-workflows/credentials.json
|
||||
shell: bash
|
||||
env:
|
||||
N8N_ENCRYPTION_KEY: ${{secrets.ENCRYPTION_KEY}}
|
||||
-
|
||||
name: Import workflows
|
||||
|
||||
- name: Import workflows
|
||||
run: n8n/packages/cli/bin/n8n import:workflow --separate --input=test-workflows/workflows
|
||||
shell: bash
|
||||
env:
|
||||
N8N_ENCRYPTION_KEY: ${{secrets.ENCRYPTION_KEY}}
|
||||
-
|
||||
name: Copy static assets
|
||||
|
||||
- name: Copy static assets
|
||||
run: |
|
||||
cp n8n/assets/n8n-logo.png /tmp/n8n-logo.png
|
||||
cp n8n/assets/n8n-screenshot.png /tmp/n8n-screenshot.png
|
||||
cp n8n/node_modules/pdf-parse/test/data/05-versions-space.pdf /tmp/05-versions-space.pdf
|
||||
cp n8n/node_modules/pdf-parse/test/data/04-valid.pdf /tmp/04-valid.pdf
|
||||
shell: bash
|
||||
-
|
||||
name: Run tests
|
||||
|
||||
- name: Run tests
|
||||
run: n8n/packages/cli/bin/n8n executeBatch --shallow --ids=test-workflows/safeList.txt --shortOutput --concurrency=16 --compare=test-workflows/snapshots
|
||||
shell: bash
|
||||
env:
|
||||
|
|
|
|||
30
.github/workflows/tests.yml
vendored
30
.github/workflows/tests.yml
vendored
|
|
@ -1,30 +0,0 @@
|
|||
name: Node CI
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
timeout-minutes: 30
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x, 16.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: npm install, build, and test
|
||||
run: |
|
||||
npm install
|
||||
npm run bootstrap
|
||||
npm run build --if-present
|
||||
npm test
|
||||
npm run lint
|
||||
env:
|
||||
CI: true
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -4,13 +4,15 @@ node_modules
|
|||
tmp
|
||||
dist
|
||||
npm-debug.log*
|
||||
lerna-debug.log
|
||||
yarn.lock
|
||||
google-generated-credentials.json
|
||||
_START_PACKAGE
|
||||
.env
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
!.vscode/settings.default.json
|
||||
.idea
|
||||
nodelinter.config.json
|
||||
packages/*/package-lock.json
|
||||
packages/*/.turbo
|
||||
*.swp
|
||||
|
|
|
|||
28
.npmignore
Normal file
28
.npmignore
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
dist/test
|
||||
dist/**/*.{js.map,d.ts}
|
||||
|
||||
.DS_Store
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw*
|
||||
|
||||
.editorconfig
|
||||
.eslintrc.js
|
||||
tsconfig.json
|
||||
tslint.json
|
||||
|
||||
.turbo
|
||||
570
.prettierignore
570
.prettierignore
|
|
@ -1,574 +1,10 @@
|
|||
dist
|
||||
packages/editor-ui
|
||||
packages/design-system
|
||||
*package.json
|
||||
package*.json
|
||||
|
||||
!packages/nodes-base/src
|
||||
!packages/nodes-base/test
|
||||
!packages/nodes-base/nodes
|
||||
!packages/nodes-base/credentials
|
||||
|
||||
packages/nodes-base/nodes/ActionNetwork
|
||||
packages/nodes-base/nodes/ActiveCampaign
|
||||
packages/nodes-base/nodes/AcuityScheduling
|
||||
packages/nodes-base/nodes/Affinity
|
||||
packages/nodes-base/nodes/AgileCrm
|
||||
packages/nodes-base/nodes/Airtable
|
||||
packages/nodes-base/nodes/Amqp
|
||||
packages/nodes-base/nodes/ApiTemplateIo
|
||||
packages/nodes-base/nodes/Asana
|
||||
packages/nodes-base/nodes/Automizy
|
||||
packages/nodes-base/nodes/Autopilot
|
||||
packages/nodes-base/nodes/Aws
|
||||
packages/nodes-base/nodes/BambooHr
|
||||
packages/nodes-base/nodes/Bannerbear
|
||||
packages/nodes-base/nodes/Baserow
|
||||
packages/nodes-base/nodes/Beeminder
|
||||
packages/nodes-base/nodes/Bitbucket
|
||||
packages/nodes-base/nodes/Bitly
|
||||
packages/nodes-base/nodes/Bitwarden
|
||||
packages/nodes-base/nodes/Box
|
||||
packages/nodes-base/nodes/Brandfetch
|
||||
packages/nodes-base/nodes/Bubble
|
||||
packages/nodes-base/nodes/Cal
|
||||
packages/nodes-base/nodes/Calendly
|
||||
packages/nodes-base/nodes/Chargebee
|
||||
packages/nodes-base/nodes/CircleCi
|
||||
packages/nodes-base/nodes/Cisco
|
||||
packages/nodes-base/nodes/Clearbit
|
||||
packages/nodes-base/nodes/ClickUp
|
||||
packages/nodes-base/nodes/Clockify
|
||||
packages/nodes-base/nodes/Cockpit
|
||||
packages/nodes-base/nodes/Coda
|
||||
packages/nodes-base/nodes/CoinGecko
|
||||
packages/nodes-base/nodes/Compression
|
||||
packages/nodes-base/nodes/Contentful
|
||||
packages/nodes-base/nodes/ConvertKit
|
||||
packages/nodes-base/nodes/Copper
|
||||
packages/nodes-base/nodes/Cortex
|
||||
packages/nodes-base/nodes/CrateDb
|
||||
packages/nodes-base/nodes/Cron
|
||||
packages/nodes-base/nodes/Crypto
|
||||
packages/nodes-base/nodes/CustomerIo
|
||||
packages/nodes-base/nodes/DateTime
|
||||
packages/nodes-base/nodes/DeepL
|
||||
packages/nodes-base/nodes/Demio
|
||||
packages/nodes-base/nodes/Dhl
|
||||
packages/nodes-base/nodes/Discord
|
||||
packages/nodes-base/nodes/Discourse
|
||||
packages/nodes-base/nodes/Disqus
|
||||
packages/nodes-base/nodes/Drift
|
||||
packages/nodes-base/nodes/Dropbox
|
||||
packages/nodes-base/nodes/Dropcontact
|
||||
packages/nodes-base/nodes/EditImage
|
||||
packages/nodes-base/nodes/Egoi
|
||||
packages/nodes-base/nodes/Elastic
|
||||
packages/nodes-base/nodes/EmailReadImap
|
||||
packages/nodes-base/nodes/EmailSend
|
||||
packages/nodes-base/nodes/Emelia
|
||||
packages/nodes-base/nodes/ERPNext
|
||||
packages/nodes-base/nodes/ErrorTrigger
|
||||
packages/nodes-base/nodes/Eventbrite
|
||||
packages/nodes-base/nodes/ExecuteCommand
|
||||
packages/nodes-base/nodes/ExecuteWorkflow
|
||||
packages/nodes-base/nodes/Facebook
|
||||
packages/nodes-base/nodes/Figma
|
||||
packages/nodes-base/nodes/FileMaker
|
||||
packages/nodes-base/nodes/Flow
|
||||
packages/nodes-base/nodes/FormIo
|
||||
packages/nodes-base/nodes/Formstack
|
||||
packages/nodes-base/nodes/Freshdesk
|
||||
packages/nodes-base/nodes/Freshservice
|
||||
packages/nodes-base/nodes/FreshworksCrm
|
||||
packages/nodes-base/nodes/Ftp
|
||||
packages/nodes-base/nodes/Function
|
||||
packages/nodes-base/nodes/FunctionItem
|
||||
packages/nodes-base/nodes/GetResponse
|
||||
packages/nodes-base/nodes/Ghost
|
||||
packages/nodes-base/nodes/Git
|
||||
packages/nodes-base/nodes/Github
|
||||
packages/nodes-base/nodes/Gitlab
|
||||
packages/nodes-base/nodes/Google
|
||||
packages/nodes-base/nodes/Gotify
|
||||
packages/nodes-base/nodes/GoToWebinar
|
||||
packages/nodes-base/nodes/Grafana
|
||||
packages/nodes-base/nodes/GraphQL
|
||||
packages/nodes-base/nodes/Grist
|
||||
packages/nodes-base/nodes/Gumroad
|
||||
packages/nodes-base/nodes/HackerNews
|
||||
packages/nodes-base/nodes/HaloPSA
|
||||
packages/nodes-base/nodes/Harvest
|
||||
packages/nodes-base/nodes/HelpScout
|
||||
packages/nodes-base/nodes/HomeAssistant
|
||||
packages/nodes-base/nodes/HtmlExtract
|
||||
packages/nodes-base/nodes/HttpRequest
|
||||
packages/nodes-base/nodes/Hubspot
|
||||
packages/nodes-base/nodes/HumanticAI
|
||||
packages/nodes-base/nodes/Hunter
|
||||
packages/nodes-base/nodes/ICalendar
|
||||
packages/nodes-base/nodes/If
|
||||
packages/nodes-base/nodes/Intercom
|
||||
packages/nodes-base/nodes/Interval
|
||||
packages/nodes-base/nodes/InvoiceNinja
|
||||
packages/nodes-base/nodes/ItemLists
|
||||
packages/nodes-base/nodes/Iterable
|
||||
packages/nodes-base/nodes/Jenkins
|
||||
packages/nodes-base/nodes/Jira
|
||||
packages/nodes-base/nodes/JotForm
|
||||
packages/nodes-base/nodes/Kafka
|
||||
packages/nodes-base/nodes/Keap
|
||||
packages/nodes-base/nodes/Kitemaker
|
||||
packages/nodes-base/nodes/KoBoToolbox
|
||||
packages/nodes-base/nodes/Lemlist
|
||||
packages/nodes-base/nodes/Line
|
||||
packages/nodes-base/nodes/Linear
|
||||
packages/nodes-base/nodes/LingvaNex
|
||||
packages/nodes-base/nodes/LinkedIn
|
||||
packages/nodes-base/nodes/LocalFileTrigger
|
||||
packages/nodes-base/nodes/Magento
|
||||
packages/nodes-base/nodes/Mailcheck
|
||||
packages/nodes-base/nodes/Mailchimp
|
||||
packages/nodes-base/nodes/MailerLite
|
||||
packages/nodes-base/nodes/Mailgun
|
||||
packages/nodes-base/nodes/Mailjet
|
||||
packages/nodes-base/nodes/Mandrill
|
||||
packages/nodes-base/nodes/Markdown
|
||||
packages/nodes-base/nodes/Marketstack
|
||||
packages/nodes-base/nodes/Matrix
|
||||
packages/nodes-base/nodes/Mattermost
|
||||
packages/nodes-base/nodes/Mautic
|
||||
packages/nodes-base/nodes/Medium
|
||||
packages/nodes-base/nodes/Merge
|
||||
packages/nodes-base/nodes/MessageBird
|
||||
packages/nodes-base/nodes/Microsoft
|
||||
packages/nodes-base/nodes/Mindee
|
||||
packages/nodes-base/nodes/Misp
|
||||
packages/nodes-base/nodes/Mocean
|
||||
packages/nodes-base/nodes/MondayCom
|
||||
packages/nodes-base/nodes/MongoDb
|
||||
packages/nodes-base/nodes/MonicaCrm
|
||||
packages/nodes-base/nodes/MoveBinaryData
|
||||
packages/nodes-base/nodes/MQTT
|
||||
packages/nodes-base/nodes/Msg91
|
||||
packages/nodes-base/nodes/MySql
|
||||
packages/nodes-base/nodes/N8nTrainingCustomerDatastore
|
||||
packages/nodes-base/nodes/N8nTrainingCustomerMessenger
|
||||
packages/nodes-base/nodes/N8nTrigger
|
||||
packages/nodes-base/nodes/Nasa
|
||||
packages/nodes-base/nodes/Netlify
|
||||
packages/nodes-base/nodes/NextCloud
|
||||
packages/nodes-base/nodes/NocoDB
|
||||
packages/nodes-base/nodes/NoOp
|
||||
packages/nodes-base/nodes/Notion
|
||||
packages/nodes-base/nodes/Odoo
|
||||
packages/nodes-base/nodes/OneSimpleApi
|
||||
packages/nodes-base/nodes/Onfleet
|
||||
packages/nodes-base/nodes/OpenThesaurus
|
||||
packages/nodes-base/nodes/OpenWeatherMap
|
||||
packages/nodes-base/nodes/Orbit
|
||||
packages/nodes-base/nodes/Oura
|
||||
packages/nodes-base/nodes/Paddle
|
||||
packages/nodes-base/nodes/PagerDuty
|
||||
packages/nodes-base/nodes/PayPal
|
||||
packages/nodes-base/nodes/Peekalink
|
||||
packages/nodes-base/nodes/Phantombuster
|
||||
packages/nodes-base/nodes/PhilipsHue
|
||||
packages/nodes-base/nodes/Pipedrive
|
||||
packages/nodes-base/nodes/Plivo
|
||||
packages/nodes-base/nodes/PostBin
|
||||
packages/nodes-base/nodes/Postgres
|
||||
packages/nodes-base/nodes/PostHog
|
||||
packages/nodes-base/nodes/Postmark
|
||||
packages/nodes-base/nodes/ProfitWell
|
||||
packages/nodes-base/nodes/Pushbullet
|
||||
packages/nodes-base/nodes/Pushcut
|
||||
packages/nodes-base/nodes/Pushover
|
||||
packages/nodes-base/nodes/QuestDb
|
||||
packages/nodes-base/nodes/QuickBase
|
||||
packages/nodes-base/nodes/QuickBooks
|
||||
packages/nodes-base/nodes/RabbitMQ
|
||||
packages/nodes-base/nodes/Raindrop
|
||||
packages/nodes-base/nodes/ReadBinaryFile
|
||||
packages/nodes-base/nodes/ReadBinaryFiles
|
||||
packages/nodes-base/nodes/ReadPdf
|
||||
packages/nodes-base/nodes/Reddit
|
||||
packages/nodes-base/nodes/Redis
|
||||
packages/nodes-base/nodes/RenameKeys
|
||||
packages/nodes-base/nodes/RespondToWebhook
|
||||
packages/nodes-base/nodes/Rocketchat
|
||||
packages/nodes-base/nodes/RssFeedRead
|
||||
packages/nodes-base/nodes/Rundeck
|
||||
packages/nodes-base/nodes/S3
|
||||
packages/nodes-base/nodes/Salesforce
|
||||
packages/nodes-base/nodes/Salesmate
|
||||
packages/nodes-base/nodes/SeaTable
|
||||
packages/nodes-base/nodes/SecurityScorecard
|
||||
packages/nodes-base/nodes/Segment
|
||||
packages/nodes-base/nodes/SendGrid
|
||||
packages/nodes-base/nodes/Sendy
|
||||
packages/nodes-base/nodes/SentryIo
|
||||
packages/nodes-base/nodes/ServiceNow
|
||||
packages/nodes-base/nodes/Set
|
||||
packages/nodes-base/nodes/Shopify
|
||||
packages/nodes-base/nodes/Signl4
|
||||
packages/nodes-base/nodes/Slack
|
||||
packages/nodes-base/nodes/Sms77
|
||||
packages/nodes-base/nodes/Snowflake
|
||||
packages/nodes-base/nodes/SplitInBatches
|
||||
packages/nodes-base/nodes/Splunk
|
||||
packages/nodes-base/nodes/Spontit
|
||||
packages/nodes-base/nodes/Spotify
|
||||
packages/nodes-base/nodes/SpreadsheetFile
|
||||
packages/nodes-base/nodes/SseTrigger
|
||||
packages/nodes-base/nodes/Ssh
|
||||
packages/nodes-base/nodes/Stackby
|
||||
packages/nodes-base/nodes/Start
|
||||
packages/nodes-base/nodes/StickyNote
|
||||
packages/nodes-base/nodes/StopAndError
|
||||
packages/nodes-base/nodes/Storyblok
|
||||
packages/nodes-base/nodes/Strapi
|
||||
packages/nodes-base/nodes/Strava
|
||||
packages/nodes-base/nodes/Stripe
|
||||
packages/nodes-base/nodes/Supabase
|
||||
packages/nodes-base/nodes/SurveyMonkey
|
||||
packages/nodes-base/nodes/Switch
|
||||
packages/nodes-base/nodes/SyncroMSP
|
||||
packages/nodes-base/nodes/Taiga
|
||||
packages/nodes-base/nodes/Tapfiliate
|
||||
packages/nodes-base/nodes/Telegram
|
||||
packages/nodes-base/nodes/TheHive
|
||||
packages/nodes-base/nodes/TimescaleDb
|
||||
packages/nodes-base/nodes/Todoist
|
||||
packages/nodes-base/nodes/Toggl
|
||||
packages/nodes-base/nodes/TravisCi
|
||||
packages/nodes-base/nodes/Trello
|
||||
packages/nodes-base/nodes/Twake
|
||||
packages/nodes-base/nodes/Twilio
|
||||
packages/nodes-base/nodes/Twist
|
||||
packages/nodes-base/nodes/Twitter
|
||||
packages/nodes-base/nodes/Typeform
|
||||
packages/nodes-base/nodes/UnleashedSoftware
|
||||
packages/nodes-base/nodes/Uplead
|
||||
packages/nodes-base/nodes/UProc
|
||||
packages/nodes-base/nodes/UptimeRobot
|
||||
packages/nodes-base/nodes/UrlScanIo
|
||||
packages/nodes-base/nodes/utils
|
||||
packages/nodes-base/nodes/Vero
|
||||
packages/nodes-base/nodes/Vonage
|
||||
packages/nodes-base/nodes/Wait
|
||||
packages/nodes-base/nodes/Webflow
|
||||
packages/nodes-base/nodes/Webhook
|
||||
packages/nodes-base/nodes/Wekan
|
||||
packages/nodes-base/nodes/Wise
|
||||
packages/nodes-base/nodes/WooCommerce
|
||||
packages/nodes-base/nodes/Wordpress
|
||||
packages/nodes-base/nodes/Workable
|
||||
packages/nodes-base/nodes/WorkflowTrigger
|
||||
packages/nodes-base/nodes/WriteBinaryFile
|
||||
packages/nodes-base/nodes/Wufoo
|
||||
packages/nodes-base/nodes/Xero
|
||||
packages/nodes-base/nodes/Xml
|
||||
packages/nodes-base/nodes/Yourls
|
||||
packages/nodes-base/nodes/Zammad
|
||||
packages/nodes-base/nodes/Zendesk
|
||||
packages/nodes-base/nodes/Zoho
|
||||
packages/nodes-base/nodes/Zoom
|
||||
packages/nodes-base/nodes/Zulip
|
||||
|
||||
packages/nodes-base/credentials/ActionNetworkApi.credentials.ts
|
||||
packages/nodes-base/credentials/ActiveCampaignApi.credentials.ts
|
||||
packages/nodes-base/credentials/AcuitySchedulingApi.credentials.ts
|
||||
packages/nodes-base/credentials/AcuitySchedulingOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/AffinityApi.credentials.ts
|
||||
packages/nodes-base/credentials/AgileCrmApi.credentials.ts
|
||||
packages/nodes-base/credentials/AirtableApi.credentials.ts
|
||||
packages/nodes-base/credentials/Amqp.credentials.ts
|
||||
packages/nodes-base/credentials/ApiTemplateIoApi.credentials.ts
|
||||
packages/nodes-base/credentials/AsanaApi.credentials.ts
|
||||
packages/nodes-base/credentials/AsanaOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/AutomizyApi.credentials.ts
|
||||
packages/nodes-base/credentials/AutopilotApi.credentials.ts
|
||||
packages/nodes-base/credentials/Aws.credentials.ts
|
||||
packages/nodes-base/credentials/AWS.svg
|
||||
packages/nodes-base/credentials/BambooHrApi.credentials.ts
|
||||
packages/nodes-base/credentials/BannerbearApi.credentials.ts
|
||||
packages/nodes-base/credentials/BaserowApi.credentials.ts
|
||||
packages/nodes-base/credentials/BeeminderApi.credentials.ts
|
||||
packages/nodes-base/credentials/BitbucketApi.credentials.ts
|
||||
packages/nodes-base/credentials/BitlyApi.credentials.ts
|
||||
packages/nodes-base/credentials/BitlyOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/BitwardenApi.credentials.ts
|
||||
packages/nodes-base/credentials/BoxOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/BrandfetchApi.credentials.ts
|
||||
packages/nodes-base/credentials/BubbleApi.credentials.ts
|
||||
packages/nodes-base/credentials/CalApi.credentials.ts
|
||||
packages/nodes-base/credentials/CalendlyApi.credentials.ts
|
||||
packages/nodes-base/credentials/ChargebeeApi.credentials.ts
|
||||
packages/nodes-base/credentials/CircleCiApi.credentials.ts
|
||||
packages/nodes-base/credentials/CiscoWebexOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/ClearbitApi.credentials.ts
|
||||
packages/nodes-base/credentials/ClickUpApi.credentials.ts
|
||||
packages/nodes-base/credentials/ClickUpOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/ClockifyApi.credentials.ts
|
||||
packages/nodes-base/credentials/CockpitApi.credentials.ts
|
||||
packages/nodes-base/credentials/CodaApi.credentials.ts
|
||||
packages/nodes-base/credentials/ContentfulApi.credentials.ts
|
||||
packages/nodes-base/credentials/ConvertKitApi.credentials.ts
|
||||
packages/nodes-base/credentials/CopperApi.credentials.ts
|
||||
packages/nodes-base/credentials/CortexApi.credentials.ts
|
||||
packages/nodes-base/credentials/CrateDb.credentials.ts
|
||||
packages/nodes-base/credentials/CustomerIoApi.credentials.ts
|
||||
packages/nodes-base/credentials/DeepLApi.credentials.ts
|
||||
packages/nodes-base/credentials/DemioApi.credentials.ts
|
||||
packages/nodes-base/credentials/DhlApi.credentials.ts
|
||||
packages/nodes-base/credentials/DiscourseApi.credentials.ts
|
||||
packages/nodes-base/credentials/DisqusApi.credentials.ts
|
||||
packages/nodes-base/credentials/DriftApi.credentials.ts
|
||||
packages/nodes-base/credentials/DriftOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/DropboxApi.credentials.ts
|
||||
packages/nodes-base/credentials/DropboxOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/DropcontactApi.credentials.ts
|
||||
packages/nodes-base/credentials/EgoiApi.credentials.ts
|
||||
packages/nodes-base/credentials/ElasticsearchApi.credentials.ts
|
||||
packages/nodes-base/credentials/ElasticSecurityApi.credentials.ts
|
||||
packages/nodes-base/credentials/EmeliaApi.credentials.ts
|
||||
packages/nodes-base/credentials/ERPNextApi.credentials.ts
|
||||
packages/nodes-base/credentials/EventbriteApi.credentials.ts
|
||||
packages/nodes-base/credentials/EventbriteOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/FacebookGraphApi.credentials.ts
|
||||
packages/nodes-base/credentials/FacebookGraphAppApi.credentials.ts
|
||||
packages/nodes-base/credentials/FigmaApi.credentials.ts
|
||||
packages/nodes-base/credentials/FileMaker.credentials.ts
|
||||
packages/nodes-base/credentials/FlowApi.credentials.ts
|
||||
packages/nodes-base/credentials/FormIoApi.credentials.ts
|
||||
packages/nodes-base/credentials/FormstackApi.credentials.ts
|
||||
packages/nodes-base/credentials/FormstackOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/FreshdeskApi.credentials.ts
|
||||
packages/nodes-base/credentials/FreshserviceApi.credentials.ts
|
||||
packages/nodes-base/credentials/FreshworksCrmApi.credentials.ts
|
||||
packages/nodes-base/credentials/Ftp.credentials.ts
|
||||
packages/nodes-base/credentials/GetResponseApi.credentials.ts
|
||||
packages/nodes-base/credentials/GetResponseOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GhostAdminApi.credentials.ts
|
||||
packages/nodes-base/credentials/GhostContentApi.credentials.ts
|
||||
packages/nodes-base/credentials/GithubApi.credentials.ts
|
||||
packages/nodes-base/credentials/GithubOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GitlabApi.credentials.ts
|
||||
packages/nodes-base/credentials/GitlabOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GitPassword.credentials.ts
|
||||
packages/nodes-base/credentials/GmailOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/Google.svg
|
||||
packages/nodes-base/credentials/GoogleAnalyticsOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GoogleApi.credentials.ts
|
||||
packages/nodes-base/credentials/GoogleBigQueryOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GoogleBooksOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GoogleCalendarOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GoogleCloudNaturalLanguageOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GoogleContactsOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GoogleDocsOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GoogleDriveOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GoogleFirebaseCloudFirestoreOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GoogleFirebaseRealtimeDatabaseOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GoogleOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GooglePerspectiveOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GoogleSheetsOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GoogleSlidesOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GoogleTasksOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GoogleTranslateOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GotifyApi.credentials.ts
|
||||
packages/nodes-base/credentials/GoToWebinarOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GrafanaApi.credentials.ts
|
||||
packages/nodes-base/credentials/GristApi.credentials.ts
|
||||
packages/nodes-base/credentials/GSuiteAdminOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/GumroadApi.credentials.ts
|
||||
packages/nodes-base/credentials/HaloPSAApi.credentials.ts
|
||||
packages/nodes-base/credentials/HarvestApi.credentials.ts
|
||||
packages/nodes-base/credentials/HarvestOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/HelpScoutOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/HomeAssistantApi.credentials.ts
|
||||
packages/nodes-base/credentials/HttpBasicAuth.credentials.ts
|
||||
packages/nodes-base/credentials/HttpDigestAuth.credentials.ts
|
||||
packages/nodes-base/credentials/HttpHeaderAuth.credentials.ts
|
||||
packages/nodes-base/credentials/HttpQueryAuth.credentials.ts
|
||||
packages/nodes-base/credentials/HubspotApi.credentials.ts
|
||||
packages/nodes-base/credentials/HubspotAppToken.credentials.ts
|
||||
packages/nodes-base/credentials/HubspotDeveloperApi.credentials.ts
|
||||
packages/nodes-base/credentials/HubspotOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/HumanticAiApi.credentials.ts
|
||||
packages/nodes-base/credentials/HunterApi.credentials.ts
|
||||
packages/nodes-base/credentials/Imap.credentials.ts
|
||||
packages/nodes-base/credentials/IntercomApi.credentials.ts
|
||||
packages/nodes-base/credentials/InvoiceNinjaApi.credentials.ts
|
||||
packages/nodes-base/credentials/IterableApi.credentials.ts
|
||||
packages/nodes-base/credentials/JenkinsApi.credentials.ts
|
||||
packages/nodes-base/credentials/JiraSoftwareCloudApi.credentials.ts
|
||||
packages/nodes-base/credentials/JiraSoftwareServerApi.credentials.ts
|
||||
packages/nodes-base/credentials/JotFormApi.credentials.ts
|
||||
packages/nodes-base/credentials/Kafka.credentials.ts
|
||||
packages/nodes-base/credentials/KeapOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/KitemakerApi.credentials.ts
|
||||
packages/nodes-base/credentials/KoBoToolboxApi.credentials.ts
|
||||
packages/nodes-base/credentials/LemlistApi.credentials.ts
|
||||
packages/nodes-base/credentials/LinearApi.credentials.ts
|
||||
packages/nodes-base/credentials/LineNotifyOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/LingvaNexApi.credentials.ts
|
||||
packages/nodes-base/credentials/LinkedInOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/Magento2Api.credentials.ts
|
||||
packages/nodes-base/credentials/MailcheckApi.credentials.ts
|
||||
packages/nodes-base/credentials/MailchimpApi.credentials.ts
|
||||
packages/nodes-base/credentials/MailchimpOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/MailerLiteApi.credentials.ts
|
||||
packages/nodes-base/credentials/MailgunApi.credentials.ts
|
||||
packages/nodes-base/credentials/MailjetEmailApi.credentials.ts
|
||||
packages/nodes-base/credentials/MailjetSmsApi.credentials.ts
|
||||
packages/nodes-base/credentials/MandrillApi.credentials.ts
|
||||
packages/nodes-base/credentials/MarketstackApi.credentials.ts
|
||||
packages/nodes-base/credentials/MatrixApi.credentials.ts
|
||||
packages/nodes-base/credentials/MattermostApi.credentials.ts
|
||||
packages/nodes-base/credentials/MauticApi.credentials.ts
|
||||
packages/nodes-base/credentials/MauticOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/MediumApi.credentials.ts
|
||||
packages/nodes-base/credentials/MediumOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/MessageBirdApi.credentials.ts
|
||||
packages/nodes-base/credentials/Microsoft.svg
|
||||
packages/nodes-base/credentials/MicrosoftDynamicsOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/MicrosoftExcelOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/MicrosoftGraphSecurityOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/MicrosoftOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/MicrosoftOneDriveOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/MicrosoftOutlookOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/MicrosoftSql.credentials.ts
|
||||
packages/nodes-base/credentials/MicrosoftTeamsOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/MicrosoftToDoOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/MindeeInvoiceApi.credentials.ts
|
||||
packages/nodes-base/credentials/MindeeReceiptApi.credentials.ts
|
||||
packages/nodes-base/credentials/MispApi.credentials.ts
|
||||
packages/nodes-base/credentials/MoceanApi.credentials.ts
|
||||
packages/nodes-base/credentials/MondayComApi.credentials.ts
|
||||
packages/nodes-base/credentials/MondayComOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/MongoDb.credentials.ts
|
||||
packages/nodes-base/credentials/MonicaCrmApi.credentials.ts
|
||||
packages/nodes-base/credentials/Mqtt.credentials.ts
|
||||
packages/nodes-base/credentials/Msg91Api.credentials.ts
|
||||
packages/nodes-base/credentials/MySql.credentials.ts
|
||||
packages/nodes-base/credentials/NasaApi.credentials.ts
|
||||
packages/nodes-base/credentials/NetlifyApi.credentials.ts
|
||||
packages/nodes-base/credentials/NetlifyOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/NextCloudApi.credentials.ts
|
||||
packages/nodes-base/credentials/NextCloudOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/NocoDb.credentials.ts
|
||||
packages/nodes-base/credentials/NotionApi.credentials.ts
|
||||
packages/nodes-base/credentials/NotionOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/OAuth1Api.credentials.ts
|
||||
packages/nodes-base/credentials/OAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/OdooApi.credentials.ts
|
||||
packages/nodes-base/credentials/OneSimpleApi.credentials.ts
|
||||
packages/nodes-base/credentials/OnfleetApi.credentials.ts
|
||||
packages/nodes-base/credentials/OpenWeatherMapApi.credentials.ts
|
||||
packages/nodes-base/credentials/OrbitApi.credentials.ts
|
||||
packages/nodes-base/credentials/OuraApi.credentials.ts
|
||||
packages/nodes-base/credentials/PaddleApi.credentials.ts
|
||||
packages/nodes-base/credentials/PagerDutyApi.credentials.ts
|
||||
packages/nodes-base/credentials/PagerDutyOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/PayPalApi.credentials.ts
|
||||
packages/nodes-base/credentials/PeekalinkApi.credentials.ts
|
||||
packages/nodes-base/credentials/PhantombusterApi.credentials.ts
|
||||
packages/nodes-base/credentials/PhilipsHueOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/PipedriveApi.credentials.ts
|
||||
packages/nodes-base/credentials/PipedriveOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/PlivoApi.credentials.ts
|
||||
packages/nodes-base/credentials/Postgres.credentials.ts
|
||||
packages/nodes-base/credentials/PostHogApi.credentials.ts
|
||||
packages/nodes-base/credentials/PostmarkApi.credentials.ts
|
||||
packages/nodes-base/credentials/ProfitWellApi.credentials.ts
|
||||
packages/nodes-base/credentials/PushbulletOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/PushcutApi.credentials.ts
|
||||
packages/nodes-base/credentials/PushoverApi.credentials.ts
|
||||
packages/nodes-base/credentials/QuestDb.credentials.ts
|
||||
packages/nodes-base/credentials/QuickBaseApi.credentials.ts
|
||||
packages/nodes-base/credentials/QuickBooksOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/RabbitMQ.credentials.ts
|
||||
packages/nodes-base/credentials/RaindropOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/RedditOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/Redis.credentials.ts
|
||||
packages/nodes-base/credentials/RocketchatApi.credentials.ts
|
||||
packages/nodes-base/credentials/RundeckApi.credentials.ts
|
||||
packages/nodes-base/credentials/S3.credentials.ts
|
||||
packages/nodes-base/credentials/SalesforceJwtApi.credentials.ts
|
||||
packages/nodes-base/credentials/SalesforceOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/SalesmateApi.credentials.ts
|
||||
packages/nodes-base/credentials/SeaTableApi.credentials.ts
|
||||
packages/nodes-base/credentials/SecurityScorecardApi.credentials.ts
|
||||
packages/nodes-base/credentials/SegmentApi.credentials.ts
|
||||
packages/nodes-base/credentials/SendGridApi.credentials.ts
|
||||
packages/nodes-base/credentials/SendyApi.credentials.ts
|
||||
packages/nodes-base/credentials/SentryIoApi.credentials.ts
|
||||
packages/nodes-base/credentials/SentryIoOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/SentryIoServerApi.credentials.ts
|
||||
packages/nodes-base/credentials/ServiceNowBasicApi.credentials.ts
|
||||
packages/nodes-base/credentials/ServiceNowOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/Sftp.credentials.ts
|
||||
packages/nodes-base/credentials/ShopifyApi.credentials.ts
|
||||
packages/nodes-base/credentials/Signl4Api.credentials.ts
|
||||
packages/nodes-base/credentials/SlackApi.credentials.ts
|
||||
packages/nodes-base/credentials/SlackOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/Sms77Api.credentials.ts
|
||||
packages/nodes-base/credentials/Smtp.credentials.ts
|
||||
packages/nodes-base/credentials/Snowflake.credentials.ts
|
||||
packages/nodes-base/credentials/SplunkApi.credentials.ts
|
||||
packages/nodes-base/credentials/SpontitApi.credentials.ts
|
||||
packages/nodes-base/credentials/SpotifyOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/SshPassword.credentials.ts
|
||||
packages/nodes-base/credentials/SshPrivateKey.credentials.ts
|
||||
packages/nodes-base/credentials/StackbyApi.credentials.ts
|
||||
packages/nodes-base/credentials/StoryblokContentApi.credentials.ts
|
||||
packages/nodes-base/credentials/StoryblokManagementApi.credentials.ts
|
||||
packages/nodes-base/credentials/StrapiApi.credentials.ts
|
||||
packages/nodes-base/credentials/StravaOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/StripeApi.credentials.ts
|
||||
packages/nodes-base/credentials/SupabaseApi.credentials.ts
|
||||
packages/nodes-base/credentials/SurveyMonkeyApi.credentials.ts
|
||||
packages/nodes-base/credentials/SurveyMonkeyOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/SyncroMspApi.credentials.ts
|
||||
packages/nodes-base/credentials/TaigaApi.credentials.ts
|
||||
packages/nodes-base/credentials/TapfiliateApi.credentials.ts
|
||||
packages/nodes-base/credentials/TelegramApi.credentials.ts
|
||||
packages/nodes-base/credentials/TheHiveApi.credentials.ts
|
||||
packages/nodes-base/credentials/TimescaleDb.credentials.ts
|
||||
packages/nodes-base/credentials/TodoistApi.credentials.ts
|
||||
packages/nodes-base/credentials/TodoistOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/TogglApi.credentials.ts
|
||||
packages/nodes-base/credentials/TravisCiApi.credentials.ts
|
||||
packages/nodes-base/credentials/TrelloApi.credentials.ts
|
||||
packages/nodes-base/credentials/TwakeCloudApi.credentials.ts
|
||||
packages/nodes-base/credentials/TwakeServerApi.credentials.ts
|
||||
packages/nodes-base/credentials/TwilioApi.credentials.ts
|
||||
packages/nodes-base/credentials/TwistOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/TwitterOAuth1Api.credentials.ts
|
||||
packages/nodes-base/credentials/TypeformApi.credentials.ts
|
||||
packages/nodes-base/credentials/TypeformOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/UnleashedSoftwareApi.credentials.ts
|
||||
packages/nodes-base/credentials/UpleadApi.credentials.ts
|
||||
packages/nodes-base/credentials/UProcApi.credentials.ts
|
||||
packages/nodes-base/credentials/UptimeRobotApi.credentials.ts
|
||||
packages/nodes-base/credentials/UrlScanIoApi.credentials.ts
|
||||
packages/nodes-base/credentials/VeroApi.credentials.ts
|
||||
packages/nodes-base/credentials/VonageApi.credentials.ts
|
||||
packages/nodes-base/credentials/WebflowApi.credentials.ts
|
||||
packages/nodes-base/credentials/WebflowOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/WekanApi.credentials.ts
|
||||
packages/nodes-base/credentials/WiseApi.credentials.ts
|
||||
packages/nodes-base/credentials/WooCommerceApi.credentials.ts
|
||||
packages/nodes-base/credentials/WordpressApi.credentials.ts
|
||||
packages/nodes-base/credentials/WorkableApi.credentials.ts
|
||||
packages/nodes-base/credentials/WufooApi.credentials.ts
|
||||
packages/nodes-base/credentials/XeroOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/YourlsApi.credentials.ts
|
||||
packages/nodes-base/credentials/YouTubeOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/ZammadBasicAuthApi.credentials.ts
|
||||
packages/nodes-base/credentials/ZammadTokenAuthApi.credentials.ts
|
||||
packages/nodes-base/credentials/ZendeskApi.credentials.ts
|
||||
packages/nodes-base/credentials/ZendeskOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/ZohoOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/ZoomApi.credentials.ts
|
||||
packages/nodes-base/credentials/ZoomOAuth2Api.credentials.ts
|
||||
packages/nodes-base/credentials/ZulipApi.credentials.ts
|
||||
packages/nodes-base/nodes/UProc/Json/Tools.ts
|
||||
|
|
|
|||
10
.vscode/DEBUGGER.md
vendored
10
.vscode/DEBUGGER.md
vendored
|
|
@ -18,7 +18,7 @@ Breakpoints are noted with a red dot in front of the line, meaning that whenever
|
|||
|
||||
## What if I change the code?
|
||||
|
||||
You might need to restart the debugger if you make changes to your code, since the running process will be executing an oudated version of the code.
|
||||
You might need to restart the debugger if you make changes to your code, since the running process will be executing an outdated version of the code.
|
||||
|
||||
In order to make this process easier you can simply run `npm run watch` in another terminal window, so you don't have to fully build the project. Please note that restarting n8n is still required, but this is much faster.
|
||||
|
||||
|
|
@ -26,13 +26,13 @@ In order to make this process easier you can simply run `npm run watch` in anoth
|
|||
|
||||
Docker debugging is currently not functional. We offer 2 other methods:
|
||||
|
||||
1) Launch n8n from inside VSCode:
|
||||
1. Launch n8n from inside VSCode:
|
||||
From the "Run and Debug" section in VSCode you can choose the option named "Launch n8n with debug".
|
||||
This will start n8n to run as normal, but with debugger attached.
|
||||
2) Another possibility is if n8n is already running, say, in your terminal.
|
||||
This will start n8n to run as normal, but with debugger attached.
|
||||
2. Another possibility is if n8n is already running, say, in your terminal.
|
||||
You can attach the debugger to it.
|
||||
This is done by choosing the option "Attach to running n8n".
|
||||
VSCode will present you with a prompt to select the n8n process. It usually is displayed with `node ./n8n`
|
||||
VSCode will present you with a prompt to select the n8n process. It usually is displayed with `node ./n8n`
|
||||
|
||||
## What can be debugged?
|
||||
|
||||
|
|
|
|||
1
.vscode/extensions.json
vendored
1
.vscode/extensions.json
vendored
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"dangmai.workspace-default-settings",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"EditorConfig.EditorConfig",
|
||||
"esbenp.prettier-vscode",
|
||||
|
|
|
|||
25
.vscode/launch.json
vendored
25
.vscode/launch.json
vendored
|
|
@ -8,23 +8,32 @@
|
|||
"name": "Attach to running n8n",
|
||||
"processId": "${command:PickProcess}",
|
||||
"request": "attach",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"skipFiles": ["<node_internals>/**"],
|
||||
"type": "node"
|
||||
},
|
||||
{
|
||||
"name": "Launch n8n with debug",
|
||||
"program": "${workspaceFolder}/packages/cli/bin/n8n",
|
||||
"request": "launch",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"skipFiles": ["<node_internals>/**"],
|
||||
"type": "node",
|
||||
"env": {
|
||||
// "N8N_PORT": "5679",
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "Debug CLI tests",
|
||||
"cwd": "${workspaceFolder}/packages/cli",
|
||||
"runtimeExecutable": "npm",
|
||||
"args": [
|
||||
"run",
|
||||
"test",
|
||||
// "--",
|
||||
// "ActiveExecutions"
|
||||
],
|
||||
"type": "node",
|
||||
"request": "launch"
|
||||
},
|
||||
]
|
||||
|
||||
/**
|
||||
|
|
|
|||
11
.vscode/settings.default.json
vendored
Normal file
11
.vscode/settings.default.json
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"search.exclude": {
|
||||
"node_modules": true,
|
||||
"dist": true,
|
||||
"package-lock.json": true
|
||||
},
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"workspace-default-settings.runOnActivation": true
|
||||
}
|
||||
720
CHANGELOG.md
720
CHANGELOG.md
|
|
@ -1,174 +1,613 @@
|
|||
## [0.186.1](https://github.com/n8n-io/n8n/compare/n8n@0.186.0...n8n@0.186.1) (2022-07-14)
|
||||
## [0.197.1](https://github.com/n8n-io/n8n/compare/n8n@0.197.0...n8n@0.197.1) (2022-10-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Airtable Node:** Fix authentication issue ([#3709](https://github.com/n8n-io/n8n/issues/3709)) ([33d8042](https://github.com/n8n-io/n8n/commit/33d804284ae02140749ab94eecfca1699e13afee))
|
||||
* **editor:** Fix resource locator width for trigger nodes ([#4302](https://github.com/n8n-io/n8n/issues/4302)) ([845d1f8](https://github.com/n8n-io/n8n/commit/845d1f8bd9763e9b886ac70c7ccbd37ff1c24b43))
|
||||
|
||||
|
||||
# [0.197.0](https://github.com/n8n-io/n8n/compare/n8n@0.196.0...n8n@0.197.0) (2022-10-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cli:** Cache generated assets in user writable directory instead ([#4275](https://github.com/n8n-io/n8n/issues/4275)) ([e63eee2](https://github.com/n8n-io/n8n/commit/e63eee28e00ae01fe4db92ac1235d7be7f25b76d))
|
||||
* **core:** Fix excess run for pinned trigger in partial execution ([#4185](https://github.com/n8n-io/n8n/issues/4185)) ([a751fd3](https://github.com/n8n-io/n8n/commit/a751fd3ce762df99490889153d36029ff4cd00da))
|
||||
* **core:** Fix hooks URLs no longer added to `index.html` ([#4262](https://github.com/n8n-io/n8n/issues/4262)) ([cc2a2e4](https://github.com/n8n-io/n8n/commit/cc2a2e438b0dee703b40dab67b4770dc06c76a7e))
|
||||
* **editor:** Fix `pairedItem` in combination with pinned data ([#4257](https://github.com/n8n-io/n8n/issues/4257)) ([e30c78f](https://github.com/n8n-io/n8n/commit/e30c78febeac8bfcfbe5f1c4c13122594d8a518e))
|
||||
* **Github Trigger Node:** Fix issue with trigger not always activating ([#4284](https://github.com/n8n-io/n8n/issues/4284)) ([694f1ba](https://github.com/n8n-io/n8n/commit/694f1ba4f5780b2e9821db52e579883bbc289df4))
|
||||
* **Microsoft Excel Node:** Fix issue with pagination when getting all items ([#4247](https://github.com/n8n-io/n8n/issues/4247)) ([1067ec0](https://github.com/n8n-io/n8n/commit/1067ec0f5bd8e57650ccd9924e01fc52fbf0c43c))
|
||||
* **Microsoft ToDo Node:** Fix pagination issue when getting all items ([#4222](https://github.com/n8n-io/n8n/issues/4222)) ([4595b54](https://github.com/n8n-io/n8n/commit/4595b54e562c50c48bdfe8049cb170196713cc8b))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **AWS Certificate Manager Node:** Add AWS Certificate Manager node ([#4263](https://github.com/n8n-io/n8n/issues/4263)) ([9b3f30d](https://github.com/n8n-io/n8n/commit/9b3f30d584901e7dc5fa87854e72f438f2557665))
|
||||
* **AWS Elastic Load Balancer Node:** Add Elastic Load Balancer node ([#4264](https://github.com/n8n-io/n8n/issues/4264)) ([fac6efb](https://github.com/n8n-io/n8n/commit/fac6efbb4158aa713bf5472d27b6fe341db8047d))
|
||||
* **Citrix ADC Node:** Add Citrix ADC node ([#4274](https://github.com/n8n-io/n8n/issues/4274)) ([7abc7e6](https://github.com/n8n-io/n8n/commit/7abc7e64082b60fa48f99f4b1f41d176fbb6d6ad))
|
||||
* **Cloudflare Node:** Add Cloudflare node ([#4271](https://github.com/n8n-io/n8n/issues/4271)) ([94a02c6](https://github.com/n8n-io/n8n/commit/94a02c64928205c441af5515739fe8eab7160b33))
|
||||
* **core:** Improve light versioning support in declarative node design ([#4254](https://github.com/n8n-io/n8n/issues/4254)) ([1b320cd](https://github.com/n8n-io/n8n/commit/1b320cd8c9b1e00257c03f92a175e3c9ab9f8030))
|
||||
* **Crypto Node:** Add SHA3 support ([#4285](https://github.com/n8n-io/n8n/issues/4285)) ([9407fdd](https://github.com/n8n-io/n8n/commit/9407fddd21295b7bdf2757736b69b046a02e798c))
|
||||
* **editor:** JSON mapping ([#4270](https://github.com/n8n-io/n8n/issues/4270)) ([19e333e](https://github.com/n8n-io/n8n/commit/19e333e6602648feacd80277e170d8af38ce06c4))
|
||||
* **Venafi TLS Protect Cloud Node:** Add Venafi TLS Protect Cloud ([#4253](https://github.com/n8n-io/n8n/issues/4253)) ([d36e920](https://github.com/n8n-io/n8n/commit/d36e920997d55957385e4ab4d6734639a4c28648))
|
||||
* **Venafi TLS Protect Datacenter Node:** Add Venafi TLS Protect Datacenter node ([#4255](https://github.com/n8n-io/n8n/issues/4255)) ([a14110e](https://github.com/n8n-io/n8n/commit/a14110e663caca8e886312a116805c41020ba812))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **tooling:** Upgrade to TypeScript 4.8 ([#4207](https://github.com/n8n-io/n8n/issues/4207)) ([9089dbe](https://github.com/n8n-io/n8n/commit/9089dbe94220f1789d2cea74608352a070e09bac))
|
||||
|
||||
|
||||
|
||||
# [0.196.0](https://github.com/n8n-io/n8n/compare/n8n@0.195.5...n8n@0.196.0) (2022-09-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **build:** Add typing for SSE channel ([#4196](https://github.com/n8n-io/n8n/issues/4196)) ([eaf13cd](https://github.com/n8n-io/n8n/commit/eaf13cdf759497816255926ccc4a60f176d36a1a))
|
||||
* **build:** Fix lint issue to fix build ([#4232](https://github.com/n8n-io/n8n/issues/4232)) ([40795d6](https://github.com/n8n-io/n8n/commit/40795d6adf383ec09290ca2a9da7e6ebeeaffb03))
|
||||
* **Trello Node:** cardId property not showing up for completed checklist in Trello ([#4186](https://github.com/n8n-io/n8n/issues/4186)) ([05d2275](https://github.com/n8n-io/n8n/commit/05d227571d53a93380aab05444c5de38e448a317))
|
||||
* **cli:** Add git to all docker images ([#4189](https://github.com/n8n-io/n8n/issues/4189)) ([0b6a958](https://github.com/n8n-io/n8n/commit/0b6a9585d41992f5dcc1a5683adc3f36e43955af))
|
||||
* **cli:** Disable `X-Powered-By: Express` Header ([#4224](https://github.com/n8n-io/n8n/issues/4224)) ([a8da9c3](https://github.com/n8n-io/n8n/commit/a8da9c31a95dabbbdc4eb67e5157dd5631ff3031))
|
||||
* **cli:** Disable CORS on SSE connections in production ([#4190](https://github.com/n8n-io/n8n/issues/4190)) ([e6e4f29](https://github.com/n8n-io/n8n/commit/e6e4f297c697c3371743bc1e1b2524235c4aea19))
|
||||
* **core:** Remove commented out lines ([6ac442a](https://github.com/n8n-io/n8n/commit/6ac442a2accdeb4e51a3333ac6c45c8bfde0608d))
|
||||
* delete unused dependencies ([#4231](https://github.com/n8n-io/n8n/issues/4231)) ([737cbf9](https://github.com/n8n-io/n8n/commit/737cbf9694296b76bc6c19716ffd6d4dcccf1c18))
|
||||
* **editor:** Add missing event handler to accordion component ([#4179](https://github.com/n8n-io/n8n/issues/4179)) ([e709cb5](https://github.com/n8n-io/n8n/commit/e709cb5fe28839cf314a511a5a40f374a8ad4647))
|
||||
* **editor:** Fix storybook setup ([#4234](https://github.com/n8n-io/n8n/issues/4234)) ([43dc8e6](https://github.com/n8n-io/n8n/commit/43dc8e6da1970d7ea4bb67635c8b20354150c87d))
|
||||
* **editor:** Fix `BASE_URL` replacement on windows ([#4202](https://github.com/n8n-io/n8n/issues/4202)) ([5f0c656](https://github.com/n8n-io/n8n/commit/5f0c65690b8dddd21f5a694d6e74980296c7fbb8))
|
||||
* **editor:** Fix ParameterInput inputField ref focus ([#4215](https://github.com/n8n-io/n8n/issues/4215)) ([ed40397](https://github.com/n8n-io/n8n/commit/ed403972a929c710180b2ac47fa4057ec47c4a35))
|
||||
* **editor:** Make lodash aliases work on case-sensitive filesystems ([#4233](https://github.com/n8n-io/n8n/issues/4233)) ([a381729](https://github.com/n8n-io/n8n/commit/a3817291d7795345542b63641e265fe8f29e8750))
|
||||
* **editor:** Fix copy-pasting workflow into pin data code editor ([#4193](https://github.com/n8n-io/n8n/issues/4193)) ([a4f9f04](https://github.com/n8n-io/n8n/commit/a4f9f041a07bea641c09d517942393c24d5e4a37))
|
||||
* **editor:** Fix run data footer overflow ([#4175](https://github.com/n8n-io/n8n/issues/4175)) ([20b0e14](https://github.com/n8n-io/n8n/commit/20b0e14f728cd9b77e993ee15e3bd276b102e427))
|
||||
* **editor:** Fix run data pagination selector not showing ([#4187](https://github.com/n8n-io/n8n/issues/4187)) ([2b3a090](https://github.com/n8n-io/n8n/commit/2b3a0901aa07046dc68cc6ece6c015819835cfd4))
|
||||
* **editor:** Fix run selector not opening ([#4199](https://github.com/n8n-io/n8n/issues/4199)) ([67513e1](https://github.com/n8n-io/n8n/commit/67513e191d82dfa97a477e38770fe610dd9fca65))
|
||||
* **editor:** Updating leftover i18n references in NodeView ([#4236](https://github.com/n8n-io/n8n/issues/4236)) ([068c5db](https://github.com/n8n-io/n8n/commit/068c5db1eecd60d650c3646f62eeadfad42df470))
|
||||
* **editor:** Updating wrong i18n string reference ([#4209](https://github.com/n8n-io/n8n/issues/4209)) ([80e2d65](https://github.com/n8n-io/n8n/commit/80e2d65933101e69dee98ba69e80156f2ad3b7a9))
|
||||
* **editor:** Fix slow loading times for nodeTypes, node creator vuex reference, and pushConnection in settings views ([#4230](https://github.com/n8n-io/n8n/issues/4230)) ([d3c0d99](https://github.com/n8n-io/n8n/commit/d3c0d998679965f53fb170e0f476f7bd17665645))
|
||||
* **Merge Node:** Update description in merge node ([47eb531](https://github.com/n8n-io/n8n/commit/47eb531e980b1998fdaaece5cf533dc3903dc796))
|
||||
* **core:** Fix and harmonize all primaryDocumentation links ([#4191](https://github.com/n8n-io/n8n/issues/4191)) ([6e8e4f5](https://github.com/n8n-io/n8n/commit/6e8e4f5937eb257efcbb4ff37c6b9403a044eecf))
|
||||
* **core:** Remove --forceExit flag from cli tests ([#4211](https://github.com/n8n-io/n8n/issues/4211)) ([faaeb52](https://github.com/n8n-io/n8n/commit/faaeb52a14a40b30ffe90cddb84c45af55acdf93))
|
||||
* **Wekan Node:** Fix authentication with new versions of Wekan ([#4088](https://github.com/n8n-io/n8n/issues/4088)) ([764bd35](https://github.com/n8n-io/n8n/commit/764bd3522b72d6188f2425df0710d16c5b34a20b))
|
||||
* **Wufoo Trigger Node:** Fix form names not being listed correctly ([#4151](https://github.com/n8n-io/n8n/issues/4151)) ([616d62a](https://github.com/n8n-io/n8n/commit/616d62aa8ef64952eb248b162176460a7ac65cc3))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **editor:** Add support for unit testing using vitest in editor-ui ([#4184](https://github.com/n8n-io/n8n/issues/4184)) ([bb66e60](https://github.com/n8n-io/n8n/commit/bb66e60afcbf120f3f916339c983b881ea185487))
|
||||
* **cli:** Optimise serving static assets ([#4182](https://github.com/n8n-io/n8n/issues/4182)) ([8b0ccc0](https://github.com/n8n-io/n8n/commit/8b0ccc017bab28903d57a91602331981e45077d9))
|
||||
* **core:** Improve paired item and add additional variables ([#3765](https://github.com/n8n-io/n8n/issues/3765)) ([5526057](https://github.com/n8n-io/n8n/commit/5526057efc7d27a1373dc2c46beda2737ed54689))
|
||||
* **editor:** Update ResourceLocator error text ([#4242](https://github.com/n8n-io/n8n/issues/4242)) ([b0397f0](https://github.com/n8n-io/n8n/commit/b0397f0262f8a921a0552179ca95cba5f03295ce))
|
||||
* **editor:** Main navigation redesign ([#4144](https://github.com/n8n-io/n8n/issues/4144)) ([3db53a1](https://github.com/n8n-io/n8n/commit/3db53a193418db2554e00d7499457d7f400663e1)), closes [#4060](https://github.com/n8n-io/n8n/issues/4060)
|
||||
* **HTTP Request Node:** Redesign and add the ability to import cURL commands ([#3860](https://github.com/n8n-io/n8n/issues/3860)) ([f37d6ba](https://github.com/n8n-io/n8n/commit/f37d6ba03bcac82a50b2e9ee60c29d6a1a4be911))
|
||||
* **editor:** Migrate editor-ui to Vite.js and various DX improvements (N8N-2277) ([#4061](https://github.com/n8n-io/n8n/issues/4061)) ([27e2ce0](https://github.com/n8n-io/n8n/commit/27e2ce047060ca8bfdef43cb7fe50b58c9508375)), closes [#4069](https://github.com/n8n-io/n8n/issues/4069)
|
||||
* **n8n Api node:** Add core node for consuming the n8n API ([#4076](https://github.com/n8n-io/n8n/issues/4076)) ([929315f](https://github.com/n8n-io/n8n/commit/929315f9e4b56d975783b7d069bdb163218aa7d5))
|
||||
* **RabbitMQ Trigger Node:** Automatically reconnect on disconnect ([#4019](https://github.com/n8n-io/n8n/issues/4019)) ([23bd71b](https://github.com/n8n-io/n8n/commit/23bd71b82aafb4d894091a115a168a049c5f594c))
|
||||
* **core:** Share unshared credentials with owner on reset ([#4216](https://github.com/n8n-io/n8n/issues/4216)) ([3b7de6d](https://github.com/n8n-io/n8n/commit/3b7de6db725cffbd5ee9f06aee00029d984fe7b8))
|
||||
* **Slack Node:** Add operation get many for user resource ([#3150](https://github.com/n8n-io/n8n/issues/3150)) ([2714b4c](https://github.com/n8n-io/n8n/commit/2714b4ced786212906f79c11fae28819aae420e4))
|
||||
* **WhatsApp Business node:** Add WhatsApp node ([#3659](https://github.com/n8n-io/n8n/issues/3659)) ([f63710a](https://github.com/n8n-io/n8n/commit/f63710a8923bd742f3259822870f3a2f0b7e04aa))
|
||||
|
||||
|
||||
|
||||
## [0.195.5](https://github.com/n8n-io/n8n/compare/n8n@0.195.4...n8n@0.195.5) (2022-09-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **editor:** Fix extract value logic for expressions ([#4178](https://github.com/n8n-io/n8n/issues/4178)) ([46f9562](https://github.com/n8n-io/n8n/commit/46f95622e38e0327c01927bc41f4ea3c413db466))
|
||||
|
||||
|
||||
|
||||
## [0.195.4](https://github.com/n8n-io/n8n/compare/n8n@0.195.3...n8n@0.195.4) (2022-09-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** Fix resolve RL values in expressions ([#4173](https://github.com/n8n-io/n8n/issues/4173)) ([469c391](https://github.com/n8n-io/n8n/commit/469c391fee70479d8095a90e6eb525032a0e02a5))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **editor-ui:** Resizable main panel ([#3980](https://github.com/n8n-io/n8n/issues/3980)) ([d01f7d4](https://github.com/n8n-io/n8n/commit/d01f7d4d93366054075fdfcadfdff5cf03913472)), closes [#3930](https://github.com/n8n-io/n8n/issues/3930)
|
||||
|
||||
|
||||
|
||||
## [0.195.3](https://github.com/n8n-io/n8n/compare/n8n@0.195.2...n8n@0.195.3) (2022-09-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **editor:** Fix expressions bug with numbers and booleans ([#4169](https://github.com/n8n-io/n8n/issues/4169)) ([19d08e6](https://github.com/n8n-io/n8n/commit/19d08e641896fa9b1c9edf04505eac213e1de71a))
|
||||
* **MSSQL Node:** Support tdsVersion option ([89d2d10](https://github.com/n8n-io/n8n/commit/89d2d10c520482f47ddd755e76b0bdf3d45e6008))
|
||||
|
||||
|
||||
## [0.195.2](https://github.com/n8n-io/n8n/compare/n8n@0.195.1...n8n@0.195.2) (2022-09-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** Fix mysql migration ([#4166](https://github.com/n8n-io/n8n/issues/4166)) ([0aeb55d](https://github.com/n8n-io/n8n/commit/0aeb55dcfd6c107c67e4c974e3371e29e188310b))
|
||||
|
||||
|
||||
|
||||
## [0.195.1](https://github.com/n8n-io/n8n/compare/n8n@0.195.0...n8n@0.195.1) (2022-09-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** Fix postgres migration ([#4164](https://github.com/n8n-io/n8n/issues/4164)) ([2598ec8](https://github.com/n8n-io/n8n/commit/2598ec8a3e7a7d4e444cd4767d5944fa691dd9e1))
|
||||
|
||||
|
||||
|
||||
# [0.195.0](https://github.com/n8n-io/n8n/compare/n8n@0.194.0...n8n@0.195.0) (2022-09-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Box Node:** Fix issue with response data not being returned ([#4147](https://github.com/n8n-io/n8n/issues/4147)) ([3cfc5b5](https://github.com/n8n-io/n8n/commit/3cfc5b55abe6aba3b68ae27846cd18e3ec79b518))
|
||||
* **cli:** Fix issue with n8n crashing when error in poll method ([#4008](https://github.com/n8n-io/n8n/issues/4008)) ([6c41b29](https://github.com/n8n-io/n8n/commit/6c41b29ad2c1fffc5710d06250037e2a278b9b4a))
|
||||
* **editor:** Fix broken output panel for wait node executions ([#4156](https://github.com/n8n-io/n8n/issues/4156)) ([40ebbea](https://github.com/n8n-io/n8n/commit/40ebbeaefc3a8c0e730468cd8171590dc823106c))
|
||||
* **core:** Prevent calls to constructor to forbid arbitrary code execution ([#4139](https://github.com/n8n-io/n8n/issues/4139)) ([a8030db](https://github.com/n8n-io/n8n/commit/a8030dbda5b17ee158ac7ef7f586f212698252f7))
|
||||
* **HTTP Node:** Fix instance crashing when batching enabled ([#3902](https://github.com/n8n-io/n8n/issues/3902)) ([0ab89ad](https://github.com/n8n-io/n8n/commit/0ab89ad5d66c1082ec2464813a9622431fa7f230))
|
||||
* **public-api:** Create correct OAuth2 credential schema ([#4111](https://github.com/n8n-io/n8n/issues/4111)) ([28ab4f6](https://github.com/n8n-io/n8n/commit/28ab4f66f096eb6ec483e344bffe98b9a81520c6))
|
||||
* **Xero Node:** fix line amount types being ignored when creating new invoices ([#4146](https://github.com/n8n-io/n8n/issues/4146)) ([3e2e9e6](https://github.com/n8n-io/n8n/commit/3e2e9e6009301006be7c7e96444ff4bbf824358c))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **editor:** Add resource locator parameter ([#3932](https://github.com/n8n-io/n8n/issues/3932)) ([ad73f89](https://github.com/n8n-io/n8n/commit/ad73f8995c34a664391dcc467aca55f44f4bde71))
|
||||
* **cli:** User Management and Credentials sharing ([#3602](https://github.com/n8n-io/n8n/issues/3602)) ([97cd564](https://github.com/n8n-io/n8n/commit/97cd564f7b4c5ba1472e517e0d54897b2cabcc26))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **ci:** Cache npm dependencies ([#4138](https://github.com/n8n-io/n8n/issues/4138)) ([1bdc102](https://github.com/n8n-io/n8n/commit/1bdc102892e77f2723ffed383874092cf4e07810))
|
||||
|
||||
|
||||
|
||||
# [0.194.0](https://github.com/n8n-io/n8n/compare/n8n@0.193.5...n8n@0.194.0) (2022-09-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* AWS credential testing issue ([#4107](https://github.com/n8n-io/n8n/issues/4107)) ([5130529](https://github.com/n8n-io/n8n/commit/51305290663dc4bc05cdbb075d685673217081f9))
|
||||
* **cli,core:** Address Dependabot warnings [N8N-4121] ([#3883](https://github.com/n8n-io/n8n/issues/3883)) ([461848f](https://github.com/n8n-io/n8n/commit/461848fcc4a33b0adf9958bebb2557bfa15100d6))
|
||||
* **cli:** Avoid scanning unnecessary directories on windows ([#4082](https://github.com/n8n-io/n8n/issues/4082)) ([84b56eb](https://github.com/n8n-io/n8n/commit/84b56eb48e727389189c517598aadadd6f2ccf23)), closes [#4007](https://github.com/n8n-io/n8n/issues/4007)
|
||||
* **cli:** Load nodes and credentials on windows using the correct file-path ([#4084](https://github.com/n8n-io/n8n/issues/4084)) ([b6c1187](https://github.com/n8n-io/n8n/commit/b6c1187922ab6552e303c98341c5732ffa96c55f))
|
||||
* **cli:** Password reset should trigger internal and external hooks ([#4066](https://github.com/n8n-io/n8n/issues/4066)) ([12507d3](https://github.com/n8n-io/n8n/commit/12507d39d68a2961c6e567b6b7d83759010918b0))
|
||||
* **cli:** Use absolute paths for loading custom nodes and credentials ([#4099](https://github.com/n8n-io/n8n/issues/4099)) ([43c9f01](https://github.com/n8n-io/n8n/commit/43c9f019bd3e25215134970570c574da663dd3e0)), closes [#4082](https://github.com/n8n-io/n8n/issues/4082)
|
||||
* **core & Function nodes:** Update function nodes to work with binary-data-mode 'filesystem'. ([#3845](https://github.com/n8n-io/n8n/issues/3845)) ([f6064ef](https://github.com/n8n-io/n8n/commit/f6064ef278bb481a78942af3af9675f29e59045b)), closes [#1](https://github.com/n8n-io/n8n/issues/1)
|
||||
* **core:** Fix issue with returnJsonArray helper breaking nodes that return no data ([3de0e22](https://github.com/n8n-io/n8n/commit/3de0e228cb78f292ead4d0103040d2c00943deae))
|
||||
* **core:** Fix node renaming in expressions ([381c09f](https://github.com/n8n-io/n8n/commit/381c09fa47212a12f6c7bc166ac641afd97c9681))
|
||||
* **core:** Update oauth endpoints to use instance base url ([dd3ba96](https://github.com/n8n-io/n8n/commit/dd3ba963723fbdef7d4239f0890c0776bffd062e))
|
||||
* **eslint:** Setup eslint to run on every package ([#4050](https://github.com/n8n-io/n8n/issues/4050)) ([69eb979](https://github.com/n8n-io/n8n/commit/69eb97999da0543308285ebc834f3454c2eea727))
|
||||
* **GoogleBigQuery Node:** Fix empty response when creating records ([#4056](https://github.com/n8n-io/n8n/issues/4056)) ([9f92a4d](https://github.com/n8n-io/n8n/commit/9f92a4d681918cb8d9f0d5b0bd322b93da0ba3ef))
|
||||
* **Hubspot Node:** Correct canvas name of HubSpot node ([#4054](https://github.com/n8n-io/n8n/issues/4054)) ([e1025e8](https://github.com/n8n-io/n8n/commit/e1025e888c56995d284e0b5889af2e93b57ad3eb))
|
||||
* Issue with versioned nodes not loading properly ([#4094](https://github.com/n8n-io/n8n/issues/4094)) ([9e1fa4c](https://github.com/n8n-io/n8n/commit/9e1fa4c0459b0bebe725f5e6db84104bcd37690d))
|
||||
* **MongoDB Node:** Update mongo driver to 4.9.1 ([#4095](https://github.com/n8n-io/n8n/issues/4095)) ([f70e6d2](https://github.com/n8n-io/n8n/commit/f70e6d23455b5b380ffb607100e0090203e31047))
|
||||
* **node:** Google Cloud Storage linting rules ([36ec81f](https://github.com/n8n-io/n8n/commit/36ec81f62489a7bc3442e46048f92d2ae9de1ce7))
|
||||
* **public-api:** Fix error updating workflow with property not defined in the schema ([#4089](https://github.com/n8n-io/n8n/issues/4089)) ([f40ae50](https://github.com/n8n-io/n8n/commit/f40ae501b4dca8f00db41d8fc07b496ad06cf10f))
|
||||
* **typescript:** Use consistent typescript configs ([#4049](https://github.com/n8n-io/n8n/issues/4049)) ([9267e8f](https://github.com/n8n-io/n8n/commit/9267e8fb1283794e7ebc109772e584b0471bef27))
|
||||
* **workflow:** Remove a few `ts-ignore` and `eslint-disable` ([#3958](https://github.com/n8n-io/n8n/issues/3958)) ([a73ac1d](https://github.com/n8n-io/n8n/commit/a73ac1d94f5081051d1280b7ebc467f22e3d100d))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Adalo Node:** Add Adalo node ([#3102](https://github.com/n8n-io/n8n/issues/3102)) ([9a59d0a](https://github.com/n8n-io/n8n/commit/9a59d0a5d10b83ed4642e59c16310a436fd92a7a))
|
||||
* **cli:** Load all nodes and credentials code in isolation ([#3906](https://github.com/n8n-io/n8n/issues/3906)) ([b450e97](https://github.com/n8n-io/n8n/commit/b450e977a32944a5289db2553bf12bdef4e1d3b3))
|
||||
* **core, editor-ui:** Introduce node deprecation ([#4103](https://github.com/n8n-io/n8n/issues/4103)) ([98ed207](https://github.com/n8n-io/n8n/commit/98ed2076072858109f5ed512786af61dff0314d6))
|
||||
* **editor:** Implement HTML sanitization for Notification and Message components ([#4081](https://github.com/n8n-io/n8n/issues/4081)) ([ea2d18b](https://github.com/n8n-io/n8n/commit/ea2d18b66dba1393a0425b5074884b782f959e5c))
|
||||
* **editor:** Show input number for multi-input nodes ([#4000](https://github.com/n8n-io/n8n/issues/4000)) ([8c95d6e](https://github.com/n8n-io/n8n/commit/8c95d6ec53b735cc322a3b5f2a5a78002ae8441a))
|
||||
* **gmail:** Overhaul Gmail node + create gmail trigger ([#3734](https://github.com/n8n-io/n8n/issues/3734)) ([74304db](https://github.com/n8n-io/n8n/commit/74304db4e2ae66b82695244d07c6ff8a9ffe37cf))
|
||||
* **Google Cloud Storage Node:** Add GCS Node with Bucket and Object operations ([1e963d8](https://github.com/n8n-io/n8n/commit/1e963d8e1ed6956e8af02e70da304211aa725ea1))
|
||||
* **Merge Node:** Overhaul of merge node ([f1a5697](https://github.com/n8n-io/n8n/commit/f1a569791d5289ced8ac78d97452f6ad5bf8d1b8))
|
||||
* **typescript:** Setup Typescript incremental builds ([#3876](https://github.com/n8n-io/n8n/issues/3876)) ([799676b](https://github.com/n8n-io/n8n/commit/799676b24d9ba5628dc875de1c0bbcf7e51a51cc))
|
||||
|
||||
|
||||
|
||||
## [0.193.5](https://github.com/n8n-io/n8n/compare/n8n@0.193.4...n8n@0.193.5) (2022-09-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **editor:** Disable editing in Function nodes in executions view ([#4041](https://github.com/n8n-io/n8n/issues/4041)) ([772836a](https://github.com/n8n-io/n8n/commit/772836abc7d81fce74547dd3644c45eaea9c0a75))
|
||||
* **editor:** use correct attribute on button to make it full width ([#4048](https://github.com/n8n-io/n8n/issues/4048)) ([b26545d](https://github.com/n8n-io/n8n/commit/b26545d94c9b718e20580e511aab676e98de66dc))
|
||||
* **editor:** Wrong popup title when "Click To Copy" on OAuth2 Redirect Url credentials ([#4043](https://github.com/n8n-io/n8n/issues/4043)) ([0acac35](https://github.com/n8n-io/n8n/commit/0acac355e1bfff326d3bb575d5b21f0004a0c792))
|
||||
* **Gmail Node:** Fix node and improve helper so to avoid double wrapping in json key ([#4052](https://github.com/n8n-io/n8n/issues/4052)) ([fbd044b](https://github.com/n8n-io/n8n/commit/fbd044bf874f270c9f9e7cda9aaecdc235ddc677))
|
||||
|
||||
|
||||
|
||||
## [0.193.4](https://github.com/n8n-io/n8n/compare/n8n@0.193.3...n8n@0.193.4) (2022-09-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **AWS Nodes:** Handle query string and body properly for AWS related requests ([#4039](https://github.com/n8n-io/n8n/issues/4039)) ([103f04e](https://github.com/n8n-io/n8n/commit/103f04e4eba08a1cd888e71073cf24178a2b52ba))
|
||||
* **AWS Lambda Node:** Fix json data being sent to AWS Lambda as string ([#4029](https://github.com/n8n-io/n8n/issues/4029)) ([c28f69b](https://github.com/n8n-io/n8n/commit/c28f69b276fe46c42dfb62753b565ebae37431f5))
|
||||
* **Beeminder Node:** Fix request id not being sent when creating a new datapoint ([73c5210](https://github.com/n8n-io/n8n/commit/73c52102949274c4c67ae34c458a6afa9520c150))
|
||||
* **cli:** Include "auth-excluded" endpoints on the history middleware as well ([#4028](https://github.com/n8n-io/n8n/issues/4028)) ([d554128](https://github.com/n8n-io/n8n/commit/d55412845784fda4d42a1dcaca60515ad10d2aa0))
|
||||
* **core:** Fix MySQL migration issue with table prefix ([#4013](https://github.com/n8n-io/n8n/issues/4013)) ([fc6484b](https://github.com/n8n-io/n8n/commit/fc6484ba4d48363fd846d5c800a25a207082f58d))
|
||||
* Correct all the spelling typos ([#3960](https://github.com/n8n-io/n8n/issues/3960)) ([49c85a1](https://github.com/n8n-io/n8n/commit/49c85a1df8417918797c3fe6db46f35f9fe86bdf))
|
||||
* Fix n8n-square-button import. ([#4024](https://github.com/n8n-io/n8n/issues/4024)) ([bbd967b](https://github.com/n8n-io/n8n/commit/bbd967bbdfb744874eeae5aced7ce122039b59d5))
|
||||
* **GitHub Node:** Fix binary data not being returned ([#4017](https://github.com/n8n-io/n8n/issues/4017)) ([5753110](https://github.com/n8n-io/n8n/commit/575311040261be2982a3c7107bf1ea8b7b63fbb5))
|
||||
* **GraphQL Node:** Fix issue with return items ([#4016](https://github.com/n8n-io/n8n/issues/4016)) ([6216132](https://github.com/n8n-io/n8n/commit/6216132ae2f3b908aacf266f4a34143bb8a74f0a))
|
||||
* **Postgres Node:** Fix ssue with postgres insert and paired item ([#4020](https://github.com/n8n-io/n8n/issues/4020)) ([9314086](https://github.com/n8n-io/n8n/commit/9314086b6a84ce0f24992827ab316dee4709d118))
|
||||
* **Kafka Trigger Node:** fix kafka trigger not working with default max requests value ([71cae90](https://github.com/n8n-io/n8n/commit/71cae90679d9d6fe4cf0dc898827cc9cd4457873))
|
||||
* **MonicaCrm Node:** Fix pagination when using return all ([82827d0](https://github.com/n8n-io/n8n/commit/82827d0a12e889b2fdebd422bd1fcb483860599e))
|
||||
* **Node Gmail:** Fix bug related to paired items ([2746905](https://github.com/n8n-io/n8n/commit/2746905570c2056abf9c388cc28c7d1d7b9f5102))
|
||||
* **Raindrop Node:** Fix issue refreshing OAuth2 credentials ([3163742](https://github.com/n8n-io/n8n/commit/3163742fd7ae0afa86919e5f473be3d2bd88282b))
|
||||
* **Shopify Node:** Fix pagination when empty fields are sent ([071ab40](https://github.com/n8n-io/n8n/commit/071ab40c9fa523b8ee47c9428ee6078e43985816))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add possibility to configure stop time for workers ([#4012](https://github.com/n8n-io/n8n/issues/4012)) ([a3791c2](https://github.com/n8n-io/n8n/commit/a3791c22b3f0be16324e1223aa719e6f122a51c1))
|
||||
* **cli:** Add external hooks for when members are added or deleted ([#3988](https://github.com/n8n-io/n8n/issues/3988)) ([6be9997](https://github.com/n8n-io/n8n/commit/6be999714f62f22ec5d8ab82f91f7fc5a2b55c4d))
|
||||
* **editor:** Use i18n component instead od v-html for localization ([287533e](https://github.com/n8n-io/n8n/commit/287533e6c819329dc84f2e23a33faed66181d07a))
|
||||
|
||||
|
||||
|
||||
## [0.193.3](https://github.com/n8n-io/n8n/compare/n8n@0.193.2...n8n@0.193.3) (2022-09-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cli:** Initialize mailer just if connection can be verified ([#3997](https://github.com/n8n-io/n8n/issues/3997)) ([936cb11](https://github.com/n8n-io/n8n/commit/936cb117895695f9519f0debb3bcac275d98eda8))
|
||||
* **core:** Fix disabled parent output in partial execution ([#3946](https://github.com/n8n-io/n8n/issues/3946)) ([c8743ff](https://github.com/n8n-io/n8n/commit/c8743ff6cad1563d31d4d39ffa742726830a4f38))
|
||||
* **nodes:** Remove duplicate wrap of paired item data ([#4001](https://github.com/n8n-io/n8n/issues/4001)) ([54efe20](https://github.com/n8n-io/n8n/commit/54efe20ee4834fbf9306be161b36f115b9eb0834))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **nodes:** Add database and non http credentials test ([d82e879](https://github.com/n8n-io/n8n/commit/d82e87979dc0fe47e264b0e7bb46c325157d9603))
|
||||
* **Mongo DB Node:** Add MongoDB credential testing and two operations ([#3901](https://github.com/n8n-io/n8n/issues/3901)) ([b5511e5](https://github.com/n8n-io/n8n/commit/b5511e5ac7745c6b4a20aa49d2633f2f91bdbb7b))
|
||||
|
||||
|
||||
## [0.193.2](https://github.com/n8n-io/n8n/compare/n8n@0.193.1...n8n@0.193.2) (2022-09-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **docker:** n8n docker image needs su-exec ([#3993](https://github.com/n8n-io/n8n/issues/3993)) ([aec2489](https://github.com/n8n-io/n8n/commit/aec2489aefb8fca522302bdcaa002fa62393b70a))
|
||||
* **docker:** Revert docker `USER` and `WORKDIR` changes ([#3992](https://github.com/n8n-io/n8n/issues/3992)) ([34a99fd](https://github.com/n8n-io/n8n/commit/34a99fd089a754170ed4f2b9bdc02fc951d7e9bc))
|
||||
* **core:** Fix OAuth2 issues ([#3391](https://github.com/n8n-io/n8n/pull/3991))
|
||||
|
||||
|
||||
## [0.193.1](https://github.com/n8n-io/n8n/compare/n8n@0.193.0...n8n@0.193.1) (2022-08-31)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **editor:** Fix bug where col headers don't show ([#3985](https://github.com/n8n-io/n8n/issues/3985)) ([bee3840](https://github.com/n8n-io/n8n/commit/bee38400505b8862a4e1e5bf28b18088ff8ced8f))
|
||||
|
||||
|
||||
|
||||
# [0.193.0](https://github.com/n8n-io/n8n/compare/n8n@0.192.2...n8n@0.193.0) (2022-08-31)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ci:** Setup a separate workflow action to test for pushes on master ([#3951](https://github.com/n8n-io/n8n/issues/3951)) ([1f9bdd0](https://github.com/n8n-io/n8n/commit/1f9bdd09a29a5e0564ddc874814eaf36d9380ee7))
|
||||
* **core:** Make digest auth work with query params ([087d3f9](https://github.com/n8n-io/n8n/commit/087d3f99f1f5c38db763686c10c6181e20c08307))
|
||||
* **editor:** Sending data as query on DELETE method ([#3972](https://github.com/n8n-io/n8n/issues/3972)) ([fc2ff35](https://github.com/n8n-io/n8n/commit/fc2ff35c412b1c10471659c91dc0fe11a3363495))
|
||||
* Fix credentials_entity table migration for mysql ([#3979](https://github.com/n8n-io/n8n/issues/3979)) ([349826e](https://github.com/n8n-io/n8n/commit/349826e87fdb03a9f378422ecfac83d42bb5a376))
|
||||
* **npm:** Improve .npmignore to reduce the size of the published packages ([#3970](https://github.com/n8n-io/n8n/issues/3970)) ([15d5ac6](https://github.com/n8n-io/n8n/commit/15d5ac6f3c7732374f07726c5697ba341eb9aa70))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **design-system,editor-ui:** Upgrade some of the frontend dev dependencies ([#3978](https://github.com/n8n-io/n8n/issues/3978)) ([b428e9f](https://github.com/n8n-io/n8n/commit/b428e9fb9ffb506c97f91d45072e32241a3b07d6))
|
||||
* **docker:** Reduce the size of alpine docker images ([#3973](https://github.com/n8n-io/n8n/issues/3973)) ([398adb2](https://github.com/n8n-io/n8n/commit/398adb23e8785c92478c4d80c944e60e9278ffdf))
|
||||
* **editor:** Limit when to show mapping tooltip ([#3976](https://github.com/n8n-io/n8n/issues/3976)) ([8fc9f07](https://github.com/n8n-io/n8n/commit/8fc9f07f39edf8944214200dd787b2d0c9b6caff))
|
||||
* **HighLevel Node:** Add HighLevel node ([c2e97a8](https://github.com/n8n-io/n8n/commit/c2e97a89f923bbebe0a6d882e86d792fcda3116d))
|
||||
|
||||
|
||||
|
||||
## [0.192.2](https://github.com/n8n-io/n8n/compare/n8n@0.192.1...n8n@0.192.2) (2022-08-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **editor:** Fix feature flag check when PH is unavailable ([#3944](https://github.com/n8n-io/n8n/issues/3944)) ([93c26da](https://github.com/n8n-io/n8n/commit/93c26dac286e8fa984cb6fb6fecd6167fc4143f3))
|
||||
* **editor:** fix mapping bug when val is null ([#3942](https://github.com/n8n-io/n8n/issues/3942)) ([a21dbdc](https://github.com/n8n-io/n8n/commit/a21dbdc45b6f434f7ecd8b541bb32d397fd95c89))
|
||||
|
||||
|
||||
|
||||
## [0.192.1](https://github.com/n8n-io/n8n/compare/n8n@0.192.0...n8n@0.192.1) (2022-08-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cli:** Account for non-array in pindata migration ([#3938](https://github.com/n8n-io/n8n/issues/3938)) ([f052187](https://github.com/n8n-io/n8n/commit/f0521873e1acf8c6491b75f37be1dd824bb355bc))
|
||||
|
||||
|
||||
|
||||
# [0.192.0](https://github.com/n8n-io/n8n/compare/n8n@0.191.1...n8n@0.192.0) (2022-08-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cli:** Account for unparseable string in JSON key migration ([#3927](https://github.com/n8n-io/n8n/issues/3927)) ([ab45898](https://github.com/n8n-io/n8n/commit/ab45898a69dd9354cdb365187dec0d58a1836418))
|
||||
* **cli:** Fix excessive instantiation type error for flattened execution ([#3921](https://github.com/n8n-io/n8n/issues/3921)) ([1d4f92a](https://github.com/n8n-io/n8n/commit/1d4f92a6575a7af6dbd4f03b61202cb56badf6a1))
|
||||
* **cli:** Init nodes dir to ensure `npm install` succeeds ([#3934](https://github.com/n8n-io/n8n/issues/3934)) ([2d6eea8](https://github.com/n8n-io/n8n/commit/2d6eea82d324d4560f7445d87647ce0d5e87c678))
|
||||
* **cli:** tsc build errors should fail turborepo builds as well ([#3923](https://github.com/n8n-io/n8n/issues/3923)) ([f22bd28](https://github.com/n8n-io/n8n/commit/f22bd2805d87c552d92d0da0313bf7f9c498f103))
|
||||
* **core:** Account for enabled state in first pinned trigger ([#3912](https://github.com/n8n-io/n8n/issues/3912)) ([6bd7a09](https://github.com/n8n-io/n8n/commit/6bd7a09a455b61eae5edad1d93e8a7e00c0c68b3))
|
||||
* **core:** Fix pinned trigger execution ([#3895](https://github.com/n8n-io/n8n/issues/3895)) ([17799cd](https://github.com/n8n-io/n8n/commit/17799cda46ad764f537d9546346ab4e04e36e681))
|
||||
* **NextCloud Node:** Fix issue with credential verification and sharing file ([2b4f5c6](https://github.com/n8n-io/n8n/commit/2b4f5c6c785ab6ffc7198f60369886c44dea6ef2))
|
||||
* **Freshdesk Node:** Fix issue when getAll operation requires non existent options ([329fe95](https://github.com/n8n-io/n8n/commit/329fe9581f63fe44daba5ef79724d9339cb8c813))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **cli:** Notify external hooks about user profile and password changes ([#3919](https://github.com/n8n-io/n8n/issues/3919)) ([7d74dda](https://github.com/n8n-io/n8n/commit/7d74ddab29e05a81962fd80469248e8cee8bf9bf))
|
||||
* **core, editor:** Support `pairedItem` for pinned data ([#3843](https://github.com/n8n-io/n8n/issues/3843)) ([b1e7152](https://github.com/n8n-io/n8n/commit/b1e715299d8a78188fad413392babdea7d044049))
|
||||
* **core:** Add command to scripts for easy launch n8n with tunnel ([725a567](https://github.com/n8n-io/n8n/commit/725a567f07c08767f58d4ceb88386a9be694bfd2))
|
||||
* **editor, core:** Integrate PostHog ([#3865](https://github.com/n8n-io/n8n/issues/3865)) ([43e054f](https://github.com/n8n-io/n8n/commit/43e054f5abae87b989ffe391a251961a2bc05542))
|
||||
* **editor:** Map expressions from input table ([#3864](https://github.com/n8n-io/n8n/issues/3864)) ([ce076dc](https://github.com/n8n-io/n8n/commit/ce076dca48847562067c5149ecdd529fcc014e3f))
|
||||
|
||||
|
||||
|
||||
## [0.191.1](https://github.com/n8n-io/n8n/compare/n8n@0.191.0...n8n@0.191.1) (2022-08-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **editor:** Fix issue with disappearing connections after rename ([#3899](https://github.com/n8n-io/n8n/issues/3899)) ([ad0c214](https://github.com/n8n-io/n8n/commit/ad0c214f8ec2088ff30f408fe5ec51216468cdff))
|
||||
|
||||
|
||||
|
||||
# [0.191.0](https://github.com/n8n-io/n8n/compare/n8n@0.190.0...n8n@0.191.0) (2022-08-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cli:** Fix community nodes tests on Postgres and MySQL ([#3861](https://github.com/n8n-io/n8n/issues/3861)) ([620525e](https://github.com/n8n-io/n8n/commit/620525ea85b7de24c0c5f3d3b57350a0a578d9b4))
|
||||
* **core:** Fix issue with not displayed child workflow executions ([#3867](https://github.com/n8n-io/n8n/issues/3867)) ([f782bcd](https://github.com/n8n-io/n8n/commit/f782bcd52dbe364d1fca1bd29c9222f434df90ae))
|
||||
* **editor:** Handling errors when opening settings and executions ([#3877](https://github.com/n8n-io/n8n/issues/3877)) ([762b422](https://github.com/n8n-io/n8n/commit/762b4224888cc5949eced048729fe313ec055f1c))
|
||||
* **editor:** Improve expression and parameters performance ([#3874](https://github.com/n8n-io/n8n/issues/3874)) ([3608d13](https://github.com/n8n-io/n8n/commit/3608d132c0fbdb193758ba9a9c0f1da725d2313a))
|
||||
* **public-api:** Fix executions pagination in Postgres and Mysql ([52015a6](https://github.com/n8n-io/n8n/commit/52015a6f033eae5c2ea9ac125a7c947d96ce7463))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **cli:** Enable community nodes based on npm availability ([#3871](https://github.com/n8n-io/n8n/issues/3871)) ([936264b](https://github.com/n8n-io/n8n/commit/936264b3c6506cdc25b9ad55a23b314b2582275b))
|
||||
* **editor:** Added animated tooltips to draggable columns in input panel ([054cc01](https://github.com/n8n-io/n8n/commit/054cc010edfc9f0f5cc72ac94f26afe52a66a192))
|
||||
|
||||
|
||||
|
||||
# [0.190.0](https://github.com/n8n-io/n8n/compare/n8n@0.189.1...n8n@0.190.0) (2022-08-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** Fix crash caused by parallel test-webhook calls ([#3756](https://github.com/n8n-io/n8n/issues/3756)) ([8fe71db](https://github.com/n8n-io/n8n/commit/8fe71dba4bf568e70ed740ac3413aae77559ca3c))
|
||||
* **core:** Fix issue that static data did not get saved for poll-triggers ([#3853](https://github.com/n8n-io/n8n/issues/3853)) ([8311abc](https://github.com/n8n-io/n8n/commit/8311abcf9d453f0d253c269e7d1c3842fcf8e256))
|
||||
* **GitHub Trigger:** Fix typo ([#3859](https://github.com/n8n-io/n8n/issues/3859)) ([7b3d6de](https://github.com/n8n-io/n8n/commit/7b3d6de44eeb6cb066fb378c52fcc5aec60c4fdf))
|
||||
* **public-api:** fix issue paginating executions ([b9fe707](https://github.com/n8n-io/n8n/commit/b9fe707cbd9df4a33b6040215826375bef238b65))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Synchronize default VSCode settings ([#3833](https://github.com/n8n-io/n8n/issues/3833)) ([11461fd](https://github.com/n8n-io/n8n/commit/11461fda5fae10077ea9804b5cc9581074107005))
|
||||
|
||||
|
||||
|
||||
## [0.189.1](https://github.com/n8n-io/n8n/compare/n8n@0.189.0...n8n@0.189.1) (2022-08-05)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix issue with MySQL/MariaDB migration ([#3832](https://github.com/n8n-io/n8n/issues/3832))
|
||||
|
||||
# [0.189.0](https://github.com/n8n-io/n8n/compare/n8n@0.188.0...n8n@0.189.0) (2022-08-03)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **editor:** Fix label cut off ([#3820](https://github.com/n8n-io/n8n/issues/3820)) ([0f27be4](https://github.com/n8n-io/n8n/commit/0f27be4447662056a2ba13c027280830f7eab09b))
|
||||
- Fix problem saving workflow when tags disabled ([#3792](https://github.com/n8n-io/n8n/issues/3792)) ([f0dddaa](https://github.com/n8n-io/n8n/commit/f0dddaa2a585715b35e26b16e1003e1683ab9402))
|
||||
|
||||
### Features
|
||||
|
||||
- **NocoDB Node:** Add support v0.90.0+ ([#3146](https://github.com/n8n-io/n8n/issues/3146)) ([d65a9ed](https://github.com/n8n-io/n8n/commit/d65a9ed118ff16c67b6d69d68108d8b7da1814d9))
|
||||
- **SendInBlue Node:** Add SendInBlue Regular + Trigger Node ([#3746](https://github.com/n8n-io/n8n/issues/3746)) ([74cedd9](https://github.com/n8n-io/n8n/commit/74cedd94a82f0c053a24b6e925d9e3bcadcebfbc))
|
||||
- Support community nodes on Windows ([#3823](https://github.com/n8n-io/n8n/issues/3823)) ([e8eda74](https://github.com/n8n-io/n8n/commit/e8eda7470a17deec1f5eab8cded6e74a8e3aee39))
|
||||
|
||||
# [0.188.0](https://github.com/n8n-io/n8n/compare/n8n@0.187.2...n8n@0.188.0) (2022-07-27)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **AWS DynamoDB Node:** Fix expression attribute names ([#3763](https://github.com/n8n-io/n8n/issues/3763)) ([88cb265](https://github.com/n8n-io/n8n/commit/88cb26556c162aa1281dfa6a9fa8eca4cd071e9d))
|
||||
- **core:** Add windows support to import:credentials --separate ([#3589](https://github.com/n8n-io/n8n/issues/3589)) ([2fb590e](https://github.com/n8n-io/n8n/commit/2fb590e8440ac35567fdbf745b294d79feb8c5a9))
|
||||
- **editor:** Fix linking buttons color ([#3770](https://github.com/n8n-io/n8n/issues/3770)) ([deb510a](https://github.com/n8n-io/n8n/commit/deb510a8e0057280da43f3b3e72d8acca5829745))
|
||||
- **editor:** Fix pin data in executions when pinData is null. ([#3787](https://github.com/n8n-io/n8n/issues/3787)) ([30c0f21](https://github.com/n8n-io/n8n/commit/30c0f21b3f37280403848592877cb8658367b85e))
|
||||
- **editor:** Fix spaces bug ([#3774](https://github.com/n8n-io/n8n/issues/3774)) ([02549e3](https://github.com/n8n-io/n8n/commit/02549e3ba9233a6d9f75fc1f9ff138e2aff7f4b9))
|
||||
- **editor:** Fix sticky duplication and position bug ([#3755](https://github.com/n8n-io/n8n/issues/3755)) ([92614c8](https://github.com/n8n-io/n8n/commit/92614c81abfdbca51d4901b364467d3505870255))
|
||||
- **editor:** Restore pindata header colors ([#3758](https://github.com/n8n-io/n8n/issues/3758)) ([1a7318b](https://github.com/n8n-io/n8n/commit/1a7318b4cf6081e5ba743117cf90ef6920625aa0))
|
||||
- Fix node_type property in all events ([#3759](https://github.com/n8n-io/n8n/issues/3759)) ([1f1a63c](https://github.com/n8n-io/n8n/commit/1f1a63c39adc673259c951af3e5152c5edc34968))
|
||||
- **Fix Rocketchat Node:** Fix authentication issue ([#3778](https://github.com/n8n-io/n8n/issues/3778)) ([2710061](https://github.com/n8n-io/n8n/commit/271006152386511c19feb54e438fa60966dbf705))
|
||||
- **Mautic Node:** Fix authentication issue ([#3761](https://github.com/n8n-io/n8n/issues/3761)) ([fe58769](https://github.com/n8n-io/n8n/commit/fe58769b4830f388ad67ae1c32fcaa55aa0b848e))
|
||||
|
||||
### Features
|
||||
|
||||
- Improvements to pairedItem ([1348349](https://github.com/n8n-io/n8n/commit/13483497484e205975ef71091e3892f757f608e1))
|
||||
- **Item List Node:** Add operation for creating array from input items ([#3149](https://github.com/n8n-io/n8n/issues/3149)) ([553b14a](https://github.com/n8n-io/n8n/commit/553b14a13c7c9056447ef0b18c9427f26221b44d))
|
||||
- **Kafka Trigger Node:** Add additional options ([#3600](https://github.com/n8n-io/n8n/issues/3600)) ([3496a39](https://github.com/n8n-io/n8n/commit/3496a39788b654b46485955ba5cce5e5865babc7))
|
||||
- **Metabase Node:** Add Metabase Node ([#3033](https://github.com/n8n-io/n8n/issues/3033)) ([81b5828](https://github.com/n8n-io/n8n/commit/81b58285588f142c0b1cc148f0092c462eefdd73))
|
||||
|
||||
## [0.187.2](https://github.com/n8n-io/n8n/compare/n8n@0.187.1...n8n@0.187.2) (2022-07-21)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **editor:** Fix console error ([#3751](https://github.com/n8n-io/n8n/issues/3751)) ([3a98028](https://github.com/n8n-io/n8n/commit/3a98028722d634f604a650d891cf6fabf722993d))
|
||||
- **editor:** Fix login issue for non-admin users ([#3754](https://github.com/n8n-io/n8n/issues/3754)) ([ccd1ed2](https://github.com/n8n-io/n8n/commit/ccd1ed2c4c5153637a7900a79a40b1c4f53e7635))
|
||||
- **editor:** Fix problems with credentials modal if no node is opened ([#3749](https://github.com/n8n-io/n8n/issues/3749)) ([5efe4a4](https://github.com/n8n-io/n8n/commit/5efe4a4c54211f1d395202c420403be3cc7e4446))
|
||||
- **NocoDB Node:** Fix authentication issue ([#3750](https://github.com/n8n-io/n8n/issues/3750)) ([e65016c](https://github.com/n8n-io/n8n/commit/e65016c861176a7b17f23c5fbf3c0a3fcc1e5e1d))
|
||||
|
||||
## [0.187.1](https://github.com/n8n-io/n8n/compare/n8n@0.187.0...n8n@0.187.1) (2022-07-20)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **editor:** Fix issue that new nodes did not get automatically displayed in all connected browsers ([#3745](https://github.com/n8n-io/n8n/issues/3745)) ([34a9bee](https://github.com/n8n-io/n8n/commit/34a9beefa5b0f169f38ca48d3444af8f160c85a2))
|
||||
|
||||
# [0.187.0](https://github.com/n8n-io/n8n/compare/n8n@0.186.1...n8n@0.187.0) (2022-07-20)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **api:** Add missing node settings parameters ([#3737](https://github.com/n8n-io/n8n/issues/3737)) ([803e009](https://github.com/n8n-io/n8n/commit/803e0097fada1bf0385ac37965f0cc47bed28948))
|
||||
- **api:** Validate static data value for resource workflow ([#3736](https://github.com/n8n-io/n8n/issues/3736)) ([7ba9a05](https://github.com/n8n-io/n8n/commit/7ba9a055cdeb2b0713857747a5b722dab65d3678))
|
||||
- **Baserow Node:** Fix issue that table names are not getting pulled in new version ([#3721](https://github.com/n8n-io/n8n/issues/3721)) ([f65a5db](https://github.com/n8n-io/n8n/commit/f65a5db478da0da65735bdc5bb09774f1d473ec9))
|
||||
- **editor:** Hide 'Execute previous node' button in readonly mode ([#3714](https://github.com/n8n-io/n8n/issues/3714)) ([7fb81dc](https://github.com/n8n-io/n8n/commit/7fb81dcd8a6c56e6e104be94278c690caf35c846))
|
||||
- **editor:** Hide tabs if only 1 branch ([#3743](https://github.com/n8n-io/n8n/issues/3743)) ([fb67543](https://github.com/n8n-io/n8n/commit/fb67543b2f10c558abcacc5454d6fa0687ee4702))
|
||||
- Fix broken links in nodes ([#3716](https://github.com/n8n-io/n8n/issues/3716)) ([c9b7b6d](https://github.com/n8n-io/n8n/commit/c9b7b6d30fe822bddb3d68e1b4757ffe654e918b))
|
||||
|
||||
### Features
|
||||
|
||||
- Add more credentials tests ([#3668](https://github.com/n8n-io/n8n/issues/3668)) ([683d2df](https://github.com/n8n-io/n8n/commit/683d2dfc98136503971a4beb1692e5ca191d5016))
|
||||
- Add support for preAuthentication and add Metabase credentials ([#3399](https://github.com/n8n-io/n8n/issues/3399)) ([994c89a](https://github.com/n8n-io/n8n/commit/994c89a6c6ade5b99d6218c9776adc15c286b619))
|
||||
- **core:** Autofix pairedItem information if inputItems(n) === outputItems(n) ([68fb1c6](https://github.com/n8n-io/n8n/commit/68fb1c64dca99fb603fe6d52fd50c4749a2ca898))
|
||||
- **editor:** Add data pinning functionality ([#3511](https://github.com/n8n-io/n8n/issues/3511)) ([15693b0](https://github.com/n8n-io/n8n/commit/15693b0056097129a57dfc600807dbc5e1cc07f1)
|
||||
- **editor:** Add drag and drop data mapping ([#3708](https://github.com/n8n-io/n8n/issues/3708)) ([577c73e](https://github.com/n8n-io/n8n/commit/577c73ee25c5bfc943ef5ed1de550fcb489f4998))
|
||||
- **ERPNext Node:** Add credential test and add support for unauthorized certs ([#3732](https://github.com/n8n-io/n8n/issues/3732)) ([a02b206](https://github.com/n8n-io/n8n/commit/a02b20617071e1ca398735456cb416d6ab3f34a0)), closes [#3739](https://github.com/n8n-io/n8n/issues/3739)
|
||||
- **Google Drive Node:** Add move to trash support ([#3693](https://github.com/n8n-io/n8n/issues/3693)) ([7406432](https://github.com/n8n-io/n8n/commit/74064325c892c5b506260e650d3361636b578b1e))
|
||||
- Make it possible to dynamically load community nodes ([#2849](https://github.com/n8n-io/n8n/issues/2849)) ([c85faff](https://github.com/n8n-io/n8n/commit/c85faff4f1c6ba11c02cf5c14122d2c7341f3ec3)), closes [#3497](https://github.com/n8n-io/n8n/issues/3497) [#3501](https://github.com/n8n-io/n8n/issues/3501) [#3527](https://github.com/n8n-io/n8n/issues/3527) [#3562](https://github.com/n8n-io/n8n/issues/3562)
|
||||
- **Mindee Node:** Add support for new version ([#3596](https://github.com/n8n-io/n8n/issues/3596)) ([1965407](https://github.com/n8n-io/n8n/commit/1965407030638cc309c99d344121f47805c93799))
|
||||
- **Notion Node:** Allow to ignore Notion URL properties if empty ([#3564](https://github.com/n8n-io/n8n/issues/3564)) ([6cb9aef](https://github.com/n8n-io/n8n/commit/6cb9aefb0b3e4d17382042371a20e63f23641581))
|
||||
- **Shopify Node:** Add OAuth support ([#3389](https://github.com/n8n-io/n8n/issues/3389)) ([945e25a](https://github.com/n8n-io/n8n/commit/945e25a77cf9ba33bc3e4b70053319ea86230cf7))
|
||||
|
||||
## [0.186.1](https://github.com/n8n-io/n8n/compare/n8n@0.186.0...n8n@0.186.1) (2022-07-14)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **Airtable Node:** Fix authentication issue ([#3709](https://github.com/n8n-io/n8n/issues/3709)) ([33d8042](https://github.com/n8n-io/n8n/commit/33d804284ae02140749ab94eecfca1699e13afee))
|
||||
|
||||
# [0.186.0](https://github.com/n8n-io/n8n/compare/n8n@0.185.0...n8n@0.186.0) (2022-07-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **editor:** Fix error after multiple executions ([#3697](https://github.com/n8n-io/n8n/issues/3697)) ([d200661](https://github.com/n8n-io/n8n/commit/d200661b84c36b3f04d812cf022bb338f9664392))
|
||||
* **EmailReadImap Node:** Improve handling of network problems ([#3406](https://github.com/n8n-io/n8n/issues/3406)) ([6f5809e](https://github.com/n8n-io/n8n/commit/6f5809edb3f9cac0c29d448300b37ab9b6e74c08))
|
||||
* **Google Drive Node:** Process all input items with List operation ([#3525](https://github.com/n8n-io/n8n/issues/3525)) ([ece1836](https://github.com/n8n-io/n8n/commit/ece1836c45707d349330f742eb3b83fa1f4eaebb))
|
||||
* **Telegram Node:** Fix sending binaryData media (photo, document, video etc.) ([#3408](https://github.com/n8n-io/n8n/issues/3408)) ([af45a07](https://github.com/n8n-io/n8n/commit/af45a07f21d8448bad5c12ed702b7aa983017a2b))
|
||||
|
||||
- **editor:** Fix error after multiple executions ([#3697](https://github.com/n8n-io/n8n/issues/3697)) ([d200661](https://github.com/n8n-io/n8n/commit/d200661b84c36b3f04d812cf022bb338f9664392))
|
||||
- **EmailReadImap Node:** Improve handling of network problems ([#3406](https://github.com/n8n-io/n8n/issues/3406)) ([6f5809e](https://github.com/n8n-io/n8n/commit/6f5809edb3f9cac0c29d448300b37ab9b6e74c08))
|
||||
- **Google Drive Node:** Process all input items with List operation ([#3525](https://github.com/n8n-io/n8n/issues/3525)) ([ece1836](https://github.com/n8n-io/n8n/commit/ece1836c45707d349330f742eb3b83fa1f4eaebb))
|
||||
- **Telegram Node:** Fix sending binaryData media (photo, document, video etc.) ([#3408](https://github.com/n8n-io/n8n/issues/3408)) ([af45a07](https://github.com/n8n-io/n8n/commit/af45a07f21d8448bad5c12ed702b7aa983017a2b))
|
||||
|
||||
### Features
|
||||
|
||||
* Add item information to more node errors ([#3681](https://github.com/n8n-io/n8n/issues/3681)) ([2a8043c](https://github.com/n8n-io/n8n/commit/2a8043cd27968b92b1857135d130e3ee54aae779))
|
||||
* **AWS DynamoDB Node:** Improve error handling + add optional GetAll Scan FilterExpression ([#3318](https://github.com/n8n-io/n8n/issues/3318)) ([732c8fc](https://github.com/n8n-io/n8n/commit/732c8fcf8488fc35839855499f75202436fc4c9a))
|
||||
* **Customer.io Node:** Add support for tracking API region selection ([#3378](https://github.com/n8n-io/n8n/issues/3378)) ([82a254a](https://github.com/n8n-io/n8n/commit/82a254a8d9295901e42ec999432a7f5b40f38281))
|
||||
* **Elasticsearch Node:** Add 'Source Excludes' and 'Source Includes' options on 'Document: getAll' operation ([#3660](https://github.com/n8n-io/n8n/issues/3660)) ([8999403](https://github.com/n8n-io/n8n/commit/899940322831612bdf6e59db7f696c34f96cd496))
|
||||
* **Elasticsearch Node:** Add credential tests, index pipelines and index refresh ([#2420](https://github.com/n8n-io/n8n/issues/2420))
|
||||
* **Freshworks CRM Node:** Add Search + Lookup functionality ([#3131](https://github.com/n8n-io/n8n/issues/3131)) ([dbc0280](https://github.com/n8n-io/n8n/commit/dbc02803db5351d759b1420e94b14f2c7c8b1bef))
|
||||
* **Jira Trigger Node:** Add optional query auth for security ([#3172](https://github.com/n8n-io/n8n/issues/3172)) ([25093b6](https://github.com/n8n-io/n8n/commit/25093b64e693a33a76efd1bd12f00ce0d4cc0f3c))
|
||||
* **Postgres Node:** Improvement handling of large numbers ([#3360](https://github.com/n8n-io/n8n/issues/3360)) ([9f908e7](https://github.com/n8n-io/n8n/commit/9f908e7405d687bf57391e503ad724d58caaac07))
|
||||
* **Redis Node:** Add push and pop operations ([#3127](https://github.com/n8n-io/n8n/issues/3127)) ([32c68eb](https://github.com/n8n-io/n8n/commit/32c68eb126f8411d1a3261dc8a900c109b99da6f))
|
||||
* **Rename Node:** Add regex replace ([#2576](https://github.com/n8n-io/n8n/issues/2576)) ([eae9a60](https://github.com/n8n-io/n8n/commit/eae9a60a431bc08fb58016e3249328abb90716b0))
|
||||
* **SpreadsheetFile Node:** Allow skipping headers when writing spreadsheets ([#3234](https://github.com/n8n-io/n8n/issues/3234)) ([dbfb8d5](https://github.com/n8n-io/n8n/commit/dbfb8d56dc6290837701dea5957d4e73db418892))
|
||||
* Updated multiple credentials with tests and allow to be used on HTTP Request Node ([#3670](https://github.com/n8n-io/n8n/issues/3670)) ([d5d4dd3](https://github.com/n8n-io/n8n/commit/d5d4dd38450b788ee0ce3ed8ad0eb714c86977d2))
|
||||
|
||||
|
||||
- Add item information to more node errors ([#3681](https://github.com/n8n-io/n8n/issues/3681)) ([2a8043c](https://github.com/n8n-io/n8n/commit/2a8043cd27968b92b1857135d130e3ee54aae779))
|
||||
- **AWS DynamoDB Node:** Improve error handling + add optional GetAll Scan FilterExpression ([#3318](https://github.com/n8n-io/n8n/issues/3318)) ([732c8fc](https://github.com/n8n-io/n8n/commit/732c8fcf8488fc35839855499f75202436fc4c9a))
|
||||
- **Customer.io Node:** Add support for tracking API region selection ([#3378](https://github.com/n8n-io/n8n/issues/3378)) ([82a254a](https://github.com/n8n-io/n8n/commit/82a254a8d9295901e42ec999432a7f5b40f38281))
|
||||
- **Elasticsearch Node:** Add 'Source Excludes' and 'Source Includes' options on 'Document: getAll' operation ([#3660](https://github.com/n8n-io/n8n/issues/3660)) ([8999403](https://github.com/n8n-io/n8n/commit/899940322831612bdf6e59db7f696c34f96cd496))
|
||||
- **Elasticsearch Node:** Add credential tests, index pipelines and index refresh ([#2420](https://github.com/n8n-io/n8n/issues/2420))
|
||||
- **Freshworks CRM Node:** Add Search + Lookup functionality ([#3131](https://github.com/n8n-io/n8n/issues/3131)) ([dbc0280](https://github.com/n8n-io/n8n/commit/dbc02803db5351d759b1420e94b14f2c7c8b1bef))
|
||||
- **Jira Trigger Node:** Add optional query auth for security ([#3172](https://github.com/n8n-io/n8n/issues/3172)) ([25093b6](https://github.com/n8n-io/n8n/commit/25093b64e693a33a76efd1bd12f00ce0d4cc0f3c))
|
||||
- **Postgres Node:** Improvement handling of large numbers ([#3360](https://github.com/n8n-io/n8n/issues/3360)) ([9f908e7](https://github.com/n8n-io/n8n/commit/9f908e7405d687bf57391e503ad724d58caaac07))
|
||||
- **Redis Node:** Add push and pop operations ([#3127](https://github.com/n8n-io/n8n/issues/3127)) ([32c68eb](https://github.com/n8n-io/n8n/commit/32c68eb126f8411d1a3261dc8a900c109b99da6f))
|
||||
- **Rename Node:** Add regex replace ([#2576](https://github.com/n8n-io/n8n/issues/2576)) ([eae9a60](https://github.com/n8n-io/n8n/commit/eae9a60a431bc08fb58016e3249328abb90716b0))
|
||||
- **SpreadsheetFile Node:** Allow skipping headers when writing spreadsheets ([#3234](https://github.com/n8n-io/n8n/issues/3234)) ([dbfb8d5](https://github.com/n8n-io/n8n/commit/dbfb8d56dc6290837701dea5957d4e73db418892))
|
||||
- Updated multiple credentials with tests and allow to be used on HTTP Request Node ([#3670](https://github.com/n8n-io/n8n/issues/3670)) ([d5d4dd3](https://github.com/n8n-io/n8n/commit/d5d4dd38450b788ee0ce3ed8ad0eb714c86977d2))
|
||||
|
||||
# [0.185.0](https://github.com/n8n-io/n8n/compare/n8n@0.184.0...n8n@0.185.0) (2022-07-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Hubspot Node:** Fix search endpoints ([#3640](https://github.com/n8n-io/n8n/issues/3640)) ([16b9926](https://github.com/n8n-io/n8n/commit/16b9926cd25abf4a2ae4c9eba494340eab58082f))
|
||||
* **KoboToolbox Node:** Improve attachment matching logic and GeoJSON Polygon format ([#3535](https://github.com/n8n-io/n8n/issues/3535)) ([637e815](https://github.com/n8n-io/n8n/commit/637e81552f86788058567342cf69e2784e3d6b2f))
|
||||
* **Odoo Node:** Prevent possible issues with some custom fields ([#3496](https://github.com/n8n-io/n8n/issues/3496)) ([7d968ec](https://github.com/n8n-io/n8n/commit/7d968ec202ceccc6a009ec150747cc927273f841))
|
||||
* **Sticky Node:** Fix main header hiding ([#3654](https://github.com/n8n-io/n8n/issues/3654)) ([88486bc](https://github.com/n8n-io/n8n/commit/88486bc778786d4a47ef1bb5c743c9fb206aee01))
|
||||
* **Todoist Node:** Fix multiple item support ([#3614](https://github.com/n8n-io/n8n/issues/3614)) ([7ba85c4](https://github.com/n8n-io/n8n/commit/7ba85c4ab910ed02696078ece12c88f2141cccad))
|
||||
|
||||
- **Hubspot Node:** Fix search endpoints ([#3640](https://github.com/n8n-io/n8n/issues/3640)) ([16b9926](https://github.com/n8n-io/n8n/commit/16b9926cd25abf4a2ae4c9eba494340eab58082f))
|
||||
- **KoboToolbox Node:** Improve attachment matching logic and GeoJSON Polygon format ([#3535](https://github.com/n8n-io/n8n/issues/3535)) ([637e815](https://github.com/n8n-io/n8n/commit/637e81552f86788058567342cf69e2784e3d6b2f))
|
||||
- **Odoo Node:** Prevent possible issues with some custom fields ([#3496](https://github.com/n8n-io/n8n/issues/3496)) ([7d968ec](https://github.com/n8n-io/n8n/commit/7d968ec202ceccc6a009ec150747cc927273f841))
|
||||
- **Sticky Node:** Fix main header hiding ([#3654](https://github.com/n8n-io/n8n/issues/3654)) ([88486bc](https://github.com/n8n-io/n8n/commit/88486bc778786d4a47ef1bb5c743c9fb206aee01))
|
||||
- **Todoist Node:** Fix multiple item support ([#3614](https://github.com/n8n-io/n8n/issues/3614)) ([7ba85c4](https://github.com/n8n-io/n8n/commit/7ba85c4ab910ed02696078ece12c88f2141cccad))
|
||||
|
||||
### Features
|
||||
* **core:** Add `action` to `INodePropertyOptions` ([#3610](https://github.com/n8n-io/n8n/issues/3610)) ([3c65968](https://github.com/n8n-io/n8n/commit/3c659682e94cdd01fd6f267a468a031b028cf690))
|
||||
* **DeepL Node:** Add support for longer texts + Credential tests ([#3651](https://github.com/n8n-io/n8n/issues/3651)) ([88d6cfc](https://github.com/n8n-io/n8n/commit/88d6cfc07bfd2be64a39f285d235e22aae8c1522))
|
||||
* **Facebook Node:** Add support for Facebook Graph API versions 14 ([#3656](https://github.com/n8n-io/n8n/issues/3656)) ([174d063](https://github.com/n8n-io/n8n/commit/174d06383191e6e70ba27bc3e6e46527731c80b5))
|
||||
* **Google Ads Node:** Add new node ([#3526](https://github.com/n8n-io/n8n/issues/3526)) ([088daf9](https://github.com/n8n-io/n8n/commit/088daf952ea7340a3101362bce18668147b8431f))
|
||||
* **Jira Node:** Use Jira rendered fields with simplify option ([#3323](https://github.com/n8n-io/n8n/issues/3323)) ([07b6cff](https://github.com/n8n-io/n8n/commit/07b6cffdba55a48bfed629a1faec8cf88bee88bc))
|
||||
* **Webflow Trigger Node:** Reduce chance of webhook duplication and add credential test ([#3594](https://github.com/n8n-io/n8n/issues/3594)) ([224e008](https://github.com/n8n-io/n8n/commit/224e008fb64dabef99998508eb4385e1b872c5ad))
|
||||
* **Wordpress Node:** Add post template option ([#3139](https://github.com/n8n-io/n8n/issues/3139)) ([02bc3da](https://github.com/n8n-io/n8n/commit/02bc3da78545de4771edf6fdc68720b0e7d596b9))
|
||||
|
||||
|
||||
- **core:** Add `action` to `INodePropertyOptions` ([#3610](https://github.com/n8n-io/n8n/issues/3610)) ([3c65968](https://github.com/n8n-io/n8n/commit/3c659682e94cdd01fd6f267a468a031b028cf690))
|
||||
- **DeepL Node:** Add support for longer texts + Credential tests ([#3651](https://github.com/n8n-io/n8n/issues/3651)) ([88d6cfc](https://github.com/n8n-io/n8n/commit/88d6cfc07bfd2be64a39f285d235e22aae8c1522))
|
||||
- **Facebook Node:** Add support for Facebook Graph API versions 14 ([#3656](https://github.com/n8n-io/n8n/issues/3656)) ([174d063](https://github.com/n8n-io/n8n/commit/174d06383191e6e70ba27bc3e6e46527731c80b5))
|
||||
- **Google Ads Node:** Add new node ([#3526](https://github.com/n8n-io/n8n/issues/3526)) ([088daf9](https://github.com/n8n-io/n8n/commit/088daf952ea7340a3101362bce18668147b8431f))
|
||||
- **Jira Node:** Use Jira rendered fields with simplify option ([#3323](https://github.com/n8n-io/n8n/issues/3323)) ([07b6cff](https://github.com/n8n-io/n8n/commit/07b6cffdba55a48bfed629a1faec8cf88bee88bc))
|
||||
- **Webflow Trigger Node:** Reduce chance of webhook duplication and add credential test ([#3594](https://github.com/n8n-io/n8n/issues/3594)) ([224e008](https://github.com/n8n-io/n8n/commit/224e008fb64dabef99998508eb4385e1b872c5ad))
|
||||
- **Wordpress Node:** Add post template option ([#3139](https://github.com/n8n-io/n8n/issues/3139)) ([02bc3da](https://github.com/n8n-io/n8n/commit/02bc3da78545de4771edf6fdc68720b0e7d596b9))
|
||||
|
||||
# [0.184.0](https://github.com/n8n-io/n8n/compare/n8n@0.183.0...n8n@0.184.0) (2022-06-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** Fix logger error when logging circular json ([#3583](https://github.com/n8n-io/n8n/issues/3583)) ([3cb693d](https://github.com/n8n-io/n8n/commit/3cb693d5d4b8aaf800df70e62c1b2ca2ff208c4d))
|
||||
* Correct misfix from `node-param-display-name-wrong-for-dynamic-multi-options` ([#3575](https://github.com/n8n-io/n8n/issues/3575)) ([2ccc7fb](https://github.com/n8n-io/n8n/commit/2ccc7fbc9d1df3f044cf42fe1af72bc7352caa9f))
|
||||
* **Cortex Node:** Fix issue that not all Analyzers got returned ([#3606](https://github.com/n8n-io/n8n/issues/3606)) ([6e595c7](https://github.com/n8n-io/n8n/commit/6e595c72760f47107f67c1fd2bdbe76c31af4a8b))
|
||||
* **editor:** Display full text of long error messages ([#3561](https://github.com/n8n-io/n8n/issues/3561)) ([8db4405](https://github.com/n8n-io/n8n/commit/8db44057f2101698ef4869fca436862e4dd39fc1))
|
||||
* **editor:** Fix credentials rendering when the node has no parameters ([#3563](https://github.com/n8n-io/n8n/issues/3563)) ([55bab19](https://github.com/n8n-io/n8n/commit/55bab19eb440ed9d58137f4334a37d5f731afe0f))
|
||||
* Fix issue with required optional parameters ([#3577](https://github.com/n8n-io/n8n/issues/3577)) ([42d2959](https://github.com/n8n-io/n8n/commit/42d2959f47f33defda4239a4d2fbba6927d98617))
|
||||
* Fix issue with required optional parameters ([#3597](https://github.com/n8n-io/n8n/issues/3597)) ([848fcfd](https://github.com/n8n-io/n8n/commit/848fcfde5d95d952170e9a3d51b629971a13b832))
|
||||
* **HTTP Request Node:** Make all OAuth2 credentials work with HTTP Request Node ([#3503](https://github.com/n8n-io/n8n/issues/3503)) ([acdb4d9](https://github.com/n8n-io/n8n/commit/acdb4d92c8ef95646e69694b2451a9111a81c52f))
|
||||
* **LinkedIn Node:** Fix LinkedIn image preview ([#3528](https://github.com/n8n-io/n8n/issues/3528)) ([32f245d](https://github.com/n8n-io/n8n/commit/32f245da53c186a03172dbb23761a05b5e301532))
|
||||
* **Salesforce Node:** Fix issue with lead status not using name on update ([#3599](https://github.com/n8n-io/n8n/issues/3599)) ([7ccae7c](https://github.com/n8n-io/n8n/commit/7ccae7c9b22f2848a8aa357227d145241801ba82))
|
||||
|
||||
- **core:** Fix logger error when logging circular json ([#3583](https://github.com/n8n-io/n8n/issues/3583)) ([3cb693d](https://github.com/n8n-io/n8n/commit/3cb693d5d4b8aaf800df70e62c1b2ca2ff208c4d))
|
||||
- Correct misfix from `node-param-display-name-wrong-for-dynamic-multi-options` ([#3575](https://github.com/n8n-io/n8n/issues/3575)) ([2ccc7fb](https://github.com/n8n-io/n8n/commit/2ccc7fbc9d1df3f044cf42fe1af72bc7352caa9f))
|
||||
- **Cortex Node:** Fix issue that not all Analyzers got returned ([#3606](https://github.com/n8n-io/n8n/issues/3606)) ([6e595c7](https://github.com/n8n-io/n8n/commit/6e595c72760f47107f67c1fd2bdbe76c31af4a8b))
|
||||
- **editor:** Display full text of long error messages ([#3561](https://github.com/n8n-io/n8n/issues/3561)) ([8db4405](https://github.com/n8n-io/n8n/commit/8db44057f2101698ef4869fca436862e4dd39fc1))
|
||||
- **editor:** Fix credentials rendering when the node has no parameters ([#3563](https://github.com/n8n-io/n8n/issues/3563)) ([55bab19](https://github.com/n8n-io/n8n/commit/55bab19eb440ed9d58137f4334a37d5f731afe0f))
|
||||
- Fix issue with required optional parameters ([#3577](https://github.com/n8n-io/n8n/issues/3577)) ([42d2959](https://github.com/n8n-io/n8n/commit/42d2959f47f33defda4239a4d2fbba6927d98617))
|
||||
- Fix issue with required optional parameters ([#3597](https://github.com/n8n-io/n8n/issues/3597)) ([848fcfd](https://github.com/n8n-io/n8n/commit/848fcfde5d95d952170e9a3d51b629971a13b832))
|
||||
- **HTTP Request Node:** Make all OAuth2 credentials work with HTTP Request Node ([#3503](https://github.com/n8n-io/n8n/issues/3503)) ([acdb4d9](https://github.com/n8n-io/n8n/commit/acdb4d92c8ef95646e69694b2451a9111a81c52f))
|
||||
- **LinkedIn Node:** Fix LinkedIn image preview ([#3528](https://github.com/n8n-io/n8n/issues/3528)) ([32f245d](https://github.com/n8n-io/n8n/commit/32f245da53c186a03172dbb23761a05b5e301532))
|
||||
- **Salesforce Node:** Fix issue with lead status not using name on update ([#3599](https://github.com/n8n-io/n8n/issues/3599)) ([7ccae7c](https://github.com/n8n-io/n8n/commit/7ccae7c9b22f2848a8aa357227d145241801ba82))
|
||||
|
||||
### Features
|
||||
|
||||
* **Clockify Node:** Add more resources and improvements ([#3411](https://github.com/n8n-io/n8n/issues/3411)) ([447d190](https://github.com/n8n-io/n8n/commit/447d19024c512eea8e290d8ebc6c3ce82a53f002))
|
||||
* **core:** Expose item index being processed ([#3590](https://github.com/n8n-io/n8n/issues/3590)) ([1e4fd9e](https://github.com/n8n-io/n8n/commit/1e4fd9e4df524fdee8195de7be244ff03d97f917))
|
||||
* **core:** Give access to getBinaryDataBuffer in preSend method ([#3588](https://github.com/n8n-io/n8n/issues/3588)) ([522b31a](https://github.com/n8n-io/n8n/commit/522b31a47b4f4e9990e07dcc504ef2821a1fd0a5))
|
||||
* Migrated to npm release of riot-tmpl fork ([#3581](https://github.com/n8n-io/n8n/issues/3581)) ([891844e](https://github.com/n8n-io/n8n/commit/891844ea8b3248195355f736d7331fd967ee99e1))
|
||||
|
||||
|
||||
- **Clockify Node:** Add more resources and improvements ([#3411](https://github.com/n8n-io/n8n/issues/3411)) ([447d190](https://github.com/n8n-io/n8n/commit/447d19024c512eea8e290d8ebc6c3ce82a53f002))
|
||||
- **core:** Expose item index being processed ([#3590](https://github.com/n8n-io/n8n/issues/3590)) ([1e4fd9e](https://github.com/n8n-io/n8n/commit/1e4fd9e4df524fdee8195de7be244ff03d97f917))
|
||||
- **core:** Give access to getBinaryDataBuffer in preSend method ([#3588](https://github.com/n8n-io/n8n/issues/3588)) ([522b31a](https://github.com/n8n-io/n8n/commit/522b31a47b4f4e9990e07dcc504ef2821a1fd0a5))
|
||||
- Migrated to npm release of riot-tmpl fork ([#3581](https://github.com/n8n-io/n8n/issues/3581)) ([891844e](https://github.com/n8n-io/n8n/commit/891844ea8b3248195355f736d7331fd967ee99e1))
|
||||
|
||||
# [0.183.0](https://github.com/n8n-io/n8n/compare/n8n@0.182.1...n8n@0.183.0) (2022-06-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** Do allow OPTIONS requests from any source ([#3555](https://github.com/n8n-io/n8n/issues/3555)) ([74e6b06](https://github.com/n8n-io/n8n/commit/74e6b06467f8d0059c8cc45154e2d2822dc9b0c5))
|
||||
* **core:** Fix issue that GET /workflows/:id does not return tags ([#3522](https://github.com/n8n-io/n8n/issues/3522)) ([f75f5d7](https://github.com/n8n-io/n8n/commit/f75f5d711f886892a1afcebff722ab476390f4f0))
|
||||
* **core:** Fix issue that some predefined credentials do not show up on HTTP Request Node ([#3556](https://github.com/n8n-io/n8n/issues/3556)) ([d417ea7](https://github.com/n8n-io/n8n/commit/d417ea7ffad9e2210f3b2b5e7122ffbe70f2ba27))
|
||||
* **core:** Return correct error message if Axios error ([#3478](https://github.com/n8n-io/n8n/issues/3478)) ([1bef4df](https://github.com/n8n-io/n8n/commit/1bef4df75f999ac2e413b6c179baab3321c52fa2))
|
||||
* **core:** Updated expressions allowlist and denylist. ([#3424](https://github.com/n8n-io/n8n/issues/3424)) ([d18a29d](https://github.com/n8n-io/n8n/commit/d18a29d5882fb8f4475258189f6badcd0a573b34))
|
||||
|
||||
- **core:** Do allow OPTIONS requests from any source ([#3555](https://github.com/n8n-io/n8n/issues/3555)) ([74e6b06](https://github.com/n8n-io/n8n/commit/74e6b06467f8d0059c8cc45154e2d2822dc9b0c5))
|
||||
- **core:** Fix issue that GET /workflows/:id does not return tags ([#3522](https://github.com/n8n-io/n8n/issues/3522)) ([f75f5d7](https://github.com/n8n-io/n8n/commit/f75f5d711f886892a1afcebff722ab476390f4f0))
|
||||
- **core:** Fix issue that some predefined credentials do not show up on HTTP Request Node ([#3556](https://github.com/n8n-io/n8n/issues/3556)) ([d417ea7](https://github.com/n8n-io/n8n/commit/d417ea7ffad9e2210f3b2b5e7122ffbe70f2ba27))
|
||||
- **core:** Return correct error message if Axios error ([#3478](https://github.com/n8n-io/n8n/issues/3478)) ([1bef4df](https://github.com/n8n-io/n8n/commit/1bef4df75f999ac2e413b6c179baab3321c52fa2))
|
||||
- **core:** Updated expressions allowlist and denylist. ([#3424](https://github.com/n8n-io/n8n/issues/3424)) ([d18a29d](https://github.com/n8n-io/n8n/commit/d18a29d5882fb8f4475258189f6badcd0a573b34))
|
||||
|
||||
### Features
|
||||
|
||||
* **editor:** Improve trigger panel ([#3509](https://github.com/n8n-io/n8n/issues/3509)) ([a2f6289](https://github.com/n8n-io/n8n/commit/a2f628927dff7ea6741ef8e4a60bcafd95dac7bf))
|
||||
* **Hubspot Node:** Allow to set Stage on Ticket Update ([#3317](https://github.com/n8n-io/n8n/issues/3317)) ([0ac9e3f](https://github.com/n8n-io/n8n/commit/0ac9e3f975b73e88acabb66de8b8565f881f64ec))
|
||||
* **Todoist Node:** Make it possible to move tasks between sections ([#3074](https://github.com/n8n-io/n8n/issues/3074)) ([049e454](https://github.com/n8n-io/n8n/commit/049e4544d9ccc0acce2a596aced06ec86992e09a))
|
||||
* **Twake Node:** Update icon, add cred test and custom operation support ([#3431](https://github.com/n8n-io/n8n/issues/3431)) ([6d64e84](https://github.com/n8n-io/n8n/commit/6d64e84f5e19d5f6d83ccc0a55cdcbd256e5804f))
|
||||
|
||||
|
||||
- **editor:** Improve trigger panel ([#3509](https://github.com/n8n-io/n8n/issues/3509)) ([a2f6289](https://github.com/n8n-io/n8n/commit/a2f628927dff7ea6741ef8e4a60bcafd95dac7bf))
|
||||
- **Hubspot Node:** Allow to set Stage on Ticket Update ([#3317](https://github.com/n8n-io/n8n/issues/3317)) ([0ac9e3f](https://github.com/n8n-io/n8n/commit/0ac9e3f975b73e88acabb66de8b8565f881f64ec))
|
||||
- **Todoist Node:** Make it possible to move tasks between sections ([#3074](https://github.com/n8n-io/n8n/issues/3074)) ([049e454](https://github.com/n8n-io/n8n/commit/049e4544d9ccc0acce2a596aced06ec86992e09a))
|
||||
- **Twake Node:** Update icon, add cred test and custom operation support ([#3431](https://github.com/n8n-io/n8n/issues/3431)) ([6d64e84](https://github.com/n8n-io/n8n/commit/6d64e84f5e19d5f6d83ccc0a55cdcbd256e5804f))
|
||||
|
||||
## [0.182.1](https://github.com/n8n-io/n8n/compare/n8n@0.182.0...n8n@0.182.1) (2022-06-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** Fix issue with restarting waiting executions ([#3531](https://github.com/n8n-io/n8n/issues/3531)) ([c9273bc](https://github.com/n8n-io/n8n/commit/c9273bcd3862217b4918ac8abb37fae9c2e64622))
|
||||
|
||||
|
||||
- **core:** Fix issue with restarting waiting executions ([#3531](https://github.com/n8n-io/n8n/issues/3531)) ([c9273bc](https://github.com/n8n-io/n8n/commit/c9273bcd3862217b4918ac8abb37fae9c2e64622))
|
||||
|
||||
# [0.182.0](https://github.com/n8n-io/n8n/compare/n8n@0.181.2...n8n@0.182.0) (2022-06-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** Fix issue that parameters got lost in some edge cases ([04f0bf5](https://github.com/n8n-io/n8n/commit/04f0bf5b65c8224a4fdfd3c9d2c896f63dfbcc1d))
|
||||
* **core:** Fix issue with combined expression not resolving if one is invalid ([#3506](https://github.com/n8n-io/n8n/issues/3506)) ([9ff5762](https://github.com/n8n-io/n8n/commit/9ff57629c5afb2f0fd4aee84cda79c9a6f7962d0))
|
||||
* **core:** Fix Public API failing to build on Windows ([#3499](https://github.com/n8n-io/n8n/issues/3499)) ([c121952](https://github.com/n8n-io/n8n/commit/c121952324619434e8a7be540970c167df715b13))
|
||||
* **editor:** Fix issue that some errors did not show up correctly ([#3507](https://github.com/n8n-io/n8n/issues/3507)) ([955db0a](https://github.com/n8n-io/n8n/commit/955db0ab101feb17efffe760c79ec2820e1d4c3b))
|
||||
* **HTTP Request Node:** Fix issue with requests that return null ([#3498](https://github.com/n8n-io/n8n/issues/3498)) ([7346da0](https://github.com/n8n-io/n8n/commit/7346da0b34b5fdf7ab630ccc5cda102cf80c8036))
|
||||
* **Pipedrive Node:** Fix limit issue with Lead -> GetAll ([#3436](https://github.com/n8n-io/n8n/issues/3436)) ([34e891c](https://github.com/n8n-io/n8n/commit/34e891c0f8c987c9be9cff463422b9972f02269f))
|
||||
* **PostBin Node:** Fix issue with it throwing unnecessary error ([#3494](https://github.com/n8n-io/n8n/issues/3494)) ([9df3e30](https://github.com/n8n-io/n8n/commit/9df3e30d36104d8e31972c773cb71f4cc82f6970))
|
||||
|
||||
- **core:** Fix issue that parameters got lost in some edge cases ([04f0bf5](https://github.com/n8n-io/n8n/commit/04f0bf5b65c8224a4fdfd3c9d2c896f63dfbcc1d))
|
||||
- **core:** Fix issue with combined expression not resolving if one is invalid ([#3506](https://github.com/n8n-io/n8n/issues/3506)) ([9ff5762](https://github.com/n8n-io/n8n/commit/9ff57629c5afb2f0fd4aee84cda79c9a6f7962d0))
|
||||
- **core:** Fix Public API failing to build on Windows ([#3499](https://github.com/n8n-io/n8n/issues/3499)) ([c121952](https://github.com/n8n-io/n8n/commit/c121952324619434e8a7be540970c167df715b13))
|
||||
- **editor:** Fix issue that some errors did not show up correctly ([#3507](https://github.com/n8n-io/n8n/issues/3507)) ([955db0a](https://github.com/n8n-io/n8n/commit/955db0ab101feb17efffe760c79ec2820e1d4c3b))
|
||||
- **HTTP Request Node:** Fix issue with requests that return null ([#3498](https://github.com/n8n-io/n8n/issues/3498)) ([7346da0](https://github.com/n8n-io/n8n/commit/7346da0b34b5fdf7ab630ccc5cda102cf80c8036))
|
||||
- **Pipedrive Node:** Fix limit issue with Lead -> GetAll ([#3436](https://github.com/n8n-io/n8n/issues/3436)) ([34e891c](https://github.com/n8n-io/n8n/commit/34e891c0f8c987c9be9cff463422b9972f02269f))
|
||||
- **PostBin Node:** Fix issue with it throwing unnecessary error ([#3494](https://github.com/n8n-io/n8n/issues/3494)) ([9df3e30](https://github.com/n8n-io/n8n/commit/9df3e30d36104d8e31972c773cb71f4cc82f6970))
|
||||
|
||||
### Features
|
||||
|
||||
* **core:** Add "Client Credentials" grant type to OAuth2 ([#3489](https://github.com/n8n-io/n8n/issues/3489)) ([e29c597](https://github.com/n8n-io/n8n/commit/e29c5975e1f1ad089167df46021203e9f67c8ef1))
|
||||
* **Twilio Node:** Add ability to make a voice call using TTS ([#3467](https://github.com/n8n-io/n8n/issues/3467)) ([eff97e8](https://github.com/n8n-io/n8n/commit/eff97e8d67cd3f0342bbb9648503b351f4691f46))
|
||||
* **Wise Node:** Add Support to download statements as JSON, CSV or PDF ([#3468](https://github.com/n8n-io/n8n/issues/3468)) ([51663c1](https://github.com/n8n-io/n8n/commit/51663c1fcbe879e29790af942b73318e95065d8f))
|
||||
|
||||
|
||||
- **core:** Add "Client Credentials" grant type to OAuth2 ([#3489](https://github.com/n8n-io/n8n/issues/3489)) ([e29c597](https://github.com/n8n-io/n8n/commit/e29c5975e1f1ad089167df46021203e9f67c8ef1))
|
||||
- **Twilio Node:** Add ability to make a voice call using TTS ([#3467](https://github.com/n8n-io/n8n/issues/3467)) ([eff97e8](https://github.com/n8n-io/n8n/commit/eff97e8d67cd3f0342bbb9648503b351f4691f46))
|
||||
- **Wise Node:** Add Support to download statements as JSON, CSV or PDF ([#3468](https://github.com/n8n-io/n8n/issues/3468)) ([51663c1](https://github.com/n8n-io/n8n/commit/51663c1fcbe879e29790af942b73318e95065d8f))
|
||||
|
||||
## [0.181.2](https://github.com/n8n-io/n8n/compare/n8n@0.181.1...n8n@0.181.2) (2022-06-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** Fix issue when a node does not return data ([5eea3cd](https://github.com/n8n-io/n8n/commit/5eea3cd6d0b59963dc7c7a9e1ca597137cf3ce98))
|
||||
|
||||
|
||||
- **core:** Fix issue when a node does not return data ([5eea3cd](https://github.com/n8n-io/n8n/commit/5eea3cd6d0b59963dc7c7a9e1ca597137cf3ce98))
|
||||
|
||||
## [0.181.1](https://github.com/n8n-io/n8n/compare/n8n@0.181.0...n8n@0.181.1) (2022-06-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** Fix another possible issue with multi input nodes ([e88fab5](https://github.com/n8n-io/n8n/commit/e88fab5ee2b82665c3d68c52894a5479ce6eccf6))
|
||||
* **core:** Fix issue with multi input nodes ([f79675d](https://github.com/n8n-io/n8n/commit/f79675d5c7876875065fc29504eb0590678d67d3))
|
||||
|
||||
|
||||
- **core:** Fix another possible issue with multi input nodes ([e88fab5](https://github.com/n8n-io/n8n/commit/e88fab5ee2b82665c3d68c52894a5479ce6eccf6))
|
||||
- **core:** Fix issue with multi input nodes ([f79675d](https://github.com/n8n-io/n8n/commit/f79675d5c7876875065fc29504eb0590678d67d3))
|
||||
|
||||
# [0.181.0](https://github.com/n8n-io/n8n/compare/n8n@0.180.0...n8n@0.181.0) (2022-06-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** Properly resolve expressions in declarative node design ([1999f4b](https://github.com/n8n-io/n8n/commit/1999f4b066784cc1dd6a962f51d7c11641577a8b))
|
||||
|
||||
- **core:** Properly resolve expressions in declarative node design ([1999f4b](https://github.com/n8n-io/n8n/commit/1999f4b066784cc1dd6a962f51d7c11641577a8b))
|
||||
|
||||
### Features
|
||||
|
||||
* Add n8n Public API ([#3064](https://github.com/n8n-io/n8n/issues/3064)) ([a18081d](https://github.com/n8n-io/n8n/commit/a18081d749c51d497645d43614fdccb220344607))
|
||||
* **core:** Make it possible to block access to environment variables ([ddb3baa](https://github.com/n8n-io/n8n/commit/ddb3baa4eddeb85e2f7abe4465ac4ff4058e1ece))
|
||||
|
||||
|
||||
- Add n8n Public API ([#3064](https://github.com/n8n-io/n8n/issues/3064)) ([a18081d](https://github.com/n8n-io/n8n/commit/a18081d749c51d497645d43614fdccb220344607))
|
||||
- **core:** Make it possible to block access to environment variables ([ddb3baa](https://github.com/n8n-io/n8n/commit/ddb3baa4eddeb85e2f7abe4465ac4ff4058e1ece))
|
||||
|
||||
# [0.180.0](https://github.com/n8n-io/n8n/compare/n8n@0.179.0...n8n@0.180.0) (2022-06-07)
|
||||
|
||||
|
|
@ -193,7 +632,6 @@
|
|||
- **GitHub Node:**: Add Organization -> Get All operation ([#3247](https://github.com/n8n-io/n8n/pull/3247))
|
||||
- **QuickBooks Node:** Add optional Tax item field ([#3404](https://github.com/n8n-io/n8n/issues/3404)) ([c341b45](https://github.com/n8n-io/n8n/commit/c341b45396c7282da087046ade16265c99c8d9dd))
|
||||
|
||||
|
||||
# [0.179.0](https://github.com/n8n-io/n8n/compare/n8n@0.178.2...n8n@0.179.0) (2022-05-30)
|
||||
|
||||
### Bug Fixes
|
||||
|
|
@ -217,93 +655,71 @@
|
|||
- **ServiceNow Node:** Add attachment functionality ([#3137](https://github.com/n8n-io/n8n/issues/3137)) ([c38f6af](https://github.com/n8n-io/n8n/commit/c38f6af4993cd695888ff18b3f95e0d900e65711))
|
||||
- **Todoist Node:** Add support for specifying the parent task when adding and listing tasks ([#3161](https://github.com/n8n-io/n8n/issues/3161)) ([dc77594](https://github.com/n8n-io/n8n/commit/dc77594a1eaec73fa34ed09c52d108482002ffff))
|
||||
|
||||
|
||||
## [0.178.2](https://github.com/n8n-io/n8n/compare/n8n@0.178.1...n8n@0.178.2) (2022-05-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **editor:** Fix parameter loading bug ([#3374](https://github.com/n8n-io/n8n/issues/3374)) ([c7c2061](https://github.com/n8n-io/n8n/commit/c7c2061590493a1b24a8ab4e2615d6d9eb2641e1))
|
||||
|
||||
|
||||
- **editor:** Fix parameter loading bug ([#3374](https://github.com/n8n-io/n8n/issues/3374)) ([c7c2061](https://github.com/n8n-io/n8n/commit/c7c2061590493a1b24a8ab4e2615d6d9eb2641e1))
|
||||
|
||||
## [0.178.1](https://github.com/n8n-io/n8n/compare/n8n@0.178.0...n8n@0.178.1) (2022-05-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **editor:** Fix problem with HTTP Request Node 1 credentials to be set ([#3371](https://github.com/n8n-io/n8n/issues/3371)) ([c5fc3bc](https://github.com/n8n-io/n8n/commit/c5fc3bc45e80eec47f4c06b950ab8b3ddaf66f2f))
|
||||
|
||||
|
||||
- **editor:** Fix problem with HTTP Request Node 1 credentials to be set ([#3371](https://github.com/n8n-io/n8n/issues/3371)) ([c5fc3bc](https://github.com/n8n-io/n8n/commit/c5fc3bc45e80eec47f4c06b950ab8b3ddaf66f2f))
|
||||
|
||||
# [0.178.0](https://github.com/n8n-io/n8n/compare/n8n@0.177.0...n8n@0.178.0) (2022-05-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **editor:** Do not display diving line unless necessary ([68db12c](https://github.com/n8n-io/n8n/commit/68db12ce6d8bfc99cd0891cfa44f8b64674dada7))
|
||||
* **editor:** Do not display welcome sticky in template workflows ([#3320](https://github.com/n8n-io/n8n/issues/3320)) ([29ddac3](https://github.com/n8n-io/n8n/commit/29ddac30d33caff1cf8a061d619742fdb3402d49))
|
||||
* **Slack Node:** Fix Channel->Kick ([#3365](https://github.com/n8n-io/n8n/issues/3365)) ([0212d65](https://github.com/n8n-io/n8n/commit/0212d65dae885a6a153c67095f04215f5e1f8278))
|
||||
|
||||
- **editor:** Do not display diving line unless necessary ([68db12c](https://github.com/n8n-io/n8n/commit/68db12ce6d8bfc99cd0891cfa44f8b64674dada7))
|
||||
- **editor:** Do not display welcome sticky in template workflows ([#3320](https://github.com/n8n-io/n8n/issues/3320)) ([29ddac3](https://github.com/n8n-io/n8n/commit/29ddac30d33caff1cf8a061d619742fdb3402d49))
|
||||
- **Slack Node:** Fix Channel->Kick ([#3365](https://github.com/n8n-io/n8n/issues/3365)) ([0212d65](https://github.com/n8n-io/n8n/commit/0212d65dae885a6a153c67095f04215f5e1f8278))
|
||||
|
||||
### Features
|
||||
|
||||
* **core:** Allow credential reuse on HTTP Request node ([#3228](https://github.com/n8n-io/n8n/issues/3228)) ([336fc9e](https://github.com/n8n-io/n8n/commit/336fc9e2a820476931a9e9b482e4be284c0337d0)), closes [#3230](https://github.com/n8n-io/n8n/issues/3230) [#3231](https://github.com/n8n-io/n8n/issues/3231) [#3222](https://github.com/n8n-io/n8n/issues/3222) [#3229](https://github.com/n8n-io/n8n/issues/3229) [#3304](https://github.com/n8n-io/n8n/issues/3304) [#3282](https://github.com/n8n-io/n8n/issues/3282) [#3359](https://github.com/n8n-io/n8n/issues/3359)
|
||||
* **editor:** Add input panel to NDV ([#3204](https://github.com/n8n-io/n8n/issues/3204)) ([3af0abd](https://github.com/n8n-io/n8n/commit/3af0abd9e066a721ac873f255eeb9311ebe6dd27))
|
||||
* **Salesforce Node:** Add country field ([#3314](https://github.com/n8n-io/n8n/issues/3314)) ([90a1bc1](https://github.com/n8n-io/n8n/commit/90a1bc120bc2e291432c977768929da773dcb96e))
|
||||
|
||||
|
||||
- **core:** Allow credential reuse on HTTP Request node ([#3228](https://github.com/n8n-io/n8n/issues/3228)) ([336fc9e](https://github.com/n8n-io/n8n/commit/336fc9e2a820476931a9e9b482e4be284c0337d0)), closes [#3230](https://github.com/n8n-io/n8n/issues/3230) [#3231](https://github.com/n8n-io/n8n/issues/3231) [#3222](https://github.com/n8n-io/n8n/issues/3222) [#3229](https://github.com/n8n-io/n8n/issues/3229) [#3304](https://github.com/n8n-io/n8n/issues/3304) [#3282](https://github.com/n8n-io/n8n/issues/3282) [#3359](https://github.com/n8n-io/n8n/issues/3359)
|
||||
- **editor:** Add input panel to NDV ([#3204](https://github.com/n8n-io/n8n/issues/3204)) ([3af0abd](https://github.com/n8n-io/n8n/commit/3af0abd9e066a721ac873f255eeb9311ebe6dd27))
|
||||
- **Salesforce Node:** Add country field ([#3314](https://github.com/n8n-io/n8n/issues/3314)) ([90a1bc1](https://github.com/n8n-io/n8n/commit/90a1bc120bc2e291432c977768929da773dcb96e))
|
||||
|
||||
# [0.177.0](https://github.com/n8n-io/n8n/compare/n8n@0.176.0...n8n@0.177.0) (2022-05-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** Fix call to `/executions-current` with unsaved workflow ([#3280](https://github.com/n8n-io/n8n/issues/3280)) ([7090a79](https://github.com/n8n-io/n8n/commit/7090a79b5da611d829da4d027a0194fcb60b4755))
|
||||
* **core:** Fix issue with fixedCollection having all default values ([7ced654](https://github.com/n8n-io/n8n/commit/7ced65484fa7c91e10e96f70d6791b689a5686d3))
|
||||
* **Edit Image Node:** Fix font selection ([#3287](https://github.com/n8n-io/n8n/issues/3287)) ([8a8feb1](https://github.com/n8n-io/n8n/commit/8a8feb11c8e22e6a548e077b55e40702f2fb724a))
|
||||
* **Ghost Node:** Fix post tags and add credential tests ([#3278](https://github.com/n8n-io/n8n/issues/3278)) ([a14d85e](https://github.com/n8n-io/n8n/commit/a14d85ea481b8227ba306f07e13263f45eafa6ca))
|
||||
* **Google Calendar Node:** Make it work with public calendars and clean up ([#3283](https://github.com/n8n-io/n8n/issues/3283)) ([a7d960c](https://github.com/n8n-io/n8n/commit/a7d960c56122bd3b602f0e9a121919916e5d6174))
|
||||
* **KoBoToolbox Node:** Fix query and sort + use question name in attachments ([#3017](https://github.com/n8n-io/n8n/issues/3017)) ([c885115](https://github.com/n8n-io/n8n/commit/c8851157684fe15c77db1fe716fa4333b54450cb))
|
||||
* **Mailjet Trigger Node:** Fix issue that node could not get activated ([#3281](https://github.com/n8n-io/n8n/issues/3281)) ([e09e349](https://github.com/n8n-io/n8n/commit/e09e349fedfe067929556e328a70a32d30759e4d))
|
||||
* **Pipedrive Node:** Fix resolve properties when multi option field is used ([#3277](https://github.com/n8n-io/n8n/issues/3277)) ([7eb1261](https://github.com/n8n-io/n8n/commit/7eb12615cf3eebac29e3561a079451017f80de5c))
|
||||
|
||||
- **core:** Fix call to `/executions-current` with unsaved workflow ([#3280](https://github.com/n8n-io/n8n/issues/3280)) ([7090a79](https://github.com/n8n-io/n8n/commit/7090a79b5da611d829da4d027a0194fcb60b4755))
|
||||
- **core:** Fix issue with fixedCollection having all default values ([7ced654](https://github.com/n8n-io/n8n/commit/7ced65484fa7c91e10e96f70d6791b689a5686d3))
|
||||
- **Edit Image Node:** Fix font selection ([#3287](https://github.com/n8n-io/n8n/issues/3287)) ([8a8feb1](https://github.com/n8n-io/n8n/commit/8a8feb11c8e22e6a548e077b55e40702f2fb724a))
|
||||
- **Ghost Node:** Fix post tags and add credential tests ([#3278](https://github.com/n8n-io/n8n/issues/3278)) ([a14d85e](https://github.com/n8n-io/n8n/commit/a14d85ea481b8227ba306f07e13263f45eafa6ca))
|
||||
- **Google Calendar Node:** Make it work with public calendars and clean up ([#3283](https://github.com/n8n-io/n8n/issues/3283)) ([a7d960c](https://github.com/n8n-io/n8n/commit/a7d960c56122bd3b602f0e9a121919916e5d6174))
|
||||
- **KoBoToolbox Node:** Fix query and sort + use question name in attachments ([#3017](https://github.com/n8n-io/n8n/issues/3017)) ([c885115](https://github.com/n8n-io/n8n/commit/c8851157684fe15c77db1fe716fa4333b54450cb))
|
||||
- **Mailjet Trigger Node:** Fix issue that node could not get activated ([#3281](https://github.com/n8n-io/n8n/issues/3281)) ([e09e349](https://github.com/n8n-io/n8n/commit/e09e349fedfe067929556e328a70a32d30759e4d))
|
||||
- **Pipedrive Node:** Fix resolve properties when multi option field is used ([#3277](https://github.com/n8n-io/n8n/issues/3277)) ([7eb1261](https://github.com/n8n-io/n8n/commit/7eb12615cf3eebac29e3561a079451017f80de5c))
|
||||
|
||||
### Features
|
||||
|
||||
* **core:** Automatically convert Luxon Dates to string ([#3266](https://github.com/n8n-io/n8n/issues/3266)) ([3fcee14](https://github.com/n8n-io/n8n/commit/3fcee14bf5c61ec11fc1d4f30256f5ceba09e7f4))
|
||||
* **editor:** Improve n8n welcome experience ([#3289](https://github.com/n8n-io/n8n/issues/3289)) ([35f2ce2](https://github.com/n8n-io/n8n/commit/35f2ce2359bb84437ad6fc68a7115081daeb46fe))
|
||||
* **Google Drive Node:** Add Shared Drive support for operations upload, delete and share ([#3294](https://github.com/n8n-io/n8n/issues/3294)) ([03cdb1f](https://github.com/n8n-io/n8n/commit/03cdb1fea4fa4967eaafa861f3a9ff4ff7ca625a))
|
||||
* **Microsoft OneDrive Node:** Add rename option for files and folders ([#3224](https://github.com/n8n-io/n8n/issues/3224)) ([50246d1](https://github.com/n8n-io/n8n/commit/50246d174a274fc9ba3dea44fc83c3605b4db691))
|
||||
|
||||
|
||||
- **core:** Automatically convert Luxon Dates to string ([#3266](https://github.com/n8n-io/n8n/issues/3266)) ([3fcee14](https://github.com/n8n-io/n8n/commit/3fcee14bf5c61ec11fc1d4f30256f5ceba09e7f4))
|
||||
- **editor:** Improve n8n welcome experience ([#3289](https://github.com/n8n-io/n8n/issues/3289)) ([35f2ce2](https://github.com/n8n-io/n8n/commit/35f2ce2359bb84437ad6fc68a7115081daeb46fe))
|
||||
- **Google Drive Node:** Add Shared Drive support for operations upload, delete and share ([#3294](https://github.com/n8n-io/n8n/issues/3294)) ([03cdb1f](https://github.com/n8n-io/n8n/commit/03cdb1fea4fa4967eaafa861f3a9ff4ff7ca625a))
|
||||
- **Microsoft OneDrive Node:** Add rename option for files and folders ([#3224](https://github.com/n8n-io/n8n/issues/3224)) ([50246d1](https://github.com/n8n-io/n8n/commit/50246d174a274fc9ba3dea44fc83c3605b4db691))
|
||||
|
||||
# [0.176.0](https://github.com/n8n-io/n8n/compare/n8n@0.175.1...n8n@0.176.0) (2022-05-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** Fix executions list filtering by waiting status ([#3241](https://github.com/n8n-io/n8n/issues/3241)) ([71afcd6](https://github.com/n8n-io/n8n/commit/71afcd6314a73ab6cc04e22afd69e86ca764bd42))
|
||||
* **core:** Improve webhook error messages ([49d0e3e](https://github.com/n8n-io/n8n/commit/49d0e3e885003b11092cf3c890847154426dee41))
|
||||
* **Edit Image Node:** Make node work with binary-data-mode 'filesystem' ([#3274](https://github.com/n8n-io/n8n/issues/3274)) ([a4db0d0](https://github.com/n8n-io/n8n/commit/a4db0d051b18bc224c6cd69faeabf03cf5fba659))
|
||||
|
||||
- **core:** Fix executions list filtering by waiting status ([#3241](https://github.com/n8n-io/n8n/issues/3241)) ([71afcd6](https://github.com/n8n-io/n8n/commit/71afcd6314a73ab6cc04e22afd69e86ca764bd42))
|
||||
- **core:** Improve webhook error messages ([49d0e3e](https://github.com/n8n-io/n8n/commit/49d0e3e885003b11092cf3c890847154426dee41))
|
||||
- **Edit Image Node:** Make node work with binary-data-mode 'filesystem' ([#3274](https://github.com/n8n-io/n8n/issues/3274)) ([a4db0d0](https://github.com/n8n-io/n8n/commit/a4db0d051b18bc224c6cd69faeabf03cf5fba659))
|
||||
|
||||
### Features
|
||||
|
||||
* **Pipedrive Node:** Add support for filters to getAll:organization ([#3211](https://github.com/n8n-io/n8n/issues/3211)) ([1ef10dd](https://github.com/n8n-io/n8n/commit/1ef10dd23fef0b2e3e0ef76c8116d3bebc36bc4e))
|
||||
* **Pushover Node:** Add 'HTML Formatting' option and credential test ([#3082](https://github.com/n8n-io/n8n/issues/3082)) ([b3dc6d9](https://github.com/n8n-io/n8n/commit/b3dc6d9d9c640f1e0f04cb56d0fabe2aafb948b6))
|
||||
* **UProc Node:** Add new tools ([#3104](https://github.com/n8n-io/n8n/issues/3104)) ([ff2bf11](https://github.com/n8n-io/n8n/commit/ff2bf1112f07b7c3fd75f60e8faefdef4e2a02af))
|
||||
|
||||
|
||||
- **Pipedrive Node:** Add support for filters to getAll:organization ([#3211](https://github.com/n8n-io/n8n/issues/3211)) ([1ef10dd](https://github.com/n8n-io/n8n/commit/1ef10dd23fef0b2e3e0ef76c8116d3bebc36bc4e))
|
||||
- **Pushover Node:** Add 'HTML Formatting' option and credential test ([#3082](https://github.com/n8n-io/n8n/issues/3082)) ([b3dc6d9](https://github.com/n8n-io/n8n/commit/b3dc6d9d9c640f1e0f04cb56d0fabe2aafb948b6))
|
||||
- **UProc Node:** Add new tools ([#3104](https://github.com/n8n-io/n8n/issues/3104)) ([ff2bf11](https://github.com/n8n-io/n8n/commit/ff2bf1112f07b7c3fd75f60e8faefdef4e2a02af))
|
||||
|
||||
## [0.175.1](https://github.com/n8n-io/n8n/compare/n8n@0.175.0...n8n@0.175.1) (2022-05-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **editor:** Fix bug with node version ([ed56481](https://github.com/n8n-io/n8n/commit/ed564812435a279760a32e76f3935f492f84f487))
|
||||
|
||||
|
||||
- **editor:** Fix bug with node version ([ed56481](https://github.com/n8n-io/n8n/commit/ed564812435a279760a32e76f3935f492f84f487))
|
||||
|
||||
# [0.175.0](https://github.com/n8n-io/n8n/compare/n8n@0.174.0...n8n@0.175.0) (2022-05-02)
|
||||
|
||||
|
|
|
|||
|
|
@ -14,22 +14,22 @@ appearance, race, religion, or sexual identity and orientation.
|
|||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
- Using welcoming and inclusive language
|
||||
- Being respectful of differing viewpoints and experiences
|
||||
- Gracefully accepting constructive criticism
|
||||
- Focusing on what is best for the community
|
||||
- Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
- The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
- Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
|
|
|
|||
117
CONTRIBUTING.md
117
CONTRIBUTING.md
|
|
@ -27,20 +27,20 @@ n8n is split up in different modules which are all in a single mono repository.
|
|||
|
||||
The most important directories:
|
||||
|
||||
- [/docker/image](/docker/images) - Dockerfiles to create n8n containers
|
||||
- [/docker/compose](/docker/compose) - Examples Docker Setups
|
||||
- [/packages](/packages) - The different n8n modules
|
||||
- [/packages/cli](/packages/cli) - CLI code to run front- & backend
|
||||
- [/packages/core](/packages/core) - Core code which handles workflow
|
||||
execution, active webhooks and
|
||||
workflows. **Contact n8n before
|
||||
starting on any changes here**
|
||||
- [/packages/design-system](/packages/design-system) - Vue frontend components
|
||||
- [/packages/editor-ui](/packages/editor-ui) - Vue frontend workflow editor
|
||||
- [/packages/node-dev](/packages/node-dev) - CLI to create new n8n-nodes
|
||||
- [/packages/nodes-base](/packages/nodes-base) - Base n8n nodes
|
||||
- [/packages/workflow](/packages/workflow) - Workflow code with interfaces which
|
||||
get used by front- & backend
|
||||
- [/docker/image](/docker/images) - Dockerfiles to create n8n containers
|
||||
- [/docker/compose](/docker/compose) - Examples Docker Setups
|
||||
- [/packages](/packages) - The different n8n modules
|
||||
- [/packages/cli](/packages/cli) - CLI code to run front- & backend
|
||||
- [/packages/core](/packages/core) - Core code which handles workflow
|
||||
execution, active webhooks and
|
||||
workflows. **Contact n8n before
|
||||
starting on any changes here**
|
||||
- [/packages/design-system](/packages/design-system) - Vue frontend components
|
||||
- [/packages/editor-ui](/packages/editor-ui) - Vue frontend workflow editor
|
||||
- [/packages/node-dev](/packages/node-dev) - CLI to create new n8n-nodes
|
||||
- [/packages/nodes-base](/packages/nodes-base) - Base n8n nodes
|
||||
- [/packages/workflow](/packages/workflow) - Workflow code with interfaces which
|
||||
get used by front- & backend
|
||||
|
||||
## Development setup
|
||||
|
||||
|
|
@ -51,40 +51,37 @@ dependencies are installed and the packages get linked correctly. Here a short g
|
|||
|
||||
#### Node.js
|
||||
|
||||
We suggest using the current [Node.js](https://nodejs.org/en/) LTS version (14.18.0 which includes npm 6.14.15) for development purposes.
|
||||
We suggest using [Node.js](https://nodejs.org/en/) version 16 for development purposes.
|
||||
|
||||
#### Build tools
|
||||
|
||||
The packages which n8n uses depend on a few build tools:
|
||||
|
||||
Debian/Ubuntu:
|
||||
|
||||
```
|
||||
apt-get install -y build-essential python
|
||||
```
|
||||
|
||||
CentOS:
|
||||
|
||||
```
|
||||
yum install gcc gcc-c++ make
|
||||
```
|
||||
|
||||
Windows:
|
||||
|
||||
```
|
||||
npm install -g windows-build-tools
|
||||
```
|
||||
|
||||
#### lerna
|
||||
#### npm workspaces
|
||||
|
||||
n8n is split up in different modules which are all in a single mono repository.
|
||||
To facilitate those modules management, [lerna](https://lerna.js.org) gets
|
||||
used. It automatically sets up file-links between modules which depend on each
|
||||
To facilitate the module management, [npm workspaces](https://docs.npmjs.com/cli/v7/using-npm/workspaces) are
|
||||
used. This automatically sets up file-links between modules which depend on each
|
||||
other.
|
||||
|
||||
So for the setup to work correctly lerna has to be installed globally like this:
|
||||
|
||||
```
|
||||
npm install -g lerna
|
||||
```
|
||||
|
||||
### Actual n8n setup
|
||||
|
||||
> **IMPORTANT**: All the steps below have to get executed at least once to get the development setup up and running!
|
||||
|
|
@ -94,30 +91,34 @@ checked out and set up:
|
|||
|
||||
1. [Fork](https://guides.github.com/activities/forking/#fork) the n8n repository
|
||||
|
||||
1. Clone your forked repository
|
||||
```
|
||||
git clone https://github.com/<your_github_username>/n8n.git
|
||||
```
|
||||
2. Clone your forked repository
|
||||
|
||||
1. Add the original n8n repository as `upstream` to your forked repository
|
||||
```
|
||||
git remote add upstream https://github.com/n8n-io/n8n.git
|
||||
```
|
||||
```
|
||||
git clone https://github.com/<your_github_username>/n8n.git
|
||||
```
|
||||
|
||||
1. Go into repository folder
|
||||
```
|
||||
cd n8n
|
||||
```
|
||||
3. Go into repository folder
|
||||
|
||||
1. Install all dependencies of all modules and link them together:
|
||||
```
|
||||
lerna bootstrap --hoist
|
||||
```
|
||||
```
|
||||
cd n8n
|
||||
```
|
||||
|
||||
1. Build all the code:
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
4. Add the original n8n repository as `upstream` to your forked repository
|
||||
|
||||
```
|
||||
git remote add upstream https://github.com/n8n-io/n8n.git
|
||||
```
|
||||
|
||||
5. Install all dependencies of all modules and link them together:
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
6. Build all the code:
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Start
|
||||
|
||||
|
|
@ -128,6 +129,7 @@ npm run start
|
|||
```
|
||||
|
||||
To start n8n with tunnel:
|
||||
|
||||
```
|
||||
./packages/cli/bin/n8n start --tunnel
|
||||
```
|
||||
|
|
@ -139,25 +141,26 @@ automatically build your code, restart the backend and refresh the frontend
|
|||
(editor-ui) on every change you make.
|
||||
|
||||
1. Start n8n in development mode:
|
||||
```
|
||||
npm run dev
|
||||
```
|
||||
```
|
||||
npm run dev
|
||||
```
|
||||
1. Hack, hack, hack
|
||||
1. Check if everything still runs in production mode
|
||||
```
|
||||
npm run build
|
||||
npm run start
|
||||
```
|
||||
```
|
||||
npm run build
|
||||
npm run start
|
||||
```
|
||||
1. Create tests
|
||||
1. Run all [tests](#test-suite)
|
||||
```
|
||||
npm run test
|
||||
```
|
||||
```
|
||||
npm run test
|
||||
```
|
||||
1. Commit code and [create a pull request](https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork)
|
||||
|
||||
### Test suite
|
||||
|
||||
The tests can be started via:
|
||||
|
||||
```
|
||||
npm run test
|
||||
```
|
||||
|
|
@ -170,17 +173,17 @@ tests of all packages.
|
|||
|
||||
> **IMPORTANT**: Avoid use of external libraries to ensure your custom nodes can be reviewed and merged quickly.
|
||||
|
||||
Learn about [using the node dev CLI](https://docs.n8n.io/nodes/creating-nodes/node-dev-cli.html) to create custom nodes for n8n.
|
||||
Learn about [using the node dev CLI](https://docs.n8n.io/integrations/creating-nodes/archive/node-developer-cli/) to create custom nodes for n8n.
|
||||
|
||||
More information can be found in the documentation of [n8n-node-dev](https://github.com/n8n-io/n8n/tree/master/packages/node-dev), a small CLI which helps with n8n-node-development.
|
||||
|
||||
## Create a new node to contribute to n8n
|
||||
|
||||
Follow this tutorial on [creating your first node](https://docs.n8n.io/nodes/creating-nodes/create-node.html) for n8n.
|
||||
Follow this tutorial on [creating your first node](https://docs.n8n.io/integrations/creating-nodes/build/) for n8n.
|
||||
|
||||
## Checklist before submitting a new node
|
||||
|
||||
There are several things to keep in mind when creating a node. To help you, we prepared a [checklist](https://docs.n8n.io/nodes/creating-nodes/node-review-checklist.html) that covers the requirements for creating nodes, from preparation to submission. This will help us be quicker to review and merge your PR.
|
||||
There are several things to keep in mind when creating a node. To help you, we prepared a [checklist](https://docs.n8n.io/integrations/creating-nodes/build/reference/) that covers the requirements for creating nodes, from preparation to submission. This will help us be quicker to review and merge your PR.
|
||||
|
||||
## Extend documentation
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# n8n Contributor License Agreement
|
||||
|
||||
I give n8n permission to license my contributions on any terms they like. I am giving them this license in order to make it possible for them to accept my contributions into their project.
|
||||
I give n8n permission to license my contributions on any terms they like. I am giving them this license in order to make it possible for them to accept my contributions into their project.
|
||||
|
||||
***As far as the law allows, my contributions come as is, without any warranty or condition, and I will not be liable to anyone for any damages related to this software or this license, under any kind of legal claim.***
|
||||
**_As far as the law allows, my contributions come as is, without any warranty or condition, and I will not be liable to anyone for any damages related to this software or this license, under any kind of legal claim._**
|
||||
|
|
|
|||
69
LICENSE.md
69
LICENSE.md
|
|
@ -1,43 +1,69 @@
|
|||
# Sustainable Use License
|
||||
# License
|
||||
|
||||
Portions of this software are licensed as follows:
|
||||
|
||||
- All source code files of this repository that contain ".ee." in their filename are licensed under the n8n Enterprise License defined in "LICENSE_EE.md".
|
||||
- All third party components incorporated into the n8n Software are licensed under the original license
|
||||
provided by the owner of the applicable component.
|
||||
- Content outside of the above mentioned files or restrictions above is available under the "Sustainable Use
|
||||
License" as defined below.
|
||||
|
||||
## Sustainable Use License
|
||||
|
||||
Version 1.0
|
||||
|
||||
## Acceptance
|
||||
### Acceptance
|
||||
|
||||
By using the software, you agree to all of the terms and conditions below.
|
||||
|
||||
## Copyright License
|
||||
### Copyright License
|
||||
|
||||
The licensor grants you a non-exclusive, royalty-free, worldwide, non-sublicensable, non-transferable license to use, copy, distribute, make available, and prepare derivative works of the software, in each case subject to the limitations below.
|
||||
The licensor grants you a non-exclusive, royalty-free, worldwide, non-sublicensable, non-transferable license
|
||||
to use, copy, distribute, make available, and prepare derivative works of the software, in each case subject
|
||||
to the limitations below.
|
||||
|
||||
## Limitations
|
||||
### Limitations
|
||||
|
||||
You may use or modify the software only for your own internal business purposes or for non-commercial or personal use.
|
||||
You may distribute the software or provide it to others only if you do so free of charge for non-commercial purposes.
|
||||
You may not alter, remove, or obscure any licensing, copyright, or other notices of the licensor in the software. Any use of the licensor’s trademarks is subject to applicable law.
|
||||
You may use or modify the software only for your own internal business purposes or for non-commercial or
|
||||
personal use. You may distribute the software or provide it to others only if you do so free of charge for
|
||||
non-commercial purposes. You may not alter, remove, or obscure any licensing, copyright, or other notices of
|
||||
the licensor in the software. Any use of the licensor’s trademarks is subject to applicable law.
|
||||
|
||||
## Patents
|
||||
### Patents
|
||||
|
||||
The licensor grants you a license, under any patent claims the licensor can license, or becomes able to license, to make, have made, use, sell, offer for sale, import and have imported the software, in each case subject to the limitations and conditions in this license. This license does not cover any patent claims that you cause to be infringed by modifications or additions to the software. If you or your company make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
|
||||
The licensor grants you a license, under any patent claims the licensor can license, or becomes able to
|
||||
license, to make, have made, use, sell, offer for sale, import and have imported the software, in each case
|
||||
subject to the limitations and conditions in this license. This license does not cover any patent claims that
|
||||
you cause to be infringed by modifications or additions to the software. If you or your company make any
|
||||
written claim that the software infringes or contributes to infringement of any patent, your patent license
|
||||
for the software granted under these terms ends immediately. If your company makes such a claim, your patent
|
||||
license ends immediately for work on behalf of your company.
|
||||
|
||||
## Notices
|
||||
### Notices
|
||||
|
||||
You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms.
|
||||
If you modify the software, you must include in any modified copies of the software a prominent notice stating that you have modified the software.
|
||||
You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these
|
||||
terms. If you modify the software, you must include in any modified copies of the software a prominent notice
|
||||
stating that you have modified the software.
|
||||
|
||||
## No Other Rights
|
||||
### No Other Rights
|
||||
|
||||
These terms do not imply any licenses other than those expressly granted in these terms.
|
||||
|
||||
## Termination
|
||||
### Termination
|
||||
|
||||
If you use the software in violation of these terms, such use is not licensed, and your license will automatically terminate. If the licensor provides you with a notice of your violation, and you cease all violation of this license no later than 30 days after you receive that notice, your license will be reinstated retroactively. However, if you violate these terms after such reinstatement, any additional violation of these terms will cause your license to terminate automatically and permanently.
|
||||
If you use the software in violation of these terms, such use is not licensed, and your license will
|
||||
automatically terminate. If the licensor provides you with a notice of your violation, and you cease all
|
||||
violation of this license no later than 30 days after you receive that notice, your license will be reinstated
|
||||
retroactively. However, if you violate these terms after such reinstatement, any additional violation of these
|
||||
terms will cause your license to terminate automatically and permanently.
|
||||
|
||||
## No Liability
|
||||
### No Liability
|
||||
|
||||
As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.
|
||||
As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will
|
||||
not be liable to you for any damages arising out of these terms or the use or nature of the software, under
|
||||
any kind of legal claim.
|
||||
|
||||
## Definitions
|
||||
### Definitions
|
||||
|
||||
The “licensor” is the entity offering these terms.
|
||||
|
||||
|
|
@ -45,7 +71,10 @@ The “software” is the software the licensor makes available under these term
|
|||
|
||||
“You” refers to the individual or entity agreeing to these terms.
|
||||
|
||||
“Your company” is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. Control means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
|
||||
“Your company” is any legal entity, sole proprietorship, or other kind of organization that you work for, plus
|
||||
all organizations that have control over, are under the control of, or are under common control with that
|
||||
organization. Control means ownership of substantially all the assets of an entity, or the power to direct its
|
||||
management and policies by vote, contract, or otherwise. Control can be direct or indirect.
|
||||
|
||||
“Your license” is the license granted to you for the software under these terms.
|
||||
|
||||
|
|
|
|||
27
LICENSE_EE.md
Normal file
27
LICENSE_EE.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# The n8n Enterprise License (the “Enterprise License”)
|
||||
|
||||
Copyright (c) 2022-present n8n GmbH.
|
||||
|
||||
With regard to the n8n Software:
|
||||
|
||||
This software and associated documentation files (the "Software") may only be used in production, if
|
||||
you (and any entity that you represent) hold a valid n8n Enterprise license corresponding to your
|
||||
usage. Subject to the foregoing sentence, you are free to modify this Software and publish patches
|
||||
to the Software. You agree that n8n and/or its licensors (as applicable) retain all right, title and
|
||||
interest in and to all such modifications and/or patches, and all such modifications and/or patches
|
||||
may only be used, copied, modified, displayed, distributed, or otherwise exploited with a valid n8n
|
||||
Enterprise license for the corresponding usage. Notwithstanding the foregoing, you may copy and
|
||||
modify the Software for development and testing purposes, without requiring a subscription. You
|
||||
agree that n8n and/or its licensors (as applicable) retain all right, title and interest in and to
|
||||
all such modifications. You are not granted any other rights beyond what is expressly stated herein.
|
||||
Subject to the foregoing, it is forbidden to copy, merge, publish, distribute, sublicense, and/or
|
||||
sell the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For all third party components incorporated into the n8n Software, those components are licensed
|
||||
under the original license provided by the owner of the applicable component.
|
||||
55
README.md
55
README.md
|
|
@ -2,17 +2,22 @@
|
|||
|
||||
# n8n - Workflow automation tool
|
||||
|
||||
n8n is an extendable workflow automation tool. With a [fair-code](http://faircode.io) distribution model, n8n will always have visible source code, be available to self-host, and allow you to add your own custom functions, logic and apps. n8n's node-based approach makes it highly versatile, enabling you to connect anything to everything.
|
||||
n8n is an extendable workflow automation tool. With a [fair-code](http://faircode.io) distribution model, n8n
|
||||
will always have visible source code, be available to self-host, and allow you to add your own custom
|
||||
functions, logic and apps. n8n's node-based approach makes it highly versatile, enabling you to connect
|
||||
anything to everything.
|
||||
|
||||
<a href="https://raw.githubusercontent.com/n8n-io/n8n/master/assets/n8n-screenshot.png"><img src="https://raw.githubusercontent.com/n8n-io/n8n/master/assets/n8n-screenshot.png" alt="n8n.io - Screenshot"></a>
|
||||

|
||||
|
||||
## Demo
|
||||
|
||||
[:tv: A short video (< 4 min)](https://www.youtube.com/watch?v=RpjQTGKm-ok) that goes over key concepts of creating workflows in n8n.
|
||||
[:tv: A short video (< 4 min)](https://www.youtube.com/watch?v=RpjQTGKm-ok) that goes over key concepts of
|
||||
creating workflows in n8n.
|
||||
|
||||
## Available integrations
|
||||
|
||||
n8n has 200+ different nodes to automate workflows. The list can be found on: [https://n8n.io/integrations](https://n8n.io/integrations)
|
||||
n8n has 200+ different nodes to automate workflows. The list can be found on:
|
||||
[https://n8n.io/integrations](https://n8n.io/integrations)
|
||||
|
||||
## Documentation
|
||||
|
||||
|
|
@ -20,16 +25,19 @@ The official n8n documentation can be found under: [https://docs.n8n.io](https:/
|
|||
|
||||
Additional information and example workflows on the n8n.io website: [https://n8n.io](https://n8n.io)
|
||||
|
||||
The changelog can be found [here](https://docs.n8n.io/reference/changelog.html) and the list of breaking changes [here](https://github.com/n8n-io/n8n/blob/master/packages/cli/BREAKING-CHANGES.md).
|
||||
The changelog can be found [here](https://docs.n8n.io/reference/changelog.html) and the list of breaking
|
||||
changes [here](https://github.com/n8n-io/n8n/blob/master/packages/cli/BREAKING-CHANGES.md).
|
||||
|
||||
## Usage
|
||||
|
||||
- :books: Learn [how to **install** and **use** it from the command line](https://github.com/n8n-io/n8n/tree/master/packages/cli/README.md)
|
||||
- :whale: Learn [how to run n8n in **Docker**](https://github.com/n8n-io/n8n/tree/master/docker/images/n8n/README.md)
|
||||
- :books: Learn
|
||||
[how to **install** and **use** it from the command line](https://github.com/n8n-io/n8n/tree/master/packages/cli/README.md)
|
||||
- :whale: Learn
|
||||
[how to run n8n in **Docker**](https://github.com/n8n-io/n8n/tree/master/docker/images/n8n/README.md)
|
||||
|
||||
## Start
|
||||
|
||||
Execute: `npm run start`
|
||||
Execute: `npx n8n`
|
||||
|
||||
## n8n cloud
|
||||
|
||||
|
|
@ -49,29 +57,32 @@ If you have problems or questions go to our forum, we will then try to help you
|
|||
|
||||
## Jobs
|
||||
|
||||
If you are interested in working for n8n and so shape the future of the project
|
||||
check out our [job posts](https://apply.workable.com/n8n/)
|
||||
If you are interested in working for n8n and so shape the future of the project check out our
|
||||
[job posts](https://apply.workable.com/n8n/)
|
||||
|
||||
## What does n8n mean and how do you pronounce it?
|
||||
|
||||
**Short answer:** It means "nodemation" and it is pronounced as n-eight-n.
|
||||
|
||||
**Long answer:** "I get that question quite often (more often than I expected)
|
||||
so I decided it is probably best to answer it here. While looking for a
|
||||
good name for the project with a free domain I realized very quickly that all the
|
||||
good ones I could think of were already taken. So, in the end, I chose
|
||||
nodemation. 'node-' in the sense that it uses a Node-View and that it uses
|
||||
Node.js and '-mation' for 'automation' which is what the project is supposed to help with.
|
||||
However, I did not like how long the name was and I could not imagine writing
|
||||
something that long every time in the CLI. That is when I then ended up on
|
||||
'n8n'." - **Jan Oberhauser, Founder and CEO, n8n.io**
|
||||
**Long answer:** "I get that question quite often (more often than I expected) so I decided it is probably
|
||||
best to answer it here. While looking for a good name for the project with a free domain I realized very
|
||||
quickly that all the good ones I could think of were already taken. So, in the end, I chose nodemation.
|
||||
'node-' in the sense that it uses a Node-View and that it uses Node.js and '-mation' for 'automation' which is
|
||||
what the project is supposed to help with. However, I did not like how long the name was and I could not
|
||||
imagine writing something that long every time in the CLI. That is when I then ended up on 'n8n'." - **Jan
|
||||
Oberhauser, Founder and CEO, n8n.io**
|
||||
|
||||
## Development setup
|
||||
|
||||
Have you found a bug :bug: ? Or maybe you have a nice feature :sparkles: to contribute ? The [CONTRIBUTING guide](https://github.com/n8n-io/n8n/blob/master/CONTRIBUTING.md) will help you get your development environment ready in minutes.
|
||||
Have you found a bug :bug: ? Or maybe you have a nice feature :sparkles: to contribute ? The
|
||||
[CONTRIBUTING guide](https://github.com/n8n-io/n8n/blob/master/CONTRIBUTING.md) will help you get your
|
||||
development environment ready in minutes.
|
||||
|
||||
## License
|
||||
|
||||
n8n is [fair-code](http://faircode.io) distributed under the [**Sustainable Use License**](https://github.com/n8n-io/n8n/blob/master/packages/cli/LICENSE.md).
|
||||
n8n is [fair-code](http://faircode.io) distributed under the
|
||||
[**Sustainable Use License**](https://github.com/n8n-io/n8n/blob/master/packages/cli/LICENSE.md) and the
|
||||
[**n8n Enterprise License**](https://github.com/n8n-io/n8n/blob/master/packages/cli/LICENSE_EE.md).
|
||||
|
||||
Additional information about license can be found in the [FAQ](https://docs.n8n.io/#/faq?id=license).
|
||||
Additional information about the license model can be found in the
|
||||
[docs](https://docs.n8n.io/reference/license/).
|
||||
|
|
|
|||
|
|
@ -1,14 +1,12 @@
|
|||
# n8n on Subfolder with SSL
|
||||
|
||||
Starts n8n and deployes it on a subfolder
|
||||
|
||||
Starts n8n and deploys it on a subfolder
|
||||
|
||||
## Start
|
||||
|
||||
To start n8n in a subfolder simply start docker-compose by executing the following
|
||||
command in the current folder.
|
||||
|
||||
|
||||
**IMPORTANT:** But before you do that change the default users and passwords in the `.env` file!
|
||||
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1,36 +1,36 @@
|
|||
version: "3"
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
traefik:
|
||||
image: "traefik"
|
||||
image: 'traefik'
|
||||
command:
|
||||
- "--api=true"
|
||||
- "--api.insecure=true"
|
||||
- "--api.dashboard=true"
|
||||
- "--providers.docker=true"
|
||||
- "--providers.docker.exposedbydefault=false"
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
- "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
|
||||
- "--certificatesresolvers.mytlschallenge.acme.email=${SSL_EMAIL}"
|
||||
- "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
|
||||
- '--api=true'
|
||||
- '--api.insecure=true'
|
||||
- '--api.dashboard=true'
|
||||
- '--providers.docker=true'
|
||||
- '--providers.docker.exposedbydefault=false'
|
||||
- '--entrypoints.websecure.address=:443'
|
||||
- '--certificatesresolvers.mytlschallenge.acme.tlschallenge=true'
|
||||
- '--certificatesresolvers.mytlschallenge.acme.email=${SSL_EMAIL}'
|
||||
- '--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json'
|
||||
ports:
|
||||
- "443:443"
|
||||
- "80:80"
|
||||
- '443:443'
|
||||
- '80:80'
|
||||
volumes:
|
||||
- ${DATA_FOLDER}/letsencrypt:/letsencrypt
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
n8n:
|
||||
image: n8nio/n8n
|
||||
ports:
|
||||
- "127.0.0.1:5678:5678"
|
||||
- '127.0.0.1:5678:5678'
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.n8n.rule=Host(`${DOMAIN_NAME}`)
|
||||
- traefik.http.routers.n8n.tls=true
|
||||
- traefik.http.routers.n8n.entrypoints=websecure
|
||||
- "traefik.http.routers.n8n.rule=PathPrefix(`/${SUBFOLDER}{regex:$$|/.*}`)"
|
||||
- "traefik.http.middlewares.n8n-stripprefix.stripprefix.prefixes=/${SUBFOLDER}"
|
||||
- "traefik.http.routers.n8n.middlewares=n8n-stripprefix"
|
||||
- 'traefik.http.routers.n8n.rule=PathPrefix(`/${SUBFOLDER}{regex:$$|/.*}`)'
|
||||
- 'traefik.http.middlewares.n8n-stripprefix.stripprefix.prefixes=/${SUBFOLDER}'
|
||||
- 'traefik.http.routers.n8n.middlewares=n8n-stripprefix'
|
||||
- traefik.http.routers.n8n.tls.certresolver=mytlschallenge
|
||||
- traefik.http.middlewares.n8n.headers.SSLRedirect=true
|
||||
- traefik.http.middlewares.n8n.headers.STSSeconds=315360000
|
||||
|
|
|
|||
8
docker/compose/withMariaDB/.env
Normal file
8
docker/compose/withMariaDB/.env
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
MARIADB_ROOT_PASSWORD=changePassword
|
||||
|
||||
MARIADB_DATABASE=n8n
|
||||
MARIADB_USER=changeUser
|
||||
MARIADB_PASSWORD=changePassword
|
||||
|
||||
N8N_BASIC_AUTH_USER=changeUser
|
||||
N8N_BASIC_AUTH_PASSWORD=changePassword
|
||||
24
docker/compose/withMariaDB/README.md
Normal file
24
docker/compose/withMariaDB/README.md
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# n8n with MariaDB
|
||||
|
||||
Starts n8n with MariaDB as database.
|
||||
|
||||
## Start
|
||||
|
||||
To start n8n with MariaDB simply start docker-compose by executing the following
|
||||
command in the current folder.
|
||||
|
||||
**IMPORTANT:** But before you do that change the default users and passwords in the [`.env`](.env) file!
|
||||
|
||||
```
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
To stop it execute:
|
||||
|
||||
```
|
||||
docker-compose stop
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
The default name of the database, user and password for MariaDB can be changed in the [`.env`](.env) file in the current directory.
|
||||
43
docker/compose/withMariaDB/docker-compose.yml
Normal file
43
docker/compose/withMariaDB/docker-compose.yml
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
version: '3.8'
|
||||
|
||||
volumes:
|
||||
db_storage:
|
||||
n8n_storage:
|
||||
|
||||
services:
|
||||
db:
|
||||
image: mariadb:10.7
|
||||
restart: always
|
||||
environment:
|
||||
- MARIADB_ROOT_PASSWORD
|
||||
- MARIADB_DATABASE
|
||||
- MARIADB_USER
|
||||
- MARIADB_PASSWORD
|
||||
- MARIADB_MYSQL_LOCALHOST_USER=true
|
||||
volumes:
|
||||
- db_storage:/var/lib/mysql
|
||||
healthcheck:
|
||||
test: "/usr/bin/mysql --user=${MARIADB_USER} --password=${MARIADB_PASSWORD} --execute 'SELECT 1;'"
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
n8n:
|
||||
image: n8nio/n8n
|
||||
restart: always
|
||||
environment:
|
||||
- DB_TYPE=mariadb
|
||||
- DB_MYSQLDB_HOST=db
|
||||
- DB_MYSQLDB_DATABASE=${MARIADB_DATABASE}
|
||||
- DB_MYSQLDB_USER=${MARIADB_USER}
|
||||
- DB_MYSQLDB_PASSWORD=${MARIADB_PASSWORD}
|
||||
ports:
|
||||
- 5678:5678
|
||||
links:
|
||||
- db
|
||||
volumes:
|
||||
- n8n_storage:/home/node/
|
||||
command: n8n start --tunnel
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
|
|
@ -2,13 +2,11 @@
|
|||
|
||||
Starts n8n with PostgreSQL as database.
|
||||
|
||||
|
||||
## Start
|
||||
|
||||
To start n8n with PostgreSQL simply start docker-compose by executing the following
|
||||
command in the current folder.
|
||||
|
||||
|
||||
**IMPORTANT:** But before you do that change the default users and passwords in the [`.env`](.env) file!
|
||||
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
version: '3.1'
|
||||
version: '3.8'
|
||||
|
||||
volumes:
|
||||
db_storage:
|
||||
n8n_storage:
|
||||
|
||||
services:
|
||||
|
||||
postgres:
|
||||
image: postgres:11
|
||||
restart: always
|
||||
|
|
@ -12,7 +15,13 @@ services:
|
|||
- POSTGRES_NON_ROOT_USER
|
||||
- POSTGRES_NON_ROOT_PASSWORD
|
||||
volumes:
|
||||
- db_storage:/var/lib/postgresql/data
|
||||
- ./init-data.sh:/docker-entrypoint-initdb.d/init-data.sh
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
n8n:
|
||||
image: n8nio/n8n
|
||||
|
|
@ -32,7 +41,8 @@ services:
|
|||
links:
|
||||
- postgres
|
||||
volumes:
|
||||
- ~/.n8n:/home/node/.n8n
|
||||
# Wait 5 seconds to start n8n to make sure that PostgreSQL is ready
|
||||
# when n8n tries to connect to it
|
||||
command: /bin/sh -c "sleep 5; n8n start"
|
||||
- n8n_storage:/home/node/
|
||||
command: /bin/sh -c "n8n start --tunnel"
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
|
|
|
|||
9
docker/compose/withPostgresAndWorker/.env
Normal file
9
docker/compose/withPostgresAndWorker/.env
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
POSTGRES_USER=changeUser
|
||||
POSTGRES_PASSWORD=changePassword
|
||||
POSTGRES_DB=n8n
|
||||
|
||||
POSTGRES_NON_ROOT_USER=changeUser
|
||||
POSTGRES_NON_ROOT_PASSWORD=changePassword
|
||||
|
||||
N8N_BASIC_AUTH_USER=changeUser
|
||||
N8N_BASIC_AUTH_PASSWORD=changePassword
|
||||
26
docker/compose/withPostgresAndWorker/README.md
Normal file
26
docker/compose/withPostgresAndWorker/README.md
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# n8n with PostgreSQL and Worker
|
||||
|
||||
Starts n8n with PostgreSQL as database, and the Worker as a separate container.
|
||||
|
||||
|
||||
## Start
|
||||
|
||||
To start n8n simply start docker-compose by executing the following
|
||||
command in the current folder.
|
||||
|
||||
|
||||
**IMPORTANT:** But before you do that change the default users and passwords in the [`.env`](.env) file!
|
||||
|
||||
```
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
To stop it execute:
|
||||
|
||||
```
|
||||
docker-compose stop
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
The default name of the database, user and password for PostgreSQL can be changed in the [`.env`](.env) file in the current directory.
|
||||
77
docker/compose/withPostgresAndWorker/docker-compose.yml
Normal file
77
docker/compose/withPostgresAndWorker/docker-compose.yml
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
version: '3.8'
|
||||
|
||||
volumes:
|
||||
db_storage:
|
||||
n8n_storage:
|
||||
redis_storage:
|
||||
|
||||
x-shared: &shared
|
||||
restart: always
|
||||
environment:
|
||||
- DB_TYPE=postgresdb
|
||||
- DB_POSTGRESDB_HOST=postgres
|
||||
- DB_POSTGRESDB_PORT=5432
|
||||
- DB_POSTGRESDB_DATABASE=${POSTGRES_DB}
|
||||
- DB_POSTGRESDB_USER=${POSTGRES_NON_ROOT_USER}
|
||||
- DB_POSTGRESDB_PASSWORD=${POSTGRES_NON_ROOT_PASSWORD}
|
||||
- EXECUTIONS_MODE=queue
|
||||
- QUEUE_BULL_REDIS_HOST=redis
|
||||
- QUEUE_HEALTH_CHECK_ACTIVE=true
|
||||
- N8N_BASIC_AUTH_ACTIVE=true
|
||||
- N8N_BASIC_AUTH_USER
|
||||
- N8N_BASIC_AUTH_PASSWORD
|
||||
links:
|
||||
- postgres
|
||||
- redis
|
||||
volumes:
|
||||
- n8n_storage:/home/node/
|
||||
depends_on:
|
||||
redis:
|
||||
condition: service_healthy
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:11
|
||||
restart: always
|
||||
environment:
|
||||
- POSTGRES_USER
|
||||
- POSTGRES_PASSWORD
|
||||
- POSTGRES_DB
|
||||
- POSTGRES_NON_ROOT_USER
|
||||
- POSTGRES_NON_ROOT_PASSWORD
|
||||
volumes:
|
||||
- db_storage:/var/lib/postgresql/data
|
||||
- ./init-data.sh:/docker-entrypoint-initdb.d/init-data.sh
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
redis:
|
||||
image: redis:6-alpine
|
||||
restart: always
|
||||
volumes:
|
||||
- redis_storage:/data
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
n8n:
|
||||
<<: *shared
|
||||
image: n8nio/n8n
|
||||
command: /bin/sh -c "n8n start --tunnel"
|
||||
ports:
|
||||
- 5678:5678
|
||||
|
||||
n8n-worker:
|
||||
<<: *shared
|
||||
image: n8nio/n8n
|
||||
command: /bin/sh -c "sleep 5; n8n worker"
|
||||
depends_on:
|
||||
- n8n
|
||||
12
docker/compose/withPostgresAndWorker/init-data.sh
Executable file
12
docker/compose/withPostgresAndWorker/init-data.sh
Executable file
|
|
@ -0,0 +1,12 @@
|
|||
#!/bin/bash
|
||||
set -e;
|
||||
|
||||
|
||||
if [ -n "${POSTGRES_NON_ROOT_USER:-}" ] && [ -n "${POSTGRES_NON_ROOT_PASSWORD:-}" ]; then
|
||||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
||||
CREATE USER ${POSTGRES_NON_ROOT_USER} WITH PASSWORD '${POSTGRES_NON_ROOT_PASSWORD}';
|
||||
GRANT ALL PRIVILEGES ON DATABASE ${POSTGRES_DB} TO ${POSTGRES_NON_ROOT_USER};
|
||||
EOSQL
|
||||
else
|
||||
echo "SETUP INFO: No Environment variables given!"
|
||||
fi
|
||||
4
docker/images/n8n-base/.npmrc
Normal file
4
docker/images/n8n-base/.npmrc
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
audit = false
|
||||
fund = false
|
||||
loglevel = warn
|
||||
update-notifier = false
|
||||
20
docker/images/n8n-base/Dockerfile
Normal file
20
docker/images/n8n-base/Dockerfile
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
ARG NODE_VERSION=16
|
||||
FROM node:${NODE_VERSION}-alpine
|
||||
|
||||
WORKDIR /home/node
|
||||
COPY .npmrc /usr/local/etc/npmrc
|
||||
|
||||
RUN \
|
||||
apk add --update git graphicsmagick tini tzdata ca-certificates && \
|
||||
npm install -g npm@latest full-icu && \
|
||||
rm -rf /var/cache/apk/* /root/.npm /tmp/* && \
|
||||
# Install fonts
|
||||
apk --no-cache add --virtual fonts msttcorefonts-installer fontconfig && \
|
||||
update-ms-fonts && \
|
||||
fc-cache -f && \
|
||||
apk del fonts && \
|
||||
find /usr/share/fonts/truetype/msttcorefonts/ -type l -exec unlink {} \; && \
|
||||
rm -rf /var/cache/apk/* /tmp/*
|
||||
|
||||
ENV NODE_ICU_DATA /usr/local/lib/node_modules/full-icu
|
||||
EXPOSE 5678/tcp
|
||||
|
|
@ -1,55 +1,37 @@
|
|||
ARG NODE_VERSION=16
|
||||
|
||||
# 1. Create an image to build n8n
|
||||
FROM node:16-alpine as builder
|
||||
FROM n8nio/base:${NODE_VERSION} as builder
|
||||
|
||||
# Update everything and install needed dependencies
|
||||
USER root
|
||||
RUN npm install -g run-script-os turbo@1.5.5
|
||||
|
||||
# Install all needed dependencies
|
||||
RUN apk --update add --virtual build-dependencies python3 build-base ca-certificates && \
|
||||
npm_config_user=root npm install -g lerna run-script-os
|
||||
|
||||
WORKDIR /data
|
||||
|
||||
COPY lerna.json .
|
||||
COPY package.json .
|
||||
COPY packages/cli/ ./packages/cli/
|
||||
COPY packages/core/ ./packages/core/
|
||||
COPY packages/design-system/ ./packages/design-system/
|
||||
COPY packages/editor-ui/ ./packages/editor-ui/
|
||||
COPY packages/nodes-base/ ./packages/nodes-base/
|
||||
COPY packages/workflow/ ./packages/workflow/
|
||||
RUN rm -rf node_modules packages/*/node_modules packages/*/dist
|
||||
COPY turbo.json package.json package-lock.json tsconfig.json ./
|
||||
COPY packages ./packages
|
||||
COPY patches ./patches
|
||||
|
||||
RUN chown -R node:node .
|
||||
RUN npm config set legacy-peer-deps true
|
||||
RUN npm install --production --loglevel notice
|
||||
RUN lerna bootstrap --hoist -- --production
|
||||
RUN npm run build
|
||||
|
||||
USER node
|
||||
|
||||
RUN \
|
||||
npm install && \
|
||||
npm run build && \
|
||||
# TODO: removing dev dependecies is deleting `bn.js`, which breaks the Snowflake node
|
||||
npm prune --omit=dev && \
|
||||
npm i --omit=dev bn.js && \
|
||||
find . -type f -name "*.ts" -o -name "*.js.map" -o -name "*.vue" -o -name "tsconfig.json" | xargs rm &&\
|
||||
rm -rf node_modules/.cache packages/*/node_modules/.cache packages/*/.turbo .config .npm /tmp/*
|
||||
|
||||
|
||||
# 2. Start with a new clean image with just the code that is needed to run n8n
|
||||
FROM node:16-alpine
|
||||
FROM n8nio/base:${NODE_VERSION}
|
||||
COPY --from=builder /home/node ./
|
||||
COPY docker/images/n8n-custom/docker-entrypoint.sh ./
|
||||
|
||||
USER root
|
||||
|
||||
RUN apk add --update graphicsmagick tzdata tini su-exec git
|
||||
|
||||
WORKDIR /data
|
||||
|
||||
# Install all needed dependencies
|
||||
RUN npm_config_user=root npm install -g full-icu
|
||||
|
||||
# Install fonts
|
||||
RUN apk --no-cache add --virtual fonts msttcorefonts-installer fontconfig && \
|
||||
update-ms-fonts && \
|
||||
fc-cache -f && \
|
||||
apk del fonts && \
|
||||
find /usr/share/fonts/truetype/msttcorefonts/ -type l -exec unlink {} \;
|
||||
|
||||
ENV NODE_ICU_DATA /usr/local/lib/node_modules/full-icu
|
||||
|
||||
COPY --from=builder /data ./
|
||||
|
||||
COPY docker/images/n8n-custom/docker-entrypoint.sh /docker-entrypoint.sh
|
||||
ENTRYPOINT ["tini", "--", "/docker-entrypoint.sh"]
|
||||
|
||||
EXPOSE 5678/tcp
|
||||
RUN \
|
||||
mkdir .n8n && \
|
||||
chown node:node .n8n
|
||||
USER node
|
||||
ENV NODE_ENV=production
|
||||
ENTRYPOINT ["tini", "--", "./docker-entrypoint.sh"]
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
Dockerfile which allows to package up the local n8n code into
|
||||
a docker image.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Execute the following in the n8n root folder:
|
||||
|
||||
```bash
|
||||
docker build -t n8n-custom -f docker/images/n8n-custom/Dockerfile .
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1,25 +1,16 @@
|
|||
#!/bin/sh
|
||||
|
||||
if [ -d /root/.n8n ] ; then
|
||||
chmod o+rx /root
|
||||
chown -R node /root/.n8n
|
||||
ln -s /root/.n8n /home/node/
|
||||
fi
|
||||
|
||||
chown -R node /home/node
|
||||
|
||||
if [ "$#" -gt 0 ]; then
|
||||
# Got started with arguments
|
||||
COMMAND=$1;
|
||||
|
||||
if [[ "$COMMAND" == "n8n" ]]; then
|
||||
shift
|
||||
exec su-exec node ./packages/cli/bin/n8n "$@"
|
||||
(cd packages/cli; exec node ./bin/n8n "$@")
|
||||
else
|
||||
exec su-exec node "$@"
|
||||
exec node "$@"
|
||||
fi
|
||||
|
||||
else
|
||||
# Got started without arguments
|
||||
exec su-exec node ./packages/cli/bin/n8n
|
||||
cd packages/cli; exec node ./bin/n8n
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ RUN \
|
|||
# Set a custom user to not have n8n run as root
|
||||
USER root
|
||||
|
||||
RUN npm_config_user=root npm install -g full-icu n8n@${N8N_VERSION}
|
||||
RUN npm_config_user=root npm install -g npm@latest full-icu n8n@${N8N_VERSION}
|
||||
|
||||
ENV NODE_ICU_DATA /usr/local/lib/node_modules/full-icu
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ Dockerfile to build n8n with Debian.
|
|||
For information about how to run n8n with Docker check the generic
|
||||
[Docker-Readme](https://github.com/n8n-io/n8n/tree/master/docker/images/n8n/README.md)
|
||||
|
||||
|
||||
```
|
||||
docker build --build-arg N8N_VERSION=<VERSION> -t n8nio/n8n:<VERSION> .
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ RUN \
|
|||
# Set a custom user to not have n8n run as root
|
||||
USER root
|
||||
|
||||
RUN npm_config_user=root npm install -g n8n@${N8N_VERSION}
|
||||
RUN npm_config_user=root npm install -g npm@latest n8n@${N8N_VERSION}
|
||||
|
||||
WORKDIR /data
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ docker build --build-arg N8N_VERSION=<VERSION> -t n8nio/n8n:<VERSION> .
|
|||
docker build --build-arg N8N_VERSION=0.36.1 -t n8nio/n8n:0.36.1-rhel7 .
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
docker run -it --rm \
|
||||
--name n8n \
|
||||
|
|
|
|||
|
|
@ -1,36 +1,25 @@
|
|||
FROM node:16-alpine
|
||||
ARG NODE_VERSION=16
|
||||
FROM n8nio/base:${NODE_VERSION}
|
||||
|
||||
ARG N8N_VERSION
|
||||
|
||||
RUN if [ -z "$N8N_VERSION" ] ; then echo "The N8N_VERSION argument is missing!" ; exit 1; fi
|
||||
|
||||
# Update everything and install needed dependencies
|
||||
RUN apk add --update graphicsmagick tzdata git tini su-exec
|
||||
ENV NODE_ENV=production
|
||||
RUN set -eux; \
|
||||
apkArch="$(apk --print-arch)"; \
|
||||
case "$apkArch" in \
|
||||
'armv7') apk --no-cache add --virtual build-dependencies python3 build-base;; \
|
||||
esac && \
|
||||
npm install -g --omit=dev n8n@${N8N_VERSION} && \
|
||||
case "$apkArch" in \
|
||||
'armv7') apk del build-dependencies;; \
|
||||
esac && \
|
||||
find /usr/local/lib/node_modules/n8n -type f -name "*.ts" -o -name "*.js.map" -o -name "*.vue" | xargs rm && \
|
||||
rm -rf /root/.npm
|
||||
|
||||
# # Set a custom user to not have n8n run as root
|
||||
# Set a custom user to not have n8n run as root
|
||||
USER root
|
||||
|
||||
# Install n8n and the also temporary all the packages
|
||||
# it needs to build it correctly.
|
||||
RUN apk --update add --virtual build-dependencies python3 build-base ca-certificates && \
|
||||
npm config set python "$(which python3)" && \
|
||||
npm_config_user=root npm install -g full-icu n8n@${N8N_VERSION} && \
|
||||
apk del build-dependencies \
|
||||
&& rm -rf /root /tmp/* /var/cache/apk/* && mkdir /root;
|
||||
|
||||
# Install fonts
|
||||
RUN apk --no-cache add --virtual fonts msttcorefonts-installer fontconfig && \
|
||||
update-ms-fonts && \
|
||||
fc-cache -f && \
|
||||
apk del fonts && \
|
||||
find /usr/share/fonts/truetype/msttcorefonts/ -type l -exec unlink {} \; \
|
||||
&& rm -rf /root /tmp/* /var/cache/apk/* && mkdir /root
|
||||
|
||||
ENV NODE_ICU_DATA /usr/local/lib/node_modules/full-icu
|
||||
|
||||
WORKDIR /data
|
||||
|
||||
RUN apk --no-cache add su-exec
|
||||
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
||||
ENTRYPOINT ["tini", "--", "/docker-entrypoint.sh"]
|
||||
|
||||
EXPOSE 5678/tcp
|
||||
|
|
|
|||
|
|
@ -265,4 +265,4 @@ Before you upgrade to the latest version make sure to check here if there are an
|
|||
|
||||
n8n is [fair-code](http://faircode.io) distributed under the [**Sustainable Use License**](https://github.com/n8n-io/n8n/blob/master/packages/cli/LICENSE.md).
|
||||
|
||||
Additional information on the license can be found in the [FAQ](https://docs.n8n.io/reference/faq.html#license)
|
||||
Additional information about the license can be found in the [docs](https://docs.n8n.io/reference/license/).
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "independent"
|
||||
}
|
||||
195125
package-lock.json
generated
195125
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
38
package.json
38
package.json
|
|
@ -1,29 +1,41 @@
|
|||
{
|
||||
"name": "n8n",
|
||||
"version": "0.186.1",
|
||||
"version": "0.197.1",
|
||||
"private": true,
|
||||
"homepage": "https://n8n.io",
|
||||
"scripts": {
|
||||
"bootstrap": "lerna bootstrap --hoist --no-ci",
|
||||
"build": "lerna exec npm run build",
|
||||
"dev": "lerna exec npm run dev --parallel",
|
||||
"clean:dist": "lerna exec -- rimraf ./dist",
|
||||
"format": "lerna exec npm run format",
|
||||
"lint": "lerna exec npm run lint",
|
||||
"lintfix": "lerna exec npm run lintfix",
|
||||
"build": "turbo run build",
|
||||
"dev": "turbo run dev --parallel",
|
||||
"clean:dist": "npm exec -ws -- rimraf ./dist",
|
||||
"format": "turbo run format && node scripts/format.mjs",
|
||||
"lint": "turbo run lint",
|
||||
"lintfix": "turbo run lintfix",
|
||||
"optimize-svg": "find ./packages -name '*.svg' ! -name 'pipedrive.svg' -print0 | xargs -0 -P16 -L20 npx svgo",
|
||||
"postinstall": "patch-package",
|
||||
"start": "run-script-os",
|
||||
"start:default": "cd packages/cli/bin && ./n8n",
|
||||
"start:tunnel": "./packages/cli/bin/n8n start --tunnel",
|
||||
"start:windows": "cd packages/cli/bin && n8n",
|
||||
"test": "lerna run test",
|
||||
"watch": "lerna run --parallel watch",
|
||||
"test": "turbo run test",
|
||||
"watch": "turbo run watch",
|
||||
"webhook": "./packages/cli/bin/n8n webhook",
|
||||
"worker": "./packages/cli/bin/n8n worker"
|
||||
},
|
||||
"devDependencies": {
|
||||
"lerna": "^3.13.1",
|
||||
"patch-package": "^6.4.7",
|
||||
"rimraf": "^3.0.2",
|
||||
"run-script-os": "^1.0.7"
|
||||
"run-script-os": "^1.0.7",
|
||||
"turbo": "1.2.15"
|
||||
},
|
||||
"postcss": {}
|
||||
"postcss": {},
|
||||
"workspaces": [
|
||||
"packages/*",
|
||||
"packages/@n8n_io/*"
|
||||
],
|
||||
"overrides": {
|
||||
"browserslist": "^4.21.3",
|
||||
"ejs": "^3.1.8",
|
||||
"fork-ts-checker-webpack-plugin": "^6.0.4",
|
||||
"globby": "^11.0.2"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
396
packages/@n8n_io/eslint-config/base.js
Normal file
396
packages/@n8n_io/eslint-config/base.js
Normal file
|
|
@ -0,0 +1,396 @@
|
|||
/**
|
||||
* @type {import('@types/eslint').ESLint.ConfigData}
|
||||
*/
|
||||
const config = (module.exports = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
project: ['./tsconfig.json'],
|
||||
},
|
||||
|
||||
ignorePatterns: [
|
||||
'.eslintrc.js', // TODO: remove this
|
||||
'node_modules/**',
|
||||
'dist/**',
|
||||
'test/**', // TODO: remove this
|
||||
],
|
||||
|
||||
plugins: [
|
||||
/**
|
||||
* Plugin with lint rules for import/export syntax
|
||||
* https://github.com/import-js/eslint-plugin-import
|
||||
*/
|
||||
'eslint-plugin-import',
|
||||
|
||||
/**
|
||||
* @typescript-eslint/eslint-plugin is required by eslint-config-airbnb-typescript
|
||||
* See step 2: https://github.com/iamturns/eslint-config-airbnb-typescript#2-install-eslint-plugins
|
||||
*/
|
||||
'@typescript-eslint',
|
||||
|
||||
/**
|
||||
* Plugin to report formatting violations as lint violations
|
||||
* https://github.com/prettier/eslint-plugin-prettier
|
||||
*/
|
||||
'eslint-plugin-prettier',
|
||||
|
||||
/*
|
||||
* Plugin to allow specifying local ESLint rules.
|
||||
* https://github.com/ivov/eslint-plugin-n8n-local-rules
|
||||
*/
|
||||
'eslint-plugin-n8n-local-rules',
|
||||
],
|
||||
|
||||
extends: [
|
||||
/**
|
||||
* Config for typescript-eslint recommended ruleset (without type checking)
|
||||
*
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/1c1b572c3000d72cfe665b7afbada0ec415e7855/packages/eslint-plugin/src/configs/recommended.ts
|
||||
*/
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
|
||||
/**
|
||||
* Config for typescript-eslint recommended ruleset (with type checking)
|
||||
*
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/1c1b572c3000d72cfe665b7afbada0ec415e7855/packages/eslint-plugin/src/configs/recommended-requiring-type-checking.ts
|
||||
*/
|
||||
'plugin:@typescript-eslint/recommended-requiring-type-checking',
|
||||
|
||||
/**
|
||||
* Config for Airbnb style guide for TS, /base to remove React rules
|
||||
*
|
||||
* https://github.com/iamturns/eslint-config-airbnb-typescript
|
||||
* https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb-base/rules
|
||||
*/
|
||||
'eslint-config-airbnb-typescript/base',
|
||||
|
||||
/**
|
||||
* Config to disable ESLint rules covered by Prettier
|
||||
*
|
||||
* https://github.com/prettier/eslint-config-prettier
|
||||
*/
|
||||
'eslint-config-prettier',
|
||||
],
|
||||
|
||||
rules: {
|
||||
// ******************************************************************
|
||||
// required by prettier plugin
|
||||
// ******************************************************************
|
||||
|
||||
// The following rule enables eslint-plugin-prettier
|
||||
// See: https://github.com/prettier/eslint-plugin-prettier#recommended-configuration
|
||||
|
||||
'prettier/prettier': ['error', { endOfLine: 'auto' }],
|
||||
|
||||
// The following two rules must be disabled when using eslint-plugin-prettier:
|
||||
// See: https://github.com/prettier/eslint-plugin-prettier#arrow-body-style-and-prefer-arrow-callback-issue
|
||||
|
||||
/**
|
||||
* https://eslint.org/docs/rules/arrow-body-style
|
||||
*/
|
||||
'arrow-body-style': 'off',
|
||||
|
||||
/**
|
||||
* https://eslint.org/docs/rules/prefer-arrow-callback
|
||||
*/
|
||||
'prefer-arrow-callback': 'off',
|
||||
|
||||
// ******************************************************************
|
||||
// additions to base ruleset
|
||||
// ******************************************************************
|
||||
|
||||
// ----------------------------------
|
||||
// ESLint
|
||||
// ----------------------------------
|
||||
|
||||
/**
|
||||
* https://eslint.org/docs/rules/id-denylist
|
||||
*/
|
||||
'id-denylist': [
|
||||
'error',
|
||||
'err',
|
||||
'cb',
|
||||
'callback',
|
||||
'any',
|
||||
'Number',
|
||||
'number',
|
||||
'String',
|
||||
'string',
|
||||
'Boolean',
|
||||
'boolean',
|
||||
'Undefined',
|
||||
'undefined',
|
||||
],
|
||||
|
||||
'no-void': ['error', { allowAsStatement: true }],
|
||||
|
||||
// ----------------------------------
|
||||
// @typescript-eslint
|
||||
// ----------------------------------
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/array-type.md
|
||||
*/
|
||||
'@typescript-eslint/array-type': ['error', { default: 'array-simple' }],
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/ban-ts-comment.md
|
||||
*/
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/ban-types.md
|
||||
*/
|
||||
'@typescript-eslint/ban-types': [
|
||||
'error',
|
||||
{
|
||||
types: {
|
||||
Object: {
|
||||
message: 'Use object instead',
|
||||
fixWith: 'object',
|
||||
},
|
||||
String: {
|
||||
message: 'Use string instead',
|
||||
fixWith: 'string',
|
||||
},
|
||||
Boolean: {
|
||||
message: 'Use boolean instead',
|
||||
fixWith: 'boolean',
|
||||
},
|
||||
Number: {
|
||||
message: 'Use number instead',
|
||||
fixWith: 'number',
|
||||
},
|
||||
Symbol: {
|
||||
message: 'Use symbol instead',
|
||||
fixWith: 'symbol',
|
||||
},
|
||||
Function: {
|
||||
message: [
|
||||
'The `Function` type accepts any function-like value.',
|
||||
'It provides no type safety when calling the function, which can be a common source of bugs.',
|
||||
'It also accepts things like class declarations, which will throw at runtime as they will not be called with `new`.',
|
||||
'If you are expecting the function to accept certain arguments, you should explicitly define the function shape.',
|
||||
].join('\n'),
|
||||
},
|
||||
},
|
||||
extendDefaults: false,
|
||||
},
|
||||
],
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/consistent-type-assertions.md
|
||||
*/
|
||||
'@typescript-eslint/consistent-type-assertions': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/explicit-member-accessibility.md
|
||||
*/
|
||||
'@typescript-eslint/explicit-member-accessibility': ['error', { accessibility: 'no-public' }],
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/member-delimiter-style.md
|
||||
*/
|
||||
'@typescript-eslint/member-delimiter-style': [
|
||||
'error',
|
||||
{
|
||||
multiline: {
|
||||
delimiter: 'semi',
|
||||
requireLast: true,
|
||||
},
|
||||
singleline: {
|
||||
delimiter: 'semi',
|
||||
requireLast: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/naming-convention.md
|
||||
*/
|
||||
'@typescript-eslint/naming-convention': [
|
||||
'error',
|
||||
{
|
||||
selector: 'default',
|
||||
format: ['camelCase'],
|
||||
},
|
||||
{
|
||||
selector: 'variable',
|
||||
format: ['camelCase', 'snake_case', 'UPPER_CASE'],
|
||||
leadingUnderscore: 'allowSingleOrDouble',
|
||||
trailingUnderscore: 'allowSingleOrDouble',
|
||||
},
|
||||
{
|
||||
selector: 'property',
|
||||
format: ['camelCase', 'snake_case'],
|
||||
leadingUnderscore: 'allowSingleOrDouble',
|
||||
trailingUnderscore: 'allowSingleOrDouble',
|
||||
},
|
||||
{
|
||||
selector: 'typeLike',
|
||||
format: ['PascalCase'],
|
||||
},
|
||||
{
|
||||
selector: ['method', 'function'],
|
||||
format: ['camelCase'],
|
||||
leadingUnderscore: 'allowSingleOrDouble',
|
||||
},
|
||||
],
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-duplicate-imports.md
|
||||
*/
|
||||
'@typescript-eslint/no-duplicate-imports': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-invalid-void-type.md
|
||||
*/
|
||||
'@typescript-eslint/no-invalid-void-type': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-misused-promises.md
|
||||
*/
|
||||
'@typescript-eslint/no-misused-promises': ['error', { checksVoidReturn: false }],
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/v4.30.0/packages/eslint-plugin/docs/rules/no-floating-promises.md
|
||||
*/
|
||||
'@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: true }],
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/v4.33.0/packages/eslint-plugin/docs/rules/no-namespace.md
|
||||
*/
|
||||
'@typescript-eslint/no-namespace': 'off',
|
||||
|
||||
/**
|
||||
* https://eslint.org/docs/1.0.0/rules/no-throw-literal
|
||||
*/
|
||||
'@typescript-eslint/no-throw-literal': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unnecessary-boolean-literal-compare.md
|
||||
*/
|
||||
'@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unnecessary-qualifier.md
|
||||
*/
|
||||
'@typescript-eslint/no-unnecessary-qualifier': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unused-expressions.md
|
||||
*/
|
||||
'@typescript-eslint/no-unused-expressions': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unused-vars.md
|
||||
*/
|
||||
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '_' }],
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/prefer-nullish-coalescing.md
|
||||
*/
|
||||
'@typescript-eslint/prefer-nullish-coalescing': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/prefer-optional-chain.md
|
||||
*/
|
||||
'@typescript-eslint/prefer-optional-chain': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/promise-function-async.md
|
||||
*/
|
||||
'@typescript-eslint/promise-function-async': 'error',
|
||||
|
||||
// ----------------------------------
|
||||
// eslint-plugin-import
|
||||
// ----------------------------------
|
||||
|
||||
/**
|
||||
* https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-default-export.md
|
||||
*/
|
||||
'import/no-default-export': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/order.md
|
||||
*/
|
||||
'import/order': 'error',
|
||||
|
||||
// ----------------------------------
|
||||
// eslint-plugin-n8n-local-rules
|
||||
// ----------------------------------
|
||||
|
||||
// TODO: set to `error` and fix offenses
|
||||
'n8n-local-rules/no-uncaught-json-parse': 'warn',
|
||||
|
||||
// ******************************************************************
|
||||
// overrides to base ruleset
|
||||
// ******************************************************************
|
||||
|
||||
// ----------------------------------
|
||||
// ESLint
|
||||
// ----------------------------------
|
||||
|
||||
/**
|
||||
* https://eslint.org/docs/rules/class-methods-use-this
|
||||
*/
|
||||
'class-methods-use-this': 'off',
|
||||
|
||||
/**
|
||||
* https://eslint.org/docs/rules/eqeqeq
|
||||
*/
|
||||
eqeqeq: 'error',
|
||||
|
||||
/**
|
||||
* https://eslint.org/docs/rules/no-plusplus
|
||||
*/
|
||||
'no-plusplus': 'off',
|
||||
|
||||
/**
|
||||
* https://eslint.org/docs/rules/object-shorthand
|
||||
*/
|
||||
'object-shorthand': 'error',
|
||||
|
||||
/**
|
||||
* https://eslint.org/docs/rules/prefer-const
|
||||
*/
|
||||
'prefer-const': 'error',
|
||||
|
||||
/**
|
||||
* https://eslint.org/docs/rules/prefer-spread
|
||||
*/
|
||||
'prefer-spread': 'error',
|
||||
|
||||
/**
|
||||
* https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/no-unused-vars.md
|
||||
*
|
||||
* Disabled because eslint-plugin-diff fails to catch it. TODO: Revisit.
|
||||
*/
|
||||
'@typescript-eslint/no-unused-vars': 'warn',
|
||||
|
||||
// ----------------------------------
|
||||
// import
|
||||
// ----------------------------------
|
||||
|
||||
/**
|
||||
* https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/prefer-default-export.md
|
||||
*/
|
||||
'import/prefer-default-export': 'off',
|
||||
},
|
||||
});
|
||||
|
||||
if ('ESLINT_PLUGIN_DIFF_COMMIT' in process.env) {
|
||||
/**
|
||||
* Plugin to lint only changes
|
||||
*
|
||||
* https://github.com/paleite/eslint-plugin-diff#plugindiffdiff-recommended
|
||||
*/
|
||||
config.plugins.push('eslint-plugin-diff');
|
||||
|
||||
/**
|
||||
* Config for eslint-plugin-diff
|
||||
*
|
||||
* https://github.com/paleite/eslint-plugin-diff#plugindiffdiff-recommended
|
||||
*/
|
||||
config.extends.push('plugin:diff/diff');
|
||||
}
|
||||
39
packages/@n8n_io/eslint-config/frontend.js
Normal file
39
packages/@n8n_io/eslint-config/frontend.js
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* @type {import('@types/eslint').ESLint.ConfigData}
|
||||
*/
|
||||
module.exports = {
|
||||
plugins: ['vue'],
|
||||
|
||||
extends: [
|
||||
'plugin:vue/essential',
|
||||
'@vue/typescript',
|
||||
'@n8n_io/eslint-config/base',
|
||||
],
|
||||
|
||||
env: {
|
||||
browser: true,
|
||||
es6: true,
|
||||
node: true,
|
||||
},
|
||||
|
||||
parser: 'vue-eslint-parser',
|
||||
parserOptions: {
|
||||
parser: '@typescript-eslint/parser',
|
||||
},
|
||||
|
||||
ignorePatterns: [
|
||||
'**/*.js',
|
||||
'**/*.d.ts',
|
||||
'vite.config.ts',
|
||||
],
|
||||
|
||||
rules: {
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||
semi: [2, 'always'],
|
||||
indent: ['error', 'tab'],
|
||||
'comma-dangle': ['error', 'always-multiline'],
|
||||
'no-tabs': 0,
|
||||
'no-labels': 0,
|
||||
},
|
||||
};
|
||||
86
packages/@n8n_io/eslint-config/local-rules.js
Normal file
86
packages/@n8n_io/eslint-config/local-rules.js
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* This file contains any locally defined ESLint rules. They are picked up by
|
||||
* eslint-plugin-n8n-local-rules and exposed as 'n8n-local-rules/<rule-name>'.
|
||||
*/
|
||||
module.exports = {
|
||||
/**
|
||||
* A rule to detect calls to JSON.parse() that are not wrapped inside try/catch blocks.
|
||||
*
|
||||
* Valid:
|
||||
* ```js
|
||||
* try { JSON.parse(foo) } catch(err) { baz() }
|
||||
* ```
|
||||
*
|
||||
* Invalid:
|
||||
* ```js
|
||||
* JSON.parse(foo)
|
||||
* ```
|
||||
*
|
||||
* The pattern where an object is cloned with JSON.parse(JSON.stringify()) is allowed
|
||||
* (abundant in the n8n codebase):
|
||||
*
|
||||
* Valid:
|
||||
* ```js
|
||||
* JSON.parse(JSON.stringify(foo))
|
||||
* ```
|
||||
*/
|
||||
'no-uncaught-json-parse': {
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'Calls to JSON.parse() must be surrounded with a try/catch block.',
|
||||
recommended: 'error',
|
||||
},
|
||||
schema: [],
|
||||
messages: {
|
||||
noUncaughtJsonParse: 'Surround the JSON.parse() call with a try/catch block.',
|
||||
},
|
||||
},
|
||||
defaultOptions: [],
|
||||
create(context) {
|
||||
return {
|
||||
CallExpression(node) {
|
||||
if (!isJsonParseCall(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDeepCloneOperation(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (context.getAncestors().find((node) => node.type === 'TryStatement') !== undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Found a JSON.parse() call not wrapped into a try/catch, so report it
|
||||
context.report({
|
||||
messageId: 'noUncaughtJsonParse',
|
||||
node,
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const isJsonParseCall = (node) =>
|
||||
node.callee.type === 'MemberExpression' &&
|
||||
node.callee.object.type === 'Identifier' &&
|
||||
node.callee.object.name === 'JSON' &&
|
||||
node.callee.property.type === 'Identifier' &&
|
||||
node.callee.property.name === 'parse';
|
||||
|
||||
const isDeepCloneOperation = (node) => {
|
||||
const parseArg = node.arguments?.[0];
|
||||
return (
|
||||
parseArg !== undefined &&
|
||||
parseArg.type === 'CallExpression' &&
|
||||
parseArg.callee.type === 'MemberExpression' &&
|
||||
parseArg.callee.object.type === 'Identifier' &&
|
||||
parseArg.callee.object.name === 'JSON' &&
|
||||
parseArg.callee.property.type === 'Identifier' &&
|
||||
parseArg.callee.property.name === 'stringify'
|
||||
);
|
||||
};
|
||||
23
packages/@n8n_io/eslint-config/local-rules.test.js
Normal file
23
packages/@n8n_io/eslint-config/local-rules.test.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
'use strict';
|
||||
|
||||
const rules = require('./local-rules'),
|
||||
RuleTester = require('eslint').RuleTester;
|
||||
|
||||
const ruleTester = new RuleTester();
|
||||
|
||||
ruleTester.run('no-uncaught-json-parse', rules['no-uncaught-json-parse'], {
|
||||
valid: [
|
||||
{
|
||||
code: 'try { JSON.parse(foo) } catch (e) {}',
|
||||
},
|
||||
{
|
||||
code: 'JSON.parse(JSON.stringify(foo))',
|
||||
},
|
||||
],
|
||||
invalid: [
|
||||
{
|
||||
code: 'JSON.parse(foo)',
|
||||
errors: [{ messageId: 'noUncaughtJsonParse' }],
|
||||
},
|
||||
],
|
||||
});
|
||||
11
packages/@n8n_io/eslint-config/node.js
Normal file
11
packages/@n8n_io/eslint-config/node.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* @type {import('@types/eslint').ESLint.ConfigData}
|
||||
*/
|
||||
module.exports = {
|
||||
extends: ['@n8n_io/eslint-config/base'],
|
||||
|
||||
env: {
|
||||
es6: true,
|
||||
node: true,
|
||||
},
|
||||
};
|
||||
22
packages/@n8n_io/eslint-config/package.json
Normal file
22
packages/@n8n_io/eslint-config/package.json
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "@n8n_io/eslint-config",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@types/eslint": "8.4.6",
|
||||
"@typescript-eslint/eslint-plugin": "^5.36.2",
|
||||
"@typescript-eslint/parser": "^5.36.2",
|
||||
"@vue/eslint-config-typescript": "^11.0.0",
|
||||
"eslint": "8.23.0",
|
||||
"eslint-config-airbnb-typescript": "^17.0.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-diff": "^2.0.1",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-n8n-local-rules": "^1.0.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-vue": "^9.4.0",
|
||||
"jest": "^28.1.3"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "jest"
|
||||
}
|
||||
}
|
||||
16
packages/cli/.eslintrc.js
Normal file
16
packages/cli/.eslintrc.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* @type {import('@types/eslint').ESLint.ConfigData}
|
||||
*/
|
||||
module.exports = {
|
||||
extends: ['@n8n_io/eslint-config/node'],
|
||||
ignorePatterns: [
|
||||
'jest.config.js',
|
||||
// TODO: Remove these
|
||||
'src/databases/migrations/**',
|
||||
'src/databases/ormconfig.ts',
|
||||
],
|
||||
rules: {
|
||||
// TODO: Remove this
|
||||
'import/order': 'off',
|
||||
},
|
||||
};
|
||||
|
|
@ -1,43 +1,69 @@
|
|||
# Sustainable Use License
|
||||
# License
|
||||
|
||||
Portions of this software are licensed as follows:
|
||||
|
||||
- All source code files of this repository that contain ".ee." in their filename are licensed under the n8n Enterprise License defined in "LICENSE_EE.md".
|
||||
- All third party components incorporated into the n8n Software are licensed under the original license
|
||||
provided by the owner of the applicable component.
|
||||
- Content outside of the above mentioned files or restrictions above is available under the "Sustainable Use
|
||||
License" as defined below.
|
||||
|
||||
## Sustainable Use License
|
||||
|
||||
Version 1.0
|
||||
|
||||
## Acceptance
|
||||
### Acceptance
|
||||
|
||||
By using the software, you agree to all of the terms and conditions below.
|
||||
|
||||
## Copyright License
|
||||
### Copyright License
|
||||
|
||||
The licensor grants you a non-exclusive, royalty-free, worldwide, non-sublicensable, non-transferable license to use, copy, distribute, make available, and prepare derivative works of the software, in each case subject to the limitations below.
|
||||
The licensor grants you a non-exclusive, royalty-free, worldwide, non-sublicensable, non-transferable license
|
||||
to use, copy, distribute, make available, and prepare derivative works of the software, in each case subject
|
||||
to the limitations below.
|
||||
|
||||
## Limitations
|
||||
### Limitations
|
||||
|
||||
You may use or modify the software only for your own internal business purposes or for non-commercial or personal use.
|
||||
You may distribute the software or provide it to others only if you do so free of charge for non-commercial purposes.
|
||||
You may not alter, remove, or obscure any licensing, copyright, or other notices of the licensor in the software. Any use of the licensor’s trademarks is subject to applicable law.
|
||||
You may use or modify the software only for your own internal business purposes or for non-commercial or
|
||||
personal use. You may distribute the software or provide it to others only if you do so free of charge for
|
||||
non-commercial purposes. You may not alter, remove, or obscure any licensing, copyright, or other notices of
|
||||
the licensor in the software. Any use of the licensor’s trademarks is subject to applicable law.
|
||||
|
||||
## Patents
|
||||
### Patents
|
||||
|
||||
The licensor grants you a license, under any patent claims the licensor can license, or becomes able to license, to make, have made, use, sell, offer for sale, import and have imported the software, in each case subject to the limitations and conditions in this license. This license does not cover any patent claims that you cause to be infringed by modifications or additions to the software. If you or your company make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
|
||||
The licensor grants you a license, under any patent claims the licensor can license, or becomes able to
|
||||
license, to make, have made, use, sell, offer for sale, import and have imported the software, in each case
|
||||
subject to the limitations and conditions in this license. This license does not cover any patent claims that
|
||||
you cause to be infringed by modifications or additions to the software. If you or your company make any
|
||||
written claim that the software infringes or contributes to infringement of any patent, your patent license
|
||||
for the software granted under these terms ends immediately. If your company makes such a claim, your patent
|
||||
license ends immediately for work on behalf of your company.
|
||||
|
||||
## Notices
|
||||
### Notices
|
||||
|
||||
You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms.
|
||||
If you modify the software, you must include in any modified copies of the software a prominent notice stating that you have modified the software.
|
||||
You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these
|
||||
terms. If you modify the software, you must include in any modified copies of the software a prominent notice
|
||||
stating that you have modified the software.
|
||||
|
||||
## No Other Rights
|
||||
### No Other Rights
|
||||
|
||||
These terms do not imply any licenses other than those expressly granted in these terms.
|
||||
|
||||
## Termination
|
||||
### Termination
|
||||
|
||||
If you use the software in violation of these terms, such use is not licensed, and your license will automatically terminate. If the licensor provides you with a notice of your violation, and you cease all violation of this license no later than 30 days after you receive that notice, your license will be reinstated retroactively. However, if you violate these terms after such reinstatement, any additional violation of these terms will cause your license to terminate automatically and permanently.
|
||||
If you use the software in violation of these terms, such use is not licensed, and your license will
|
||||
automatically terminate. If the licensor provides you with a notice of your violation, and you cease all
|
||||
violation of this license no later than 30 days after you receive that notice, your license will be reinstated
|
||||
retroactively. However, if you violate these terms after such reinstatement, any additional violation of these
|
||||
terms will cause your license to terminate automatically and permanently.
|
||||
|
||||
## No Liability
|
||||
### No Liability
|
||||
|
||||
As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.
|
||||
As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will
|
||||
not be liable to you for any damages arising out of these terms or the use or nature of the software, under
|
||||
any kind of legal claim.
|
||||
|
||||
## Definitions
|
||||
### Definitions
|
||||
|
||||
The “licensor” is the entity offering these terms.
|
||||
|
||||
|
|
@ -45,7 +71,10 @@ The “software” is the software the licensor makes available under these term
|
|||
|
||||
“You” refers to the individual or entity agreeing to these terms.
|
||||
|
||||
“Your company” is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. Control means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
|
||||
“Your company” is any legal entity, sole proprietorship, or other kind of organization that you work for, plus
|
||||
all organizations that have control over, are under the control of, or are under common control with that
|
||||
organization. Control means ownership of substantially all the assets of an entity, or the power to direct its
|
||||
management and policies by vote, contract, or otherwise. Control can be direct or indirect.
|
||||
|
||||
“Your license” is the license granted to you for the software under these terms.
|
||||
|
||||
|
|
|
|||
27
packages/cli/LICENSE_EE.md
Normal file
27
packages/cli/LICENSE_EE.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# The n8n Enterprise License (the “Enterprise License”)
|
||||
|
||||
Copyright (c) 2022-present n8n GmbH.
|
||||
|
||||
With regard to the n8n Software:
|
||||
|
||||
This software and associated documentation files (the "Software") may only be used in production, if
|
||||
you (and any entity that you represent) hold a valid n8n Enterprise license corresponding to your
|
||||
usage. Subject to the foregoing sentence, you are free to modify this Software and publish patches
|
||||
to the Software. You agree that n8n and/or its licensors (as applicable) retain all right, title and
|
||||
interest in and to all such modifications and/or patches, and all such modifications and/or patches
|
||||
may only be used, copied, modified, displayed, distributed, or otherwise exploited with a valid n8n
|
||||
Enterprise license for the corresponding usage. Notwithstanding the foregoing, you may copy and
|
||||
modify the Software for development and testing purposes, without requiring a subscription. You
|
||||
agree that n8n and/or its licensors (as applicable) retain all right, title and interest in and to
|
||||
all such modifications. You are not granted any other rights beyond what is expressly stated herein.
|
||||
Subject to the foregoing, it is forbidden to copy, merge, publish, distribute, sublicense, and/or
|
||||
sell the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For all third party components incorporated into the n8n Software, those components are licensed
|
||||
under the original license provided by the owner of the applicable component.
|
||||
|
|
@ -113,7 +113,7 @@ You can find additional information and example workflows on the [n8n.io](https:
|
|||
|
||||
## Create Custom Nodes
|
||||
|
||||
You can create custom nodes for n8n. Follow the instructions mentioned in the documentation to create your node: [Creating nodes](https://docs.n8n.io/nodes/creating-nodes/create-node.html)
|
||||
You can create custom nodes for n8n. Follow the instructions mentioned in the documentation to create your node: [Creating nodes](https://docs.n8n.io/integrations/creating-nodes/build/)
|
||||
|
||||
## Contributing
|
||||
|
||||
|
|
@ -151,4 +151,4 @@ You can also find breaking changes here: [Breaking Changes](./BREAKING-CHANGES.m
|
|||
|
||||
n8n is [fair-code](http://faircode.io) distributed under the [**Sustainable Use License**](https://github.com/n8n-io/n8n/blob/master/packages/cli/LICENSE.md).
|
||||
|
||||
Additional information on the license can be found in the [FAQ](https://docs.n8n.io/reference/faq.html#license)
|
||||
Additional information about the license can be found in the [docs](https://docs.n8n.io/reference/license/).
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
var path = require('path'); // tslint:disable-line:no-var-keyword
|
||||
var path = require('path');
|
||||
|
||||
// Make sure that it also find the config folder when it
|
||||
// did get started from another folder that the root one.
|
||||
process.env.NODE_CONFIG_DIR = process.env.NODE_CONFIG_DIR || path.join(__dirname, 'config');
|
||||
|
||||
// Check if version should be displayed
|
||||
var versionFlags = [ // tslint:disable-line:no-var-keyword
|
||||
var versionFlags = [
|
||||
'-v',
|
||||
'-V',
|
||||
'--version',
|
||||
|
|
|
|||
2
packages/cli/commands/Interfaces.d.ts
vendored
2
packages/cli/commands/Interfaces.d.ts
vendored
|
|
@ -15,7 +15,7 @@ interface IResult {
|
|||
interface IExecutionResult {
|
||||
workflowId: string | number;
|
||||
workflowName: string;
|
||||
executionTime: number; // Given in seconds with decimals for milisseconds
|
||||
executionTime: number; // Given in seconds with decimals for milliseconds
|
||||
finished: boolean;
|
||||
executionStatus: ExecutionStatus;
|
||||
error?: string;
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ export class DbRevertMigrationCommand extends Command {
|
|||
if (connection) await connection.close();
|
||||
|
||||
console.error('Error reverting last migration. See log messages for details.');
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
logger.error(error.message);
|
||||
this.exit(1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable no-console */
|
||||
import { promises as fs } from 'fs';
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ export class ExecuteBatch extends Command {
|
|||
}),
|
||||
shallow: flags.boolean({
|
||||
description:
|
||||
'Compares only if attributes output from node are the same, with no regards to neste JSON objects.',
|
||||
'Compares only if attributes output from node are the same, with no regards to nested JSON objects.',
|
||||
}),
|
||||
skipList: flags.string({
|
||||
description: 'File containing a comma separated list of workflow IDs to skip.',
|
||||
|
|
@ -152,7 +152,7 @@ export class ExecuteBatch extends Command {
|
|||
executingWorkflows = activeExecutionsInstance.getActiveExecutions();
|
||||
}
|
||||
// We may receive true but when called from `process.on`
|
||||
// we get the signal (SIGNIT, etc.)
|
||||
// we get the signal (SIGINT, etc.)
|
||||
if (skipExit !== true) {
|
||||
process.exit(0);
|
||||
}
|
||||
|
|
@ -864,7 +864,7 @@ export class ExecuteBatch extends Command {
|
|||
}
|
||||
}
|
||||
// Save snapshots only after comparing - this is to make sure we're updating
|
||||
// After comparing to existing verion.
|
||||
// After comparing to existing version.
|
||||
if (ExecuteBatch.snapshot !== undefined) {
|
||||
const fileName = `${
|
||||
ExecuteBatch.snapshot.endsWith(sep)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/restrict-plus-operands */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable no-console */
|
||||
|
|
@ -85,7 +86,7 @@ export class ExportCredentialsCommand extends Command {
|
|||
|
||||
if (fs.existsSync(flags.output)) {
|
||||
if (!fs.lstatSync(flags.output).isDirectory()) {
|
||||
console.info(`The paramenter --output must be a directory`);
|
||||
console.info(`The parameter --output must be a directory`);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -104,7 +105,7 @@ export class ExportCredentialsCommand extends Command {
|
|||
} else if (flags.output) {
|
||||
if (fs.existsSync(flags.output)) {
|
||||
if (fs.lstatSync(flags.output).isDirectory()) {
|
||||
console.info(`The paramenter --output must be a writeble file`);
|
||||
console.info(`The parameter --output must be a writeable file`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable no-console */
|
||||
import { Command, flags } from '@oclif/command';
|
||||
|
|
@ -77,7 +78,7 @@ export class ExportWorkflowsCommand extends Command {
|
|||
|
||||
if (fs.existsSync(flags.output)) {
|
||||
if (!fs.lstatSync(flags.output).isDirectory()) {
|
||||
console.info(`The paramenter --output must be a directory`);
|
||||
console.info(`The parameter --output must be a directory`);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -96,7 +97,7 @@ export class ExportWorkflowsCommand extends Command {
|
|||
} else if (flags.output) {
|
||||
if (fs.existsSync(flags.output)) {
|
||||
if (fs.lstatSync(flags.output).isDirectory()) {
|
||||
console.info(`The paramenter --output must be a writeble file`);
|
||||
console.info(`The parameter --output must be a writeable file`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable no-restricted-syntax */
|
||||
/* eslint-disable @typescript-eslint/no-shadow */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
|
|
@ -13,7 +14,6 @@ import { LoggerProxy } from 'n8n-workflow';
|
|||
|
||||
import fs from 'fs';
|
||||
import glob from 'fast-glob';
|
||||
import path from 'path';
|
||||
import { EntityManager, getConnection } from 'typeorm';
|
||||
import { getLogger } from '../../src/Logger';
|
||||
import { Db } from '../../src';
|
||||
|
|
@ -87,9 +87,16 @@ export class ImportCredentialsCommand extends Command {
|
|||
const encryptionKey = await UserSettings.getEncryptionKey();
|
||||
|
||||
if (flags.separate) {
|
||||
const files = await glob(
|
||||
`${flags.input.endsWith(path.sep) ? flags.input : flags.input + path.sep}*.json`,
|
||||
);
|
||||
let { input: inputPath } = flags;
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
inputPath = inputPath.replace(/\\/g, '/');
|
||||
}
|
||||
|
||||
const files = await glob('*.json', {
|
||||
cwd: inputPath,
|
||||
absolute: true,
|
||||
});
|
||||
|
||||
totalImported = files.length;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable no-restricted-syntax */
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable @typescript-eslint/no-shadow */
|
||||
|
|
@ -16,6 +17,7 @@ import fs from 'fs';
|
|||
import glob from 'fast-glob';
|
||||
import { UserSettings } from 'n8n-core';
|
||||
import { EntityManager, getConnection } from 'typeorm';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { getLogger } from '../../src/Logger';
|
||||
import { Db, ICredentialsDb, IWorkflowToImport } from '../../src';
|
||||
import { SharedWorkflow } from '../../src/databases/entities/SharedWorkflow';
|
||||
|
|
@ -113,9 +115,10 @@ export class ImportWorkflowsCommand extends Command {
|
|||
inputPath = inputPath.replace(/\\/g, '/');
|
||||
}
|
||||
|
||||
inputPath = inputPath.replace(/\/$/g, '');
|
||||
|
||||
const files = await glob(`${inputPath}/*.json`);
|
||||
const files = await glob('*.json', {
|
||||
cwd: inputPath,
|
||||
absolute: true,
|
||||
});
|
||||
|
||||
totalImported = files.length;
|
||||
|
||||
|
|
@ -128,6 +131,11 @@ export class ImportWorkflowsCommand extends Command {
|
|||
if (credentials.length > 0) {
|
||||
workflow.nodes.forEach((node: INode) => {
|
||||
this.transformCredentials(node, credentials);
|
||||
|
||||
if (!node.id) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
node.id = uuid();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -156,6 +164,11 @@ export class ImportWorkflowsCommand extends Command {
|
|||
if (credentials.length > 0) {
|
||||
workflow.nodes.forEach((node: INode) => {
|
||||
this.transformCredentials(node, credentials);
|
||||
|
||||
if (!node.id) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
node.id = uuid();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import {
|
|||
} from '../src';
|
||||
|
||||
import { getLogger } from '../src/Logger';
|
||||
import { getAllInstalledPackages } from '../src/CommunityNodes/packageModel';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires
|
||||
const open = require('open');
|
||||
|
|
@ -60,6 +61,10 @@ export class Start extends Command {
|
|||
description:
|
||||
'runs the webhooks via a hooks.n8n.cloud tunnel server. Use only for testing and development!',
|
||||
}),
|
||||
reinstallMissingPackages: flags.boolean({
|
||||
description:
|
||||
'Attempts to self heal n8n if packages with nodes are missing. Might drastically increase startup times.',
|
||||
}),
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -87,6 +92,9 @@ export class Start extends Command {
|
|||
getLogger().info('\nStopping n8n...');
|
||||
|
||||
try {
|
||||
// Stop with trying to activate workflows that could not be activated
|
||||
activeWorkflowRunner?.removeAllQueuedWorkflowActivations();
|
||||
|
||||
const externalHooks = ExternalHooks();
|
||||
await externalHooks.run('n8n.stop', []);
|
||||
|
||||
|
|
@ -206,6 +214,23 @@ export class Start extends Command {
|
|||
// Wait till the database is ready
|
||||
await startDbInitPromise;
|
||||
|
||||
const installedPackages = await getAllInstalledPackages();
|
||||
const missingPackages = new Set<{
|
||||
packageName: string;
|
||||
version: string;
|
||||
}>();
|
||||
installedPackages.forEach((installedpackage) => {
|
||||
installedpackage.installedNodes.forEach((installedNode) => {
|
||||
if (!loadNodesAndCredentials.nodeTypes[installedNode.type]) {
|
||||
// Leave the list ready for installing in case we need.
|
||||
missingPackages.add({
|
||||
packageName: installedpackage.packageName,
|
||||
version: installedpackage.installedVersion,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
await UserSettings.getEncryptionKey();
|
||||
|
||||
// Load settings from database and set them to config.
|
||||
|
|
@ -214,6 +239,42 @@ export class Start extends Command {
|
|||
config.set(setting.key, JSON.parse(setting.value));
|
||||
});
|
||||
|
||||
config.set('nodes.packagesMissing', '');
|
||||
if (missingPackages.size) {
|
||||
LoggerProxy.error(
|
||||
'n8n detected that some packages are missing. For more information, visit https://docs.n8n.io/integrations/community-nodes/troubleshooting/',
|
||||
);
|
||||
|
||||
if (flags.reinstallMissingPackages || process.env.N8N_REINSTALL_MISSING_PACKAGES) {
|
||||
LoggerProxy.info('Attempting to reinstall missing packages', { missingPackages });
|
||||
try {
|
||||
// Optimistic approach - stop if any installation fails
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const missingPackage of missingPackages) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
void (await loadNodesAndCredentials.loadNpmModule(
|
||||
missingPackage.packageName,
|
||||
missingPackage.version,
|
||||
));
|
||||
missingPackages.delete(missingPackage);
|
||||
}
|
||||
LoggerProxy.info(
|
||||
'Packages reinstalled successfully. Resuming regular initialization.',
|
||||
);
|
||||
} catch (error) {
|
||||
LoggerProxy.error('n8n was unable to install the missing packages.');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (missingPackages.size) {
|
||||
config.set(
|
||||
'nodes.packagesMissing',
|
||||
Array.from(missingPackages)
|
||||
.map((missingPackage) => `${missingPackage.packageName}@${missingPackage.version}`)
|
||||
.join(' '),
|
||||
);
|
||||
}
|
||||
|
||||
if (config.getEnv('executions.mode') === 'queue') {
|
||||
const redisHost = config.getEnv('queue.bull.redis.host');
|
||||
const redisPassword = config.getEnv('queue.bull.redis.password');
|
||||
|
|
@ -269,6 +330,7 @@ export class Start extends Command {
|
|||
if (error.toString().includes('ECONNREFUSED') === true) {
|
||||
logger.warn('Redis unavailable - trying to reconnect...');
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
logger.warn('Error with Redis: ', error);
|
||||
}
|
||||
});
|
||||
|
|
@ -357,6 +419,7 @@ export class Start extends Command {
|
|||
process.stdin.setRawMode(true);
|
||||
process.stdin.resume();
|
||||
process.stdin.setEncoding('utf8');
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
let inputText = '';
|
||||
|
||||
if (flags.open) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable no-console */
|
||||
import { Command, flags } from '@oclif/command';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Not } from 'typeorm';
|
||||
import { Db } from '../../src';
|
||||
import { CredentialsEntity } from '../../src/databases/entities/CredentialsEntity';
|
||||
import { BaseCommand } from '../BaseCommand';
|
||||
|
||||
export class Reset extends BaseCommand {
|
||||
|
|
@ -31,6 +32,20 @@ export class Reset extends BaseCommand {
|
|||
await Db.collections.User.delete({ id: Not(owner.id) });
|
||||
await Db.collections.User.save(Object.assign(owner, this.defaultUserProps));
|
||||
|
||||
const danglingCredentials: CredentialsEntity[] =
|
||||
(await Db.collections.Credentials.createQueryBuilder('credentials')
|
||||
.leftJoinAndSelect('credentials.shared', 'shared')
|
||||
.where('shared.credentialsId is null')
|
||||
.getMany()) as CredentialsEntity[];
|
||||
const newSharedCredentials = danglingCredentials.map((credentials) =>
|
||||
Db.collections.SharedCredentials.create({
|
||||
credentials,
|
||||
user: owner,
|
||||
role: ownerCredentialRole,
|
||||
}),
|
||||
);
|
||||
await Db.collections.SharedCredentials.save(newSharedCredentials);
|
||||
|
||||
await Db.collections.Settings.update(
|
||||
{ key: 'userManagement.isInstanceOwnerSetUp' },
|
||||
{ value: 'false' },
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable no-console */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
|
|
@ -105,7 +106,7 @@ export class Webhook extends Command {
|
|||
* as it is unable to determine if it is still running or crashed
|
||||
* - You cannot stop currently executing jobs from webhook processes
|
||||
* when running without queues as the main process cannot talk to
|
||||
* the wehbook processes to communicate workflow execution interruption.
|
||||
* the webhook processes to communicate workflow execution interruption.
|
||||
*/
|
||||
|
||||
this.error('Webhook processes can only run with execution mode as queue.');
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable no-console */
|
||||
/* eslint-disable @typescript-eslint/no-shadow */
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
|
|
@ -12,23 +13,18 @@ import http from 'http';
|
|||
import PCancelable from 'p-cancelable';
|
||||
|
||||
import { Command, flags } from '@oclif/command';
|
||||
import { BinaryDataManager, IBinaryDataConfig, UserSettings, WorkflowExecute } from 'n8n-core';
|
||||
import { BinaryDataManager, UserSettings, WorkflowExecute } from 'n8n-core';
|
||||
|
||||
import { IExecuteResponsePromiseData, INodeTypes, IRun, Workflow, LoggerProxy } from 'n8n-workflow';
|
||||
|
||||
import { FindOneOptions, getConnectionManager } from 'typeorm';
|
||||
|
||||
import Bull from 'bull';
|
||||
import {
|
||||
CredentialsOverwrites,
|
||||
CredentialTypes,
|
||||
Db,
|
||||
ExternalHooks,
|
||||
GenericHelpers,
|
||||
IBullJobData,
|
||||
IBullJobResponse,
|
||||
IBullWebhookResponse,
|
||||
IExecutionFlattedDb,
|
||||
InternalHooksManager,
|
||||
LoadNodesAndCredentials,
|
||||
NodeTypes,
|
||||
|
|
@ -45,6 +41,7 @@ import {
|
|||
checkPermissionsForExecution,
|
||||
getWorkflowOwner,
|
||||
} from '../src/UserManagement/UserManagementHelper';
|
||||
import { generateFailedExecutionFromError } from '../src/WorkflowHelpers';
|
||||
|
||||
export class Worker extends Command {
|
||||
static description = '\nStarts a n8n worker';
|
||||
|
|
@ -63,7 +60,7 @@ export class Worker extends Command {
|
|||
[key: string]: PCancelable<IRun>;
|
||||
} = {};
|
||||
|
||||
static jobQueue: Bull.Queue;
|
||||
static jobQueue: Queue.JobQueue;
|
||||
|
||||
static processExistCode = 0;
|
||||
// static activeExecutions = ActiveExecutions.getInstance();
|
||||
|
|
@ -84,7 +81,7 @@ export class Worker extends Command {
|
|||
const externalHooks = ExternalHooks();
|
||||
await externalHooks.run('n8n.stop', []);
|
||||
|
||||
const maxStopTime = 30000;
|
||||
const maxStopTime = config.getEnv('queue.bull.gracefulShutdownTimeout') * 1000;
|
||||
|
||||
const stopTime = new Date().getTime() + maxStopTime;
|
||||
|
||||
|
|
@ -117,30 +114,28 @@ export class Worker extends Command {
|
|||
process.exit(Worker.processExistCode);
|
||||
}
|
||||
|
||||
async runJob(job: Bull.Job, nodeTypes: INodeTypes): Promise<IBullJobResponse> {
|
||||
const jobData = job.data as IBullJobData;
|
||||
const executionDb = await Db.collections.Execution.findOne(jobData.executionId);
|
||||
async runJob(job: Queue.Job, nodeTypes: INodeTypes): Promise<Queue.JobResponse> {
|
||||
const { executionId, loadStaticData } = job.data;
|
||||
const executionDb = await Db.collections.Execution.findOne(executionId);
|
||||
|
||||
if (!executionDb) {
|
||||
LoggerProxy.error(
|
||||
`Worker failed to find data of execution "${jobData.executionId}" in database. Cannot continue.`,
|
||||
{
|
||||
executionId: jobData.executionId,
|
||||
},
|
||||
`Worker failed to find data of execution "${executionId}" in database. Cannot continue.`,
|
||||
{ executionId },
|
||||
);
|
||||
throw new Error(
|
||||
`Unable to find data of execution "${jobData.executionId}" in database. Aborting execution.`,
|
||||
`Unable to find data of execution "${executionId}" in database. Aborting execution.`,
|
||||
);
|
||||
}
|
||||
const currentExecutionDb = ResponseHelper.unflattenExecutionData(executionDb);
|
||||
LoggerProxy.info(
|
||||
`Start job: ${job.id} (Workflow ID: ${currentExecutionDb.workflowData.id} | Execution: ${jobData.executionId})`,
|
||||
`Start job: ${job.id} (Workflow ID: ${currentExecutionDb.workflowData.id} | Execution: ${executionId})`,
|
||||
);
|
||||
|
||||
const workflowOwner = await getWorkflowOwner(currentExecutionDb.workflowData.id!.toString());
|
||||
|
||||
let { staticData } = currentExecutionDb.workflowData;
|
||||
if (jobData.loadStaticData) {
|
||||
if (loadStaticData) {
|
||||
const findOptions = {
|
||||
select: ['id', 'staticData'],
|
||||
} as FindOneOptions;
|
||||
|
|
@ -153,7 +148,7 @@ export class Worker extends Command {
|
|||
'Worker execution failed because workflow could not be found in database.',
|
||||
{
|
||||
workflowId: currentExecutionDb.workflowData.id,
|
||||
executionId: jobData.executionId,
|
||||
executionId,
|
||||
},
|
||||
);
|
||||
throw new Error(
|
||||
|
|
@ -189,8 +184,6 @@ export class Worker extends Command {
|
|||
settings: currentExecutionDb.workflowData.settings,
|
||||
});
|
||||
|
||||
await checkPermissionsForExecution(workflow, workflowOwner.id);
|
||||
|
||||
const additionalData = await WorkflowExecuteAdditionalData.getBase(
|
||||
workflowOwner.id,
|
||||
undefined,
|
||||
|
|
@ -203,16 +196,31 @@ export class Worker extends Command {
|
|||
{ retryOf: currentExecutionDb.retryOf as string },
|
||||
);
|
||||
|
||||
try {
|
||||
await checkPermissionsForExecution(workflow, workflowOwner.id);
|
||||
} catch (error) {
|
||||
const failedExecution = generateFailedExecutionFromError(
|
||||
currentExecutionDb.mode,
|
||||
error,
|
||||
error.node,
|
||||
);
|
||||
await additionalData.hooks.executeHookFunctions('workflowExecuteAfter', [failedExecution]);
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
}
|
||||
|
||||
additionalData.hooks.hookFunctions.sendResponse = [
|
||||
async (response: IExecuteResponsePromiseData): Promise<void> => {
|
||||
await job.progress({
|
||||
executionId: job.data.executionId as string,
|
||||
const progress: Queue.WebhookResponse = {
|
||||
executionId,
|
||||
response: WebhookHelpers.encodeWebhookResponse(response),
|
||||
} as IBullWebhookResponse);
|
||||
};
|
||||
await job.progress(progress);
|
||||
},
|
||||
];
|
||||
|
||||
additionalData.executionId = jobData.executionId;
|
||||
additionalData.executionId = executionId;
|
||||
|
||||
let workflowExecute: WorkflowExecute;
|
||||
let workflowRun: PCancelable<IRun>;
|
||||
|
|
@ -362,6 +370,8 @@ export class Worker extends Command {
|
|||
const port = config.getEnv('queue.health.port');
|
||||
|
||||
const app = express();
|
||||
app.disable('x-powered-by');
|
||||
|
||||
const server = http.createServer(app);
|
||||
|
||||
app.get(
|
||||
|
|
@ -390,7 +400,7 @@ export class Worker extends Command {
|
|||
}
|
||||
|
||||
// Just to be complete, generally will the worker stop automatically
|
||||
// if it loses the conection to redis
|
||||
// if it loses the connection to redis
|
||||
try {
|
||||
// Redis ping
|
||||
await Worker.jobQueue.client.ping();
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ export const schema = {
|
|||
// Allows to set default values for credentials which
|
||||
// get automatically prefilled and the user does not get
|
||||
// displayed and can not change.
|
||||
// Format: { CREDENTIAL_NAME: { PARAMTER: VALUE }}
|
||||
// Format: { CREDENTIAL_NAME: { PARAMETER: VALUE }}
|
||||
doc: 'Overwrites for credentials',
|
||||
format: '*',
|
||||
default: '{}',
|
||||
|
|
@ -248,7 +248,7 @@ export const schema = {
|
|||
env: 'EXECUTIONS_DATA_SAVE_ON_SUCCESS',
|
||||
},
|
||||
saveExecutionProgress: {
|
||||
doc: 'Wether or not to save progress for each node executed',
|
||||
doc: 'Whether or not to save progress for each node executed',
|
||||
format: 'Boolean',
|
||||
default: false,
|
||||
env: 'EXECUTIONS_DATA_SAVE_ON_PROGRESS',
|
||||
|
|
@ -351,13 +351,19 @@ export const schema = {
|
|||
default: 60,
|
||||
env: 'QUEUE_RECOVERY_INTERVAL',
|
||||
},
|
||||
gracefulShutdownTimeout: {
|
||||
doc: 'How long should n8n wait for running executions before exiting worker process',
|
||||
format: Number,
|
||||
default: 30,
|
||||
env: 'QUEUE_WORKER_TIMEOUT',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
generic: {
|
||||
// The timezone to use. Is important for nodes like "Cron" which start the
|
||||
// workflow automatically at a specified time. This setting can also be
|
||||
// overwritten on a per worfklow basis in the workflow settings in the
|
||||
// overwritten on a per workflow basis in the workflow settings in the
|
||||
// editor.
|
||||
timezone: {
|
||||
doc: 'The timezone to use',
|
||||
|
|
@ -601,7 +607,7 @@ export const schema = {
|
|||
format: Boolean,
|
||||
default: false,
|
||||
env: 'N8N_WORKFLOW_TAGS_DISABLED',
|
||||
doc: 'Disable worfklow tags.',
|
||||
doc: 'Disable workflow tags.',
|
||||
},
|
||||
|
||||
userManagement: {
|
||||
|
|
@ -681,6 +687,13 @@ export const schema = {
|
|||
},
|
||||
},
|
||||
|
||||
externalFrontendHooksUrls: {
|
||||
doc: 'URLs to external frontend hooks files, ; separated',
|
||||
format: String,
|
||||
default: 'https://public.n8n.cloud/posthog-hooks.js',
|
||||
env: 'EXTERNAL_FRONTEND_HOOKS_URLS',
|
||||
},
|
||||
|
||||
externalHookFiles: {
|
||||
doc: 'Files containing external hooks. Multiple files can be separated by colon (":")',
|
||||
format: String,
|
||||
|
|
@ -740,6 +753,14 @@ export const schema = {
|
|||
default: 'n8n-nodes-base.errorTrigger',
|
||||
env: 'NODES_ERROR_TRIGGER_TYPE',
|
||||
},
|
||||
communityPackages: {
|
||||
enabled: {
|
||||
doc: 'Allows you to disable the usage of community packages for nodes',
|
||||
format: Boolean,
|
||||
default: true,
|
||||
env: 'N8N_COMMUNITY_PACKAGES_ENABLED',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
logs: {
|
||||
|
|
@ -854,6 +875,21 @@ export const schema = {
|
|||
},
|
||||
},
|
||||
|
||||
enterprise: {
|
||||
features: {
|
||||
sharing: {
|
||||
format: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
// This is a temporary flag (acting as feature toggle)
|
||||
// Will be removed when feature goes live
|
||||
workflowSharingEnabled: {
|
||||
format: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
hiringBanner: {
|
||||
enabled: {
|
||||
doc: 'Whether hiring banner in browser console is enabled.',
|
||||
|
|
@ -880,6 +916,26 @@ export const schema = {
|
|||
env: 'N8N_DIAGNOSTICS_ENABLED',
|
||||
},
|
||||
config: {
|
||||
posthog: {
|
||||
apiKey: {
|
||||
doc: 'API key for PostHog',
|
||||
format: String,
|
||||
default: 'phc_4URIAm1uYfJO7j8kWSe0J8lc8IqnstRLS7Jx8NcakHo',
|
||||
env: 'N8N_DIAGNOSTICS_POSTHOG_API_KEY',
|
||||
},
|
||||
apiHost: {
|
||||
doc: 'API host for PostHog',
|
||||
format: String,
|
||||
default: 'https://app.posthog.com',
|
||||
env: 'N8N_DIAGNOSTICS_POSTHOG_API_HOST',
|
||||
},
|
||||
disableSessionRecording: {
|
||||
doc: 'Disable posthog session recording',
|
||||
format: Boolean,
|
||||
default: true,
|
||||
env: 'N8N_DIAGNOSTICS_POSTHOG_DISABLE_RECORDING',
|
||||
},
|
||||
},
|
||||
frontend: {
|
||||
doc: 'Diagnostics config for frontend.',
|
||||
format: String,
|
||||
|
|
@ -901,4 +957,13 @@ export const schema = {
|
|||
default: 'en',
|
||||
env: 'N8N_DEFAULT_LOCALE',
|
||||
},
|
||||
|
||||
onboardingCallPrompt: {
|
||||
enabled: {
|
||||
doc: 'Whether onboarding call prompt feature is available',
|
||||
format: Boolean,
|
||||
default: true,
|
||||
env: 'N8N_ONBOARDING_CALL_PROMPTS_ENABLED',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
1
packages/cli/config/types.d.ts
vendored
1
packages/cli/config/types.d.ts
vendored
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
|
||||
import { IBinaryDataConfig } from '../../core/dist/src';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
module.exports = {
|
||||
verbose: true,
|
||||
transform: {
|
||||
'^.+\\.ts?$': 'ts-jest',
|
||||
'^.+\\.ts$': 'ts-jest',
|
||||
},
|
||||
testURL: 'http://localhost/',
|
||||
testRegex: '(/__tests__/.*|(\\.|/)(test))\\.ts$',
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n",
|
||||
"version": "0.186.1",
|
||||
"version": "0.197.1",
|
||||
"description": "n8n Workflow Automation Tool",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
|
|
@ -22,18 +22,18 @@
|
|||
"build": "node scripts/build.mjs",
|
||||
"dev": "concurrently -k -n \"TypeScript,Node\" -c \"yellow.bold,cyan.bold\" \"npm run watch\" \"nodemon\"",
|
||||
"format": "cd ../.. && node_modules/prettier/bin-prettier.js packages/cli/**/**.ts --write",
|
||||
"lint": "cd ../.. && node_modules/eslint/bin/eslint.js packages/cli",
|
||||
"lintfix": "cd ../.. && node_modules/eslint/bin/eslint.js packages/cli --fix",
|
||||
"lint": "eslint .",
|
||||
"lintfix": "eslint . --fix",
|
||||
"postpack": "rm -f oclif.manifest.json",
|
||||
"prepack": "oclif-dev manifest",
|
||||
"start": "run-script-os",
|
||||
"start:default": "cd bin && ./n8n",
|
||||
"start:windows": "cd bin && n8n",
|
||||
"test": "npm run test:sqlite",
|
||||
"test:sqlite": "export N8N_LOG_LEVEL=silent && export DB_TYPE=sqlite && jest --forceExit",
|
||||
"test:postgres": "export N8N_LOG_LEVEL=silent && export DB_TYPE=postgresdb && jest",
|
||||
"test:postgres:alt-schema": "export DB_POSTGRESDB_SCHEMA=alt_schema && npm run test:postgres",
|
||||
"test:mysql": "export N8N_LOG_LEVEL=silent && export DB_TYPE=mysqldb && jest",
|
||||
"test:sqlite": "N8N_LOG_LEVEL=silent DB_TYPE=sqlite jest",
|
||||
"test:postgres": "N8N_LOG_LEVEL=silent DB_TYPE=postgresdb jest",
|
||||
"test:postgres:alt-schema": "DB_POSTGRESDB_SCHEMA=alt_schema npm run test:postgres",
|
||||
"test:mysql": "N8N_LOG_LEVEL=silent DB_TYPE=mysqldb jest",
|
||||
"watch": "tsc --watch",
|
||||
"typeorm": "ts-node -T ../../node_modules/typeorm/cli.js"
|
||||
},
|
||||
|
|
@ -58,6 +58,8 @@
|
|||
"oclif.manifest.json"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@apidevtools/swagger-cli": "4.0.0",
|
||||
"@n8n_io/eslint-config": "",
|
||||
"@oclif/dev-cli": "^1.22.2",
|
||||
"@types/basic-auth": "^1.1.2",
|
||||
"@types/bcryptjs": "^2.4.2",
|
||||
|
|
@ -66,49 +68,47 @@
|
|||
"@types/connect-history-api-fallback": "^1.3.1",
|
||||
"@types/convict": "^4.2.1",
|
||||
"@types/cookie-parser": "^1.4.2",
|
||||
"@types/dotenv": "^8.2.0",
|
||||
"@types/express": "^4.17.6",
|
||||
"@types/jest": "^27.4.0",
|
||||
"@types/json-diff": "^0.5.1",
|
||||
"@types/jsonwebtoken": "^8.5.2",
|
||||
"@types/localtunnel": "^1.9.0",
|
||||
"@types/lodash.get": "^4.4.6",
|
||||
"@types/lodash.intersection": "^4.4.7",
|
||||
"@types/lodash.merge": "^4.6.6",
|
||||
"@types/lodash.omit": "^4.5.7",
|
||||
"@types/lodash.pick": "^4.4.7",
|
||||
"@types/lodash.set": "^4.3.6",
|
||||
"@types/lodash.split": "^4.4.7",
|
||||
"@types/lodash.unset": "^4.5.7",
|
||||
"@types/node": "^16.11.22",
|
||||
"@types/open": "^6.1.0",
|
||||
"@types/parseurl": "^1.3.1",
|
||||
"@types/passport-jwt": "^3.0.6",
|
||||
"@types/psl": "^1.1.0",
|
||||
"@types/request-promise-native": "~1.0.15",
|
||||
"@types/send": "^0.17.1",
|
||||
"@types/shelljs": "^0.8.11",
|
||||
"@types/superagent": "4.1.13",
|
||||
"@types/supertest": "^2.0.11",
|
||||
"@types/uuid": "^8.3.0",
|
||||
"@types/swagger-ui-express": "^4.1.3",
|
||||
"@types/uuid": "^8.3.2",
|
||||
"@types/validator": "^13.7.0",
|
||||
"axios": "^0.21.1",
|
||||
"@types/yamljs": "^0.2.31",
|
||||
"concurrently": "^5.1.0",
|
||||
"jest": "^27.4.7",
|
||||
"jest-mock": "^28.1.3",
|
||||
"nodemon": "^2.0.2",
|
||||
"run-script-os": "^1.0.7",
|
||||
"supertest": "^6.2.2",
|
||||
"ts-jest": "^27.1.3",
|
||||
"ts-node": "^8.9.1",
|
||||
"tslint": "^6.1.2",
|
||||
"typescript": "~4.6.0"
|
||||
"typescript": "~4.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@oclif/core": "^1.9.3",
|
||||
"@apidevtools/swagger-cli": "4.0.0",
|
||||
"@oclif/command": "^1.5.18",
|
||||
"@oclif/core": "^1.9.3",
|
||||
"@oclif/errors": "^1.2.2",
|
||||
"@rudderstack/rudder-sdk-node": "1.0.6",
|
||||
"@types/json-diff": "^0.5.1",
|
||||
"@types/jsonwebtoken": "^8.5.2",
|
||||
"@types/lodash.intersection": "^4.4.7",
|
||||
"@types/shelljs": "^0.8.11",
|
||||
"@types/swagger-ui-express": "^4.1.3",
|
||||
"@types/yamljs": "^0.2.31",
|
||||
"axios": "^0.21.1",
|
||||
"basic-auth": "^2.0.1",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"body-parser": "^1.18.3",
|
||||
|
|
@ -122,14 +122,16 @@
|
|||
"connect-history-api-fallback": "^1.6.0",
|
||||
"convict": "^6.0.1",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"crypto-js": "^4.1.1",
|
||||
"crypto-js": "~4.1.1",
|
||||
"csrf": "^3.1.0",
|
||||
"curlconverter": "^3.0.0",
|
||||
"dotenv": "^8.0.0",
|
||||
"express": "^4.16.4",
|
||||
"express-openapi-validator": "^4.13.6",
|
||||
"fast-glob": "^3.2.5",
|
||||
"flatted": "^3.2.4",
|
||||
"google-timezones-json": "^1.0.2",
|
||||
"handlebars": "4.7.7",
|
||||
"inquirer": "^7.0.1",
|
||||
"json-diff": "^0.5.4",
|
||||
"jsonschema": "^1.4.1",
|
||||
|
|
@ -140,33 +142,34 @@
|
|||
"lodash.intersection": "^4.4.0",
|
||||
"lodash.merge": "^4.6.2",
|
||||
"lodash.omit": "^4.5.0",
|
||||
"lodash.pick": "^4.4.0",
|
||||
"lodash.set": "^4.3.2",
|
||||
"lodash.split": "^4.4.2",
|
||||
"lodash.unset": "^4.5.2",
|
||||
"mysql2": "~2.3.0",
|
||||
"n8n-core": "~0.126.0",
|
||||
"n8n-editor-ui": "~0.152.0",
|
||||
"n8n-nodes-base": "~0.184.1",
|
||||
"n8n-workflow": "~0.108.0",
|
||||
"n8n-core": "~0.137.0",
|
||||
"n8n-editor-ui": "~0.163.1",
|
||||
"n8n-nodes-base": "~0.195.1",
|
||||
"n8n-workflow": "~0.119.0",
|
||||
"nodemailer": "^6.7.1",
|
||||
"oauth-1.0a": "^2.2.6",
|
||||
"open": "^7.0.0",
|
||||
"openapi-types": "^10.0.0",
|
||||
"p-cancelable": "^2.0.0",
|
||||
"passport": "^0.5.0",
|
||||
"passport": "^0.6.0",
|
||||
"passport-cookie": "^1.0.9",
|
||||
"passport-jwt": "^4.0.0",
|
||||
"pg": "^8.3.0",
|
||||
"posthog-node": "^1.3.0",
|
||||
"prom-client": "^13.1.0",
|
||||
"psl": "^1.8.0",
|
||||
"request-promise-native": "^1.0.7",
|
||||
"shelljs": "^0.8.5",
|
||||
"sqlite3": "^5.0.2",
|
||||
"sse-channel": "^3.1.1",
|
||||
"swagger-ui-express": "^4.3.0",
|
||||
"tslib": "1.14.1",
|
||||
"typeorm": "0.2.45",
|
||||
"uuid": "^8.3.0",
|
||||
"uuid": "^8.3.2",
|
||||
"validator": "13.7.0",
|
||||
"winston": "^3.3.3",
|
||||
"yamljs": "^0.3.0"
|
||||
|
|
|
|||
|
|
@ -14,7 +14,12 @@ const publicApiEnabled = process.env.N8N_PUBLIC_API_DISABLED !== 'true';
|
|||
|
||||
shell.rm('-rf', path.resolve(ROOT_DIR, 'dist'));
|
||||
|
||||
shell.exec('tsc');
|
||||
const tscCompilation = shell.exec('tsc', { silent: true })
|
||||
if (tscCompilation.code !== 0) {
|
||||
shell.echo('Typescript Compilation failed:');
|
||||
shell.echo(tscCompilation.stdout);
|
||||
shell.exit(1);
|
||||
}
|
||||
|
||||
if (userManagementEnabled) {
|
||||
copyUserManagementEmailTemplates();
|
||||
|
|
|
|||
|
|
@ -36,10 +36,6 @@ export class ActiveExecutions {
|
|||
/**
|
||||
* Add a new active execution
|
||||
*
|
||||
* @param {ChildProcess} process
|
||||
* @param {IWorkflowExecutionDataProcess} executionData
|
||||
* @returns {string}
|
||||
* @memberof ActiveExecutions
|
||||
*/
|
||||
async add(
|
||||
executionData: IWorkflowExecutionDataProcess,
|
||||
|
|
@ -103,9 +99,6 @@ export class ActiveExecutions {
|
|||
/**
|
||||
* Attaches an execution
|
||||
*
|
||||
* @param {string} executionId
|
||||
* @param {PCancelable<IRun>} workflowExecution
|
||||
* @memberof ActiveExecutions
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
attachWorkflowExecution(executionId: string, workflowExecution: PCancelable<IRun>) {
|
||||
|
|
@ -143,10 +136,6 @@ export class ActiveExecutions {
|
|||
/**
|
||||
* Remove an active execution
|
||||
*
|
||||
* @param {string} executionId
|
||||
* @param {IRun} fullRunData
|
||||
* @returns {void}
|
||||
* @memberof ActiveExecutions
|
||||
*/
|
||||
remove(executionId: string, fullRunData?: IRun): void {
|
||||
if (this.activeExecutions[executionId] === undefined) {
|
||||
|
|
@ -168,8 +157,6 @@ export class ActiveExecutions {
|
|||
*
|
||||
* @param {string} executionId The id of the execution to stop
|
||||
* @param {string} timeout String 'timeout' given if stop due to timeout
|
||||
* @returns {(Promise<IRun | undefined>)}
|
||||
* @memberof ActiveExecutions
|
||||
*/
|
||||
async stopExecution(executionId: string, timeout?: string): Promise<IRun | undefined> {
|
||||
if (this.activeExecutions[executionId] === undefined) {
|
||||
|
|
@ -204,8 +191,6 @@ export class ActiveExecutions {
|
|||
* with the given id
|
||||
*
|
||||
* @param {string} executionId The id of the execution to wait for
|
||||
* @returns {Promise<IRun>}
|
||||
* @memberof ActiveExecutions
|
||||
*/
|
||||
async getPostExecutePromise(executionId: string): Promise<IRun | undefined> {
|
||||
// Create the promise which will be resolved when the execution finished
|
||||
|
|
@ -224,8 +209,6 @@ export class ActiveExecutions {
|
|||
/**
|
||||
* Returns all the currently active executions
|
||||
*
|
||||
* @returns {IExecutionsCurrentSummary[]}
|
||||
* @memberof ActiveExecutions
|
||||
*/
|
||||
getActiveExecutions(): IExecutionsCurrentSummary[] {
|
||||
const returnData: IExecutionsCurrentSummary[] = [];
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import express from 'express';
|
|||
import {
|
||||
Db,
|
||||
IActivationError,
|
||||
IQueuedWorkflowActivations,
|
||||
IResponseCallbackData,
|
||||
IWebhookDb,
|
||||
IWorkflowDb,
|
||||
|
|
@ -57,6 +58,8 @@ import { User } from './databases/entities/User';
|
|||
import { whereClause } from './WorkflowHelpers';
|
||||
import { WorkflowEntity } from './databases/entities/WorkflowEntity';
|
||||
import * as ActiveExecutions from './ActiveExecutions';
|
||||
import { createErrorExecution } from './GenericHelpers';
|
||||
import { WORKFLOW_REACTIVATE_INITIAL_TIMEOUT, WORKFLOW_REACTIVATE_MAX_TIMEOUT } from './constants';
|
||||
|
||||
const activeExecutions = ActiveExecutions.getInstance();
|
||||
|
||||
|
|
@ -69,13 +72,17 @@ export class ActiveWorkflowRunner {
|
|||
[key: string]: IActivationError;
|
||||
} = {};
|
||||
|
||||
private queuedWorkflowActivations: {
|
||||
[key: string]: IQueuedWorkflowActivations;
|
||||
} = {};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
async init() {
|
||||
// Get the active workflows from database
|
||||
|
||||
// NOTE
|
||||
// Here I guess we can have a flag on the workflow table like hasTrigger
|
||||
// so intead of pulling all the active wehhooks just pull the actives that have a trigger
|
||||
// so instead of pulling all the active webhooks just pull the actives that have a trigger
|
||||
const workflowsData: IWorkflowDb[] = (await Db.collections.Workflow.find({
|
||||
where: { active: true },
|
||||
relations: ['shared', 'shared.user', 'shared.user.globalRole'],
|
||||
|
|
@ -101,7 +108,7 @@ export class ActiveWorkflowRunner {
|
|||
console.info(' ================================');
|
||||
|
||||
for (const workflowData of workflowsData) {
|
||||
console.log(` - ${workflowData.name}`);
|
||||
console.log(` - ${workflowData.name} (ID: ${workflowData.id})`);
|
||||
Logger.debug(`Initializing active workflow "${workflowData.name}" (startup)`, {
|
||||
workflowName: workflowData.name,
|
||||
workflowId: workflowData.id,
|
||||
|
|
@ -114,14 +121,23 @@ export class ActiveWorkflowRunner {
|
|||
});
|
||||
console.log(` => Started`);
|
||||
} catch (error) {
|
||||
console.log(` => ERROR: Workflow could not be activated`);
|
||||
console.log(
|
||||
` => ERROR: Workflow could not be activated on first try, keep on trying`,
|
||||
);
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
console.log(` ${error.message}`);
|
||||
Logger.error(`Unable to initialize workflow "${workflowData.name}" (startup)`, {
|
||||
workflowName: workflowData.name,
|
||||
workflowId: workflowData.id,
|
||||
});
|
||||
Logger.error(
|
||||
`Issue on intital workflow activation try "${workflowData.name}" (startup)`,
|
||||
{
|
||||
workflowName: workflowData.name,
|
||||
workflowId: workflowData.id,
|
||||
},
|
||||
);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
this.executeErrorWorkflow(error, workflowData, 'internal');
|
||||
|
||||
// Keep on trying to activate the workflow
|
||||
this.addQueuedWorkflowActivation('init', workflowData);
|
||||
}
|
||||
}
|
||||
Logger.verbose('Finished initializing active workflows (startup)');
|
||||
|
|
@ -138,8 +154,6 @@ export class ActiveWorkflowRunner {
|
|||
/**
|
||||
* Removes all the currently active workflows
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
* @memberof ActiveWorkflowRunner
|
||||
*/
|
||||
async removeAll(): Promise<void> {
|
||||
let activeWorkflowIds: string[] = [];
|
||||
|
|
@ -169,12 +183,6 @@ export class ActiveWorkflowRunner {
|
|||
/**
|
||||
* Checks if a webhook for the given method and path exists and executes the workflow.
|
||||
*
|
||||
* @param {WebhookHttpMethod} httpMethod
|
||||
* @param {string} path
|
||||
* @param {express.Request} req
|
||||
* @param {express.Response} res
|
||||
* @returns {Promise<object>}
|
||||
* @memberof ActiveWorkflowRunner
|
||||
*/
|
||||
async executeWebhook(
|
||||
httpMethod: WebhookHttpMethod,
|
||||
|
|
@ -182,7 +190,7 @@ export class ActiveWorkflowRunner {
|
|||
req: express.Request,
|
||||
res: express.Response,
|
||||
): Promise<IResponseCallbackData> {
|
||||
Logger.debug(`Received webhoook "${httpMethod}" for path "${path}"`);
|
||||
Logger.debug(`Received webhook "${httpMethod}" for path "${path}"`);
|
||||
if (this.activeWorkflows === null) {
|
||||
throw new ResponseHelper.ResponseError(
|
||||
'The "activeWorkflows" instance did not get initialized yet.',
|
||||
|
|
@ -338,8 +346,6 @@ export class ActiveWorkflowRunner {
|
|||
* Gets all request methods associated with a single webhook
|
||||
*
|
||||
* @param {string} path webhook path
|
||||
* @returns {Promise<string[]>}
|
||||
* @memberof ActiveWorkflowRunner
|
||||
*/
|
||||
async getWebhookMethods(path: string): Promise<string[]> {
|
||||
const webhooks = await Db.collections.Webhook.find({ webhookPath: path });
|
||||
|
|
@ -352,8 +358,6 @@ export class ActiveWorkflowRunner {
|
|||
/**
|
||||
* Returns the ids of the currently active workflows
|
||||
*
|
||||
* @returns {string[]}
|
||||
* @memberof ActiveWorkflowRunner
|
||||
*/
|
||||
async getActiveWorkflows(user?: User): Promise<IWorkflowDb[]> {
|
||||
let activeWorkflows: WorkflowEntity[] = [];
|
||||
|
|
@ -385,8 +389,6 @@ export class ActiveWorkflowRunner {
|
|||
* Returns if the workflow is active
|
||||
*
|
||||
* @param {string} id The id of the workflow to check
|
||||
* @returns {boolean}
|
||||
* @memberof ActiveWorkflowRunner
|
||||
*/
|
||||
async isActive(id: string): Promise<boolean> {
|
||||
const workflow = await Db.collections.Workflow.findOne(id);
|
||||
|
|
@ -397,8 +399,6 @@ export class ActiveWorkflowRunner {
|
|||
* Return error if there was a problem activating the workflow
|
||||
*
|
||||
* @param {string} id The id of the workflow to return the error of
|
||||
* @returns {(IActivationError | undefined)}
|
||||
* @memberof ActiveWorkflowRunner
|
||||
*/
|
||||
getActivationError(id: string): IActivationError | undefined {
|
||||
if (this.activationErrors[id] === undefined) {
|
||||
|
|
@ -411,11 +411,6 @@ export class ActiveWorkflowRunner {
|
|||
/**
|
||||
* Adds all the webhooks of the workflow
|
||||
*
|
||||
* @param {Workflow} workflow
|
||||
* @param {IWorkflowExecuteAdditionalDataWorkflow} additionalData
|
||||
* @param {WorkflowExecuteMode} mode
|
||||
* @returns {Promise<void>}
|
||||
* @memberof ActiveWorkflowRunner
|
||||
*/
|
||||
async addWorkflowWebhooks(
|
||||
workflow: Workflow,
|
||||
|
|
@ -479,7 +474,7 @@ export class ActiveWorkflowRunner {
|
|||
config.getEnv('endpoints.skipWebhoooksDeregistrationOnShutdown') &&
|
||||
error.name === 'QueryFailedError'
|
||||
) {
|
||||
// When skipWebhoooksDeregistrationOnShutdown is enabled,
|
||||
// When skipWebhooksDeregistrationOnShutdown is enabled,
|
||||
// n8n does not remove the registered webhooks on exit.
|
||||
// This means that further initializations will always fail
|
||||
// when inserting to database. This is why we ignore this error
|
||||
|
|
@ -503,7 +498,7 @@ export class ActiveWorkflowRunner {
|
|||
if (error.name === 'QueryFailedError') {
|
||||
error.message = `The URL path that the "${webhook.node}" node uses is already taken. Please change it to something else.`;
|
||||
} else if (error.detail) {
|
||||
// it's a error runnig the webhook methods (checkExists, create)
|
||||
// it's a error running the webhook methods (checkExists, create)
|
||||
error.message = error.detail;
|
||||
}
|
||||
|
||||
|
|
@ -517,9 +512,6 @@ export class ActiveWorkflowRunner {
|
|||
/**
|
||||
* Remove all the webhooks of the workflow
|
||||
*
|
||||
* @param {string} workflowId
|
||||
* @returns
|
||||
* @memberof ActiveWorkflowRunner
|
||||
*/
|
||||
async removeWorkflowWebhooks(workflowId: string): Promise<void> {
|
||||
const workflowData = await Db.collections.Workflow.findOne(workflowId, {
|
||||
|
|
@ -572,13 +564,6 @@ export class ActiveWorkflowRunner {
|
|||
/**
|
||||
* Runs the given workflow
|
||||
*
|
||||
* @param {IWorkflowDb} workflowData
|
||||
* @param {INode} node
|
||||
* @param {INodeExecutionData[][]} data
|
||||
* @param {IWorkflowExecuteAdditionalDataWorkflow} additionalData
|
||||
* @param {WorkflowExecuteMode} mode
|
||||
* @returns
|
||||
* @memberof ActiveWorkflowRunner
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
async runWorkflow(
|
||||
|
|
@ -628,11 +613,6 @@ export class ActiveWorkflowRunner {
|
|||
* Return poll function which gets the global functions from n8n-core
|
||||
* and overwrites the __emit to be able to start it in subprocess
|
||||
*
|
||||
* @param {IWorkflowDb} workflowData
|
||||
* @param {IWorkflowExecuteAdditionalDataWorkflow} additionalData
|
||||
* @param {WorkflowExecuteMode} mode
|
||||
* @returns {IGetExecutePollFunctions}
|
||||
* @memberof ActiveWorkflowRunner
|
||||
*/
|
||||
getExecutePollFunctions(
|
||||
workflowData: IWorkflowDb,
|
||||
|
|
@ -649,9 +629,17 @@ export class ActiveWorkflowRunner {
|
|||
activation,
|
||||
);
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
returnFunctions.__emit = (data: INodeExecutionData[][]): void => {
|
||||
returnFunctions.__emit = async (
|
||||
data: INodeExecutionData[][] | ExecutionError,
|
||||
): Promise<void> => {
|
||||
if (data instanceof Error) {
|
||||
await createErrorExecution(data, node, workflowData, workflow, mode);
|
||||
this.executeErrorWorkflow(data, workflowData, mode);
|
||||
return;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
Logger.debug(`Received event to trigger execution for workflow "${workflow.name}"`);
|
||||
WorkflowHelpers.saveStaticData(workflow);
|
||||
this.runWorkflow(workflowData, node, data, additionalData, mode);
|
||||
};
|
||||
return returnFunctions;
|
||||
|
|
@ -662,11 +650,6 @@ export class ActiveWorkflowRunner {
|
|||
* Return trigger function which gets the global functions from n8n-core
|
||||
* and overwrites the emit to be able to start it in subprocess
|
||||
*
|
||||
* @param {IWorkflowDb} workflowData
|
||||
* @param {IWorkflowExecuteAdditionalDataWorkflow} additionalData
|
||||
* @param {WorkflowExecuteMode} mode
|
||||
* @returns {IGetExecuteTriggerFunctions}
|
||||
* @memberof ActiveWorkflowRunner
|
||||
*/
|
||||
getExecuteTriggerFunctions(
|
||||
workflowData: IWorkflowDb,
|
||||
|
|
@ -712,6 +695,17 @@ export class ActiveWorkflowRunner {
|
|||
}
|
||||
};
|
||||
returnFunctions.emitError = async (error: Error): Promise<void> => {
|
||||
Logger.info(
|
||||
`The trigger node "${node.name}" of workflow "${workflowData.name}" failed with the error: "${error.message}". Will try to reactivate.`,
|
||||
{
|
||||
nodeName: node.name,
|
||||
workflowId: workflowData.id.toString(),
|
||||
workflowName: workflowData.name,
|
||||
},
|
||||
);
|
||||
|
||||
// Remove the workflow as "active"
|
||||
|
||||
await this.activeWorkflows?.remove(workflowData.id.toString());
|
||||
this.activationErrors[workflowData.id.toString()] = {
|
||||
time: new Date().getTime(),
|
||||
|
|
@ -719,13 +713,16 @@ export class ActiveWorkflowRunner {
|
|||
message: error.message,
|
||||
},
|
||||
};
|
||||
|
||||
// Run Error Workflow if defined
|
||||
const activationError = new WorkflowActivationError(
|
||||
'There was a problem with the trigger, for that reason did the workflow had to be deactivated',
|
||||
`There was a problem with the trigger node "${node.name}", for that reason did the workflow had to be deactivated`,
|
||||
error,
|
||||
node,
|
||||
);
|
||||
|
||||
this.executeErrorWorkflow(activationError, workflowData, mode);
|
||||
|
||||
this.addQueuedWorkflowActivation(activation, workflowData);
|
||||
};
|
||||
return returnFunctions;
|
||||
};
|
||||
|
|
@ -757,8 +754,6 @@ export class ActiveWorkflowRunner {
|
|||
*
|
||||
* @param {string} workflowId The id of the workflow to activate
|
||||
* @param {IWorkflowDb} [workflowData] If workflowData is given it saves the DB query
|
||||
* @returns {Promise<void>}
|
||||
* @memberof ActiveWorkflowRunner
|
||||
*/
|
||||
async add(
|
||||
workflowId: string,
|
||||
|
|
@ -841,6 +836,9 @@ export class ActiveWorkflowRunner {
|
|||
});
|
||||
}
|
||||
|
||||
// Workflow got now successfully activated so make sure nothing is left in the queue
|
||||
this.removeQueuedWorkflowActivation(workflowId);
|
||||
|
||||
if (this.activationErrors[workflowId] !== undefined) {
|
||||
// If there were activation errors delete them
|
||||
delete this.activationErrors[workflowId];
|
||||
|
|
@ -864,12 +862,86 @@ export class ActiveWorkflowRunner {
|
|||
await WorkflowHelpers.saveStaticData(workflowInstance!);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a workflow to the activation queue.
|
||||
* Meaning it will keep on trying to activate it in regular
|
||||
* amounts indefinetly.
|
||||
*/
|
||||
addQueuedWorkflowActivation(
|
||||
activationMode: WorkflowActivateMode,
|
||||
workflowData: IWorkflowDb,
|
||||
): void {
|
||||
const workflowId = workflowData.id.toString();
|
||||
const workflowName = workflowData.name;
|
||||
|
||||
const retryFunction = async () => {
|
||||
Logger.info(`Try to activate workflow "${workflowName}" (${workflowId})`, {
|
||||
workflowId,
|
||||
workflowName,
|
||||
});
|
||||
try {
|
||||
await this.add(workflowId, activationMode, workflowData);
|
||||
} catch (error) {
|
||||
let lastTimeout = this.queuedWorkflowActivations[workflowId].lastTimeout;
|
||||
if (lastTimeout < WORKFLOW_REACTIVATE_MAX_TIMEOUT) {
|
||||
lastTimeout = Math.min(lastTimeout * 2, WORKFLOW_REACTIVATE_MAX_TIMEOUT);
|
||||
}
|
||||
|
||||
Logger.info(
|
||||
` -> Activation of workflow "${workflowName}" (${workflowId}) did fail with error: "${
|
||||
error.message as string
|
||||
}" | retry in ${Math.floor(lastTimeout / 1000)} seconds`,
|
||||
{
|
||||
workflowId,
|
||||
workflowName,
|
||||
},
|
||||
);
|
||||
|
||||
this.queuedWorkflowActivations[workflowId].lastTimeout = lastTimeout;
|
||||
this.queuedWorkflowActivations[workflowId].timeout = setTimeout(retryFunction, lastTimeout);
|
||||
return;
|
||||
}
|
||||
Logger.info(` -> Activation of workflow "${workflowName}" (${workflowId}) was successful!`, {
|
||||
workflowId,
|
||||
workflowName,
|
||||
});
|
||||
};
|
||||
|
||||
// Just to be sure that there is not chance that for any reason
|
||||
// multiple run in parallel
|
||||
this.removeQueuedWorkflowActivation(workflowId);
|
||||
|
||||
this.queuedWorkflowActivations[workflowId] = {
|
||||
activationMode,
|
||||
lastTimeout: WORKFLOW_REACTIVATE_INITIAL_TIMEOUT,
|
||||
timeout: setTimeout(retryFunction, WORKFLOW_REACTIVATE_INITIAL_TIMEOUT),
|
||||
workflowData,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a workflow from the activation queue
|
||||
*/
|
||||
removeQueuedWorkflowActivation(workflowId: string): void {
|
||||
if (this.queuedWorkflowActivations[workflowId]) {
|
||||
clearTimeout(this.queuedWorkflowActivations[workflowId].timeout);
|
||||
delete this.queuedWorkflowActivations[workflowId];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all workflows from the activation queue
|
||||
*/
|
||||
removeAllQueuedWorkflowActivations(): void {
|
||||
for (const workflowId in this.queuedWorkflowActivations) {
|
||||
this.removeQueuedWorkflowActivation(workflowId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a workflow inactive
|
||||
*
|
||||
* @param {string} workflowId The id of the workflow to deactivate
|
||||
* @returns {Promise<void>}
|
||||
* @memberof ActiveWorkflowRunner
|
||||
*/
|
||||
async remove(workflowId: string): Promise<void> {
|
||||
if (this.activeWorkflows !== null) {
|
||||
|
|
@ -888,6 +960,10 @@ export class ActiveWorkflowRunner {
|
|||
delete this.activationErrors[workflowId];
|
||||
}
|
||||
|
||||
if (this.queuedWorkflowActivations[workflowId] !== undefined) {
|
||||
this.removeQueuedWorkflowActivation(workflowId);
|
||||
}
|
||||
|
||||
// if it's active in memory then it's a trigger
|
||||
// so remove from list of actives workflows
|
||||
if (this.activeWorkflows.isActive(workflowId)) {
|
||||
|
|
|
|||
247
packages/cli/src/CommunityNodes/helpers.ts
Normal file
247
packages/cli/src/CommunityNodes/helpers.ts
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
/* eslint-disable no-restricted-syntax */
|
||||
/* eslint-disable import/no-cycle */
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { promisify } from 'util';
|
||||
import { exec } from 'child_process';
|
||||
import { access as fsAccess, mkdir as fsMkdir } from 'fs/promises';
|
||||
import { createContext, Script } from 'vm';
|
||||
import axios from 'axios';
|
||||
import { UserSettings } from 'n8n-core';
|
||||
import { LoggerProxy, PublicInstalledPackage } from 'n8n-workflow';
|
||||
|
||||
import {
|
||||
NODE_PACKAGE_PREFIX,
|
||||
NPM_COMMAND_TOKENS,
|
||||
NPM_PACKAGE_STATUS_GOOD,
|
||||
RESPONSE_ERROR_MESSAGES,
|
||||
UNKNOWN_FAILURE_REASON,
|
||||
} from '../constants';
|
||||
import { InstalledPackages } from '../databases/entities/InstalledPackages';
|
||||
import config from '../../config';
|
||||
|
||||
import type { CommunityPackages } from '../Interfaces';
|
||||
|
||||
const {
|
||||
PACKAGE_NAME_NOT_PROVIDED,
|
||||
DISK_IS_FULL,
|
||||
PACKAGE_FAILED_TO_INSTALL,
|
||||
PACKAGE_VERSION_NOT_FOUND,
|
||||
PACKAGE_DOES_NOT_CONTAIN_NODES,
|
||||
PACKAGE_NOT_FOUND,
|
||||
} = RESPONSE_ERROR_MESSAGES;
|
||||
|
||||
const {
|
||||
NPM_PACKAGE_NOT_FOUND_ERROR,
|
||||
NPM_NO_VERSION_AVAILABLE,
|
||||
NPM_DISK_NO_SPACE,
|
||||
NPM_DISK_INSUFFICIENT_SPACE,
|
||||
NPM_PACKAGE_VERSION_NOT_FOUND_ERROR,
|
||||
} = NPM_COMMAND_TOKENS;
|
||||
|
||||
const execAsync = promisify(exec);
|
||||
|
||||
const INVALID_OR_SUSPICIOUS_PACKAGE_NAME = /[^0-9a-z@\-./]/;
|
||||
|
||||
export const parseNpmPackageName = (rawString?: string): CommunityPackages.ParsedPackageName => {
|
||||
if (!rawString) throw new Error(PACKAGE_NAME_NOT_PROVIDED);
|
||||
|
||||
if (INVALID_OR_SUSPICIOUS_PACKAGE_NAME.test(rawString))
|
||||
throw new Error('Package name must be a single word');
|
||||
|
||||
const scope = rawString.includes('/') ? rawString.split('/')[0] : undefined;
|
||||
|
||||
const packageNameWithoutScope = scope ? rawString.replace(`${scope}/`, '') : rawString;
|
||||
|
||||
if (!packageNameWithoutScope.startsWith(NODE_PACKAGE_PREFIX)) {
|
||||
throw new Error(`Package name must start with ${NODE_PACKAGE_PREFIX}`);
|
||||
}
|
||||
|
||||
const version = packageNameWithoutScope.includes('@')
|
||||
? packageNameWithoutScope.split('@')[1]
|
||||
: undefined;
|
||||
|
||||
const packageName = version ? rawString.replace(`@${version}`, '') : rawString;
|
||||
|
||||
return {
|
||||
packageName,
|
||||
scope,
|
||||
version,
|
||||
rawString,
|
||||
};
|
||||
};
|
||||
|
||||
export const sanitizeNpmPackageName = parseNpmPackageName;
|
||||
|
||||
export const executeCommand = async (
|
||||
command: string,
|
||||
options?: { doNotHandleError?: boolean },
|
||||
): Promise<string> => {
|
||||
const downloadFolder = UserSettings.getUserN8nFolderDowloadedNodesPath();
|
||||
|
||||
const execOptions = {
|
||||
cwd: downloadFolder,
|
||||
env: {
|
||||
NODE_PATH: process.env.NODE_PATH,
|
||||
PATH: process.env.PATH,
|
||||
APPDATA: process.env.APPDATA,
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
await fsAccess(downloadFolder);
|
||||
} catch (_) {
|
||||
await fsMkdir(downloadFolder);
|
||||
// Also init the folder since some versions
|
||||
// of npm complain if the folder is empty
|
||||
await execAsync('npm init -y', execOptions);
|
||||
}
|
||||
|
||||
try {
|
||||
const commandResult = await execAsync(command, execOptions);
|
||||
|
||||
return commandResult.stdout;
|
||||
} catch (error) {
|
||||
if (options?.doNotHandleError) throw error;
|
||||
|
||||
const errorMessage = error instanceof Error ? error.message : UNKNOWN_FAILURE_REASON;
|
||||
|
||||
const map = {
|
||||
[NPM_PACKAGE_NOT_FOUND_ERROR]: PACKAGE_NOT_FOUND,
|
||||
[NPM_NO_VERSION_AVAILABLE]: PACKAGE_NOT_FOUND,
|
||||
[NPM_PACKAGE_VERSION_NOT_FOUND_ERROR]: PACKAGE_VERSION_NOT_FOUND,
|
||||
[NPM_DISK_NO_SPACE]: DISK_IS_FULL,
|
||||
[NPM_DISK_INSUFFICIENT_SPACE]: DISK_IS_FULL,
|
||||
};
|
||||
|
||||
Object.entries(map).forEach(([npmMessage, n8nMessage]) => {
|
||||
if (errorMessage.includes(npmMessage)) throw new Error(n8nMessage);
|
||||
});
|
||||
|
||||
LoggerProxy.warn('npm command failed', { errorMessage });
|
||||
|
||||
throw new Error(PACKAGE_FAILED_TO_INSTALL);
|
||||
}
|
||||
};
|
||||
|
||||
export function matchPackagesWithUpdates(
|
||||
packages: InstalledPackages[],
|
||||
updates?: CommunityPackages.AvailableUpdates,
|
||||
): PublicInstalledPackage[] {
|
||||
if (!updates) return packages;
|
||||
|
||||
return packages.reduce<PublicInstalledPackage[]>((acc, cur) => {
|
||||
const publicPackage: PublicInstalledPackage = { ...cur };
|
||||
|
||||
const update = updates[cur.packageName];
|
||||
|
||||
if (update) publicPackage.updateAvailable = update.latest;
|
||||
|
||||
acc.push(publicPackage);
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
|
||||
export function matchMissingPackages(
|
||||
installedPackages: PublicInstalledPackage[],
|
||||
missingPackages: string,
|
||||
): PublicInstalledPackage[] {
|
||||
const missingPackageNames = missingPackages.split(' ');
|
||||
|
||||
const missingPackagesList = missingPackageNames.map((missingPackageName: string) => {
|
||||
// Strip away versions but maintain scope and package name
|
||||
try {
|
||||
const parsedPackageData = parseNpmPackageName(missingPackageName);
|
||||
return parsedPackageData.packageName;
|
||||
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (_) {}
|
||||
return undefined;
|
||||
});
|
||||
|
||||
const hydratedPackageList = [] as PublicInstalledPackage[];
|
||||
|
||||
installedPackages.forEach((installedPackage) => {
|
||||
const hydratedInstalledPackage = { ...installedPackage };
|
||||
if (missingPackagesList.includes(hydratedInstalledPackage.packageName)) {
|
||||
hydratedInstalledPackage.failedLoading = true;
|
||||
}
|
||||
hydratedPackageList.push(hydratedInstalledPackage);
|
||||
});
|
||||
|
||||
return hydratedPackageList;
|
||||
}
|
||||
|
||||
export async function checkNpmPackageStatus(
|
||||
packageName: string,
|
||||
): Promise<CommunityPackages.PackageStatusCheck> {
|
||||
const N8N_BACKEND_SERVICE_URL = 'https://api.n8n.io/api/package';
|
||||
|
||||
try {
|
||||
const response = await axios.post<CommunityPackages.PackageStatusCheck>(
|
||||
N8N_BACKEND_SERVICE_URL,
|
||||
{ name: packageName },
|
||||
{ method: 'POST' },
|
||||
);
|
||||
|
||||
if (response.data.status !== NPM_PACKAGE_STATUS_GOOD) return response.data;
|
||||
} catch (error) {
|
||||
// Do nothing if service is unreachable
|
||||
}
|
||||
|
||||
return { status: NPM_PACKAGE_STATUS_GOOD };
|
||||
}
|
||||
|
||||
export function hasPackageLoaded(packageName: string): boolean {
|
||||
const missingPackages = config.get('nodes.packagesMissing') as string | undefined;
|
||||
|
||||
if (!missingPackages) return true;
|
||||
|
||||
return !missingPackages
|
||||
.split(' ')
|
||||
.some(
|
||||
(packageNameAndVersion) =>
|
||||
packageNameAndVersion.startsWith(packageName) &&
|
||||
packageNameAndVersion.replace(packageName, '').startsWith('@'),
|
||||
);
|
||||
}
|
||||
|
||||
export function removePackageFromMissingList(packageName: string): void {
|
||||
try {
|
||||
const failedPackages = (config.get('nodes.packagesMissing') as string).split(' ');
|
||||
|
||||
const packageFailedToLoad = failedPackages.filter(
|
||||
(packageNameAndVersion) =>
|
||||
!packageNameAndVersion.startsWith(packageName) ||
|
||||
!packageNameAndVersion.replace(packageName, '').startsWith('@'),
|
||||
);
|
||||
|
||||
config.set('nodes.packagesMissing', packageFailedToLoad.join(' '));
|
||||
} catch (_error) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
export const isClientError = (error: Error): boolean => {
|
||||
const clientErrors = [
|
||||
PACKAGE_VERSION_NOT_FOUND,
|
||||
PACKAGE_DOES_NOT_CONTAIN_NODES,
|
||||
PACKAGE_NOT_FOUND,
|
||||
];
|
||||
|
||||
return clientErrors.some((message) => error.message.includes(message));
|
||||
};
|
||||
|
||||
export function isNpmError(error: unknown): error is { code: number; stdout: string } {
|
||||
return typeof error === 'object' && error !== null && 'code' in error && 'stdout' in error;
|
||||
}
|
||||
|
||||
const context = createContext({ require });
|
||||
export const loadClassInIsolation = (filePath: string, className: string) => {
|
||||
if (process.platform === 'win32') {
|
||||
filePath = filePath.replace(/\\/g, '/');
|
||||
}
|
||||
const script = new Script(`new (require('${filePath}').${className})()`);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
return script.runInContext(context);
|
||||
};
|
||||
76
packages/cli/src/CommunityNodes/packageModel.ts
Normal file
76
packages/cli/src/CommunityNodes/packageModel.ts
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/* eslint-disable import/no-cycle */
|
||||
import { INodeTypeData, INodeTypeNameVersion, LoggerProxy } from 'n8n-workflow';
|
||||
import { Db } from '..';
|
||||
import { InstalledNodes } from '../databases/entities/InstalledNodes';
|
||||
import { InstalledPackages } from '../databases/entities/InstalledPackages';
|
||||
|
||||
export async function findInstalledPackage(
|
||||
packageName: string,
|
||||
): Promise<InstalledPackages | undefined> {
|
||||
return Db.collections.InstalledPackages.findOne(packageName, { relations: ['installedNodes'] });
|
||||
}
|
||||
|
||||
export async function isPackageInstalled(packageName: string): Promise<boolean> {
|
||||
const installedPackage = await findInstalledPackage(packageName);
|
||||
return installedPackage !== undefined;
|
||||
}
|
||||
|
||||
export async function getAllInstalledPackages(): Promise<InstalledPackages[]> {
|
||||
return Db.collections.InstalledPackages.find({ relations: ['installedNodes'] });
|
||||
}
|
||||
|
||||
export async function removePackageFromDatabase(
|
||||
packageName: InstalledPackages,
|
||||
): Promise<InstalledPackages> {
|
||||
return Db.collections.InstalledPackages.remove(packageName);
|
||||
}
|
||||
|
||||
export async function persistInstalledPackageData(
|
||||
installedPackageName: string,
|
||||
installedPackageVersion: string,
|
||||
installedNodes: INodeTypeNameVersion[],
|
||||
loadedNodeTypes: INodeTypeData,
|
||||
authorName?: string,
|
||||
authorEmail?: string,
|
||||
): Promise<InstalledPackages> {
|
||||
let installedPackage: InstalledPackages;
|
||||
|
||||
try {
|
||||
await Db.transaction(async (transactionManager) => {
|
||||
const promises = [];
|
||||
|
||||
const installedPackagePayload = Object.assign(new InstalledPackages(), {
|
||||
packageName: installedPackageName,
|
||||
installedVersion: installedPackageVersion,
|
||||
authorName,
|
||||
authorEmail,
|
||||
});
|
||||
installedPackage = await transactionManager.save<InstalledPackages>(installedPackagePayload);
|
||||
installedPackage.installedNodes = [];
|
||||
|
||||
promises.push(
|
||||
...installedNodes.map(async (loadedNode) => {
|
||||
const installedNodePayload = Object.assign(new InstalledNodes(), {
|
||||
name: loadedNodeTypes[loadedNode.name].type.description.displayName,
|
||||
type: loadedNode.name,
|
||||
latestVersion: loadedNode.version,
|
||||
package: installedPackageName,
|
||||
});
|
||||
installedPackage.installedNodes.push(installedNodePayload);
|
||||
return transactionManager.save<InstalledNodes>(installedNodePayload);
|
||||
}),
|
||||
);
|
||||
|
||||
return promises;
|
||||
});
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return installedPackage!;
|
||||
} catch (error) {
|
||||
LoggerProxy.error('Failed to save installed packages and nodes', {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
error,
|
||||
packageName: installedPackageName,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
/* eslint-disable no-restricted-syntax */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
|
|
@ -91,7 +92,6 @@ export class CredentialsHelper extends ICredentialsHelper {
|
|||
if (credentialType.authenticate) {
|
||||
if (typeof credentialType.authenticate === 'function') {
|
||||
// Special authentication function is defined
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
return credentialType.authenticate(credentials, requestOptions as IHttpRequestOptions);
|
||||
}
|
||||
|
|
@ -250,8 +250,6 @@ export class CredentialsHelper extends ICredentialsHelper {
|
|||
*
|
||||
* @param {INodeCredentialsDetails} nodeCredential id and name to return instance of
|
||||
* @param {string} type Type of the credential to return instance of
|
||||
* @returns {Credentials}
|
||||
* @memberof CredentialsHelper
|
||||
*/
|
||||
async getCredentials(
|
||||
nodeCredential: INodeCredentialsDetails,
|
||||
|
|
@ -287,8 +285,6 @@ export class CredentialsHelper extends ICredentialsHelper {
|
|||
* Returns all the properties of the credentials with the given name
|
||||
*
|
||||
* @param {string} type The name of the type to return credentials off
|
||||
* @returns {INodeProperties[]}
|
||||
* @memberof CredentialsHelper
|
||||
*/
|
||||
getCredentialsProperties(type: string): INodeProperties[] {
|
||||
const credentialTypeData = this.credentialTypes.getByName(type);
|
||||
|
|
@ -307,7 +303,7 @@ export class CredentialsHelper extends ICredentialsHelper {
|
|||
NodeHelpers.mergeNodeProperties(combineProperties, mergeCredentialProperties);
|
||||
}
|
||||
|
||||
// The properties defined on the parent credentials take presidence
|
||||
// The properties defined on the parent credentials take precedence
|
||||
NodeHelpers.mergeNodeProperties(combineProperties, credentialTypeData.properties);
|
||||
|
||||
return combineProperties;
|
||||
|
|
@ -319,8 +315,6 @@ export class CredentialsHelper extends ICredentialsHelper {
|
|||
* @param {INodeCredentialsDetails} nodeCredentials id and name to return instance of
|
||||
* @param {string} type Type of the credentials to return data of
|
||||
* @param {boolean} [raw] Return the data as supplied without defaults or overwrites
|
||||
* @returns {ICredentialDataDecryptedObject}
|
||||
* @memberof CredentialsHelper
|
||||
*/
|
||||
async getDecrypted(
|
||||
nodeCredentials: INodeCredentialsDetails,
|
||||
|
|
@ -351,8 +345,6 @@ export class CredentialsHelper extends ICredentialsHelper {
|
|||
*
|
||||
* @param {ICredentialDataDecryptedObject} decryptedDataOriginal The credential data to overwrite data on
|
||||
* @param {string} type Type of the credentials to overwrite data of
|
||||
* @returns {ICredentialDataDecryptedObject}
|
||||
* @memberof CredentialsHelper
|
||||
*/
|
||||
applyDefaultsAndOverwrites(
|
||||
decryptedDataOriginal: ICredentialDataDecryptedObject,
|
||||
|
|
@ -443,8 +435,6 @@ export class CredentialsHelper extends ICredentialsHelper {
|
|||
* @param {string} name Name of the credentials to set data of
|
||||
* @param {string} type Type of the credentials to set data of
|
||||
* @param {ICredentialDataDecryptedObject} data The data to set
|
||||
* @returns {Promise<void>}
|
||||
* @memberof CredentialsHelper
|
||||
*/
|
||||
async updateCredentials(
|
||||
nodeCredentials: INodeCredentialsDetails,
|
||||
|
|
@ -526,11 +516,11 @@ export class CredentialsHelper extends ICredentialsHelper {
|
|||
}
|
||||
}
|
||||
}
|
||||
// Test is defined as string which links to a functoin
|
||||
// Test is defined as string which links to a function
|
||||
return (node as unknown as INodeType).methods?.credentialTest![credential.testedBy];
|
||||
}
|
||||
|
||||
// Test is defined as JSON with a defintion for the request to make
|
||||
// Test is defined as JSON with a definition for the request to make
|
||||
return {
|
||||
nodeType,
|
||||
testRequest: credential.testedBy,
|
||||
|
|
@ -558,7 +548,6 @@ export class CredentialsHelper extends ICredentialsHelper {
|
|||
nodeToTestWith?: string,
|
||||
): Promise<INodeCredentialTestResult> {
|
||||
const credentialTestFunction = this.getCredentialTestFunction(credentialType, nodeToTestWith);
|
||||
|
||||
if (credentialTestFunction === undefined) {
|
||||
return Promise.resolve({
|
||||
status: 'Error',
|
||||
|
|
@ -575,7 +564,7 @@ export class CredentialsHelper extends ICredentialsHelper {
|
|||
|
||||
// Credentials get tested via request instructions
|
||||
|
||||
// TODO: Temp worfklows get created at multiple locations (for example also LoadNodeParameterOptions),
|
||||
// TODO: Temp workflows get created at multiple locations (for example also LoadNodeParameterOptions),
|
||||
// check if some of them are identical enough that it can be combined
|
||||
|
||||
let nodeType: INodeType;
|
||||
|
|
@ -587,6 +576,7 @@ export class CredentialsHelper extends ICredentialsHelper {
|
|||
}
|
||||
|
||||
const node: INode = {
|
||||
id: 'temp',
|
||||
parameters: {},
|
||||
name: 'Temp-Node',
|
||||
type: nodeType.description.name,
|
||||
|
|
@ -689,7 +679,6 @@ export class CredentialsHelper extends ICredentialsHelper {
|
|||
statusCode: error.cause.response.status,
|
||||
statusMessage: error.cause.response.statusText,
|
||||
};
|
||||
|
||||
if (credentialTestFunction.testRequest.rules) {
|
||||
// Special testing rules are defined so check all in order
|
||||
for (const rule of credentialTestFunction.testRequest.rules) {
|
||||
|
|
@ -715,6 +704,11 @@ export class CredentialsHelper extends ICredentialsHelper {
|
|||
`Received HTTP status code: ${errorResponseData.statusCode}`,
|
||||
};
|
||||
}
|
||||
} else if (error.cause.code) {
|
||||
return {
|
||||
status: 'Error',
|
||||
message: error.cause.code,
|
||||
};
|
||||
}
|
||||
Logger.debug('Credential test failed', error);
|
||||
return {
|
||||
|
|
@ -801,7 +795,7 @@ export async function getCredentialWithoutUser(
|
|||
return credential;
|
||||
}
|
||||
|
||||
export function createCredentiasFromCredentialsEntity(
|
||||
export function createCredentialsFromCredentialsEntity(
|
||||
credential: CredentialsEntity,
|
||||
encrypt = false,
|
||||
): Credentials {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
import { ICredentialDataDecryptedObject } from 'n8n-workflow';
|
||||
|
||||
|
|
|
|||
5
packages/cli/src/CurlConverter.d.ts
vendored
Normal file
5
packages/cli/src/CurlConverter.d.ts
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
/* eslint-disable import/no-default-export */
|
||||
declare module 'curlconverter' {
|
||||
export function toJsonString(data: string): string;
|
||||
}
|
||||
466
packages/cli/src/CurlConverterHelper.ts
Normal file
466
packages/cli/src/CurlConverterHelper.ts
Normal file
|
|
@ -0,0 +1,466 @@
|
|||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import curlconverter from 'curlconverter';
|
||||
import get from 'lodash.get';
|
||||
|
||||
interface CurlJson {
|
||||
url: string;
|
||||
raw_url?: string;
|
||||
method: string;
|
||||
contentType?: string;
|
||||
cookies?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
auth?: {
|
||||
user: string;
|
||||
password: string;
|
||||
};
|
||||
headers?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
files?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
queries: {
|
||||
[key: string]: string;
|
||||
};
|
||||
data?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface Parameter {
|
||||
parameterType?: string;
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface HttpNodeParameters {
|
||||
url?: string;
|
||||
method: string;
|
||||
sendBody?: boolean;
|
||||
authentication: string;
|
||||
contentType?: 'form-urlencoded' | 'multipart-form-data' | 'json' | 'raw' | 'binaryData';
|
||||
rawContentType?: string;
|
||||
specifyBody?: 'json' | 'keypair';
|
||||
bodyParameters?: {
|
||||
parameters: Parameter[];
|
||||
};
|
||||
jsonBody?: object;
|
||||
options: {
|
||||
allowUnauthorizedCerts?: boolean;
|
||||
proxy?: string;
|
||||
timeout?: number;
|
||||
redirect: {
|
||||
redirect: {
|
||||
followRedirects?: boolean;
|
||||
maxRedirects?: number;
|
||||
};
|
||||
};
|
||||
response: {
|
||||
response: {
|
||||
fullResponse?: boolean;
|
||||
responseFormat?: string;
|
||||
outputPropertyName?: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
sendHeaders?: boolean;
|
||||
headerParameters?: {
|
||||
parameters: Parameter[];
|
||||
};
|
||||
sendQuery?: boolean;
|
||||
queryParameters?: {
|
||||
parameters: Parameter[];
|
||||
};
|
||||
}
|
||||
|
||||
type HttpNodeHeaders = Pick<HttpNodeParameters, 'sendHeaders' | 'headerParameters'>;
|
||||
|
||||
type HttpNodeQueries = Pick<HttpNodeParameters, 'sendQuery' | 'queryParameters'>;
|
||||
|
||||
enum ContentTypes {
|
||||
applicationJson = 'application/json',
|
||||
applicationFormUrlEncoded = 'application/x-www-form-urlencoded',
|
||||
applicationMultipart = 'multipart/form-data',
|
||||
}
|
||||
|
||||
const SUPPORTED_CONTENT_TYPES = [
|
||||
ContentTypes.applicationJson,
|
||||
ContentTypes.applicationFormUrlEncoded,
|
||||
ContentTypes.applicationMultipart,
|
||||
];
|
||||
|
||||
const CONTENT_TYPE_KEY = 'content-type';
|
||||
|
||||
const FOLLOW_REDIRECT_FLAGS = ['--location', '-L'];
|
||||
|
||||
const MAX_REDIRECT_FLAG = '--max-redirs';
|
||||
|
||||
const PROXY_FLAGS = ['-x', '--proxy'];
|
||||
|
||||
const INCLUDE_HEADERS_IN_OUTPUT_FLAGS = ['-i', '--include'];
|
||||
|
||||
const REQUEST_FLAGS = ['-X', '--request'];
|
||||
|
||||
const TIMEOUT_FLAGS = ['--connect-timeout'];
|
||||
|
||||
const DOWNLOAD_FILE_FLAGS = ['-O', '-o'];
|
||||
|
||||
const IGNORE_SSL_ISSUES_FLAGS = ['-k', '--insecure'];
|
||||
|
||||
const curlToJson = (curlCommand: string): CurlJson => {
|
||||
// eslint-disable-next-line n8n-local-rules/no-uncaught-json-parse
|
||||
return JSON.parse(curlconverter.toJsonString(curlCommand)) as CurlJson;
|
||||
};
|
||||
|
||||
const isContentType = (headers: CurlJson['headers'], contentType: ContentTypes): boolean => {
|
||||
return get(headers, CONTENT_TYPE_KEY) === contentType;
|
||||
};
|
||||
|
||||
const isJsonRequest = (curlJson: CurlJson): boolean => {
|
||||
if (isContentType(curlJson.headers, ContentTypes.applicationJson)) return true;
|
||||
|
||||
if (curlJson.data) {
|
||||
const bodyKey = Object.keys(curlJson.data)[0];
|
||||
try {
|
||||
JSON.parse(bodyKey);
|
||||
return true;
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const isFormUrlEncodedRequest = (curlJson: CurlJson): boolean => {
|
||||
if (isContentType(curlJson.headers, ContentTypes.applicationFormUrlEncoded)) return true;
|
||||
if (curlJson.data && !curlJson.files) return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
const isMultipartRequest = (curlJson: CurlJson): boolean => {
|
||||
if (isContentType(curlJson.headers, ContentTypes.applicationMultipart)) return true;
|
||||
|
||||
// only multipart/form-data request include files
|
||||
if (curlJson.files) return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
const isBinaryRequest = (curlJson: CurlJson): boolean => {
|
||||
if (curlJson?.headers?.[CONTENT_TYPE_KEY]) {
|
||||
const contentType = curlJson?.headers?.[CONTENT_TYPE_KEY];
|
||||
return ['image', 'video', 'audio'].some((d) => contentType.includes(d));
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const sanatizeCurlCommand = (curlCommand: string) =>
|
||||
curlCommand
|
||||
.replace(/\r\n/g, ' ')
|
||||
.replace(/\n/g, ' ')
|
||||
.replace(/\\/g, ' ')
|
||||
.replace(/[ ]{2,}/g, ' ');
|
||||
|
||||
const toKeyValueArray = ([key, value]: string[]) => ({ name: key, value });
|
||||
|
||||
const extractHeaders = (headers: CurlJson['headers'] = {}): HttpNodeHeaders => {
|
||||
const emptyHeaders = !Object.keys(headers).length;
|
||||
|
||||
const onlyContentTypeHeaderDefined =
|
||||
Object.keys(headers).length === 1 && headers[CONTENT_TYPE_KEY] !== undefined;
|
||||
|
||||
if (emptyHeaders || onlyContentTypeHeaderDefined) return { sendHeaders: false };
|
||||
|
||||
return {
|
||||
sendHeaders: true,
|
||||
headerParameters: {
|
||||
parameters: Object.entries(headers)
|
||||
.map(toKeyValueArray)
|
||||
.filter((parameter) => parameter.name !== CONTENT_TYPE_KEY),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const extractQueries = (queries: CurlJson['queries'] = {}): HttpNodeQueries => {
|
||||
const emptyQueries = !Object.keys(queries).length;
|
||||
|
||||
if (emptyQueries) return { sendQuery: false };
|
||||
|
||||
return {
|
||||
sendQuery: true,
|
||||
queryParameters: {
|
||||
parameters: Object.entries(queries).map(toKeyValueArray),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const extractJson = (body: CurlJson['data']) =>
|
||||
//@ts-ignore
|
||||
// eslint-disable-next-line n8n-local-rules/no-uncaught-json-parse
|
||||
JSON.parse(Object.keys(body)[0]) as { [key: string]: string };
|
||||
|
||||
const jsonBodyToNodeParameters = (body: CurlJson['data'] = {}): Parameter[] | [] => {
|
||||
const data = extractJson(body);
|
||||
return Object.entries(data).map(toKeyValueArray);
|
||||
};
|
||||
|
||||
const multipartToNodeParameters = (
|
||||
body: CurlJson['data'] = {},
|
||||
files: CurlJson['files'] = {},
|
||||
): Parameter[] | [] => {
|
||||
return [
|
||||
...Object.entries(body)
|
||||
.map(toKeyValueArray)
|
||||
.map((e) => ({ parameterType: 'formData', ...e })),
|
||||
...Object.entries(files)
|
||||
.map(toKeyValueArray)
|
||||
.map((e) => ({ parameterType: 'formBinaryData', ...e })),
|
||||
];
|
||||
};
|
||||
|
||||
const keyValueBodyToNodeParameters = (body: CurlJson['data'] = {}): Parameter[] | [] => {
|
||||
return Object.entries(body).map(toKeyValueArray);
|
||||
};
|
||||
|
||||
const lowerCaseContentTypeKey = (obj: { [x: string]: string }): void => {
|
||||
const regex = new RegExp(CONTENT_TYPE_KEY, 'gi');
|
||||
|
||||
const contentTypeKey = Object.keys(obj).find((key) => {
|
||||
const group = Array.from(key.matchAll(regex));
|
||||
if (group.length) return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
if (!contentTypeKey) return;
|
||||
|
||||
const value = obj[contentTypeKey];
|
||||
delete obj[contentTypeKey];
|
||||
obj[CONTENT_TYPE_KEY] = value;
|
||||
};
|
||||
|
||||
const encodeBasicAuthentication = (username: string, password: string) =>
|
||||
Buffer.from(`${username}:${password}`).toString('base64');
|
||||
|
||||
const jsonHasNestedObjects = (json: { [key: string]: string | number | object }) =>
|
||||
Object.values(json).some((e) => typeof e === 'object');
|
||||
|
||||
const extractGroup = (curlCommand: string, regex: RegExp) => curlCommand.matchAll(regex);
|
||||
|
||||
const mapCookies = (cookies: CurlJson['cookies']): { cookie: string } | {} => {
|
||||
if (!cookies) return {};
|
||||
|
||||
const cookiesValues = Object.entries(cookies).reduce(
|
||||
(accumulator: string, entry: [string, string]) => {
|
||||
accumulator += `${entry[0]}=${entry[1]};`;
|
||||
return accumulator;
|
||||
},
|
||||
'',
|
||||
);
|
||||
|
||||
if (!cookiesValues) return {};
|
||||
|
||||
return {
|
||||
cookie: cookiesValues,
|
||||
};
|
||||
};
|
||||
|
||||
export const toHttpNodeParameters = (curlCommand: string): HttpNodeParameters => {
|
||||
const curlJson = curlToJson(curlCommand);
|
||||
|
||||
if (!curlJson.headers) curlJson.headers = {};
|
||||
|
||||
lowerCaseContentTypeKey(curlJson.headers);
|
||||
|
||||
// set basic authentication
|
||||
if (curlJson.auth) {
|
||||
const { user, password: pass } = curlJson.auth;
|
||||
Object.assign(curlJson.headers, {
|
||||
authorization: `Basic ${encodeBasicAuthentication(user, pass)}`,
|
||||
});
|
||||
}
|
||||
|
||||
const httpNodeParameters: HttpNodeParameters = {
|
||||
url: curlJson.url,
|
||||
authentication: 'none',
|
||||
method: curlJson.method.toUpperCase(),
|
||||
...extractHeaders({ ...curlJson.headers, ...mapCookies(curlJson.cookies) }),
|
||||
...extractQueries(curlJson.queries),
|
||||
options: {
|
||||
redirect: {
|
||||
redirect: {},
|
||||
},
|
||||
response: {
|
||||
response: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
//attempt to get the curl flags not supported by the library
|
||||
const curl = sanatizeCurlCommand(curlCommand);
|
||||
|
||||
//check for follow redirect flags
|
||||
if (FOLLOW_REDIRECT_FLAGS.some((flag) => curl.includes(` ${flag}`))) {
|
||||
Object.assign(httpNodeParameters.options.redirect?.redirect, { followRedirects: true });
|
||||
|
||||
if (curl.includes(` ${MAX_REDIRECT_FLAG}`)) {
|
||||
const extractedValue = Array.from(
|
||||
extractGroup(curl, new RegExp(` ${MAX_REDIRECT_FLAG} (\\d+)`, 'g')),
|
||||
);
|
||||
if (extractedValue.length) {
|
||||
const [_, maxRedirects] = extractedValue[0];
|
||||
if (maxRedirects) {
|
||||
Object.assign(httpNodeParameters.options.redirect?.redirect, { maxRedirects });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//check for proxy flags
|
||||
if (PROXY_FLAGS.some((flag) => curl.includes(` ${flag}`))) {
|
||||
const foundFlag = PROXY_FLAGS.find((flag) => curl.includes(` ${flag}`));
|
||||
if (foundFlag) {
|
||||
const extractedValue = Array.from(
|
||||
extractGroup(curl, new RegExp(` ${foundFlag} (\\S*)`, 'g')),
|
||||
);
|
||||
if (extractedValue.length) {
|
||||
const [_, proxy] = extractedValue[0];
|
||||
Object.assign(httpNodeParameters.options, { proxy });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for "include header in output" flag
|
||||
if (INCLUDE_HEADERS_IN_OUTPUT_FLAGS.some((flag) => curl.includes(` ${flag}`))) {
|
||||
Object.assign(httpNodeParameters.options?.response?.response, {
|
||||
fullResponse: true,
|
||||
responseFormat: 'autodetect',
|
||||
});
|
||||
}
|
||||
|
||||
// check for request flag
|
||||
if (REQUEST_FLAGS.some((flag) => curl.includes(` ${flag}`))) {
|
||||
const foundFlag = REQUEST_FLAGS.find((flag) => curl.includes(` ${flag}`));
|
||||
if (foundFlag) {
|
||||
const extractedValue = Array.from(
|
||||
extractGroup(curl, new RegExp(` ${foundFlag} (\\w+)`, 'g')),
|
||||
);
|
||||
if (extractedValue.length) {
|
||||
const [_, request] = extractedValue[0];
|
||||
httpNodeParameters.method = request.toUpperCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for timeout flag
|
||||
if (TIMEOUT_FLAGS.some((flag) => curl.includes(` ${flag}`))) {
|
||||
const foundFlag = TIMEOUT_FLAGS.find((flag) => curl.includes(` ${flag}`));
|
||||
if (foundFlag) {
|
||||
const extractedValue = Array.from(
|
||||
extractGroup(curl, new RegExp(` ${foundFlag} (\\d+)`, 'g')),
|
||||
);
|
||||
if (extractedValue.length) {
|
||||
const [_, timeout] = extractedValue[0];
|
||||
Object.assign(httpNodeParameters.options, {
|
||||
timeout: parseInt(timeout, 10) * 1000,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for download flag
|
||||
if (DOWNLOAD_FILE_FLAGS.some((flag) => curl.includes(` ${flag}`))) {
|
||||
const foundFlag = DOWNLOAD_FILE_FLAGS.find((flag) => curl.includes(` ${flag}`));
|
||||
if (foundFlag) {
|
||||
Object.assign(httpNodeParameters.options.response.response, {
|
||||
responseFormat: 'file',
|
||||
outputPropertyName: 'data',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (IGNORE_SSL_ISSUES_FLAGS.some((flag) => curl.includes(` ${flag}`))) {
|
||||
const foundFlag = IGNORE_SSL_ISSUES_FLAGS.find((flag) => curl.includes(` ${flag}`));
|
||||
if (foundFlag) {
|
||||
Object.assign(httpNodeParameters.options, {
|
||||
allowUnauthorizedCerts: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const contentType = curlJson?.headers?.[CONTENT_TYPE_KEY] as ContentTypes;
|
||||
|
||||
if (isBinaryRequest(curlJson)) {
|
||||
return Object.assign(httpNodeParameters, {
|
||||
contentType: 'binaryData',
|
||||
sendBody: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (contentType && !SUPPORTED_CONTENT_TYPES.includes(contentType)) {
|
||||
return Object.assign(httpNodeParameters, {
|
||||
sendBody: true,
|
||||
contentType: 'raw',
|
||||
rawContentType: contentType,
|
||||
body: Object.keys(curlJson?.data ?? {})[0],
|
||||
});
|
||||
}
|
||||
|
||||
if (isJsonRequest(curlJson)) {
|
||||
Object.assign(httpNodeParameters, {
|
||||
contentType: 'json',
|
||||
sendBody: true,
|
||||
});
|
||||
|
||||
const json = extractJson(curlJson.data);
|
||||
|
||||
if (jsonHasNestedObjects(json)) {
|
||||
// json body
|
||||
Object.assign(httpNodeParameters, {
|
||||
specifyBody: 'json',
|
||||
jsonBody: JSON.stringify(json),
|
||||
});
|
||||
} else {
|
||||
// key-value body
|
||||
Object.assign(httpNodeParameters, {
|
||||
specifyBody: 'keypair',
|
||||
bodyParameters: {
|
||||
parameters: jsonBodyToNodeParameters(curlJson.data),
|
||||
},
|
||||
});
|
||||
}
|
||||
} else if (isFormUrlEncodedRequest(curlJson)) {
|
||||
Object.assign(httpNodeParameters, {
|
||||
contentType: 'form-urlencoded',
|
||||
sendBody: true,
|
||||
specifyBody: 'keypair',
|
||||
bodyParameters: {
|
||||
parameters: keyValueBodyToNodeParameters(curlJson.data),
|
||||
},
|
||||
});
|
||||
} else if (isMultipartRequest(curlJson)) {
|
||||
Object.assign(httpNodeParameters, {
|
||||
contentType: 'multipart-form-data',
|
||||
sendBody: true,
|
||||
bodyParameters: {
|
||||
parameters: multipartToNodeParameters(curlJson.data, curlJson.files),
|
||||
},
|
||||
});
|
||||
} else {
|
||||
// could not figure the content type so do not set the body
|
||||
Object.assign(httpNodeParameters, {
|
||||
sendBody: false,
|
||||
});
|
||||
}
|
||||
|
||||
if (!Object.keys(httpNodeParameters.options?.redirect.redirect).length) {
|
||||
// @ts-ignore
|
||||
delete httpNodeParameters.options.redirect;
|
||||
}
|
||||
|
||||
if (!Object.keys(httpNodeParameters.options.response.response).length) {
|
||||
// @ts-ignore
|
||||
delete httpNodeParameters.options.response;
|
||||
}
|
||||
|
||||
return httpNodeParameters;
|
||||
};
|
||||
|
|
@ -13,6 +13,7 @@ import {
|
|||
EntityTarget,
|
||||
getRepository,
|
||||
LoggerOptions,
|
||||
ObjectLiteral,
|
||||
Repository,
|
||||
} from 'typeorm';
|
||||
import { TlsOptions } from 'tls';
|
||||
|
|
@ -38,7 +39,9 @@ export async function transaction<T>(fn: (entityManager: EntityManager) => Promi
|
|||
return connection.transaction(fn);
|
||||
}
|
||||
|
||||
export function linkRepository<Entity>(entityClass: EntityTarget<Entity>): Repository<Entity> {
|
||||
export function linkRepository<Entity extends ObjectLiteral>(
|
||||
entityClass: EntityTarget<Entity>,
|
||||
): Repository<Entity> {
|
||||
return getRepository(entityClass, connection.name);
|
||||
}
|
||||
|
||||
|
|
@ -183,9 +186,12 @@ export async function init(
|
|||
}
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
collections.Credentials = linkRepository(entities.CredentialsEntity);
|
||||
// @ts-ignore
|
||||
collections.Execution = linkRepository(entities.ExecutionEntity);
|
||||
collections.Workflow = linkRepository(entities.WorkflowEntity);
|
||||
// @ts-ignore
|
||||
collections.Webhook = linkRepository(entities.WebhookEntity);
|
||||
collections.Tag = linkRepository(entities.TagEntity);
|
||||
|
||||
|
|
@ -194,6 +200,9 @@ export async function init(
|
|||
collections.SharedCredentials = linkRepository(entities.SharedCredentials);
|
||||
collections.SharedWorkflow = linkRepository(entities.SharedWorkflow);
|
||||
collections.Settings = linkRepository(entities.Settings);
|
||||
collections.InstalledPackages = linkRepository(entities.InstalledPackages);
|
||||
collections.InstalledNodes = linkRepository(entities.InstalledNodes);
|
||||
collections.CredentialUsage = linkRepository(entities.CredentialUsage);
|
||||
|
||||
isInitialized = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ class ExternalHooksClass implements IExternalHooksClass {
|
|||
}
|
||||
|
||||
for (const externalHookFunction of this.externalHooks[hookName]) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
// eslint-disable-next-line no-await-in-loop, @typescript-eslint/await-thenable
|
||||
await externalHookFunction.apply(externalHookFunctions, hookParameters);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,12 +8,27 @@
|
|||
import express from 'express';
|
||||
import { join as pathJoin } from 'path';
|
||||
import { readFile as fsReadFile } from 'fs/promises';
|
||||
import { IDataObject } from 'n8n-workflow';
|
||||
import {
|
||||
ExecutionError,
|
||||
IDataObject,
|
||||
INode,
|
||||
IRunExecutionData,
|
||||
Workflow,
|
||||
WorkflowExecuteMode,
|
||||
} from 'n8n-workflow';
|
||||
import { validate } from 'class-validator';
|
||||
import config from '../config';
|
||||
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
import { Db, ICredentialsDb, IPackageVersions, ResponseHelper } from '.';
|
||||
import {
|
||||
Db,
|
||||
ICredentialsDb,
|
||||
IExecutionDb,
|
||||
IExecutionFlattedDb,
|
||||
IPackageVersions,
|
||||
IWorkflowDb,
|
||||
ResponseHelper,
|
||||
} from '.';
|
||||
// eslint-disable-next-line import/order
|
||||
import { Like } from 'typeorm';
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
|
|
@ -27,8 +42,6 @@ let versionCache: IPackageVersions | undefined;
|
|||
/**
|
||||
* Returns the base URL n8n is reachable from
|
||||
*
|
||||
* @export
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getBaseUrl(): string {
|
||||
const protocol = config.getEnv('protocol');
|
||||
|
|
@ -45,9 +58,6 @@ export function getBaseUrl(): string {
|
|||
/**
|
||||
* Returns the session id if one is set
|
||||
*
|
||||
* @export
|
||||
* @param {express.Request} req
|
||||
* @returns {(string | undefined)}
|
||||
*/
|
||||
export function getSessionId(req: express.Request): string | undefined {
|
||||
return req.headers.sessionid as string | undefined;
|
||||
|
|
@ -56,8 +66,6 @@ export function getSessionId(req: express.Request): string | undefined {
|
|||
/**
|
||||
* Returns information which version of the packages are installed
|
||||
*
|
||||
* @export
|
||||
* @returns {Promise<IPackageVersions>}
|
||||
*/
|
||||
export async function getVersions(): Promise<IPackageVersions> {
|
||||
if (versionCache !== undefined) {
|
||||
|
|
@ -79,9 +87,6 @@ export async function getVersions(): Promise<IPackageVersions> {
|
|||
/**
|
||||
* Extracts configuration schema for key
|
||||
*
|
||||
* @param {string} configKey
|
||||
* @param {IDataObject} configSchema
|
||||
* @returns {IDataObject} schema of the configKey
|
||||
*/
|
||||
function extractSchemaForKey(configKey: string, configSchema: IDataObject): IDataObject {
|
||||
const configKeyParts = configKey.split('.');
|
||||
|
|
@ -103,9 +108,7 @@ function extractSchemaForKey(configKey: string, configSchema: IDataObject): IDat
|
|||
/**
|
||||
* Gets value from config with support for "_FILE" environment variables
|
||||
*
|
||||
* @export
|
||||
* @param {string} configKey The key of the config data to get
|
||||
* @returns {(Promise<string | boolean | number | undefined>)}
|
||||
*/
|
||||
export async function getConfigValue(
|
||||
configKey: string,
|
||||
|
|
@ -121,7 +124,7 @@ export async function getConfigValue(
|
|||
return config.getEnv(configKey);
|
||||
}
|
||||
|
||||
// Check if special file enviroment variable exists
|
||||
// Check if special file environment variable exists
|
||||
const fileEnvironmentVariable = process.env[`${currentSchema.env}_FILE`];
|
||||
if (fileEnvironmentVariable === undefined) {
|
||||
// Does not exist, so return value from config
|
||||
|
|
@ -214,4 +217,85 @@ export async function validateEntity(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an error execution
|
||||
*
|
||||
* @param {INode} node
|
||||
* @param {IWorkflowDb} workflowData
|
||||
* @param {Workflow} workflow
|
||||
* @param {WorkflowExecuteMode} mode
|
||||
* @returns
|
||||
* @memberof ActiveWorkflowRunner
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
export async function createErrorExecution(
|
||||
error: ExecutionError,
|
||||
node: INode,
|
||||
workflowData: IWorkflowDb,
|
||||
workflow: Workflow,
|
||||
mode: WorkflowExecuteMode,
|
||||
): Promise<void> {
|
||||
const saveDataErrorExecutionDisabled = workflowData?.settings?.saveDataErrorExecution === 'none';
|
||||
|
||||
if (saveDataErrorExecutionDisabled) return;
|
||||
|
||||
const executionData: IRunExecutionData = {
|
||||
startData: {
|
||||
destinationNode: node.name,
|
||||
runNodeFilter: [node.name],
|
||||
},
|
||||
executionData: {
|
||||
contextData: {},
|
||||
nodeExecutionStack: [
|
||||
{
|
||||
node,
|
||||
data: {
|
||||
main: [
|
||||
[
|
||||
{
|
||||
json: {},
|
||||
pairedItem: {
|
||||
item: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
source: null,
|
||||
},
|
||||
],
|
||||
waitingExecution: {},
|
||||
waitingExecutionSource: {},
|
||||
},
|
||||
resultData: {
|
||||
runData: {
|
||||
[node.name]: [
|
||||
{
|
||||
startTime: 0,
|
||||
executionTime: 0,
|
||||
error,
|
||||
source: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
error,
|
||||
lastNodeExecuted: node.name,
|
||||
},
|
||||
};
|
||||
|
||||
const fullExecutionData: IExecutionDb = {
|
||||
data: executionData,
|
||||
mode,
|
||||
finished: false,
|
||||
startedAt: new Date(),
|
||||
workflowData,
|
||||
workflowId: workflow.id,
|
||||
stoppedAt: new Date(),
|
||||
};
|
||||
|
||||
const execution = ResponseHelper.flattenExecutionData(fullExecutionData);
|
||||
|
||||
await Db.collections.Execution.save(execution as IExecutionFlattedDb);
|
||||
}
|
||||
|
||||
export const DEFAULT_EXECUTIONS_GET_ALL_LIMIT = 20;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {
|
|||
IDataObject,
|
||||
IDeferredPromise,
|
||||
IExecuteResponsePromiseData,
|
||||
IPinData,
|
||||
IRun,
|
||||
IRunData,
|
||||
IRunExecutionData,
|
||||
|
|
@ -16,6 +17,7 @@ import {
|
|||
ITelemetryTrackProperties,
|
||||
IWorkflowBase as IWorkflowBaseWorkflow,
|
||||
Workflow,
|
||||
WorkflowActivateMode,
|
||||
WorkflowExecuteMode,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
|
|
@ -27,14 +29,18 @@ import { Repository } from 'typeorm';
|
|||
|
||||
import { ChildProcess } from 'child_process';
|
||||
import { Url } from 'url';
|
||||
import { Request } from 'express';
|
||||
import { WorkflowEntity } from './databases/entities/WorkflowEntity';
|
||||
import { TagEntity } from './databases/entities/TagEntity';
|
||||
import { Role } from './databases/entities/Role';
|
||||
import { User } from './databases/entities/User';
|
||||
import { SharedCredentials } from './databases/entities/SharedCredentials';
|
||||
import { SharedWorkflow } from './databases/entities/SharedWorkflow';
|
||||
import { Settings } from './databases/entities/Settings';
|
||||
|
||||
import type { Request } from 'express';
|
||||
import type { InstalledNodes } from './databases/entities/InstalledNodes';
|
||||
import type { InstalledPackages } from './databases/entities/InstalledPackages';
|
||||
import type { Role } from './databases/entities/Role';
|
||||
import type { Settings } from './databases/entities/Settings';
|
||||
import type { SharedCredentials } from './databases/entities/SharedCredentials';
|
||||
import type { SharedWorkflow } from './databases/entities/SharedWorkflow';
|
||||
import type { TagEntity } from './databases/entities/TagEntity';
|
||||
import type { User } from './databases/entities/User';
|
||||
import type { WorkflowEntity } from './databases/entities/WorkflowEntity';
|
||||
import { CredentialUsage } from './databases/entities/CredentialUsage';
|
||||
|
||||
export interface IActivationError {
|
||||
time: number;
|
||||
|
|
@ -43,18 +49,11 @@ export interface IActivationError {
|
|||
};
|
||||
}
|
||||
|
||||
export interface IBullJobData {
|
||||
executionId: string;
|
||||
loadStaticData: boolean;
|
||||
}
|
||||
|
||||
export interface IBullJobResponse {
|
||||
success: boolean;
|
||||
}
|
||||
|
||||
export interface IBullWebhookResponse {
|
||||
executionId: string;
|
||||
response: IExecuteResponsePromiseData;
|
||||
export interface IQueuedWorkflowActivations {
|
||||
activationMode: WorkflowActivateMode;
|
||||
lastTimeout: number;
|
||||
timeout: NodeJS.Timeout;
|
||||
workflowData: IWorkflowDb;
|
||||
}
|
||||
|
||||
export interface ICustomRequest extends Request {
|
||||
|
|
@ -83,6 +82,9 @@ export interface IDatabaseCollections {
|
|||
SharedCredentials: Repository<SharedCredentials>;
|
||||
SharedWorkflow: Repository<SharedWorkflow>;
|
||||
Settings: Repository<Settings>;
|
||||
InstalledPackages: Repository<InstalledPackages>;
|
||||
InstalledNodes: Repository<InstalledNodes>;
|
||||
CredentialUsage: Repository<CredentialUsage>;
|
||||
}
|
||||
|
||||
export interface IWebhookDb {
|
||||
|
|
@ -139,7 +141,7 @@ export interface IWorkflowBase extends IWorkflowBaseWorkflow {
|
|||
// Almost identical to editor-ui.Interfaces.ts
|
||||
export interface IWorkflowDb extends IWorkflowBase {
|
||||
id: number | string;
|
||||
tags: ITagDb[];
|
||||
tags?: ITagDb[];
|
||||
}
|
||||
|
||||
export interface IWorkflowToImport extends IWorkflowBase {
|
||||
|
|
@ -162,6 +164,7 @@ export interface ICredentialsBase {
|
|||
export interface ICredentialsDb extends ICredentialsBase, ICredentialsEncrypted {
|
||||
id: number | string;
|
||||
name: string;
|
||||
shared?: SharedCredentials[];
|
||||
}
|
||||
|
||||
export interface ICredentialsResponse extends ICredentialsDb {
|
||||
|
|
@ -211,7 +214,7 @@ export interface IExecutionResponse extends IExecutionBase {
|
|||
workflowData: IWorkflowBase;
|
||||
}
|
||||
|
||||
// Flatted data to save memory when saving in database or transfering
|
||||
// Flatted data to save memory when saving in database or transferring
|
||||
// via REST API
|
||||
export interface IExecutionFlatted extends IExecutionBase {
|
||||
data: string;
|
||||
|
|
@ -222,7 +225,7 @@ export interface IExecutionFlattedDb extends IExecutionBase {
|
|||
id: number | string;
|
||||
data: string;
|
||||
waitTill?: Date | null;
|
||||
workflowData: IWorkflowBase;
|
||||
workflowData: Omit<IWorkflowBase, 'pinData'>;
|
||||
}
|
||||
|
||||
export interface IExecutionFlattedResponse extends IExecutionFlatted {
|
||||
|
|
@ -461,6 +464,19 @@ export interface IVersionNotificationSettings {
|
|||
infoUrl: string;
|
||||
}
|
||||
|
||||
export interface IN8nNodePackageJson {
|
||||
name: string;
|
||||
version: string;
|
||||
n8n?: {
|
||||
credentials?: string[];
|
||||
nodes?: string[];
|
||||
};
|
||||
author?: {
|
||||
name?: string;
|
||||
email?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IN8nUISettings {
|
||||
endpointWebhook: string;
|
||||
endpointWebhookTest: string;
|
||||
|
|
@ -494,6 +510,18 @@ export interface IN8nUISettings {
|
|||
enabled: boolean;
|
||||
host: string;
|
||||
};
|
||||
onboardingCallPromptEnabled: boolean;
|
||||
missingPackages?: boolean;
|
||||
executionMode: 'regular' | 'queue';
|
||||
communityNodesEnabled: boolean;
|
||||
deployment: {
|
||||
type: string;
|
||||
};
|
||||
isNpmAvailable: boolean;
|
||||
enterprise: {
|
||||
sharing: boolean;
|
||||
workflowSharing: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IPersonalizationSurveyAnswers {
|
||||
|
|
@ -532,6 +560,8 @@ export type IPushData =
|
|||
| PushDataExecuteAfter
|
||||
| PushDataExecuteBefore
|
||||
| PushDataConsoleMessage
|
||||
| PushDataReloadNodeType
|
||||
| PushDataRemoveNodeType
|
||||
| PushDataTestWebhook;
|
||||
|
||||
type PushDataExecutionFinished = {
|
||||
|
|
@ -559,6 +589,16 @@ type PushDataConsoleMessage = {
|
|||
type: 'sendConsoleMessage';
|
||||
};
|
||||
|
||||
type PushDataReloadNodeType = {
|
||||
data: IPushDataReloadNodeType;
|
||||
type: 'reloadNodeType';
|
||||
};
|
||||
|
||||
type PushDataRemoveNodeType = {
|
||||
data: IPushDataRemoveNodeType;
|
||||
type: 'removeNodeType';
|
||||
};
|
||||
|
||||
type PushDataTestWebhook = {
|
||||
data: IPushDataTestWebhook;
|
||||
type: 'testWebhookDeleted' | 'testWebhookReceived';
|
||||
|
|
@ -590,6 +630,16 @@ export interface IPushDataNodeExecuteBefore {
|
|||
nodeName: string;
|
||||
}
|
||||
|
||||
export interface IPushDataReloadNodeType {
|
||||
name: string;
|
||||
version: number;
|
||||
}
|
||||
|
||||
export interface IPushDataRemoveNodeType {
|
||||
name: string;
|
||||
version: number;
|
||||
}
|
||||
|
||||
export interface IPushDataTestWebhook {
|
||||
executionId: string;
|
||||
workflowId: string;
|
||||
|
|
@ -646,6 +696,7 @@ export interface IWorkflowExecutionDataProcess {
|
|||
executionMode: WorkflowExecuteMode;
|
||||
executionData?: IRunExecutionData;
|
||||
runData?: IRunData;
|
||||
pinData?: IPinData;
|
||||
retryOf?: number | string;
|
||||
sessionId?: string;
|
||||
startNodes?: string[];
|
||||
|
|
@ -669,6 +720,33 @@ export interface IWorkflowExecuteProcess {
|
|||
|
||||
export type WhereClause = Record<string, { id: string }>;
|
||||
|
||||
// ----------------------------------
|
||||
// community nodes
|
||||
// ----------------------------------
|
||||
|
||||
export namespace CommunityPackages {
|
||||
export type ParsedPackageName = {
|
||||
packageName: string;
|
||||
rawString: string;
|
||||
scope?: string;
|
||||
version?: string;
|
||||
};
|
||||
|
||||
export type AvailableUpdates = {
|
||||
[packageName: string]: {
|
||||
current: string;
|
||||
wanted: string;
|
||||
latest: string;
|
||||
location: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type PackageStatusCheck = {
|
||||
status: 'OK' | 'Banned';
|
||||
reason?: string;
|
||||
};
|
||||
}
|
||||
|
||||
// ----------------------------------
|
||||
// telemetry
|
||||
// ----------------------------------
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* eslint-disable import/no-cycle */
|
||||
import { get as pslGet } from 'psl';
|
||||
import { snakeCase } from 'change-case';
|
||||
import { BinaryDataManager } from 'n8n-core';
|
||||
import {
|
||||
INodesGraphResult,
|
||||
|
|
@ -8,7 +8,7 @@ import {
|
|||
ITelemetryTrackProperties,
|
||||
TelemetryHelpers,
|
||||
} from 'n8n-workflow';
|
||||
import { snakeCase } from 'change-case';
|
||||
import { get as pslGet } from 'psl';
|
||||
import {
|
||||
IDiagnosticInfo,
|
||||
IInternalHooksClass,
|
||||
|
|
@ -16,15 +16,20 @@ import {
|
|||
IWorkflowBase,
|
||||
IWorkflowDb,
|
||||
} from '.';
|
||||
import { Telemetry } from './telemetry';
|
||||
import { IExecutionTrackProperties } from './Interfaces';
|
||||
import { Telemetry } from './telemetry';
|
||||
|
||||
export class InternalHooksClass implements IInternalHooksClass {
|
||||
private versionCli: string;
|
||||
|
||||
private nodeTypes: INodeTypes;
|
||||
|
||||
constructor(private telemetry: Telemetry, versionCli: string, nodeTypes: INodeTypes) {
|
||||
constructor(
|
||||
private telemetry: Telemetry,
|
||||
private instanceId: string,
|
||||
versionCli: string,
|
||||
nodeTypes: INodeTypes,
|
||||
) {
|
||||
this.versionCli = versionCli;
|
||||
this.nodeTypes = nodeTypes;
|
||||
}
|
||||
|
|
@ -73,6 +78,7 @@ export class InternalHooksClass implements IInternalHooksClass {
|
|||
return this.telemetry.track(
|
||||
'User responded to personalization questions',
|
||||
personalizationSurveyData,
|
||||
{ withPostHog: true },
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -106,16 +112,20 @@ export class InternalHooksClass implements IInternalHooksClass {
|
|||
(note) => note.overlapping,
|
||||
).length;
|
||||
|
||||
return this.telemetry.track('User saved workflow', {
|
||||
user_id: userId,
|
||||
workflow_id: workflow.id,
|
||||
node_graph_string: JSON.stringify(nodeGraph),
|
||||
notes_count_overlapping: overlappingCount,
|
||||
notes_count_non_overlapping: notesCount - overlappingCount,
|
||||
version_cli: this.versionCli,
|
||||
num_tags: workflow.tags?.length ?? 0,
|
||||
public_api: publicApi,
|
||||
});
|
||||
return this.telemetry.track(
|
||||
'User saved workflow',
|
||||
{
|
||||
user_id: userId,
|
||||
workflow_id: workflow.id,
|
||||
node_graph_string: JSON.stringify(nodeGraph),
|
||||
notes_count_overlapping: overlappingCount,
|
||||
notes_count_non_overlapping: notesCount - overlappingCount,
|
||||
version_cli: this.versionCli,
|
||||
num_tags: workflow.tags?.length ?? 0,
|
||||
public_api: publicApi,
|
||||
},
|
||||
{ withPostHog: true },
|
||||
);
|
||||
}
|
||||
|
||||
async onWorkflowPostExecute(
|
||||
|
|
@ -150,8 +160,14 @@ export class InternalHooksClass implements IInternalHooksClass {
|
|||
|
||||
if (!properties.success && runData?.data.resultData.error) {
|
||||
properties.error_message = runData?.data.resultData.error.message;
|
||||
let errorNodeName = runData?.data.resultData.error.node?.name;
|
||||
properties.error_node_type = runData?.data.resultData.error.node?.type;
|
||||
let errorNodeName =
|
||||
'node' in runData?.data.resultData.error
|
||||
? runData?.data.resultData.error.node?.name
|
||||
: undefined;
|
||||
properties.error_node_type =
|
||||
'node' in runData?.data.resultData.error
|
||||
? runData?.data.resultData.error.node?.type
|
||||
: undefined;
|
||||
|
||||
if (runData.data.resultData.lastNodeExecuted) {
|
||||
const lastNode = TelemetryHelpers.getNodeTypeForName(
|
||||
|
|
@ -182,6 +198,7 @@ export class InternalHooksClass implements IInternalHooksClass {
|
|||
}
|
||||
|
||||
const manualExecEventProperties: ITelemetryTrackProperties = {
|
||||
user_id: userId,
|
||||
workflow_id: workflow.id.toString(),
|
||||
status: properties.success ? 'success' : 'failed',
|
||||
error_message: properties.error_message as string,
|
||||
|
|
@ -197,14 +214,18 @@ export class InternalHooksClass implements IInternalHooksClass {
|
|||
}
|
||||
|
||||
if (runData.data.startData?.destinationNode) {
|
||||
const telemetryPayload = {
|
||||
...manualExecEventProperties,
|
||||
node_type: TelemetryHelpers.getNodeTypeForName(
|
||||
workflow,
|
||||
runData.data.startData?.destinationNode,
|
||||
)?.type,
|
||||
node_id: nodeGraphResult.nameIndices[runData.data.startData?.destinationNode],
|
||||
};
|
||||
|
||||
promises.push(
|
||||
this.telemetry.track('Manual node exec finished', {
|
||||
...manualExecEventProperties,
|
||||
node_type: TelemetryHelpers.getNodeTypeForName(
|
||||
workflow,
|
||||
runData.data.startData?.destinationNode,
|
||||
)?.type,
|
||||
node_id: nodeGraphResult.nameIndices[runData.data.startData?.destinationNode],
|
||||
this.telemetry.track('Manual node exec finished', telemetryPayload, {
|
||||
withPostHog: true,
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
|
|
@ -219,7 +240,9 @@ export class InternalHooksClass implements IInternalHooksClass {
|
|||
});
|
||||
|
||||
promises.push(
|
||||
this.telemetry.track('Manual workflow exec finished', manualExecEventProperties),
|
||||
this.telemetry.track('Manual workflow exec finished', manualExecEventProperties, {
|
||||
withPostHog: true,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -333,7 +356,7 @@ export class InternalHooksClass implements IInternalHooksClass {
|
|||
public_api: boolean;
|
||||
}): Promise<void> {
|
||||
return this.telemetry.track(
|
||||
'Instance sent transacptional email to user',
|
||||
'Instance sent transactional email to user',
|
||||
userTransactionalEmailData,
|
||||
);
|
||||
}
|
||||
|
|
@ -386,4 +409,73 @@ export class InternalHooksClass implements IInternalHooksClass {
|
|||
failedEmailData,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Credentials
|
||||
*/
|
||||
|
||||
async onUserCreatedCredentials(userCreatedCredentialsData: {
|
||||
credential_type: string;
|
||||
credential_id: string;
|
||||
public_api: boolean;
|
||||
}): Promise<void> {
|
||||
return this.telemetry.track('User created credentials', {
|
||||
...userCreatedCredentialsData,
|
||||
instance_id: this.instanceId,
|
||||
});
|
||||
}
|
||||
|
||||
async onUserSharedCredentials(userSharedCredentialsData: {
|
||||
credential_type: string;
|
||||
credential_id: string;
|
||||
user_id_sharer: string;
|
||||
user_ids_sharees_added: string[];
|
||||
sharees_removed: number | null;
|
||||
}): Promise<void> {
|
||||
return this.telemetry.track('User updated cred sharing', {
|
||||
...userSharedCredentialsData,
|
||||
instance_id: this.instanceId,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Community nodes backend telemetry events
|
||||
*/
|
||||
|
||||
async onCommunityPackageInstallFinished(installationData: {
|
||||
user_id: string;
|
||||
input_string: string;
|
||||
package_name: string;
|
||||
success: boolean;
|
||||
package_version?: string;
|
||||
package_node_names?: string[];
|
||||
package_author?: string;
|
||||
package_author_email?: string;
|
||||
failure_reason?: string;
|
||||
}): Promise<void> {
|
||||
return this.telemetry.track('cnr package install finished', installationData);
|
||||
}
|
||||
|
||||
async onCommunityPackageUpdateFinished(updateData: {
|
||||
user_id: string;
|
||||
package_name: string;
|
||||
package_version_current: string;
|
||||
package_version_new: string;
|
||||
package_node_names: string[];
|
||||
package_author?: string;
|
||||
package_author_email?: string;
|
||||
}): Promise<void> {
|
||||
return this.telemetry.track('cnr package updated', updateData);
|
||||
}
|
||||
|
||||
async onCommunityPackageDeleteFinished(updateData: {
|
||||
user_id: string;
|
||||
package_name: string;
|
||||
package_version: string;
|
||||
package_node_names: string[];
|
||||
package_author?: string;
|
||||
package_author_email?: string;
|
||||
}): Promise<void> {
|
||||
return this.telemetry.track('cnr package deleted', updateData);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ export class InternalHooksManager {
|
|||
if (!this.internalHooksInstance) {
|
||||
this.internalHooksInstance = new InternalHooksClass(
|
||||
new Telemetry(instanceId, versionCli),
|
||||
instanceId,
|
||||
versionCli,
|
||||
nodeTypes,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
/* eslint-disable import/no-cycle */
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
/* eslint-disable no-prototype-builtins */
|
||||
/* eslint-disable no-param-reassign */
|
||||
|
|
@ -16,6 +18,7 @@ import {
|
|||
ILogger,
|
||||
INodeType,
|
||||
INodeTypeData,
|
||||
INodeTypeNameVersion,
|
||||
INodeVersionedType,
|
||||
LoggerProxy,
|
||||
} from 'n8n-workflow';
|
||||
|
|
@ -28,11 +31,30 @@ import {
|
|||
} from 'fs/promises';
|
||||
import glob from 'fast-glob';
|
||||
import path from 'path';
|
||||
import pick from 'lodash.pick';
|
||||
import { IN8nNodePackageJson } from './Interfaces';
|
||||
import { getLogger } from './Logger';
|
||||
import config from '../config';
|
||||
import { NodeTypes } from '.';
|
||||
import { InstalledPackages } from './databases/entities/InstalledPackages';
|
||||
import { InstalledNodes } from './databases/entities/InstalledNodes';
|
||||
import { executeCommand, loadClassInIsolation } from './CommunityNodes/helpers';
|
||||
import { RESPONSE_ERROR_MESSAGES } from './constants';
|
||||
import {
|
||||
persistInstalledPackageData,
|
||||
removePackageFromDatabase,
|
||||
} from './CommunityNodes/packageModel';
|
||||
|
||||
const CUSTOM_NODES_CATEGORY = 'Custom Nodes';
|
||||
|
||||
function toJSON() {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
return {
|
||||
...this,
|
||||
authenticate: typeof this.authenticate === 'function' ? {} : this.authenticate,
|
||||
};
|
||||
}
|
||||
|
||||
class LoadNodesAndCredentialsClass {
|
||||
nodeTypes: INodeTypeData = {};
|
||||
|
||||
|
|
@ -50,6 +72,30 @@ class LoadNodesAndCredentialsClass {
|
|||
this.logger = getLogger();
|
||||
LoggerProxy.init(this.logger);
|
||||
|
||||
// Make sure the imported modules can resolve dependencies fine.
|
||||
const delimiter = process.platform === 'win32' ? ';' : ':';
|
||||
process.env.NODE_PATH = module.paths.join(delimiter);
|
||||
// @ts-ignore
|
||||
module.constructor._initPaths();
|
||||
|
||||
this.nodeModulesPath = await this.getNodeModulesFolderLocation();
|
||||
|
||||
this.excludeNodes = config.getEnv('nodes.exclude');
|
||||
this.includeNodes = config.getEnv('nodes.include');
|
||||
|
||||
// Get all the installed packages which contain n8n nodes
|
||||
const nodePackages = await this.getN8nNodePackages(this.nodeModulesPath);
|
||||
|
||||
for (const packagePath of nodePackages) {
|
||||
await this.loadDataFromPackage(packagePath);
|
||||
}
|
||||
|
||||
await this.loadNodesFromDownloadedPackages();
|
||||
|
||||
await this.loadNodesFromCustomFolders();
|
||||
}
|
||||
|
||||
async getNodeModulesFolderLocation(): Promise<string> {
|
||||
// Get the path to the node-modules folder to be later able
|
||||
// to load the credentials and nodes
|
||||
const checkPaths = [
|
||||
|
|
@ -58,34 +104,43 @@ class LoadNodesAndCredentialsClass {
|
|||
// In case "n8n" package is the root and the packages are
|
||||
// in the "node_modules" folder underneath it.
|
||||
path.join(__dirname, '..', '..', 'node_modules', 'n8n-workflow'),
|
||||
// In case "n8n" package is installed using npm/yarn workspaces
|
||||
// the node_modules folder is in the root of the workspace.
|
||||
path.join(__dirname, '..', '..', '..', '..', 'node_modules', 'n8n-workflow'),
|
||||
];
|
||||
for (const checkPath of checkPaths) {
|
||||
try {
|
||||
await fsAccess(checkPath);
|
||||
// Folder exists, so use it.
|
||||
this.nodeModulesPath = path.dirname(checkPath);
|
||||
break;
|
||||
} catch (error) {
|
||||
return path.dirname(checkPath);
|
||||
} catch (_) {
|
||||
// Folder does not exist so get next one
|
||||
// eslint-disable-next-line no-continue
|
||||
continue;
|
||||
}
|
||||
}
|
||||
throw new Error('Could not find "node_modules" folder!');
|
||||
}
|
||||
|
||||
if (this.nodeModulesPath === '') {
|
||||
throw new Error('Could not find "node_modules" folder!');
|
||||
}
|
||||
|
||||
this.excludeNodes = config.getEnv('nodes.exclude');
|
||||
this.includeNodes = config.getEnv('nodes.include');
|
||||
|
||||
// Get all the installed packages which contain n8n nodes
|
||||
const packages = await this.getN8nNodePackages();
|
||||
|
||||
for (const packageName of packages) {
|
||||
await this.loadDataFromPackage(packageName);
|
||||
async loadNodesFromDownloadedPackages(): Promise<void> {
|
||||
const nodePackages = [];
|
||||
try {
|
||||
// Read downloaded nodes and credentials
|
||||
const downloadedNodesFolder = UserSettings.getUserN8nFolderDowloadedNodesPath();
|
||||
const downloadedNodesFolderModules = path.join(downloadedNodesFolder, 'node_modules');
|
||||
await fsAccess(downloadedNodesFolderModules);
|
||||
const downloadedPackages = await this.getN8nNodePackages(downloadedNodesFolderModules);
|
||||
nodePackages.push(...downloadedPackages);
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (error) {}
|
||||
|
||||
for (const packagePath of nodePackages) {
|
||||
try {
|
||||
await this.loadDataFromPackage(packagePath);
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (error) {}
|
||||
}
|
||||
}
|
||||
|
||||
async loadNodesFromCustomFolders(): Promise<void> {
|
||||
// Read nodes and credentials from custom directories
|
||||
const customDirectories = [];
|
||||
|
||||
|
|
@ -96,8 +151,7 @@ class LoadNodesAndCredentialsClass {
|
|||
if (process.env[CUSTOM_EXTENSION_ENV] !== undefined) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const customExtensionFolders = process.env[CUSTOM_EXTENSION_ENV]!.split(';');
|
||||
// eslint-disable-next-line prefer-spread
|
||||
customDirectories.push.apply(customDirectories, customExtensionFolders);
|
||||
customDirectories.push(...customExtensionFolders);
|
||||
}
|
||||
|
||||
for (const directory of customDirectories) {
|
||||
|
|
@ -109,13 +163,11 @@ class LoadNodesAndCredentialsClass {
|
|||
* Returns all the names of the packages which could
|
||||
* contain n8n nodes
|
||||
*
|
||||
* @returns {Promise<string[]>}
|
||||
* @memberof LoadNodesAndCredentialsClass
|
||||
*/
|
||||
async getN8nNodePackages(): Promise<string[]> {
|
||||
async getN8nNodePackages(baseModulesPath: string): Promise<string[]> {
|
||||
const getN8nNodePackagesRecursive = async (relativePath: string): Promise<string[]> => {
|
||||
const results: string[] = [];
|
||||
const nodeModulesPath = `${this.nodeModulesPath}/${relativePath}`;
|
||||
const nodeModulesPath = `${baseModulesPath}/${relativePath}`;
|
||||
for (const file of await fsReaddir(nodeModulesPath)) {
|
||||
const isN8nNodesPackage = file.indexOf('n8n-nodes-') === 0;
|
||||
const isNpmScopedPackage = file.indexOf('@') === 0;
|
||||
|
|
@ -126,7 +178,7 @@ class LoadNodesAndCredentialsClass {
|
|||
continue;
|
||||
}
|
||||
if (isN8nNodesPackage) {
|
||||
results.push(`${relativePath}${file}`);
|
||||
results.push(`${baseModulesPath}/${relativePath}${file}`);
|
||||
}
|
||||
if (isNpmScopedPackage) {
|
||||
results.push(...(await getN8nNodePackagesRecursive(`${relativePath}${file}/`)));
|
||||
|
|
@ -142,28 +194,17 @@ class LoadNodesAndCredentialsClass {
|
|||
*
|
||||
* @param {string} credentialName The name of the credentials
|
||||
* @param {string} filePath The file to read credentials from
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async loadCredentialsFromFile(credentialName: string, filePath: string): Promise<void> {
|
||||
// eslint-disable-next-line import/no-dynamic-require, global-require, @typescript-eslint/no-var-requires
|
||||
const tempModule = require(filePath);
|
||||
|
||||
loadCredentialsFromFile(credentialName: string, filePath: string): void {
|
||||
let tempCredential: ICredentialType;
|
||||
try {
|
||||
tempCredential = loadClassInIsolation(filePath, credentialName);
|
||||
|
||||
// Add serializer method "toJSON" to the class so that authenticate method (if defined)
|
||||
// gets mapped to the authenticate attribute before it is sent to the client.
|
||||
// The authenticate property is used by the client to decide whether or not to
|
||||
// include the credential type in the predifined credentials (HTTP node)
|
||||
// eslint-disable-next-line func-names
|
||||
tempModule[credentialName].prototype.toJSON = function () {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
return {
|
||||
...this,
|
||||
authenticate: typeof this.authenticate === 'function' ? {} : this.authenticate,
|
||||
};
|
||||
};
|
||||
|
||||
tempCredential = new tempModule[credentialName]() as ICredentialType;
|
||||
// include the credential type in the predefined credentials (HTTP node)
|
||||
Object.assign(tempCredential, { toJSON });
|
||||
|
||||
if (tempCredential.icon && tempCredential.icon.startsWith('file:')) {
|
||||
// If a file icon gets used add the full path
|
||||
|
|
@ -188,32 +229,140 @@ class LoadNodesAndCredentialsClass {
|
|||
};
|
||||
}
|
||||
|
||||
async loadNpmModule(packageName: string, version?: string): Promise<InstalledPackages> {
|
||||
const downloadFolder = UserSettings.getUserN8nFolderDowloadedNodesPath();
|
||||
const command = `npm install ${packageName}${version ? `@${version}` : ''}`;
|
||||
|
||||
await executeCommand(command);
|
||||
|
||||
const finalNodeUnpackedPath = path.join(downloadFolder, 'node_modules', packageName);
|
||||
|
||||
const loadedNodes = await this.loadDataFromPackage(finalNodeUnpackedPath);
|
||||
|
||||
if (loadedNodes.length > 0) {
|
||||
const packageFile = await this.readPackageJson(finalNodeUnpackedPath);
|
||||
// Save info to DB
|
||||
try {
|
||||
const installedPackage = await persistInstalledPackageData(
|
||||
packageFile.name,
|
||||
packageFile.version,
|
||||
loadedNodes,
|
||||
this.nodeTypes,
|
||||
packageFile.author?.name,
|
||||
packageFile.author?.email,
|
||||
);
|
||||
this.attachNodesToNodeTypes(installedPackage.installedNodes);
|
||||
return installedPackage;
|
||||
} catch (error) {
|
||||
LoggerProxy.error('Failed to save installed packages and nodes', { error, packageName });
|
||||
throw error;
|
||||
}
|
||||
} else {
|
||||
// Remove this package since it contains no loadable nodes
|
||||
const removeCommand = `npm remove ${packageName}`;
|
||||
try {
|
||||
await executeCommand(removeCommand);
|
||||
} catch (error) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
throw new Error(RESPONSE_ERROR_MESSAGES.PACKAGE_DOES_NOT_CONTAIN_NODES);
|
||||
}
|
||||
}
|
||||
|
||||
async removeNpmModule(packageName: string, installedPackage: InstalledPackages): Promise<void> {
|
||||
const command = `npm remove ${packageName}`;
|
||||
|
||||
await executeCommand(command);
|
||||
|
||||
void (await removePackageFromDatabase(installedPackage));
|
||||
|
||||
this.unloadNodes(installedPackage.installedNodes);
|
||||
}
|
||||
|
||||
async updateNpmModule(
|
||||
packageName: string,
|
||||
installedPackage: InstalledPackages,
|
||||
): Promise<InstalledPackages> {
|
||||
const downloadFolder = UserSettings.getUserN8nFolderDowloadedNodesPath();
|
||||
|
||||
const command = `npm i ${packageName}@latest`;
|
||||
|
||||
try {
|
||||
await executeCommand(command);
|
||||
} catch (error) {
|
||||
if (error.message === RESPONSE_ERROR_MESSAGES.PACKAGE_NOT_FOUND) {
|
||||
throw new Error(`The npm package "${packageName}" could not be found.`);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.unloadNodes(installedPackage.installedNodes);
|
||||
|
||||
const finalNodeUnpackedPath = path.join(downloadFolder, 'node_modules', packageName);
|
||||
|
||||
const loadedNodes = await this.loadDataFromPackage(finalNodeUnpackedPath);
|
||||
|
||||
if (loadedNodes.length > 0) {
|
||||
const packageFile = await this.readPackageJson(finalNodeUnpackedPath);
|
||||
|
||||
// Save info to DB
|
||||
try {
|
||||
await removePackageFromDatabase(installedPackage);
|
||||
|
||||
const newlyInstalledPackage = await persistInstalledPackageData(
|
||||
packageFile.name,
|
||||
packageFile.version,
|
||||
loadedNodes,
|
||||
this.nodeTypes,
|
||||
packageFile.author?.name,
|
||||
packageFile.author?.email,
|
||||
);
|
||||
|
||||
this.attachNodesToNodeTypes(newlyInstalledPackage.installedNodes);
|
||||
|
||||
return newlyInstalledPackage;
|
||||
} catch (error) {
|
||||
LoggerProxy.error('Failed to save installed packages and nodes', { error, packageName });
|
||||
throw error;
|
||||
}
|
||||
} else {
|
||||
// Remove this package since it contains no loadable nodes
|
||||
const removeCommand = `npm remove ${packageName}`;
|
||||
try {
|
||||
await executeCommand(removeCommand);
|
||||
} catch (error) {
|
||||
// Do nothing
|
||||
}
|
||||
throw new Error(RESPONSE_ERROR_MESSAGES.PACKAGE_DOES_NOT_CONTAIN_NODES);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a node from a file
|
||||
*
|
||||
* @param {string} packageName The package name to set for the found nodes
|
||||
* @param {string} nodeName Tha name of the node
|
||||
* @param {string} filePath The file to read node from
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async loadNodeFromFile(packageName: string, nodeName: string, filePath: string): Promise<void> {
|
||||
loadNodeFromFile(
|
||||
packageName: string,
|
||||
nodeName: string,
|
||||
filePath: string,
|
||||
): INodeTypeNameVersion | undefined {
|
||||
let tempNode: INodeType | INodeVersionedType;
|
||||
let fullNodeName: string;
|
||||
|
||||
// eslint-disable-next-line import/no-dynamic-require, global-require, @typescript-eslint/no-var-requires
|
||||
const tempModule = require(filePath);
|
||||
let nodeVersion = 1;
|
||||
|
||||
try {
|
||||
tempNode = new tempModule[nodeName]();
|
||||
tempNode = loadClassInIsolation(filePath, nodeName);
|
||||
this.addCodex({ node: tempNode, filePath, isCustom: packageName === 'CUSTOM' });
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`Error loading node "${nodeName}" from: "${filePath}"`);
|
||||
// eslint-disable-next-line no-console, @typescript-eslint/restrict-template-expressions
|
||||
console.error(`Error loading node "${nodeName}" from: "${filePath}" - ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line prefer-const
|
||||
fullNodeName = `${packageName}.${tempNode.description.name}`;
|
||||
const fullNodeName = `${packageName}.${tempNode.description.name}`;
|
||||
tempNode.description.name = fullNodeName;
|
||||
|
||||
if (tempNode.description.icon !== undefined && tempNode.description.icon.startsWith('file:')) {
|
||||
|
|
@ -224,16 +373,10 @@ class LoadNodesAndCredentialsClass {
|
|||
)}`;
|
||||
}
|
||||
|
||||
if (tempNode.hasOwnProperty('executeSingle')) {
|
||||
this.logger.warn(
|
||||
`"executeSingle" will get deprecated soon. Please update the code of node "${packageName}.${nodeName}" to use "execute" instead!`,
|
||||
{ filePath },
|
||||
);
|
||||
}
|
||||
|
||||
if (tempNode.hasOwnProperty('nodeVersions')) {
|
||||
const versionedNodeType = (tempNode as INodeVersionedType).getNodeType();
|
||||
this.addCodex({ node: versionedNodeType, filePath, isCustom: packageName === 'CUSTOM' });
|
||||
nodeVersion = (tempNode as INodeVersionedType).currentVersion;
|
||||
|
||||
if (
|
||||
versionedNodeType.description.icon !== undefined &&
|
||||
|
|
@ -252,13 +395,19 @@ class LoadNodesAndCredentialsClass {
|
|||
{ filePath },
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Short renaming to avoid type issues
|
||||
const tmpNode = tempNode as INodeType;
|
||||
nodeVersion = Array.isArray(tmpNode.description.version)
|
||||
? tmpNode.description.version.slice(-1)[0]
|
||||
: tmpNode.description.version;
|
||||
}
|
||||
|
||||
if (this.includeNodes !== undefined && !this.includeNodes.includes(fullNodeName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the node should be skiped
|
||||
// Check if the node should be skipped
|
||||
if (this.excludeNodes !== undefined && this.excludeNodes.includes(fullNodeName)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -267,22 +416,31 @@ class LoadNodesAndCredentialsClass {
|
|||
type: tempNode,
|
||||
sourcePath: filePath,
|
||||
};
|
||||
|
||||
// eslint-disable-next-line consistent-return
|
||||
return {
|
||||
name: fullNodeName,
|
||||
version: nodeVersion,
|
||||
} as INodeTypeNameVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves `categories`, `subcategories` and alias (if defined)
|
||||
* from the codex data for the node at the given file path.
|
||||
* Retrieves `categories`, `subcategories`, partial `resources` and
|
||||
* alias (if defined) from the codex data for the node at the given file path.
|
||||
*
|
||||
* @param {string} filePath The file path to a `*.node.js` file
|
||||
* @returns {CodexData}
|
||||
*/
|
||||
getCodex(filePath: string): CodexData {
|
||||
// eslint-disable-next-line global-require, import/no-dynamic-require, @typescript-eslint/no-var-requires
|
||||
const { categories, subcategories, alias } = require(`${filePath}on`); // .js to .json
|
||||
const { categories, subcategories, resources: allResources, alias } = require(`${filePath}on`); // .js to .json
|
||||
|
||||
const resources = pick(allResources, ['primaryDocumentation', 'credentialDocumentation']);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
return {
|
||||
...(categories && { categories }),
|
||||
...(subcategories && { subcategories }),
|
||||
...(resources && { resources }),
|
||||
...(alias && { alias }),
|
||||
};
|
||||
}
|
||||
|
|
@ -291,11 +449,9 @@ class LoadNodesAndCredentialsClass {
|
|||
* Adds a node codex `categories` and `subcategories` (if defined)
|
||||
* to a node description `codex` property.
|
||||
*
|
||||
* @param {object} obj
|
||||
* @param obj.node Node to add categories to
|
||||
* @param obj.filePath Path to the built node
|
||||
* @param obj.isCustom Whether the node is custom
|
||||
* @returns {void}
|
||||
*/
|
||||
addCodex({
|
||||
node,
|
||||
|
|
@ -317,8 +473,7 @@ class LoadNodesAndCredentialsClass {
|
|||
|
||||
node.description.codex = codex;
|
||||
} catch (_) {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
this.logger.debug(`No codex available for: ${filePath.split('/').pop()}`);
|
||||
this.logger.debug(`No codex available for: ${filePath.split('/').pop() ?? ''}`);
|
||||
|
||||
if (isCustom) {
|
||||
node.description.codex = {
|
||||
|
|
@ -333,72 +488,87 @@ class LoadNodesAndCredentialsClass {
|
|||
*
|
||||
* @param {string} setPackageName The package name to set for the found nodes
|
||||
* @param {string} directory The directory to look in
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async loadDataFromDirectory(setPackageName: string, directory: string): Promise<void> {
|
||||
const files = await glob(path.join(directory, '**/*.@(node|credentials).js'));
|
||||
const files = await glob('**/*.@(node|credentials).js', {
|
||||
cwd: directory,
|
||||
absolute: true,
|
||||
});
|
||||
|
||||
let fileName: string;
|
||||
let type: string;
|
||||
|
||||
const loadPromises = [];
|
||||
for (const filePath of files) {
|
||||
[fileName, type] = path.parse(filePath).name.split('.');
|
||||
const [fileName, type] = path.parse(filePath).name.split('.');
|
||||
|
||||
if (type === 'node') {
|
||||
loadPromises.push(this.loadNodeFromFile(setPackageName, fileName, filePath));
|
||||
this.loadNodeFromFile(setPackageName, fileName, filePath);
|
||||
} else if (type === 'credentials') {
|
||||
loadPromises.push(this.loadCredentialsFromFile(fileName, filePath));
|
||||
this.loadCredentialsFromFile(fileName, filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(loadPromises);
|
||||
async readPackageJson(packagePath: string): Promise<IN8nNodePackageJson> {
|
||||
// Get the absolute path of the package
|
||||
const packageFileString = await fsReadFile(path.join(packagePath, 'package.json'), 'utf8');
|
||||
return JSON.parse(packageFileString) as IN8nNodePackageJson;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads nodes and credentials from the package with the given name
|
||||
*
|
||||
* @param {string} packageName The name to read data from
|
||||
* @returns {Promise<void>}
|
||||
* @param {string} packagePath The path to read data from
|
||||
*/
|
||||
async loadDataFromPackage(packageName: string): Promise<void> {
|
||||
async loadDataFromPackage(packagePath: string): Promise<INodeTypeNameVersion[]> {
|
||||
// Get the absolute path of the package
|
||||
const packagePath = path.join(this.nodeModulesPath, packageName);
|
||||
|
||||
// Read the data from the package.json file to see if any n8n data is defiend
|
||||
const packageFileString = await fsReadFile(path.join(packagePath, 'package.json'), 'utf8');
|
||||
const packageFile = JSON.parse(packageFileString);
|
||||
if (!packageFile.hasOwnProperty('n8n')) {
|
||||
return;
|
||||
const packageFile = await this.readPackageJson(packagePath);
|
||||
if (!packageFile.n8n) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let tempPath: string;
|
||||
let filePath: string;
|
||||
const packageName = packageFile.name;
|
||||
const { nodes, credentials } = packageFile.n8n;
|
||||
const returnData: INodeTypeNameVersion[] = [];
|
||||
|
||||
// Read all node types
|
||||
let fileName: string;
|
||||
let type: string;
|
||||
if (packageFile.n8n.hasOwnProperty('nodes') && Array.isArray(packageFile.n8n.nodes)) {
|
||||
for (filePath of packageFile.n8n.nodes) {
|
||||
tempPath = path.join(packagePath, filePath);
|
||||
[fileName, type] = path.parse(filePath).name.split('.');
|
||||
await this.loadNodeFromFile(packageName, fileName, tempPath);
|
||||
if (Array.isArray(nodes)) {
|
||||
for (const filePath of nodes) {
|
||||
const tempPath = path.join(packagePath, filePath);
|
||||
const [fileName] = path.parse(filePath).name.split('.');
|
||||
const loadData = this.loadNodeFromFile(packageName, fileName, tempPath);
|
||||
if (loadData) {
|
||||
returnData.push(loadData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read all credential types
|
||||
if (
|
||||
packageFile.n8n.hasOwnProperty('credentials') &&
|
||||
Array.isArray(packageFile.n8n.credentials)
|
||||
) {
|
||||
for (filePath of packageFile.n8n.credentials) {
|
||||
tempPath = path.join(packagePath, filePath);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
[fileName, type] = path.parse(filePath).name.split('.');
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
if (Array.isArray(credentials)) {
|
||||
for (const filePath of credentials) {
|
||||
const tempPath = path.join(packagePath, filePath);
|
||||
const [fileName] = path.parse(filePath).name.split('.');
|
||||
this.loadCredentialsFromFile(fileName, tempPath);
|
||||
}
|
||||
}
|
||||
|
||||
return returnData;
|
||||
}
|
||||
|
||||
unloadNodes(installedNodes: InstalledNodes[]): void {
|
||||
const nodeTypes = NodeTypes();
|
||||
installedNodes.forEach((installedNode) => {
|
||||
nodeTypes.removeNodeType(installedNode.type);
|
||||
delete this.nodeTypes[installedNode.type];
|
||||
});
|
||||
}
|
||||
|
||||
attachNodesToNodeTypes(installedNodes: InstalledNodes[]): void {
|
||||
const nodeTypes = NodeTypes();
|
||||
installedNodes.forEach((installedNode) => {
|
||||
nodeTypes.attachNodeType(
|
||||
installedNode.type,
|
||||
this.nodeTypes[installedNode.type].type,
|
||||
this.nodeTypes[installedNode.type].sourcePath,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ export class Logger implements ILogger {
|
|||
winston.format.printf(({ level, message, timestamp, metadata }) => {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
return `${timestamp} | ${level.padEnd(18)} | ${message}${
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
Object.keys(metadata).length ? ` ${JSON.stringify(inspect(metadata))}` : ''
|
||||
}`;
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -57,6 +57,21 @@ class NodeTypesClass implements INodeTypes {
|
|||
}
|
||||
return NodeHelpers.getVersionedNodeType(this.nodeTypes[nodeType].type, version);
|
||||
}
|
||||
|
||||
attachNodeType(
|
||||
nodeTypeName: string,
|
||||
nodeType: INodeType | INodeVersionedType,
|
||||
sourcePath: string,
|
||||
): void {
|
||||
this.nodeTypes[nodeTypeName] = {
|
||||
type: nodeType,
|
||||
sourcePath,
|
||||
};
|
||||
}
|
||||
|
||||
removeNodeType(nodeType: string): void {
|
||||
delete this.nodeTypes[nodeType];
|
||||
}
|
||||
}
|
||||
|
||||
let nodeTypesInstance: NodeTypesClass | undefined;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ function createApiRouter(
|
|||
): Router {
|
||||
const n8nPath = config.getEnv('path');
|
||||
const swaggerDocument = YAML.load(openApiSpecPath) as swaggerUi.JsonObject;
|
||||
// add the server depeding on the config so the user can interact with the API
|
||||
// add the server depending on the config so the user can interact with the API
|
||||
// from the Swagger UI
|
||||
swaggerDocument.server = [
|
||||
{
|
||||
|
|
|
|||
2
packages/cli/src/PublicApi/types.d.ts
vendored
2
packages/cli/src/PublicApi/types.d.ts
vendored
|
|
@ -152,7 +152,7 @@ export interface IRequired {
|
|||
}
|
||||
export interface IDependency {
|
||||
if?: { properties: {} };
|
||||
then?: { oneOf: IRequired[] };
|
||||
then?: { allOf: IRequired[] };
|
||||
else?: { allOf: IRequired[] };
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
import express from 'express';
|
||||
|
||||
import { CredentialsHelper } from '../../../../CredentialsHelper';
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user