Merge remote-tracking branch 'origin/master' into upgrade-frontend-dev-tooling

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™ 2024-09-18 10:14:04 +02:00
commit f5c541c172
No known key found for this signature in database
GPG key ID: 9300FF7CDEA1FBAA
382 changed files with 2169 additions and 1000 deletions

View file

@ -9,7 +9,7 @@
"type=bind,source=${localEnv:HOME}/.n8n,target=/home/node/.n8n,consistency=cached"
],
"forwardPorts": [8080, 5678],
"postCreateCommand": "corepack prepare --activate && pnpm install ",
"postCreateCommand": "corepack prepare --activate && pnpm install",
"postAttachCommand": "pnpm build",
"customizations": {
"codespaces": {

View file

@ -1,5 +1,5 @@
import { ROUTES } from '../constants';
import { getManualChatModal } from './modals/chat-modal';
import { ROUTES } from '../constants';
/**
* Types

View file

@ -1,5 +1,5 @@
import { WorkflowsPage as WorkflowsPageClass } from '../pages/workflows';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
import { WorkflowsPage as WorkflowsPageClass } from '../pages/workflows';
import { getUniqueWorkflowName } from '../utils/workflowUtils';
const WorkflowsPage = new WorkflowsPageClass();

View file

@ -1,6 +1,6 @@
import { SettingsLogStreamingPage } from '../pages';
import { getVisibleModalOverlay } from '../utils/modal';
import { getVisibleDropdown } from '../utils';
import { getVisibleModalOverlay } from '../utils/modal';
const settingsLogStreamingPage = new SettingsLogStreamingPage();

View file

@ -4,9 +4,9 @@ import {
SET_NODE_NAME,
EDIT_FIELDS_SET_NODE_NAME,
} from '../constants';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
import { MessageBox as MessageBoxClass } from '../pages/modals/message-box';
import { NDV } from '../pages/ndv';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
// Suite-specific constants
const CODE_NODE_NEW_NAME = 'Something else';

View file

@ -1,5 +1,3 @@
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
import { successToast } from '../pages/notifications';
import {
MANUAL_TRIGGER_NODE_NAME,
MANUAL_TRIGGER_NODE_DISPLAY_NAME,
@ -9,6 +7,8 @@ import {
IF_NODE_NAME,
HTTP_REQUEST_NODE_NAME,
} from './../constants';
import { successToast } from '../pages/notifications';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
const WorkflowPage = new WorkflowPageClass();
describe('Canvas Actions', () => {

View file

@ -1,5 +1,3 @@
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
import { NDV, WorkflowExecutionsTab } from '../pages';
import {
MANUAL_TRIGGER_NODE_NAME,
MANUAL_TRIGGER_NODE_DISPLAY_NAME,
@ -9,6 +7,8 @@ import {
SWITCH_NODE_NAME,
MERGE_NODE_NAME,
} from './../constants';
import { NDV, WorkflowExecutionsTab } from '../pages';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
const WorkflowPage = new WorkflowPageClass();
const ExecutionsTab = new WorkflowExecutionsTab();

View file

@ -1,10 +1,10 @@
import { WorkflowPage, NDV } from '../pages';
import { getVisibleSelect } from '../utils';
import {
MANUAL_TRIGGER_NODE_NAME,
MANUAL_TRIGGER_NODE_DISPLAY_NAME,
SCHEDULE_TRIGGER_NODE_NAME,
} from './../constants';
import { WorkflowPage, NDV } from '../pages';
import { getVisibleSelect } from '../utils';
const workflowPage = new WorkflowPage();
const ndv = new NDV();

View file

@ -1,7 +1,8 @@
import { nanoid } from 'nanoid';
import { BACKEND_BASE_URL, EDIT_FIELDS_SET_NODE_NAME } from '../constants';
import { WorkflowPage, NDV, CredentialsModal } from '../pages';
import { cowBase64 } from '../support/binaryTestFiles';
import { BACKEND_BASE_URL, EDIT_FIELDS_SET_NODE_NAME } from '../constants';
import { getVisibleSelect } from '../utils';
const workflowPage = new WorkflowPage();

View file

@ -1,3 +1,4 @@
import * as projects from '../composables/projects';
import { INSTANCE_MEMBERS, INSTANCE_OWNER, INSTANCE_ADMIN, NOTION_NODE_NAME } from '../constants';
import {
CredentialsModal,
@ -8,7 +9,6 @@ import {
WorkflowsPage,
} from '../pages';
import { getVisibleDropdown, getVisiblePopper, getVisibleSelect } from '../utils';
import * as projects from '../composables/projects';
/**
* User U1 - Instance owner

View file

@ -1,8 +1,8 @@
import { INSTANCE_MEMBERS, INSTANCE_OWNER, INSTANCE_ADMIN } from '../constants';
import { MainSidebar, SettingsSidebar, SettingsUsersPage } from '../pages';
import { errorToast, successToast } from '../pages/notifications';
import { PersonalSettingsPage } from '../pages/settings-personal';
import { getVisibleSelect } from '../utils';
import { errorToast, successToast } from '../pages/notifications';
/**
* User A - Instance owner

View file

@ -1,5 +1,5 @@
import { NDV, WorkflowExecutionsTab, WorkflowPage as WorkflowPageClass } from '../pages';
import { SCHEDULE_TRIGGER_NODE_NAME, EDIT_FIELDS_SET_NODE_NAME } from '../constants';
import { NDV, WorkflowExecutionsTab, WorkflowPage as WorkflowPageClass } from '../pages';
import { clearNotifications, errorToast, successToast } from '../pages/notifications';
const workflowPage = new WorkflowPageClass();

View file

@ -1,4 +1,5 @@
import { type ICredentialType } from 'n8n-workflow';
import {
AGENT_NODE_NAME,
AI_TOOL_HTTP_NODE_NAME,

View file

@ -1,7 +1,8 @@
import type { RouteHandler } from 'cypress/types/net-stubbing';
import executionOutOfMemoryServerResponse from '../fixtures/responses/execution-out-of-memory-server-response.json';
import { WorkflowPage } from '../pages';
import { WorkflowExecutionsTab } from '../pages/workflow-executions-tab';
import executionOutOfMemoryServerResponse from '../fixtures/responses/execution-out-of-memory-server-response.json';
import { getVisibleSelect } from '../utils';
const workflowPage = new WorkflowPage();

View file

@ -1,11 +1,11 @@
import type { ICredentialType } from 'n8n-workflow';
import { NodeCreator } from '../pages/features/node-creator';
import CustomNodeFixture from '../fixtures/Custom_node.json';
import { CredentialsModal, WorkflowPage } from '../pages';
import CustomNodeWithN8nCredentialFixture from '../fixtures/Custom_node_n8n_credential.json';
import CustomNodeWithCustomCredentialFixture from '../fixtures/Custom_node_custom_credential.json';
import CustomCredential from '../fixtures/Custom_credential.json';
import { getVisibleSelect } from '../utils';
import CustomNodeFixture from '../fixtures/Custom_node.json';
import CustomNodeWithCustomCredentialFixture from '../fixtures/Custom_node_custom_credential.json';
import CustomNodeWithN8nCredentialFixture from '../fixtures/Custom_node_n8n_credential.json';
import { CredentialsModal, WorkflowPage } from '../pages';
import { NodeCreator } from '../pages/features/node-creator';
import {
confirmCommunityNodeUninstall,
confirmCommunityNodeUpdate,
@ -13,6 +13,7 @@ import {
installFirstCommunityNode,
visitCommunityNodesSettings,
} from '../pages/settings-community-nodes';
import { getVisibleSelect } from '../utils';
const credentialsModal = new CredentialsModal();
const nodeCreatorFeature = new NodeCreator();

View file

@ -1,5 +1,18 @@
import type { ExecutionError } from 'n8n-workflow/src';
import { NDV, WorkflowPage as WorkflowPageClass } from '../pages';
import {
closeManualChatModal,
getManualChatMessages,
getManualChatModalLogs,
getManualChatModalLogsEntries,
sendManualChatMessage,
} from '../composables/modals/chat-modal';
import { setCredentialValues } from '../composables/modals/credential-modal';
import {
clickCreateNewCredential,
clickExecuteNode,
clickGetBackToCanvas,
} from '../composables/ndv';
import {
addLanguageModelNodeToParent,
addMemoryNodeToParent,
@ -18,19 +31,7 @@ import {
MANUAL_TRIGGER_NODE_DISPLAY_NAME,
MANUAL_TRIGGER_NODE_NAME,
} from '../constants';
import {
clickCreateNewCredential,
clickExecuteNode,
clickGetBackToCanvas,
} from '../composables/ndv';
import { setCredentialValues } from '../composables/modals/credential-modal';
import {
closeManualChatModal,
getManualChatMessages,
getManualChatModalLogs,
getManualChatModalLogsEntries,
sendManualChatMessage,
} from '../composables/modals/chat-modal';
import { NDV, WorkflowPage as WorkflowPageClass } from '../pages';
import { createMockNodeExecutionData, getVisibleSelect, runMockWorkflowExecution } from '../utils';
const ndv = new NDV();

View file

@ -1,3 +1,4 @@
import planData from '../fixtures/Plan_data_opt_in_trial.json';
import {
BannerStack,
MainSidebar,
@ -5,7 +6,6 @@ import {
visitPublicApiPage,
getPublicApiUpgradeCTA,
} from '../pages';
import planData from '../fixtures/Plan_data_opt_in_trial.json';
const mainSidebar = new MainSidebar();
const bannerStack = new BannerStack();

View file

@ -1,9 +1,10 @@
import generateOTPToken from 'cypress-otp';
import { MainSidebar } from './../pages/sidebar/main-sidebar';
import { INSTANCE_OWNER, INSTANCE_ADMIN, BACKEND_BASE_URL } from '../constants';
import { SigninPage } from '../pages';
import { PersonalSettingsPage } from '../pages/settings-personal';
import { MfaLoginPage } from '../pages/mfa-login';
import { MainSidebar } from './../pages/sidebar/main-sidebar';
import { PersonalSettingsPage } from '../pages/settings-personal';
const MFA_SECRET = 'KVKFKRCPNZQUYMLXOVYDSQKJKZDTSRLD';

View file

@ -1,9 +1,9 @@
import OnboardingWorkflow from '../fixtures/Onboarding_workflow.json';
import WorkflowTemplate from '../fixtures/Workflow_template_write_http_query.json';
import { MainSidebar } from '../pages/sidebar/main-sidebar';
import { TemplatesPage } from '../pages/templates';
import { WorkflowPage } from '../pages/workflow';
import { WorkflowsPage } from '../pages/workflows';
import { MainSidebar } from '../pages/sidebar/main-sidebar';
import OnboardingWorkflow from '../fixtures/Onboarding_workflow.json';
import WorkflowTemplate from '../fixtures/Workflow_template_write_http_query.json';
const templatesPage = new TemplatesPage();
const workflowPage = new WorkflowPage();

View file

@ -1,4 +1,34 @@
import { createMockNodeExecutionData, runMockWorkflowExecution } from '../utils';
import {
AGENT_NODE_NAME,
MANUAL_CHAT_TRIGGER_NODE_NAME,
AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME,
MANUAL_TRIGGER_NODE_NAME,
AI_MEMORY_WINDOW_BUFFER_MEMORY_NODE_NAME,
AI_TOOL_CALCULATOR_NODE_NAME,
AI_OUTPUT_PARSER_AUTO_FIXING_NODE_NAME,
AI_TOOL_CODE_NODE_NAME,
AI_TOOL_WIKIPEDIA_NODE_NAME,
BASIC_LLM_CHAIN_NODE_NAME,
EDIT_FIELDS_SET_NODE_NAME,
CHAT_TRIGGER_NODE_DISPLAY_NAME,
} from './../constants';
import {
closeManualChatModal,
getManualChatDialog,
getManualChatMessages,
getManualChatModal,
getManualChatModalLogs,
getManualChatModalLogsEntries,
getManualChatModalLogsTree,
sendManualChatMessage,
} from '../composables/modals/chat-modal';
import { setCredentialValues } from '../composables/modals/credential-modal';
import {
clickCreateNewCredential,
clickExecuteNode,
clickGetBackToCanvas,
toggleParameterCheckboxInputByName,
} from '../composables/ndv';
import {
addLanguageModelNodeToParent,
addMemoryNodeToParent,
@ -14,37 +44,7 @@ import {
openNode,
getConnectionBySourceAndTarget,
} from '../composables/workflow';
import {
clickCreateNewCredential,
clickExecuteNode,
clickGetBackToCanvas,
toggleParameterCheckboxInputByName,
} from '../composables/ndv';
import { setCredentialValues } from '../composables/modals/credential-modal';
import {
closeManualChatModal,
getManualChatDialog,
getManualChatMessages,
getManualChatModal,
getManualChatModalLogs,
getManualChatModalLogsEntries,
getManualChatModalLogsTree,
sendManualChatMessage,
} from '../composables/modals/chat-modal';
import {
AGENT_NODE_NAME,
MANUAL_CHAT_TRIGGER_NODE_NAME,
AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME,
MANUAL_TRIGGER_NODE_NAME,
AI_MEMORY_WINDOW_BUFFER_MEMORY_NODE_NAME,
AI_TOOL_CALCULATOR_NODE_NAME,
AI_OUTPUT_PARSER_AUTO_FIXING_NODE_NAME,
AI_TOOL_CODE_NODE_NAME,
AI_TOOL_WIKIPEDIA_NODE_NAME,
BASIC_LLM_CHAIN_NODE_NAME,
EDIT_FIELDS_SET_NODE_NAME,
CHAT_TRIGGER_NODE_DISPLAY_NAME,
} from './../constants';
import { createMockNodeExecutionData, runMockWorkflowExecution } from '../utils';
describe('Langchain Integration', () => {
beforeEach(() => {

View file

@ -1,7 +1,7 @@
import workflow from '../fixtures/Manual_wait_set.json';
import { importWorkflow, visitDemoPage } from '../pages/demo';
import { WorkflowPage } from '../pages/workflow';
import { errorToast } from '../pages/notifications';
import { WorkflowPage } from '../pages/workflow';
const workflowPage = new WorkflowPage();

View file

@ -1,3 +1,8 @@
import * as setupCredsModal from '../composables/modals/workflow-credential-setup-modal';
import * as formStep from '../composables/setup-template-form-step';
import { getSetupWorkflowCredentialsButton } from '../composables/setup-workflow-credentials-button';
import TestTemplate1 from '../fixtures/Test_Template_1.json';
import TestTemplate2 from '../fixtures/Test_Template_2.json';
import {
clickUseWorkflowButtonByTitle,
visitTemplateCollectionPage,
@ -5,11 +10,6 @@ import {
} from '../pages/template-collection';
import * as templateCredentialsSetupPage from '../pages/template-credential-setup';
import { WorkflowPage } from '../pages/workflow';
import * as formStep from '../composables/setup-template-form-step';
import { getSetupWorkflowCredentialsButton } from '../composables/setup-workflow-credentials-button';
import * as setupCredsModal from '../composables/modals/workflow-credential-setup-modal';
import TestTemplate1 from '../fixtures/Test_Template_1.json';
import TestTemplate2 from '../fixtures/Test_Template_2.json';
const workflowPage = new WorkflowPage();

View file

@ -1,10 +1,10 @@
import { WorkflowsPage } from '../pages/workflows';
import {
closeVersionUpdatesPanel,
getVersionCard,
getVersionUpdatesPanelOpenButton,
openVersionUpdatesPanel,
} from '../composables/versions';
import { WorkflowsPage } from '../pages/workflows';
const workflowsPage = new WorkflowsPage();

View file

@ -1,3 +1,4 @@
import * as projects from '../composables/projects';
import { INSTANCE_MEMBERS, MANUAL_TRIGGER_NODE_NAME, NOTION_NODE_NAME } from '../constants';
import {
WorkflowsPage,
@ -8,7 +9,6 @@ import {
NDV,
MainSidebar,
} from '../pages';
import * as projects from '../composables/projects';
import { getVisibleDropdown, getVisibleModalOverlay, getVisibleSelect } from '../utils';
const workflowsPage = new WorkflowsPage();

View file

@ -1,8 +1,8 @@
import { NodeCreator } from '../pages/features/node-creator';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
import { NDV } from '../pages/ndv';
import { getVisibleSelect } from '../utils';
import { IF_NODE_NAME } from '../constants';
import { NodeCreator } from '../pages/features/node-creator';
import { NDV } from '../pages/ndv';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
import { getVisibleSelect } from '../utils';
const nodeCreatorFeature = new NodeCreator();
const WorkflowPage = new WorkflowPageClass();

View file

@ -1,7 +1,7 @@
import { WorkflowsPage as WorkflowsPageClass } from '../pages/workflows';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
import { EDIT_FIELDS_SET_NODE_NAME } from '../constants';
import { getSaveChangesModal } from '../composables/modals/save-changes-modal';
import { EDIT_FIELDS_SET_NODE_NAME } from '../constants';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
import { WorkflowsPage as WorkflowsPageClass } from '../pages/workflows';
const WorkflowsPage = new WorkflowsPageClass();
const WorkflowPage = new WorkflowPageClass();

View file

@ -1,8 +1,8 @@
import { setCredentialValues } from '../composables/modals/credential-modal';
import { clickCreateNewCredential } from '../composables/ndv';
import { MANUAL_TRIGGER_NODE_DISPLAY_NAME, NOTION_NODE_NAME } from '../constants';
import { NDV, WorkflowPage } from '../pages';
import { NodeCreator } from '../pages/features/node-creator';
import { clickCreateNewCredential } from '../composables/ndv';
import { setCredentialValues } from '../composables/modals/credential-modal';
const workflowPage = new WorkflowPage();
const ndv = new NDV();

View file

@ -1,7 +1,8 @@
import { nanoid } from 'nanoid';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
import { NDV } from '../pages/ndv';
import { successToast } from '../pages/notifications';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
const WorkflowPage = new WorkflowPageClass();
const ndv = new NDV();

View file

@ -5,11 +5,11 @@ import {
EDIT_FIELDS_SET_NODE_NAME,
NOTION_NODE_NAME,
} from '../constants';
import { WorkflowExecutionsTab } from '../pages';
import { errorToast, successToast } from '../pages/notifications';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
import { WorkflowsPage as WorkflowsPageClass } from '../pages/workflows';
import { getVisibleSelect } from '../utils';
import { WorkflowExecutionsTab } from '../pages';
import { errorToast, successToast } from '../pages/notifications';
const NEW_WORKFLOW_NAME = 'Something else';
const DUPLICATE_WORKFLOW_NAME = 'Duplicated workflow';

View file

@ -15,6 +15,7 @@
"start": "cd ..; pnpm start"
},
"devDependencies": {
"@n8n/api-types": "workspace:*",
"@types/lodash": "catalog:",
"eslint-plugin-cypress": "^3.5.0",
"n8n-workflow": "workspace:*"

View file

@ -1,7 +1,7 @@
import { N8N_AUTH_COOKIE } from '../constants';
import { BasePage } from './base';
import { SigninPage } from './signin';
import { WorkflowsPage } from './workflows';
import { N8N_AUTH_COOKIE } from '../constants';
export class MfaLoginPage extends BasePage {
url = '/mfa';

View file

@ -1,5 +1,5 @@
import { BasePage } from '../base';
import { getVisibleSelect } from '../../utils';
import { BasePage } from '../base';
export class CredentialsModal extends BasePage {
getters = {

View file

@ -1,5 +1,5 @@
import { getVisiblePopper, getVisibleSelect } from '../utils';
import { BasePage } from './base';
import { getVisiblePopper, getVisibleSelect } from '../utils';
export class NDV extends BasePage {
getters = {

View file

@ -1,5 +1,5 @@
import { getVisibleSelect } from '../utils';
import { BasePage } from './base';
import { getVisibleSelect } from '../utils';
export class SettingsLogStreamingPage extends BasePage {
url = '/settings/log-streaming';

View file

@ -1,7 +1,8 @@
import generateOTPToken from 'cypress-otp';
import { BasePage } from './base';
import { ChangePasswordModal } from './modals/change-password-modal';
import { MfaSetupModal } from './modals/mfa-setup-modal';
import { BasePage } from './base';
const changePasswordModal = new ChangePasswordModal();
const mfaSetupModal = new MfaSetupModal();

View file

@ -1,8 +1,8 @@
import { SettingsSidebar } from './sidebar/settings-sidebar';
import { BasePage } from './base';
import { MainSidebar } from './sidebar/main-sidebar';
import { SettingsSidebar } from './sidebar/settings-sidebar';
import { WorkflowPage } from './workflow';
import { WorkflowsPage } from './workflows';
import { BasePage } from './base';
const workflowPage = new WorkflowPage();
const workflowsPage = new WorkflowsPage();

View file

@ -1,6 +1,6 @@
import { N8N_AUTH_COOKIE } from '../constants';
import { BasePage } from './base';
import { WorkflowsPage } from './workflows';
import { N8N_AUTH_COOKIE } from '../constants';
export class SigninPage extends BasePage {
url = '/signin';

View file

@ -1,6 +1,6 @@
import * as formStep from '../composables/setup-template-form-step';
import { overrideFeatureFlag } from '../composables/featureFlags';
import { CredentialsModal, MessageBox } from './modals';
import { overrideFeatureFlag } from '../composables/featureFlags';
import * as formStep from '../composables/setup-template-form-step';
const credentialsModal = new CredentialsModal();
const messageBox = new MessageBox();

View file

@ -1,4 +1,5 @@
import { BasePage } from './base';
import Chainable = Cypress.Chainable;
export class VariablesPage extends BasePage {

View file

@ -1,8 +1,8 @@
import { BasePage } from './base';
import { NodeCreator } from './features/node-creator';
import { META_KEY } from '../constants';
import { getVisibleSelect } from '../utils';
import { getUniqueWorkflowName } from '../utils/workflowUtils';
import { BasePage } from './base';
import { NodeCreator } from './features/node-creator';
const nodeCreator = new NodeCreator();
export class WorkflowPage extends BasePage {

View file

@ -1,7 +1,7 @@
import 'cypress-real-events';
import type { FrontendSettings } from '@n8n/api-types';
import FakeTimers from '@sinonjs/fake-timers';
import type { IN8nUISettings } from 'n8n-workflow';
import { WorkflowPage } from '../pages';
import {
BACKEND_BASE_URL,
INSTANCE_ADMIN,
@ -9,6 +9,7 @@ import {
INSTANCE_OWNER,
N8N_AUTH_COOKIE,
} from '../constants';
import { WorkflowPage } from '../pages';
import { getUniqueWorkflowName } from '../utils/workflowUtils';
Cypress.Commands.add('setAppDate', (targetDate: number | Date) => {
@ -86,8 +87,8 @@ Cypress.Commands.add('signout', () => {
cy.getCookie(N8N_AUTH_COOKIE).should('not.exist');
});
export let settings: Partial<IN8nUISettings>;
Cypress.Commands.add('overrideSettings', (value: Partial<IN8nUISettings>) => {
export let settings: Partial<FrontendSettings>;
Cypress.Commands.add('overrideSettings', (value: Partial<FrontendSettings>) => {
settings = value;
});

View file

@ -1,5 +1,6 @@
import cloneDeep from 'lodash/cloneDeep';
import merge from 'lodash/merge';
import { settings } from './commands';
before(() => {

View file

@ -1,7 +1,7 @@
// Load type definitions that come with Cypress module
/// <reference types="cypress" />
import type { IN8nUISettings } from 'n8n-workflow';
import type { FrontendSettings } from '@n8n/api-types';
Cypress.Keyboard.defaults({
keystrokeDelay: 0,
@ -45,7 +45,7 @@ declare global {
*/
signinAsMember(index?: number): void;
signout(): void;
overrideSettings(value: Partial<IN8nUISettings>): void;
overrideSettings(value: Partial<FrontendSettings>): void;
enableFeature(feature: string): void;
disableFeature(feature: string): void;
enableQueueMode(): void;

View file

@ -1,5 +1,6 @@
import { nanoid } from 'nanoid';
import type { IDataObject, IPinData, ITaskData, ITaskDataConnections } from 'n8n-workflow';
import { nanoid } from 'nanoid';
import { clickExecuteWorkflowButton } from '../composables/workflow';
export function createMockNodeExecutionData(

View file

@ -6,7 +6,7 @@ FROM --platform=linux/amd64 n8nio/base:${NODE_VERSION} AS builder
# Build the application from source
WORKDIR /src
COPY . /src
RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store --mount=type=cache,id=pnpm-metadata,target=/root/.cache/pnpm/metadata pnpm install --frozen-lockfile
RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store --mount=type=cache,id=pnpm-metadata,target=/root/.cache/pnpm/metadata DOCKER_BUILD=true pnpm install --frozen-lockfile
RUN pnpm build
# Delete all dev dependencies

View file

@ -8,7 +8,7 @@
},
"packageManager": "pnpm@9.6.0",
"scripts": {
"prepare": "lefthook install",
"prepare": "node scripts/prepare.mjs",
"preinstall": "node scripts/block-npm-install.js",
"build": "turbo run build",
"build:backend": "turbo run build:backend",

View file

@ -0,0 +1,172 @@
import type { ExpressionEvaluatorType, LogLevel, WorkflowSettings } from 'n8n-workflow';
export interface IVersionNotificationSettings {
enabled: boolean;
endpoint: string;
infoUrl: string;
}
export interface ITelemetryClientConfig {
url: string;
key: string;
}
export interface ITelemetrySettings {
enabled: boolean;
config?: ITelemetryClientConfig;
}
export type AuthenticationMethod = 'email' | 'ldap' | 'saml';
export interface IUserManagementSettings {
quota: number;
showSetupOnFirstLoad?: boolean;
smtpSetup: boolean;
authenticationMethod: AuthenticationMethod;
}
export interface FrontendSettings {
isDocker?: boolean;
databaseType: 'sqlite' | 'mariadb' | 'mysqldb' | 'postgresdb';
endpointForm: string;
endpointFormTest: string;
endpointFormWaiting: string;
endpointWebhook: string;
endpointWebhookTest: string;
saveDataErrorExecution: WorkflowSettings.SaveDataExecution;
saveDataSuccessExecution: WorkflowSettings.SaveDataExecution;
saveManualExecutions: boolean;
saveExecutionProgress: boolean;
executionTimeout: number;
maxExecutionTimeout: number;
workflowCallerPolicyDefaultOption: WorkflowSettings.CallerPolicy;
oauthCallbackUrls: {
oauth1: string;
oauth2: string;
};
timezone: string;
urlBaseWebhook: string;
urlBaseEditor: string;
versionCli: string;
nodeJsVersion: string;
concurrency: number;
authCookie: {
secure: boolean;
};
binaryDataMode: 'default' | 'filesystem' | 's3';
releaseChannel: 'stable' | 'beta' | 'nightly' | 'dev';
n8nMetadata?: {
userId?: string;
[key: string]: string | number | undefined;
};
versionNotifications: IVersionNotificationSettings;
instanceId: string;
telemetry: ITelemetrySettings;
posthog: {
enabled: boolean;
apiHost: string;
apiKey: string;
autocapture: boolean;
disableSessionRecording: boolean;
debug: boolean;
};
personalizationSurveyEnabled: boolean;
defaultLocale: string;
userManagement: IUserManagementSettings;
sso: {
saml: {
loginLabel: string;
loginEnabled: boolean;
};
ldap: {
loginLabel: string;
loginEnabled: boolean;
};
};
publicApi: {
enabled: boolean;
latestVersion: number;
path: string;
swaggerUi: {
enabled: boolean;
};
};
workflowTagsDisabled: boolean;
logLevel: LogLevel;
hiringBannerEnabled: boolean;
previewMode: boolean;
templates: {
enabled: boolean;
host: string;
};
missingPackages?: boolean;
executionMode: 'regular' | 'queue';
pushBackend: 'sse' | 'websocket';
communityNodesEnabled: boolean;
aiAssistant: {
enabled: boolean;
};
deployment: {
type: string;
};
isNpmAvailable: boolean;
allowedModules: {
builtIn?: string[];
external?: string[];
};
enterprise: {
sharing: boolean;
ldap: boolean;
saml: boolean;
logStreaming: boolean;
advancedExecutionFilters: boolean;
variables: boolean;
sourceControl: boolean;
auditLogs: boolean;
externalSecrets: boolean;
showNonProdBanner: boolean;
debugInEditor: boolean;
binaryDataS3: boolean;
workflowHistory: boolean;
workerView: boolean;
advancedPermissions: boolean;
projects: {
team: {
limit: number;
};
};
};
hideUsagePage: boolean;
license: {
planName?: string;
consumerId: string;
environment: 'development' | 'production' | 'staging';
};
variables: {
limit: number;
};
expressions: {
evaluator: ExpressionEvaluatorType;
};
mfa: {
enabled: boolean;
};
banners: {
dismissed: string[];
};
ai: {
enabled: boolean;
};
workflowHistory: {
pruneTime: number;
licensePruneTime: number;
};
pruning: {
isEnabled: boolean;
maxAge: number;
maxCount: number;
};
security: {
blockFileAccessToN8nFiles: boolean;
};
}

View file

@ -1,6 +1,7 @@
export type * from './datetime';
export type * from './push';
export type * from './scaling';
export type * from './datetime';
export type * from './frontend-settings';
export type * from './user';
export type { Collaborator } from './push/collaboration';

View file

@ -1,10 +1,10 @@
import type { ExecutionPushMessage } from './execution';
import type { WorkflowPushMessage } from './workflow';
import type { HotReloadPushMessage } from './hot-reload';
import type { WorkerPushMessage } from './worker';
import type { WebhookPushMessage } from './webhook';
import type { CollaborationPushMessage } from './collaboration';
import type { DebugPushMessage } from './debug';
import type { ExecutionPushMessage } from './execution';
import type { HotReloadPushMessage } from './hot-reload';
import type { WebhookPushMessage } from './webhook';
import type { WorkerPushMessage } from './worker';
import type { WorkflowPushMessage } from './workflow';
export type PushMessage =
| ExecutionPushMessage

View file

@ -33,6 +33,7 @@ COPY --chown=node:node ./packages/@n8n/benchmark/package.json /app/packages/@n8n
COPY --chown=node:node ./patches /app/patches
COPY --chown=node:node ./scripts /app/scripts
ENV DOCKER_BUILD=true
RUN pnpm install --frozen-lockfile
# TS config files

View file

@ -37,6 +37,17 @@ else
sudo chown -R "$CURRENT_USER":"$CURRENT_USER" /n8n
fi
### Remove unneeded dependencies
# TTY
sudo systemctl disable getty@tty1.service
sudo systemctl disable serial-getty@ttyS0.service
# Snap
sudo systemctl disable snapd.service
# Unattended upgrades
sudo systemctl disable unattended-upgrades.service
# Cron
sudo systemctl disable cron.service
# Include nodejs v20 repository
curl -fsSL https://deb.nodesource.com/setup_20.x -o nodesource_setup.sh
sudo -E bash nodesource_setup.sh

View file

@ -78,6 +78,12 @@ async function runBenchmarksOnVm(config, benchmarkEnv) {
const bootstrapScriptPath = path.join(scriptsDir, 'bootstrap.sh');
await sshClient.ssh(`chmod a+x ${bootstrapScriptPath} && ${bootstrapScriptPath}`);
// Benchmarking the VM
const vmBenchmarkScriptPath = path.join(scriptsDir, 'vm-benchmark.sh');
await sshClient.ssh(`chmod a+x ${vmBenchmarkScriptPath} && ${vmBenchmarkScriptPath}`, {
verbose: true,
});
// Give some time for the VM to be ready
await sleep(1000);

View file

@ -0,0 +1,13 @@
#!/bin/bash
# Install fio
DEBIAN_FRONTEND=noninteractive sudo apt-get -y install fio > /dev/null
# Run the disk benchmark
fio --name=rand_rw --ioengine=libaio --rw=randrw --rwmixread=70 --bs=4k --numjobs=4 --size=1G --runtime=30 --directory=/n8n --group_reporting
# Remove files
sudo rm /n8n/rand_rw.*
# Uninstall fio
DEBIAN_FRONTEND=noninteractive sudo apt-get -y remove fio > /dev/null

View file

@ -1,6 +1,7 @@
import { Command } from '@oclif/core';
import { ScenarioLoader } from '@/scenario/scenario-loader';
import { testScenariosPath } from '@/config/common-flags';
import { ScenarioLoader } from '@/scenario/scenario-loader';
export default class ListCommand extends Command {
static description = 'List all available scenarios';

View file

@ -1,11 +1,12 @@
import { Command, Flags } from '@oclif/core';
import { ScenarioLoader } from '@/scenario/scenario-loader';
import { ScenarioRunner } from '@/test-execution/scenario-runner';
import { testScenariosPath } from '@/config/common-flags';
import { N8nApiClient } from '@/n8n-api-client/n8n-api-client';
import { ScenarioDataFileLoader } from '@/scenario/scenario-data-loader';
import { ScenarioLoader } from '@/scenario/scenario-loader';
import type { K6Tag } from '@/test-execution/k6-executor';
import { K6Executor } from '@/test-execution/k6-executor';
import { testScenariosPath } from '@/config/common-flags';
import { ScenarioRunner } from '@/test-execution/scenario-runner';
export default class RunCommand extends Command {
static description = 'Run all (default) or specified test scenarios';

View file

@ -1,4 +1,5 @@
import type { AxiosRequestConfig } from 'axios';
import { N8nApiClient } from './n8n-api-client';
export class AuthenticatedN8nApiClient extends N8nApiClient {

View file

@ -1,6 +1,7 @@
import type { AuthenticatedN8nApiClient } from './authenticated-n8n-api-client';
import type { Workflow } from '@/n8n-api-client/n8n-api-client.types';
import type { AuthenticatedN8nApiClient } from './authenticated-n8n-api-client';
export class WorkflowApiClient {
constructor(private readonly apiClient: AuthenticatedN8nApiClient) {}

View file

@ -1,7 +1,8 @@
import * as fs from 'node:fs';
import * as path from 'node:path';
import type { Scenario } from '@/types/scenario';
import type { Workflow } from '@/n8n-api-client/n8n-api-client.types';
import type { Scenario } from '@/types/scenario';
/**
* Loads scenario data files from FS

View file

@ -1,6 +1,7 @@
import { createHash } from 'node:crypto';
import * as fs from 'node:fs';
import * as path from 'path';
import { createHash } from 'node:crypto';
import type { Scenario, ScenarioManifest } from '@/types/scenario';
export class ScenarioLoader {

View file

@ -1,9 +1,10 @@
import fs from 'fs';
import path from 'path';
import assert from 'node:assert/strict';
import path from 'path';
import { $, which, tmpfile } from 'zx';
import type { Scenario } from '@/types/scenario';
import { buildTestReport, type K6Tag } from '@/test-execution/test-report';
import type { Scenario } from '@/types/scenario';
export type { K6Tag };
export type K6ExecutorOpts = {

View file

@ -1,9 +1,10 @@
import type { K6Executor } from './k6-executor';
import type { Scenario } from '@/types/scenario';
import { AuthenticatedN8nApiClient } from '@/n8n-api-client/authenticated-n8n-api-client';
import type { N8nApiClient } from '@/n8n-api-client/n8n-api-client';
import type { ScenarioDataFileLoader } from '@/scenario/scenario-data-loader';
import { ScenarioDataImporter } from '@/test-execution/scenario-data-importer';
import { AuthenticatedN8nApiClient } from '@/n8n-api-client/authenticated-n8n-api-client';
import type { Scenario } from '@/types/scenario';
import type { K6Executor } from './k6-executor';
/**
* Runs scenarios

View file

@ -1,4 +1,5 @@
import { nanoid } from 'nanoid';
import type { Scenario } from '@/types/scenario';
export type K6Tag = {

View file

@ -1,8 +1,9 @@
<script lang="ts" setup>
import { computed, onMounted } from 'vue';
import hljs from 'highlight.js/lib/core';
import hljsXML from 'highlight.js/lib/languages/xml';
import hljsJavascript from 'highlight.js/lib/languages/javascript';
import hljsXML from 'highlight.js/lib/languages/xml';
import { computed, onMounted } from 'vue';
import { Chat, ChatWindow } from '@n8n/chat/components';
import { useOptions } from '@n8n/chat/composables';

View file

@ -1,8 +1,9 @@
/* eslint-disable @typescript-eslint/naming-convention */
import type { StoryObj } from '@storybook/vue3';
import { onMounted } from 'vue';
import type { ChatOptions } from '@n8n/chat/types';
import { createChat } from '@n8n/chat/index';
import type { ChatOptions } from '@n8n/chat/types';
const webhookUrl = 'http://localhost:5678/webhook/f406671e-c954-4691-b39a-66c90aa2f103/chat';

View file

@ -1,4 +1,5 @@
import { fireEvent, waitFor } from '@testing-library/vue';
import {
createFetchResponse,
createGetLatestMessagesResponse,

View file

@ -1,4 +1,5 @@
import { screen } from '@testing-library/vue';
import { defaultMountingTarget } from '@n8n/chat/constants';
export function getMountingTarget(target = defaultMountingTarget) {

View file

@ -1,11 +1,12 @@
<script setup lang="ts">
import Close from 'virtual:icons/mdi/close';
import { computed, nextTick, onMounted } from 'vue';
import Layout from '@n8n/chat/components/Layout.vue';
import GetStarted from '@n8n/chat/components/GetStarted.vue';
import GetStartedFooter from '@n8n/chat/components/GetStartedFooter.vue';
import MessagesList from '@n8n/chat/components/MessagesList.vue';
import Input from '@n8n/chat/components/Input.vue';
import Layout from '@n8n/chat/components/Layout.vue';
import MessagesList from '@n8n/chat/components/MessagesList.vue';
import { useI18n, useChat, useOptions } from '@n8n/chat/composables';
import { chatEventBus } from '@n8n/chat/event-buses';

View file

@ -1,11 +1,10 @@
<script setup lang="ts">
import IconFileText from 'virtual:icons/mdi/fileText';
import IconFileMusic from 'virtual:icons/mdi/fileMusic';
import IconFileImage from 'virtual:icons/mdi/fileImage';
import IconFileVideo from 'virtual:icons/mdi/fileVideo';
import IconDelete from 'virtual:icons/mdi/closeThick';
import IconFileImage from 'virtual:icons/mdi/fileImage';
import IconFileMusic from 'virtual:icons/mdi/fileMusic';
import IconFileText from 'virtual:icons/mdi/fileText';
import IconFileVideo from 'virtual:icons/mdi/fileVideo';
import IconPreview from 'virtual:icons/mdi/openInNew';
import { computed, type FunctionalComponent } from 'vue';
const props = defineProps<{

View file

@ -2,6 +2,7 @@
import IconChat from 'virtual:icons/mdi/chat';
import IconChevronDown from 'virtual:icons/mdi/chevron-down';
import { nextTick, ref } from 'vue';
import Chat from '@n8n/chat/components/Chat.vue';
import { chatEventBus } from '@n8n/chat/event-buses';

View file

@ -1,6 +1,6 @@
<script setup lang="ts">
import { useI18n } from '@n8n/chat/composables';
import PoweredBy from '@n8n/chat/components/PoweredBy.vue';
import { useI18n } from '@n8n/chat/composables';
const { t, te } = useI18n();
</script>

View file

@ -1,12 +1,14 @@
<script setup lang="ts">
import IconSend from 'virtual:icons/mdi/send';
import IconFilePlus from 'virtual:icons/mdi/filePlus';
import { computed, onMounted, onUnmounted, ref, unref } from 'vue';
import { useFileDialog } from '@vueuse/core';
import ChatFile from './ChatFile.vue';
import IconFilePlus from 'virtual:icons/mdi/filePlus';
import IconSend from 'virtual:icons/mdi/send';
import { computed, onMounted, onUnmounted, ref, unref } from 'vue';
import { useI18n, useChat, useOptions } from '@n8n/chat/composables';
import { chatEventBus } from '@n8n/chat/event-buses';
import ChatFile from './ChatFile.vue';
export interface ArrowKeyDownPayload {
key: 'ArrowUp' | 'ArrowDown';
currentInputValue: string;

View file

@ -1,5 +1,6 @@
<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from 'vue';
import { chatEventBus } from '@n8n/chat/event-buses';
const chatBodyRef = ref<HTMLElement | null>(null);

View file

@ -1,18 +1,20 @@
<script lang="ts" setup>
/* eslint-disable @typescript-eslint/naming-convention */
import hljs from 'highlight.js/lib/core';
import bash from 'highlight.js/lib/languages/bash';
import javascript from 'highlight.js/lib/languages/javascript';
import python from 'highlight.js/lib/languages/python';
import typescript from 'highlight.js/lib/languages/typescript';
import xml from 'highlight.js/lib/languages/xml';
import type MarkdownIt from 'markdown-it';
import markdownLink from 'markdown-it-link-attributes';
import { computed, ref, toRefs, onMounted } from 'vue';
import VueMarkdown from 'vue-markdown-render';
import hljs from 'highlight.js/lib/core';
import javascript from 'highlight.js/lib/languages/javascript';
import typescript from 'highlight.js/lib/languages/typescript';
import python from 'highlight.js/lib/languages/python';
import xml from 'highlight.js/lib/languages/xml';
import bash from 'highlight.js/lib/languages/bash';
import markdownLink from 'markdown-it-link-attributes';
import type MarkdownIt from 'markdown-it';
import ChatFile from './ChatFile.vue';
import type { ChatMessage, ChatMessageText } from '@n8n/chat/types';
import { useOptions } from '@n8n/chat/composables';
import type { ChatMessage, ChatMessageText } from '@n8n/chat/types';
import ChatFile from './ChatFile.vue';
const props = defineProps<{
message: ChatMessage;

View file

@ -1,8 +1,10 @@
<script lang="ts" setup>
import { computed, onMounted, ref } from 'vue';
import { Message } from './index';
import type { ChatMessage } from '@n8n/chat/types';
import { Message } from './index';
const props = withDefaults(
defineProps<{
animation?: 'bouncing' | 'scaling';

View file

@ -1,9 +1,10 @@
<script lang="ts" setup>
import { ref, watch } from 'vue';
import Message from '@n8n/chat/components/Message.vue';
import type { ChatMessage } from '@n8n/chat/types';
import MessageTyping from '@n8n/chat/components/MessageTyping.vue';
import { useChat } from '@n8n/chat/composables';
import type { ChatMessage } from '@n8n/chat/types';
defineProps<{
messages: ChatMessage[];

View file

@ -1,4 +1,5 @@
import { inject } from 'vue';
import { ChatSymbol } from '@n8n/chat/constants';
import type { Chat } from '@n8n/chat/types';

View file

@ -1,4 +1,5 @@
import { isRef } from 'vue';
import { useOptions } from '@n8n/chat/composables/useOptions';
export function useI18n() {

View file

@ -1,4 +1,5 @@
import { inject } from 'vue';
import { ChatOptionsSymbol } from '@n8n/chat/constants';
import type { ChatOptions } from '@n8n/chat/types';

View file

@ -1,4 +1,5 @@
import type { InjectionKey } from 'vue';
import type { Chat, ChatOptions } from '@n8n/chat/types';
// eslint-disable-next-line @typescript-eslint/naming-convention

View file

@ -1,11 +1,13 @@
import './main.scss';
import { createApp } from 'vue';
import App from './App.vue';
import type { ChatOptions } from '@n8n/chat/types';
import { defaultMountingTarget, defaultOptions } from '@n8n/chat/constants';
import { createDefaultMountingTarget } from '@n8n/chat/utils';
import { ChatPlugin } from '@n8n/chat/plugins';
import type { ChatOptions } from '@n8n/chat/types';
import { createDefaultMountingTarget } from '@n8n/chat/utils';
import App from './App.vue';
export function createChat(options?: Partial<ChatOptions>) {
const resolvedOptions: ChatOptions = {

View file

@ -1,10 +1,11 @@
import { v4 as uuidv4 } from 'uuid';
import type { Plugin } from 'vue';
import { computed, nextTick, ref } from 'vue';
import { v4 as uuidv4 } from 'uuid';
import type { ChatMessage, ChatOptions } from '@n8n/chat/types';
import { chatEventBus } from '@n8n/chat/event-buses';
import * as api from '@n8n/chat/api';
import { ChatOptionsSymbol, ChatSymbol, localStorageSessionIdKey } from '@n8n/chat/constants';
import { chatEventBus } from '@n8n/chat/event-buses';
import type { ChatMessage, ChatOptions } from '@n8n/chat/types';
// eslint-disable-next-line @typescript-eslint/naming-convention
export const ChatPlugin: Plugin<ChatOptions> = {

View file

@ -1,4 +1,5 @@
import type { Ref } from 'vue';
import type { ChatMessage } from '@n8n/chat/types/messages';
export interface Chat {

View file

@ -1,16 +1,17 @@
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-explicit-any */
import * as qs from 'querystring';
import { Agent } from 'https';
import axios from 'axios';
import type { AxiosRequestConfig } from 'axios';
import { getAuthError } from './utils';
import { Agent } from 'https';
import * as qs from 'querystring';
import type { ClientOAuth2TokenData } from './ClientOAuth2Token';
import { ClientOAuth2Token } from './ClientOAuth2Token';
import { CodeFlow } from './CodeFlow';
import { CredentialsFlow } from './CredentialsFlow';
import type { Headers } from './types';
import { getAuthError } from './utils';
export interface ClientOAuth2RequestObject {
url: string;

View file

@ -1,6 +1,6 @@
import type { ClientOAuth2, ClientOAuth2Options, ClientOAuth2RequestObject } from './ClientOAuth2';
import { auth, expects, getRequestOptions } from './utils';
import { DEFAULT_HEADERS } from './constants';
import { auth, expects, getRequestOptions } from './utils';
export interface ClientOAuth2TokenData extends Record<string, string | undefined> {
token_type?: string | undefined;

View file

@ -1,4 +1,5 @@
import * as qs from 'querystring';
import type { ClientOAuth2, ClientOAuth2Options } from './ClientOAuth2';
import type { ClientOAuth2Token, ClientOAuth2TokenData } from './ClientOAuth2Token';
import { DEFAULT_HEADERS, DEFAULT_URL_BASE } from './constants';

View file

@ -1,8 +1,10 @@
import nock from 'nock';
import { ClientOAuth2, ClientOAuth2Token } from '../src';
import * as config from './config';
import { AuthError } from '@/utils';
import * as config from './config';
import { ClientOAuth2, ClientOAuth2Token } from '../src';
describe('CodeFlow', () => {
beforeAll(async () => {
nock.disableNetConnect();

View file

@ -1,8 +1,9 @@
import nock from 'nock';
import type { Headers } from '../src/types';
import * as config from './config';
import type { ClientOAuth2Options } from '../src';
import { ClientOAuth2, ClientOAuth2Token } from '../src';
import * as config from './config';
import type { Headers } from '../src/types';
describe('CredentialsFlow', () => {
beforeAll(async () => {

View file

@ -1,5 +1,6 @@
import { LRLanguage, LanguageSupport, foldNodeProp, foldInside } from '@codemirror/language';
import { styleTags, tags as t } from '@lezer/highlight';
import { parser } from './grammar';
export const parserWithMetaData = parser.configure({

View file

@ -1,6 +1,7 @@
import { fileTests as runTestFile } from '@lezer/generator/dist/test';
import fs from 'fs';
import path from 'path';
import { fileTests as runTestFile } from '@lezer/generator/dist/test';
import { n8nLanguage } from '../../src/expressions/index';
describe('expressions language', () => {

View file

@ -1,18 +1,18 @@
import { Config, Env, Nested } from './decorators';
import { CacheConfig } from './configs/cache.config';
import { CredentialsConfig } from './configs/credentials.config';
import { DatabaseConfig } from './configs/database.config';
import { VersionNotificationsConfig } from './configs/version-notifications.config';
import { PublicApiConfig } from './configs/public-api.config';
import { ExternalSecretsConfig } from './configs/external-secrets.config';
import { TemplatesConfig } from './configs/templates.config';
import { EventBusConfig } from './configs/event-bus.config';
import { NodesConfig } from './configs/nodes.config';
import { ExternalStorageConfig } from './configs/external-storage.config';
import { WorkflowsConfig } from './configs/workflows.config';
import { EndpointsConfig } from './configs/endpoints.config';
import { CacheConfig } from './configs/cache.config';
import { EventBusConfig } from './configs/event-bus.config';
import { ExternalSecretsConfig } from './configs/external-secrets.config';
import { ExternalStorageConfig } from './configs/external-storage.config';
import { NodesConfig } from './configs/nodes.config';
import { PublicApiConfig } from './configs/public-api.config';
import { ScalingModeConfig } from './configs/scaling-mode.config';
import { TemplatesConfig } from './configs/templates.config';
import { UserManagementConfig } from './configs/user-management.config';
import { VersionNotificationsConfig } from './configs/version-notifications.config';
import { WorkflowsConfig } from './configs/workflows.config';
import { Config, Env, Nested } from './decorators';
@Config
export class GlobalConfig {

View file

@ -1,6 +1,7 @@
import fs from 'fs';
import { Container } from 'typedi';
import { mock } from 'jest-mock-extended';
import { Container } from 'typedi';
import { GlobalConfig } from '../src/index';
jest.mock('fs');

View file

@ -1,4 +1,5 @@
import { Container } from 'typedi';
import { Config, Env } from '../src/decorators';
describe('decorators', () => {

View file

@ -4,8 +4,8 @@ import type Imap from 'imap';
import { type ImapMessage } from 'imap';
import { getMessage } from './helpers/getMessage';
import type { Message, MessagePart } from './types';
import { PartData } from './PartData';
import type { Message, MessagePart } from './types';
const IMAP_EVENTS = ['alert', 'mail', 'expunge', 'uidvalidity', 'update', 'close', 'end'] as const;

View file

@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-use-before-define */
import * as qp from 'quoted-printable';
import * as iconvlite from 'iconv-lite';
import * as qp from 'quoted-printable';
import * as utf8 from 'utf8';
import * as uuencode from 'uuencode';

View file

@ -4,6 +4,7 @@ import {
type ImapMessageBodyInfo,
type ImapMessageAttributes,
} from 'imap';
import type { Message, MessageBodyPart } from '../types';
/**

View file

@ -1,8 +1,9 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-use-before-define */
import Imap from 'imap';
import { ImapSimple } from './ImapSimple';
import { ConnectionClosedError, ConnectionEndedError, ConnectionTimeoutError } from './errors';
import { ImapSimple } from './ImapSimple';
import type { ImapSimpleOptions, MessagePart } from './types';
/**

View file

@ -7,7 +7,6 @@ import {
type SupplyData,
} from 'n8n-workflow';
import type { ClientOptions } from '@langchain/openai';
import { ChatOpenAI } from '@langchain/openai';
import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
import { N8nLlmTracing } from '../N8nLlmTracing';
@ -51,6 +50,18 @@ export class LmChatAzureOpenAi implements INodeType {
],
properties: [
getConnectionHintNoticeField([NodeConnectionType.AiChain, NodeConnectionType.AiAgent]),
{
displayName:
'If using JSON response format, you must include word "json" in the prompt in your chain or agent. Also, make sure to select latest models released post November 2023.',
name: 'notice',
type: 'notice',
default: '',
displayOptions: {
show: {
'/options.responseFormat': ['json_object'],
},
},
},
{
displayName: 'Model (Deployment) Name',
name: 'model',
@ -86,6 +97,25 @@ export class LmChatAzureOpenAi implements INodeType {
maxValue: 32768,
},
},
{
displayName: 'Response Format',
name: 'responseFormat',
default: 'text',
type: 'options',
options: [
{
name: 'Text',
value: 'text',
description: 'Regular text response',
},
{
name: 'JSON',
value: 'json_object',
description:
'Enables JSON mode, which should guarantee the message the model generates is valid JSON',
},
],
},
{
displayName: 'Presence Penalty',
name: 'presencePenalty',
@ -148,10 +178,9 @@ export class LmChatAzureOpenAi implements INodeType {
presencePenalty?: number;
temperature?: number;
topP?: number;
responseFormat?: 'text' | 'json_object';
};
const configuration: ClientOptions = {};
const model = new ChatOpenAI({
azureOpenAIApiDeploymentName: modelName,
azureOpenAIApiInstanceName: credentials.resourceName,
@ -160,8 +189,12 @@ export class LmChatAzureOpenAi implements INodeType {
...options,
timeout: options.timeout ?? 60000,
maxRetries: options.maxRetries ?? 2,
configuration,
callbacks: [new N8nLlmTracing(this)],
modelKwargs: options.responseFormat
? {
response_format: { type: options.responseFormat },
}
: undefined,
});
return {

View file

@ -338,7 +338,17 @@ const config = (module.exports = {
/**
* https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/order.md
*/
'import/order': 'error',
'import/order': [
'error',
{
alphabetize: {
order: 'asc',
caseInsensitive: true,
},
groups: [['builtin', 'external'], 'internal', ['parent', 'index', 'sibling'], 'object'],
'newlines-between': 'always',
},
],
// ----------------------------------
// eslint-plugin-n8n-local-rules

View file

@ -28,17 +28,6 @@ module.exports = {
// TODO: Remove this
'import/no-cycle': 'warn',
'import/order': [
'error',
{
alphabetize: {
order: 'asc',
caseInsensitive: true,
},
groups: [['builtin', 'external'], 'internal', ['parent', 'index', 'sibling'], 'object'],
'newlines-between': 'always',
},
],
'import/extensions': 'warn',
'@typescript-eslint/ban-ts-comment': ['warn', { 'ts-ignore': true }],
'@typescript-eslint/no-explicit-any': 'warn',

View file

@ -1,5 +1,5 @@
import type { AuthenticationMethod } from '@n8n/api-types';
import type {
AuthenticationMethod,
IPersonalizationSurveyAnswersV4,
IRun,
IWorkflowBase,

Some files were not shown because too many files have changed in this diff Show more