mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 20:24:05 -08:00
refactor(core): Port nodes config (no-changelog) (#10140)
Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ <aditya@netroy.in>
This commit is contained in:
parent
d2a3a4a080
commit
95b85dd5c1
46
packages/@n8n/config/src/configs/nodes.ts
Normal file
46
packages/@n8n/config/src/configs/nodes.ts
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import { Config, Env, Nested } from '../decorators';
|
||||||
|
|
||||||
|
function isStringArray(input: unknown): input is string[] {
|
||||||
|
return Array.isArray(input) && input.every((item) => typeof item === 'string');
|
||||||
|
}
|
||||||
|
|
||||||
|
class JsonStringArray extends Array<string> {
|
||||||
|
constructor(str: string) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
let parsed: unknown;
|
||||||
|
|
||||||
|
try {
|
||||||
|
parsed = JSON.parse(str);
|
||||||
|
} catch {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return isStringArray(parsed) ? parsed : [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Config
|
||||||
|
class CommunityPackagesConfig {
|
||||||
|
/** Whether to enable community packages */
|
||||||
|
@Env('N8N_COMMUNITY_PACKAGES_ENABLED')
|
||||||
|
enabled: boolean = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Config
|
||||||
|
export class NodesConfig {
|
||||||
|
/** Node types to load. Includes all if unspecified. @example '["n8n-nodes-base.hackerNews"]' */
|
||||||
|
@Env('NODES_INCLUDE')
|
||||||
|
readonly include: JsonStringArray = [];
|
||||||
|
|
||||||
|
/** Node types not to load. Excludes none if unspecified. @example '["n8n-nodes-base.hackerNews"]' */
|
||||||
|
@Env('NODES_EXCLUDE')
|
||||||
|
readonly exclude: JsonStringArray = [];
|
||||||
|
|
||||||
|
/** Node type to use as error trigger */
|
||||||
|
@Env('NODES_ERROR_TRIGGER_TYPE')
|
||||||
|
readonly errorTriggerType: string = 'n8n-nodes-base.errorTrigger';
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
readonly communityPackages: CommunityPackagesConfig;
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import { Container, Service } from 'typedi';
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
type Class = Function;
|
type Class = Function;
|
||||||
|
type Constructable<T = unknown> = new (rawValue: string) => T;
|
||||||
type PropertyKey = string | symbol;
|
type PropertyKey = string | symbol;
|
||||||
interface PropertyMetadata {
|
interface PropertyMetadata {
|
||||||
type: unknown;
|
type: unknown;
|
||||||
|
@ -46,6 +47,8 @@ export const Config: ClassDecorator = (ConfigClass: Class) => {
|
||||||
} else {
|
} else {
|
||||||
value = value === 'true';
|
value = value === 'true';
|
||||||
}
|
}
|
||||||
|
} else if (type !== String && type !== Object) {
|
||||||
|
value = new (type as Constructable)(value as string);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value !== undefined) {
|
if (value !== undefined) {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { PublicApiConfig } from './configs/public-api';
|
||||||
import { ExternalSecretsConfig } from './configs/external-secrets';
|
import { ExternalSecretsConfig } from './configs/external-secrets';
|
||||||
import { TemplatesConfig } from './configs/templates';
|
import { TemplatesConfig } from './configs/templates';
|
||||||
import { EventBusConfig } from './configs/event-bus';
|
import { EventBusConfig } from './configs/event-bus';
|
||||||
|
import { NodesConfig } from './configs/nodes';
|
||||||
|
|
||||||
@Config
|
@Config
|
||||||
class UserManagementConfig {
|
class UserManagementConfig {
|
||||||
|
@ -39,4 +40,7 @@ export class GlobalConfig {
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
eventBus: EventBusConfig;
|
eventBus: EventBusConfig;
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
readonly nodes: NodesConfig;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ describe('GlobalConfig', () => {
|
||||||
process.env = originalEnv;
|
process.env = originalEnv;
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultConfig = {
|
const defaultConfig: GlobalConfig = {
|
||||||
database: {
|
database: {
|
||||||
logging: {
|
logging: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
|
@ -100,6 +100,14 @@ describe('GlobalConfig', () => {
|
||||||
preferGet: false,
|
preferGet: false,
|
||||||
updateInterval: 300,
|
updateInterval: 300,
|
||||||
},
|
},
|
||||||
|
nodes: {
|
||||||
|
communityPackages: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
errorTriggerType: 'n8n-nodes-base.errorTrigger',
|
||||||
|
include: [],
|
||||||
|
exclude: [],
|
||||||
|
},
|
||||||
publicApi: {
|
publicApi: {
|
||||||
disabled: false,
|
disabled: false,
|
||||||
path: 'api',
|
path: 'api',
|
||||||
|
@ -128,6 +136,7 @@ describe('GlobalConfig', () => {
|
||||||
DB_POSTGRESDB_HOST: 'some-host',
|
DB_POSTGRESDB_HOST: 'some-host',
|
||||||
DB_POSTGRESDB_USER: 'n8n',
|
DB_POSTGRESDB_USER: 'n8n',
|
||||||
DB_TABLE_PREFIX: 'test_',
|
DB_TABLE_PREFIX: 'test_',
|
||||||
|
NODES_INCLUDE: '["n8n-nodes-base.hackerNews"]',
|
||||||
};
|
};
|
||||||
const config = Container.get(GlobalConfig);
|
const config = Container.get(GlobalConfig);
|
||||||
expect(config).toEqual({
|
expect(config).toEqual({
|
||||||
|
@ -144,11 +153,15 @@ describe('GlobalConfig', () => {
|
||||||
tablePrefix: 'test_',
|
tablePrefix: 'test_',
|
||||||
type: 'sqlite',
|
type: 'sqlite',
|
||||||
},
|
},
|
||||||
|
nodes: {
|
||||||
|
...defaultConfig.nodes,
|
||||||
|
include: ['n8n-nodes-base.hackerNews'],
|
||||||
|
},
|
||||||
});
|
});
|
||||||
expect(mockFs.readFileSync).not.toHaveBeenCalled();
|
expect(mockFs.readFileSync).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should use values from env variables when defined and convert them to the correct type', () => {
|
it('should read values from files using _FILE env variables', () => {
|
||||||
const passwordFile = '/path/to/postgres/password';
|
const passwordFile = '/path/to/postgres/password';
|
||||||
process.env = {
|
process.env = {
|
||||||
DB_POSTGRESDB_PASSWORD_FILE: passwordFile,
|
DB_POSTGRESDB_PASSWORD_FILE: passwordFile,
|
||||||
|
|
|
@ -19,7 +19,6 @@ import type {
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { ApplicationError, ErrorReporterProxy as ErrorReporter } from 'n8n-workflow';
|
import { ApplicationError, ErrorReporterProxy as ErrorReporter } from 'n8n-workflow';
|
||||||
|
|
||||||
import config from '@/config';
|
|
||||||
import {
|
import {
|
||||||
CUSTOM_API_CALL_KEY,
|
CUSTOM_API_CALL_KEY,
|
||||||
CUSTOM_API_CALL_NAME,
|
CUSTOM_API_CALL_NAME,
|
||||||
|
@ -28,6 +27,7 @@ import {
|
||||||
inE2ETests,
|
inE2ETests,
|
||||||
} from '@/constants';
|
} from '@/constants';
|
||||||
import { Logger } from '@/Logger';
|
import { Logger } from '@/Logger';
|
||||||
|
import { GlobalConfig } from '@n8n/config';
|
||||||
|
|
||||||
interface LoadedNodesAndCredentials {
|
interface LoadedNodesAndCredentials {
|
||||||
nodes: INodeTypeData;
|
nodes: INodeTypeData;
|
||||||
|
@ -44,15 +44,16 @@ export class LoadNodesAndCredentials {
|
||||||
|
|
||||||
loaders: Record<string, DirectoryLoader> = {};
|
loaders: Record<string, DirectoryLoader> = {};
|
||||||
|
|
||||||
excludeNodes = config.getEnv('nodes.exclude');
|
excludeNodes = this.globalConfig.nodes.exclude;
|
||||||
|
|
||||||
includeNodes = config.getEnv('nodes.include');
|
includeNodes = this.globalConfig.nodes.include;
|
||||||
|
|
||||||
private postProcessors: Array<() => Promise<void>> = [];
|
private postProcessors: Array<() => Promise<void>> = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
private readonly instanceSettings: InstanceSettings,
|
private readonly instanceSettings: InstanceSettings,
|
||||||
|
private readonly globalConfig: GlobalConfig,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
|
|
|
@ -120,7 +120,7 @@ export class Server extends AbstractServer {
|
||||||
await Container.get(LdapService).init();
|
await Container.get(LdapService).init();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.getEnv('nodes.communityPackages.enabled')) {
|
if (this.globalConfig.nodes.communityPackages.enabled) {
|
||||||
await import('@/controllers/communityPackages.controller');
|
await import('@/controllers/communityPackages.controller');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,8 +72,7 @@ import { UrlService } from './services/url.service';
|
||||||
import { WorkflowExecutionService } from './workflows/workflowExecution.service';
|
import { WorkflowExecutionService } from './workflows/workflowExecution.service';
|
||||||
import { MessageEventBus } from '@/eventbus/MessageEventBus/MessageEventBus';
|
import { MessageEventBus } from '@/eventbus/MessageEventBus/MessageEventBus';
|
||||||
import { EventService } from './eventbus/event.service';
|
import { EventService } from './eventbus/event.service';
|
||||||
|
import { GlobalConfig } from '@n8n/config';
|
||||||
const ERROR_TRIGGER_TYPE = config.getEnv('nodes.errorTriggerType');
|
|
||||||
|
|
||||||
export function objectToError(errorObject: unknown, workflow: Workflow): Error {
|
export function objectToError(errorObject: unknown, workflow: Workflow): Error {
|
||||||
// TODO: Expand with other error types
|
// TODO: Expand with other error types
|
||||||
|
@ -176,6 +175,7 @@ export function executeErrorWorkflow(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { errorTriggerType } = Container.get(GlobalConfig).nodes;
|
||||||
// Run the error workflow
|
// Run the error workflow
|
||||||
// To avoid an infinite loop do not run the error workflow again if the error-workflow itself failed and it is its own error-workflow.
|
// To avoid an infinite loop do not run the error workflow again if the error-workflow itself failed and it is its own error-workflow.
|
||||||
const { errorWorkflow } = workflowData.settings ?? {};
|
const { errorWorkflow } = workflowData.settings ?? {};
|
||||||
|
@ -220,7 +220,7 @@ export function executeErrorWorkflow(
|
||||||
} else if (
|
} else if (
|
||||||
mode !== 'error' &&
|
mode !== 'error' &&
|
||||||
workflowId !== undefined &&
|
workflowId !== undefined &&
|
||||||
workflowData.nodes.some((node) => node.type === ERROR_TRIGGER_TYPE)
|
workflowData.nodes.some((node) => node.type === errorTriggerType)
|
||||||
) {
|
) {
|
||||||
logger.verbose('Start internal error workflow', { executionId, workflowId });
|
logger.verbose('Start internal error workflow', { executionId, workflowId });
|
||||||
void Container.get(OwnershipService)
|
void Container.get(OwnershipService)
|
||||||
|
|
|
@ -252,16 +252,15 @@ export class Start extends BaseCommand {
|
||||||
config.set(setting.key, jsonParse(setting.value, { fallbackValue: setting.value }));
|
config.set(setting.key, jsonParse(setting.value, { fallbackValue: setting.value }));
|
||||||
});
|
});
|
||||||
|
|
||||||
const areCommunityPackagesEnabled = config.getEnv('nodes.communityPackages.enabled');
|
const globalConfig = Container.get(GlobalConfig);
|
||||||
|
|
||||||
if (areCommunityPackagesEnabled) {
|
if (globalConfig.nodes.communityPackages.enabled) {
|
||||||
const { CommunityPackagesService } = await import('@/services/communityPackages.service');
|
const { CommunityPackagesService } = await import('@/services/communityPackages.service');
|
||||||
await Container.get(CommunityPackagesService).setMissingPackages({
|
await Container.get(CommunityPackagesService).setMissingPackages({
|
||||||
reinstallMissingPackages: flags.reinstallMissingPackages,
|
reinstallMissingPackages: flags.reinstallMissingPackages,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const globalConfig = Container.get(GlobalConfig);
|
|
||||||
const { type: dbType } = globalConfig.database;
|
const { type: dbType } = globalConfig.database;
|
||||||
if (dbType === 'sqlite') {
|
if (dbType === 'sqlite') {
|
||||||
const shouldRunVacuum = globalConfig.database.sqlite.executeVacuumOnStartup;
|
const shouldRunVacuum = globalConfig.database.sqlite.executeVacuumOnStartup;
|
||||||
|
|
|
@ -2,18 +2,9 @@ import path from 'path';
|
||||||
import convict from 'convict';
|
import convict from 'convict';
|
||||||
import { Container } from 'typedi';
|
import { Container } from 'typedi';
|
||||||
import { InstanceSettings } from 'n8n-core';
|
import { InstanceSettings } from 'n8n-core';
|
||||||
import { LOG_LEVELS, jsonParse } from 'n8n-workflow';
|
import { LOG_LEVELS } from 'n8n-workflow';
|
||||||
import { ensureStringArray } from './utils';
|
import { ensureStringArray } from './utils';
|
||||||
|
|
||||||
convict.addFormat({
|
|
||||||
name: 'json-string-array',
|
|
||||||
coerce: (rawStr: string) =>
|
|
||||||
jsonParse<string[]>(rawStr, {
|
|
||||||
errorMessage: `Expected this value "${rawStr}" to be valid JSON`,
|
|
||||||
}),
|
|
||||||
validate: ensureStringArray,
|
|
||||||
});
|
|
||||||
|
|
||||||
convict.addFormat({
|
convict.addFormat({
|
||||||
name: 'comma-separated-list',
|
name: 'comma-separated-list',
|
||||||
coerce: (rawStr: string) => rawStr.split(','),
|
coerce: (rawStr: string) => rawStr.split(','),
|
||||||
|
@ -615,35 +606,6 @@ export const schema = {
|
||||||
env: 'EXTERNAL_HOOK_FILES',
|
env: 'EXTERNAL_HOOK_FILES',
|
||||||
},
|
},
|
||||||
|
|
||||||
nodes: {
|
|
||||||
include: {
|
|
||||||
doc: 'Nodes to load',
|
|
||||||
format: 'json-string-array',
|
|
||||||
default: undefined,
|
|
||||||
env: 'NODES_INCLUDE',
|
|
||||||
},
|
|
||||||
exclude: {
|
|
||||||
doc: 'Nodes not to load',
|
|
||||||
format: 'json-string-array',
|
|
||||||
default: undefined,
|
|
||||||
env: 'NODES_EXCLUDE',
|
|
||||||
},
|
|
||||||
errorTriggerType: {
|
|
||||||
doc: 'Node Type to use as Error Trigger',
|
|
||||||
format: String,
|
|
||||||
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: {
|
logs: {
|
||||||
level: {
|
level: {
|
||||||
doc: 'Log output level',
|
doc: 'Log output level',
|
||||||
|
|
|
@ -75,8 +75,6 @@ type ToReturnType<T extends ConfigOptionPath> = T extends NumericPath
|
||||||
type ExceptionPaths = {
|
type ExceptionPaths = {
|
||||||
'queue.bull.redis': RedisOptions;
|
'queue.bull.redis': RedisOptions;
|
||||||
binaryDataManager: BinaryData.Config;
|
binaryDataManager: BinaryData.Config;
|
||||||
'nodes.exclude': string[] | undefined;
|
|
||||||
'nodes.include': string[] | undefined;
|
|
||||||
'userManagement.isInstanceOwnerSetUp': boolean;
|
'userManagement.isInstanceOwnerSetUp': boolean;
|
||||||
'ui.banners.dismissed': string[] | undefined;
|
'ui.banners.dismissed': string[] | undefined;
|
||||||
};
|
};
|
||||||
|
|
|
@ -88,15 +88,17 @@ export class InstanceRiskReporter implements RiskReporter {
|
||||||
const settings: Record<string, unknown> = {};
|
const settings: Record<string, unknown> = {};
|
||||||
|
|
||||||
settings.features = {
|
settings.features = {
|
||||||
communityPackagesEnabled: config.getEnv('nodes.communityPackages.enabled'),
|
communityPackagesEnabled: this.globalConfig.nodes.communityPackages.enabled,
|
||||||
versionNotificationsEnabled: this.globalConfig.versionNotifications.enabled,
|
versionNotificationsEnabled: this.globalConfig.versionNotifications.enabled,
|
||||||
templatesEnabled: this.globalConfig.templates.enabled,
|
templatesEnabled: this.globalConfig.templates.enabled,
|
||||||
publicApiEnabled: isApiEnabled(),
|
publicApiEnabled: isApiEnabled(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { exclude, include } = this.globalConfig.nodes;
|
||||||
|
|
||||||
settings.nodes = {
|
settings.nodes = {
|
||||||
nodesExclude: config.getEnv('nodes.exclude') ?? 'none',
|
nodesExclude: exclude.length === 0 ? 'none' : exclude.join(', '),
|
||||||
nodesInclude: config.getEnv('nodes.include') ?? 'none',
|
nodesInclude: include.length === 0 ? 'none' : include.join(', '),
|
||||||
};
|
};
|
||||||
|
|
||||||
settings.telemetry = {
|
settings.telemetry = {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import glob from 'fast-glob';
|
import glob from 'fast-glob';
|
||||||
import { Service } from 'typedi';
|
import { Service } from 'typedi';
|
||||||
import config from '@/config';
|
|
||||||
import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials';
|
import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials';
|
||||||
import { getNodeTypes } from '@/security-audit/utils';
|
import { getNodeTypes } from '@/security-audit/utils';
|
||||||
import {
|
import {
|
||||||
|
@ -14,12 +13,14 @@ import {
|
||||||
import type { WorkflowEntity } from '@db/entities/WorkflowEntity';
|
import type { WorkflowEntity } from '@db/entities/WorkflowEntity';
|
||||||
import type { Risk, RiskReporter } from '@/security-audit/types';
|
import type { Risk, RiskReporter } from '@/security-audit/types';
|
||||||
import { CommunityPackagesService } from '@/services/communityPackages.service';
|
import { CommunityPackagesService } from '@/services/communityPackages.service';
|
||||||
|
import { GlobalConfig } from '@n8n/config';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class NodesRiskReporter implements RiskReporter {
|
export class NodesRiskReporter implements RiskReporter {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly loadNodesAndCredentials: LoadNodesAndCredentials,
|
private readonly loadNodesAndCredentials: LoadNodesAndCredentials,
|
||||||
private readonly communityPackagesService: CommunityPackagesService,
|
private readonly communityPackagesService: CommunityPackagesService,
|
||||||
|
private readonly globalConfig: GlobalConfig,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async report(workflows: WorkflowEntity[]) {
|
async report(workflows: WorkflowEntity[]) {
|
||||||
|
@ -85,7 +86,7 @@ export class NodesRiskReporter implements RiskReporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getCommunityNodeDetails() {
|
private async getCommunityNodeDetails() {
|
||||||
if (!config.getEnv('nodes.communityPackages.enabled')) return [];
|
if (!this.globalConfig.nodes.communityPackages.enabled) return [];
|
||||||
|
|
||||||
const installedPackages = await this.communityPackagesService.getAllInstalledPackages();
|
const installedPackages = await this.communityPackagesService.getAllInstalledPackages();
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ export class FrontendService {
|
||||||
|
|
||||||
this.initSettings();
|
this.initSettings();
|
||||||
|
|
||||||
if (config.getEnv('nodes.communityPackages.enabled')) {
|
if (this.globalConfig.nodes.communityPackages.enabled) {
|
||||||
void import('@/services/communityPackages.service').then(({ CommunityPackagesService }) => {
|
void import('@/services/communityPackages.service').then(({ CommunityPackagesService }) => {
|
||||||
this.communityPackagesService = Container.get(CommunityPackagesService);
|
this.communityPackagesService = Container.get(CommunityPackagesService);
|
||||||
});
|
});
|
||||||
|
@ -154,7 +154,7 @@ export class FrontendService {
|
||||||
latestVersion: 1,
|
latestVersion: 1,
|
||||||
path: this.globalConfig.publicApi.path,
|
path: this.globalConfig.publicApi.path,
|
||||||
swaggerUi: {
|
swaggerUi: {
|
||||||
enabled: !Container.get(GlobalConfig).publicApi.swaggerUiDisabled,
|
enabled: !this.globalConfig.publicApi.swaggerUiDisabled,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
workflowTagsDisabled: config.getEnv('workflowTagsDisabled'),
|
workflowTagsDisabled: config.getEnv('workflowTagsDisabled'),
|
||||||
|
@ -166,7 +166,7 @@ export class FrontendService {
|
||||||
},
|
},
|
||||||
executionMode: config.getEnv('executions.mode'),
|
executionMode: config.getEnv('executions.mode'),
|
||||||
pushBackend: config.getEnv('push.backend'),
|
pushBackend: config.getEnv('push.backend'),
|
||||||
communityNodesEnabled: config.getEnv('nodes.communityPackages.enabled'),
|
communityNodesEnabled: this.globalConfig.nodes.communityPackages.enabled,
|
||||||
deployment: {
|
deployment: {
|
||||||
type: config.getEnv('deployment.type'),
|
type: config.getEnv('deployment.type'),
|
||||||
},
|
},
|
||||||
|
|
|
@ -16,7 +16,6 @@ import {
|
||||||
ErrorReporterProxy as ErrorReporter,
|
ErrorReporterProxy as ErrorReporter,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import config from '@/config';
|
|
||||||
import type { User } from '@db/entities/User';
|
import type { User } from '@db/entities/User';
|
||||||
import { ExecutionRepository } from '@db/repositories/execution.repository';
|
import { ExecutionRepository } from '@db/repositories/execution.repository';
|
||||||
import { WorkflowRepository } from '@db/repositories/workflow.repository';
|
import { WorkflowRepository } from '@db/repositories/workflow.repository';
|
||||||
|
@ -35,6 +34,7 @@ import { TestWebhooks } from '@/TestWebhooks';
|
||||||
import { Logger } from '@/Logger';
|
import { Logger } from '@/Logger';
|
||||||
import { PermissionChecker } from '@/UserManagement/PermissionChecker';
|
import { PermissionChecker } from '@/UserManagement/PermissionChecker';
|
||||||
import type { Project } from '@/databases/entities/Project';
|
import type { Project } from '@/databases/entities/Project';
|
||||||
|
import { GlobalConfig } from '@n8n/config';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class WorkflowExecutionService {
|
export class WorkflowExecutionService {
|
||||||
|
@ -46,6 +46,7 @@ export class WorkflowExecutionService {
|
||||||
private readonly testWebhooks: TestWebhooks,
|
private readonly testWebhooks: TestWebhooks,
|
||||||
private readonly permissionChecker: PermissionChecker,
|
private readonly permissionChecker: PermissionChecker,
|
||||||
private readonly workflowRunner: WorkflowRunner,
|
private readonly workflowRunner: WorkflowRunner,
|
||||||
|
private readonly globalConfig: GlobalConfig,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async runWorkflow(
|
async runWorkflow(
|
||||||
|
@ -230,17 +231,17 @@ export class WorkflowExecutionService {
|
||||||
|
|
||||||
let node: INode;
|
let node: INode;
|
||||||
let workflowStartNode: INode | undefined;
|
let workflowStartNode: INode | undefined;
|
||||||
const ERROR_TRIGGER_TYPE = config.getEnv('nodes.errorTriggerType');
|
const { errorTriggerType } = this.globalConfig.nodes;
|
||||||
for (const nodeName of Object.keys(workflowInstance.nodes)) {
|
for (const nodeName of Object.keys(workflowInstance.nodes)) {
|
||||||
node = workflowInstance.nodes[nodeName];
|
node = workflowInstance.nodes[nodeName];
|
||||||
if (node.type === ERROR_TRIGGER_TYPE) {
|
if (node.type === errorTriggerType) {
|
||||||
workflowStartNode = node;
|
workflowStartNode = node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (workflowStartNode === undefined) {
|
if (workflowStartNode === undefined) {
|
||||||
this.logger.error(
|
this.logger.error(
|
||||||
`Calling Error Workflow for "${workflowErrorData.workflow.id}". Could not find "${ERROR_TRIGGER_TYPE}" in workflow "${workflowId}"`,
|
`Calling Error Workflow for "${workflowErrorData.workflow.id}". Could not find "${errorTriggerType}" in workflow "${workflowId}"`,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue