Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/n8n-io/n8n into node-2187-…
Browse files Browse the repository at this point in the history
…form-node-completion-redirect-page-returns-an-error
  • Loading branch information
michael-radency committed Jan 7, 2025
2 parents f3bb685 + 1d5c9bd commit 6a6b618
Show file tree
Hide file tree
Showing 477 changed files with 2,317 additions and 652 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci-master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ jobs:
nodeVersion: ${{ matrix.node-version }}
cacheKey: ${{ github.sha }}-base:build
collectCoverage: ${{ matrix.node-version == '20.x' }}
ignoreTurboCache: ${{ matrix.node-version == '20.x' }}
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/units-tests-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ on:
required: false
default: false
type: boolean
ignoreTurboCache:
required: false
default: false
type: boolean
secrets:
CODECOV_TOKEN:
description: 'Codecov upload token.'
Expand All @@ -32,6 +36,7 @@ jobs:
name: Unit tests
runs-on: ubuntu-latest
env:
TURBO_FORCE: ${{ inputs.ignoreTurboCache }}
COVERAGE_ENABLED: ${{ inputs.collectCoverage }}
steps:
- uses: actions/[email protected]
Expand Down Expand Up @@ -73,6 +78,6 @@ jobs:

- name: Upload coverage to Codecov
if: inputs.collectCoverage
uses: codecov/codecov-action@v4.5.0
uses: codecov/codecov-action@v5.1.2
with:
token: ${{ secrets.CODECOV_TOKEN }}
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,16 @@ n8n is a workflow automation platform that gives technical teams the flexibility

Try n8n instantly with [npx](https://docs.n8n.io/hosting/installation/npm/) (requires [Node.js](https://nodejs.org/en/)):

`npx n8n`
```
npx n8n
```

Or deploy with [Docker](https://docs.n8n.io/hosting/installation/docker/):

`docker run -it --rm --name n8n -p 5678:5678 docker.n8n.io/n8nio/n8n`
```
docker volume create n8n_data
docker run -it --rm --name n8n -p 5678:5678 -v n8n_data:/home/node/.n8n docker.n8n.io/n8nio/n8n
```

Access the editor at http://localhost:5678

Expand Down
60 changes: 60 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
codecov:
max_report_age: off
require_ci_to_pass: true

coverage:
status:
patch: false
project:
default:
threshold: 0.5%

github_checks:
annotations: false

flags:
tests:
paths:
- "**"
carryforward: true

component_management:
default_rules:
statuses:
- type: project
target: auto
branches:
- "!master"
individual_components:
- component_id: backend_packages
name: Backend
paths:
- packages/@n8n/api-types/**
- packages/@n8n/config/**
- packages/@n8n/client-oauth2/**
- packages/@n8n/di/**
- packages/@n8n/imap/**
- packages/@n8n/permissions/**
- packages/@n8n/task-runner/**
- packages/workflow/**
- packages/core/**
- packages/cli/**
- component_id: frontend_packages
name: Frontend
paths:
- packages/@n8n/chat/**
- packages/@n8n/codemirror-lang/**
- packages/design-system/**
- packages/editor-ui/**
- component_id: nodes_packages
name: Nodes
paths:
- packages/node-dev/**
- packages/nodes-base/**
- packages/@n8n/json-schema-to-zod/**
- packages/@n8n/nodes-langchain/**

ignore:
- (?s:.*/[^\/]*\.spec\.ts.*)\Z
- (?s:.*/[^\/]*\.test\.ts.*)\Z
- (?s:.*/[^\/]*e2e[^\/]*\.ts.*)\Z
2 changes: 1 addition & 1 deletion cypress/composables/ndv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Getters
*/

import { getVisibleSelect } from '../utils';
import { getVisibleSelect } from '../utils/popper';

export function getCredentialSelect(eq = 0) {
return cy.getByTestId('node-credentials-select').eq(eq);
Expand Down
21 changes: 20 additions & 1 deletion cypress/composables/workflow.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getManualChatModal } from './modals/chat-modal';
import { clickGetBackToCanvas, getParameterInputByName } from './ndv';
import { ROUTES } from '../constants';

/**
Expand Down Expand Up @@ -127,7 +128,7 @@ export function navigateToNewWorkflowPage(preventNodeViewUnload = true) {
});
}

export function addSupplementalNodeToParent(
function connectNodeToParent(
nodeName: string,
endpointType: EndpointType,
parentNodeName: string,
Expand All @@ -141,6 +142,15 @@ export function addSupplementalNodeToParent(
} else {
getNodeCreatorItems().contains(nodeName).click();
}
}

export function addSupplementalNodeToParent(
nodeName: string,
endpointType: EndpointType,
parentNodeName: string,
exactMatch = false,
) {
connectNodeToParent(nodeName, endpointType, parentNodeName, exactMatch);
getConnectionBySourceAndTarget(parentNodeName, nodeName).should('exist');
}

Expand All @@ -160,6 +170,15 @@ export function addToolNodeToParent(nodeName: string, parentNodeName: string) {
addSupplementalNodeToParent(nodeName, 'ai_tool', parentNodeName);
}

export function addVectorStoreToolToParent(nodeName: string, parentNodeName: string) {
connectNodeToParent(nodeName, 'ai_tool', parentNodeName, false);
getParameterInputByName('mode')
.find('input')
.should('have.value', 'Retrieve Documents (As Tool for AI Agent)');
clickGetBackToCanvas();
getConnectionBySourceAndTarget(nodeName, parentNodeName).should('exist');
}

export function addOutputParserNodeToParent(nodeName: string, parentNodeName: string) {
addSupplementalNodeToParent(nodeName, 'ai_outputParser', parentNodeName);
}
Expand Down
14 changes: 12 additions & 2 deletions cypress/e2e/4-node-creator.cy.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { clickGetBackToCanvas } from '../composables/ndv';
import {
addNodeToCanvas,
addRetrieverNodeToParent,
addVectorStoreNodeToParent,
addVectorStoreToolToParent,
getNodeCreatorItems,
} from '../composables/workflow';
import { IF_NODE_NAME } from '../constants';
import { AGENT_NODE_NAME, IF_NODE_NAME, MANUAL_CHAT_TRIGGER_NODE_NAME } from '../constants';
import { NodeCreator } from '../pages/features/node-creator';
import { NDV } from '../pages/ndv';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
Expand Down Expand Up @@ -536,12 +538,20 @@ describe('Node Creator', () => {
});
});

it('should add node directly for sub-connection', () => {
it('should add node directly for sub-connection as vector store', () => {
addNodeToCanvas('Question and Answer Chain', true);
addRetrieverNodeToParent('Vector Store Retriever', 'Question and Answer Chain');
cy.realPress('Escape');
addVectorStoreNodeToParent('In-Memory Vector Store', 'Vector Store Retriever');
cy.realPress('Escape');
WorkflowPage.getters.canvasNodes().should('have.length', 4);
});

it('should add node directly for sub-connection as tool', () => {
addNodeToCanvas(MANUAL_CHAT_TRIGGER_NODE_NAME, true);
addNodeToCanvas(AGENT_NODE_NAME, true, true);
clickGetBackToCanvas();

addVectorStoreToolToParent('In-Memory Vector Store', AGENT_NODE_NAME);
});
});
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@
"ws": ">=8.17.1"
},
"patchedDependencies": {
"[email protected]": "patches/[email protected]",
"[email protected]": "patches/[email protected]",
"[email protected]": "patches/[email protected]",
"@types/[email protected]": "patches/@[email protected]",
Expand Down
4 changes: 2 additions & 2 deletions packages/@n8n/config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"dist/**/*"
],
"dependencies": {
"reflect-metadata": "0.2.2",
"typedi": "catalog:"
"@n8n/di": "workspace:*",
"reflect-metadata": "catalog:"
}
}
4 changes: 2 additions & 2 deletions packages/@n8n/config/src/decorators.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'reflect-metadata';
import { Container, Service } from '@n8n/di';
import { readFileSync } from 'fs';
import { Container, Service } from 'typedi';

// eslint-disable-next-line @typescript-eslint/ban-types
type Class = Function;
Expand Down Expand Up @@ -35,7 +35,7 @@ export const Config: ClassDecorator = (ConfigClass: Class) => {

for (const [key, { type, envName }] of classMetadata) {
if (typeof type === 'function' && globalMetadata.has(type)) {
config[key] = Container.get(type);
config[key] = Container.get(type as Constructable);
} else if (envName) {
const value = readEnv(envName);
if (value === undefined) continue;
Expand Down
2 changes: 1 addition & 1 deletion packages/@n8n/config/test/config.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Container } from '@n8n/di';
import fs from 'fs';
import { mock } from 'jest-mock-extended';
import { Container } from 'typedi';

import { GlobalConfig } from '../src/index';

Expand Down
2 changes: 1 addition & 1 deletion packages/@n8n/config/test/decorators.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Container } from 'typedi';
import { Container } from '@n8n/di';

import { Config, Env } from '../src/decorators';

Expand Down
3 changes: 2 additions & 1 deletion packages/@n8n/config/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
"baseUrl": "src",
"tsBuildInfoFile": "dist/typecheck.tsbuildinfo"
},
"include": ["src/**/*.ts", "test/**/*.ts"]
"include": ["src/**/*.ts", "test/**/*.ts"],
"references": [{ "path": "../di/tsconfig.build.json" }]
}
7 changes: 7 additions & 0 deletions packages/@n8n/di/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const sharedOptions = require('@n8n_io/eslint-config/shared');

/** @type {import('@types/eslint').ESLint.ConfigData} */
module.exports = {
extends: ['@n8n_io/eslint-config/base'],
...sharedOptions(__dirname),
};
52 changes: 52 additions & 0 deletions packages/@n8n/di/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
## @n8n/di

`@n8n/di` is a dependency injection (DI) container library, based on [`typedi`](https://github.com/typestack/typedi).

n8n no longer uses `typedi` because:

- `typedi` is no longer officially maintained
- Need for future-proofing, e.g. stage-3 decorators
- Small enough that it is worth the maintenance burden
- Easier to customize, e.g. to simplify unit tests

### Usage

```typescript
// from https://github.com/typestack/typedi/blob/develop/README.md
import { Container, Service } from 'typedi';

@Service()
class ExampleInjectedService {
printMessage() {
console.log('I am alive!');
}
}

@Service()
class ExampleService {
constructor(
// because we annotated ExampleInjectedService with the @Service()
// decorator TypeDI will automatically inject an instance of
// ExampleInjectedService here when the ExampleService class is requested
// from TypeDI.
public injectedService: ExampleInjectedService
) {}
}

const serviceInstance = Container.get(ExampleService);
// we request an instance of ExampleService from TypeDI

serviceInstance.injectedService.printMessage();
// logs "I am alive!" to the console
```

Requires enabling these flags in `tsconfig.json`:

```json
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
```
2 changes: 2 additions & 0 deletions packages/@n8n/di/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/** @type {import('jest').Config} */
module.exports = require('../../../jest.config');
26 changes: 26 additions & 0 deletions packages/@n8n/di/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "@n8n/di",
"version": "0.1.0",
"scripts": {
"clean": "rimraf dist .turbo",
"dev": "pnpm watch",
"typecheck": "tsc --noEmit",
"build": "tsc -p tsconfig.build.json",
"format": "biome format --write .",
"format:check": "biome ci .",
"lint": "eslint .",
"lintfix": "eslint . --fix",
"watch": "tsc -p tsconfig.build.json --watch",
"test": "jest",
"test:dev": "jest --watch"
},
"main": "dist/di.js",
"module": "src/di.ts",
"types": "dist/di.d.ts",
"files": [
"dist/**/*"
],
"dependencies": {
"reflect-metadata": "catalog:"
}
}
Loading

0 comments on commit 6a6b618

Please sign in to comment.