mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
refactor(core): Introduce @n8n/decorators package (#14784)
This commit is contained in:
@@ -37,6 +37,7 @@ component_management:
|
|||||||
- packages/@n8n/api-types/**
|
- packages/@n8n/api-types/**
|
||||||
- packages/@n8n/config/**
|
- packages/@n8n/config/**
|
||||||
- packages/@n8n/client-oauth2/**
|
- packages/@n8n/client-oauth2/**
|
||||||
|
- packages/@n8n/decorators/**
|
||||||
- packages/@n8n/constants/**
|
- packages/@n8n/constants/**
|
||||||
- packages/@n8n/di/**
|
- packages/@n8n/di/**
|
||||||
- packages/@n8n/imap/**
|
- packages/@n8n/imap/**
|
||||||
|
|||||||
7
packages/@n8n/decorators/.eslintrc.js
Normal file
7
packages/@n8n/decorators/.eslintrc.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
const sharedOptions = require('@n8n/eslint-config/shared');
|
||||||
|
|
||||||
|
/** @type {import('@types/eslint').ESLint.ConfigData} */
|
||||||
|
module.exports = {
|
||||||
|
extends: ['@n8n/eslint-config/base'],
|
||||||
|
...sharedOptions(__dirname),
|
||||||
|
};
|
||||||
7
packages/@n8n/decorators/jest.config.js
Normal file
7
packages/@n8n/decorators/jest.config.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/** @type {import('jest').Config} */
|
||||||
|
module.exports = {
|
||||||
|
...require('../../../jest.config'),
|
||||||
|
transform: {
|
||||||
|
'^.+\\.ts$': ['ts-jest', { isolatedModules: false }],
|
||||||
|
},
|
||||||
|
};
|
||||||
35
packages/@n8n/decorators/package.json
Normal file
35
packages/@n8n/decorators/package.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "@n8n/decorators",
|
||||||
|
"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/index.js",
|
||||||
|
"module": "src/index.ts",
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"files": [
|
||||||
|
"dist/**/*"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"@n8n/typescript-config": "workspace:*",
|
||||||
|
"@types/express": "catalog:",
|
||||||
|
"@types/lodash": "catalog:"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@n8n/constants": "workspace:^",
|
||||||
|
"@n8n/di": "workspace:^",
|
||||||
|
"@n8n/permissions": "workspace:^",
|
||||||
|
"lodash": "catalog:",
|
||||||
|
"n8n-workflow": "workspace:^"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
import { Container } from '@n8n/di';
|
import { Container } from '@n8n/di';
|
||||||
import { mock } from 'jest-mock-extended';
|
import { mock } from 'jest-mock-extended';
|
||||||
import type { ExecutionLifecycleHooks } from 'n8n-core';
|
|
||||||
|
|
||||||
import type { BaseN8nModule } from '../module';
|
import type { BaseN8nModule, ExecutionLifecycleHooks } from '../module';
|
||||||
import { ModuleRegistry, N8nModule } from '../module';
|
import { ModuleRegistry, N8nModule } from '../module';
|
||||||
|
|
||||||
let moduleRegistry: ModuleRegistry;
|
let moduleRegistry: ModuleRegistry;
|
||||||
@@ -1,16 +1,15 @@
|
|||||||
import { Container, Service } from '@n8n/di';
|
import { Container, Service } from '@n8n/di';
|
||||||
import { mock } from 'jest-mock-extended';
|
|
||||||
|
|
||||||
import { OnShutdown } from '@/decorators/on-shutdown';
|
import { OnShutdown } from '../on-shutdown';
|
||||||
import { ShutdownService } from '@/shutdown/shutdown.service';
|
import { ShutdownRegistryMetadata } from '../shutdown-registry-metadata';
|
||||||
|
|
||||||
describe('OnShutdown', () => {
|
describe('OnShutdown', () => {
|
||||||
let shutdownService: ShutdownService;
|
let shutdownRegistryMetadata: ShutdownRegistryMetadata;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
shutdownService = new ShutdownService(mock(), mock());
|
shutdownRegistryMetadata = new ShutdownRegistryMetadata();
|
||||||
Container.set(ShutdownService, shutdownService);
|
Container.set(ShutdownRegistryMetadata, shutdownRegistryMetadata);
|
||||||
jest.spyOn(shutdownService, 'register');
|
jest.spyOn(shutdownRegistryMetadata, 'register');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should register a methods that is decorated with OnShutdown', () => {
|
it('should register a methods that is decorated with OnShutdown', () => {
|
||||||
@@ -20,8 +19,8 @@ describe('OnShutdown', () => {
|
|||||||
async onShutdown() {}
|
async onShutdown() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(shutdownService.register).toHaveBeenCalledTimes(1);
|
expect(shutdownRegistryMetadata.register).toHaveBeenCalledTimes(1);
|
||||||
expect(shutdownService.register).toHaveBeenCalledWith(100, {
|
expect(shutdownRegistryMetadata.register).toHaveBeenCalledWith(100, {
|
||||||
methodName: 'onShutdown',
|
methodName: 'onShutdown',
|
||||||
serviceClass: TestClass,
|
serviceClass: TestClass,
|
||||||
});
|
});
|
||||||
@@ -37,12 +36,12 @@ describe('OnShutdown', () => {
|
|||||||
async two() {}
|
async two() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(shutdownService.register).toHaveBeenCalledTimes(2);
|
expect(shutdownRegistryMetadata.register).toHaveBeenCalledTimes(2);
|
||||||
expect(shutdownService.register).toHaveBeenCalledWith(100, {
|
expect(shutdownRegistryMetadata.register).toHaveBeenCalledWith(100, {
|
||||||
methodName: 'one',
|
methodName: 'one',
|
||||||
serviceClass: TestClass,
|
serviceClass: TestClass,
|
||||||
});
|
});
|
||||||
expect(shutdownService.register).toHaveBeenCalledWith(100, {
|
expect(shutdownRegistryMetadata.register).toHaveBeenCalledWith(100, {
|
||||||
methodName: 'two',
|
methodName: 'two',
|
||||||
serviceClass: TestClass,
|
serviceClass: TestClass,
|
||||||
});
|
});
|
||||||
@@ -57,9 +56,9 @@ describe('OnShutdown', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(shutdownService.register).toHaveBeenCalledTimes(1);
|
expect(shutdownRegistryMetadata.register).toHaveBeenCalledTimes(1);
|
||||||
// @ts-expect-error We are checking internal parts of the shutdown service
|
// @ts-expect-error We are checking internal parts of the shutdown service
|
||||||
expect(shutdownService.handlersByPriority[10].length).toEqual(1);
|
expect(shutdownRegistryMetadata.handlersByPriority[10].length).toEqual(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if the decorated member is not a function', () => {
|
it('should throw an error if the decorated member is not a function', () => {
|
||||||
@@ -1,10 +1,15 @@
|
|||||||
import { getRouteMetadata } from './controller.registry';
|
import { Container } from '@n8n/di';
|
||||||
|
|
||||||
|
import { ControllerRegistryMetadata } from './controller-registry-metadata';
|
||||||
import type { Arg, Controller } from './types';
|
import type { Arg, Controller } from './types';
|
||||||
|
|
||||||
const ArgDecorator =
|
const ArgDecorator =
|
||||||
(arg: Arg): ParameterDecorator =>
|
(arg: Arg): ParameterDecorator =>
|
||||||
(target, handlerName, parameterIndex) => {
|
(target, handlerName, parameterIndex) => {
|
||||||
const routeMetadata = getRouteMetadata(target.constructor as Controller, String(handlerName));
|
const routeMetadata = Container.get(ControllerRegistryMetadata).getRouteMetadata(
|
||||||
|
target.constructor as Controller,
|
||||||
|
String(handlerName),
|
||||||
|
);
|
||||||
routeMetadata.args[parameterIndex] = arg;
|
routeMetadata.args[parameterIndex] = arg;
|
||||||
};
|
};
|
||||||
|
|
||||||
36
packages/@n8n/decorators/src/controller-registry-metadata.ts
Normal file
36
packages/@n8n/decorators/src/controller-registry-metadata.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { Service } from '@n8n/di';
|
||||||
|
|
||||||
|
import type { Controller, ControllerMetadata, HandlerName, RouteMetadata } from './types';
|
||||||
|
|
||||||
|
@Service()
|
||||||
|
export class ControllerRegistryMetadata {
|
||||||
|
private registry = new Map<Controller, ControllerMetadata>();
|
||||||
|
|
||||||
|
getControllerMetadata(controllerClass: Controller) {
|
||||||
|
let metadata = this.registry.get(controllerClass);
|
||||||
|
if (!metadata) {
|
||||||
|
metadata = {
|
||||||
|
basePath: '/',
|
||||||
|
middlewares: [],
|
||||||
|
routes: new Map(),
|
||||||
|
};
|
||||||
|
this.registry.set(controllerClass, metadata);
|
||||||
|
}
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
getRouteMetadata(controllerClass: Controller, handlerName: HandlerName) {
|
||||||
|
const metadata = this.getControllerMetadata(controllerClass);
|
||||||
|
let route = metadata.routes.get(handlerName);
|
||||||
|
if (!route) {
|
||||||
|
route = {} as RouteMetadata;
|
||||||
|
route.args = [];
|
||||||
|
metadata.routes.set(handlerName, route);
|
||||||
|
}
|
||||||
|
return route;
|
||||||
|
}
|
||||||
|
|
||||||
|
get controllerClasses() {
|
||||||
|
return this.registry.keys();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,7 +19,7 @@ export const Debounce =
|
|||||||
(waitMs: number): MethodDecorator =>
|
(waitMs: number): MethodDecorator =>
|
||||||
<T>(
|
<T>(
|
||||||
_: object,
|
_: object,
|
||||||
methodName: string,
|
methodName: string | symbol,
|
||||||
originalDescriptor: PropertyDescriptor,
|
originalDescriptor: PropertyDescriptor,
|
||||||
): TypedPropertyDescriptor<T> => ({
|
): TypedPropertyDescriptor<T> => ({
|
||||||
configurable: true,
|
configurable: true,
|
||||||
20
packages/@n8n/decorators/src/index.ts
Normal file
20
packages/@n8n/decorators/src/index.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
export { Body, Query, Param } from './args';
|
||||||
|
export { RestController } from './rest-controller';
|
||||||
|
export { Get, Post, Put, Patch, Delete } from './route';
|
||||||
|
export { Middleware } from './middleware';
|
||||||
|
export { ControllerRegistryMetadata } from './controller-registry-metadata';
|
||||||
|
export { Licensed } from './licensed';
|
||||||
|
export { GlobalScope, ProjectScope } from './scoped';
|
||||||
|
export {
|
||||||
|
HIGHEST_SHUTDOWN_PRIORITY,
|
||||||
|
DEFAULT_SHUTDOWN_PRIORITY,
|
||||||
|
LOWEST_SHUTDOWN_PRIORITY,
|
||||||
|
} from './shutdown/constants';
|
||||||
|
export { ShutdownRegistryMetadata } from './shutdown-registry-metadata';
|
||||||
|
export { ModuleRegistry } from './module';
|
||||||
|
export { OnShutdown } from './on-shutdown';
|
||||||
|
export { Redactable } from './redactable';
|
||||||
|
export { BaseN8nModule, N8nModule } from './module';
|
||||||
|
export { Debounce } from './debounce';
|
||||||
|
export type { AccessScope, Controller, RateLimit } from './types';
|
||||||
|
export type { ShutdownHandler } from './types';
|
||||||
@@ -1,11 +1,15 @@
|
|||||||
import type { BooleanLicenseFeature } from '@n8n/constants';
|
import type { BooleanLicenseFeature } from '@n8n/constants';
|
||||||
|
import { Container } from '@n8n/di';
|
||||||
|
|
||||||
import { getRouteMetadata } from './controller.registry';
|
import { ControllerRegistryMetadata } from './controller-registry-metadata';
|
||||||
import type { Controller } from './types';
|
import type { Controller } from './types';
|
||||||
|
|
||||||
export const Licensed =
|
export const Licensed =
|
||||||
(licenseFeature: BooleanLicenseFeature): MethodDecorator =>
|
(licenseFeature: BooleanLicenseFeature): MethodDecorator =>
|
||||||
(target, handlerName) => {
|
(target, handlerName) => {
|
||||||
const routeMetadata = getRouteMetadata(target.constructor as Controller, String(handlerName));
|
const routeMetadata = Container.get(ControllerRegistryMetadata).getRouteMetadata(
|
||||||
|
target.constructor as Controller,
|
||||||
|
String(handlerName),
|
||||||
|
);
|
||||||
routeMetadata.licenseFeature = licenseFeature;
|
routeMetadata.licenseFeature = licenseFeature;
|
||||||
};
|
};
|
||||||
11
packages/@n8n/decorators/src/middleware.ts
Normal file
11
packages/@n8n/decorators/src/middleware.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { Container } from '@n8n/di';
|
||||||
|
|
||||||
|
import { ControllerRegistryMetadata } from './controller-registry-metadata';
|
||||||
|
import type { Controller } from './types';
|
||||||
|
|
||||||
|
export const Middleware = (): MethodDecorator => (target, handlerName) => {
|
||||||
|
const metadata = Container.get(ControllerRegistryMetadata).getControllerMetadata(
|
||||||
|
target.constructor as Controller,
|
||||||
|
);
|
||||||
|
metadata.middlewares.push(String(handlerName));
|
||||||
|
};
|
||||||
@@ -1,7 +1,15 @@
|
|||||||
import { Container, Service, type Constructable } from '@n8n/di';
|
import { Container, Service, type Constructable } from '@n8n/di';
|
||||||
import type { ExecutionLifecycleHooks } from 'n8n-core';
|
import type EventEmitter from 'node:events';
|
||||||
|
|
||||||
import type { MultiMainSetup } from '@/scaling/multi-main-setup.ee';
|
/**
|
||||||
|
* @TODO Temporary dummy type until `MultiMainSetup` registers listeners via decorators.
|
||||||
|
*/
|
||||||
|
type MultiMainSetup = EventEmitter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @TODO Temporary dummy type until `ExecutionLifecycleHooks` registers hooks via decorators.
|
||||||
|
*/
|
||||||
|
export type ExecutionLifecycleHooks = object;
|
||||||
|
|
||||||
export interface BaseN8nModule {
|
export interface BaseN8nModule {
|
||||||
initialize?(): void;
|
initialize?(): void;
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
import { Container } from '@n8n/di';
|
import { Container } from '@n8n/di';
|
||||||
import { UnexpectedError } from 'n8n-workflow';
|
import { UnexpectedError } from 'n8n-workflow';
|
||||||
|
|
||||||
import { DEFAULT_SHUTDOWN_PRIORITY } from '@/constants';
|
import { DEFAULT_SHUTDOWN_PRIORITY } from './shutdown/constants';
|
||||||
import { type ServiceClass, ShutdownService } from '@/shutdown/shutdown.service';
|
import { ShutdownRegistryMetadata } from './shutdown-registry-metadata';
|
||||||
|
import type { ServiceClass } from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decorator that registers a method as a shutdown hook. The method will
|
* Decorator that registers a method as a shutdown hook. The method will
|
||||||
@@ -30,7 +31,7 @@ export const OnShutdown =
|
|||||||
const methodName = String(propertyKey);
|
const methodName = String(propertyKey);
|
||||||
// TODO: assert that serviceClass is decorated with @Service
|
// TODO: assert that serviceClass is decorated with @Service
|
||||||
if (typeof descriptor?.value === 'function') {
|
if (typeof descriptor?.value === 'function') {
|
||||||
Container.get(ShutdownService).register(priority, { serviceClass, methodName });
|
Container.get(ShutdownRegistryMetadata).register(priority, { serviceClass, methodName });
|
||||||
} else {
|
} else {
|
||||||
const name = `${serviceClass.name}.${methodName}()`;
|
const name = `${serviceClass.name}.${methodName}()`;
|
||||||
throw new UnexpectedError(
|
throw new UnexpectedError(
|
||||||
@@ -1,5 +1,20 @@
|
|||||||
import { RedactableError } from '@/errors/redactable.error';
|
import { UnexpectedError } from 'n8n-workflow';
|
||||||
import type { UserLike } from '@/events/maps/relay.event-map';
|
|
||||||
|
type UserLike = {
|
||||||
|
id: string;
|
||||||
|
email?: string;
|
||||||
|
firstName?: string;
|
||||||
|
lastName?: string;
|
||||||
|
role: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export class RedactableError extends UnexpectedError {
|
||||||
|
constructor(fieldName: string, args: string) {
|
||||||
|
super(
|
||||||
|
`Failed to find "${fieldName}" property in argument "${args.toString()}". Please set the decorator \`@Redactable()\` only on \`LogStreamingEventRelay\` methods where the argument contains a "${fieldName}" property.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function toRedactable(userLike: UserLike) {
|
function toRedactable(userLike: UserLike) {
|
||||||
return {
|
return {
|
||||||
@@ -28,6 +43,7 @@ type FieldName = 'user' | 'inviter' | 'invitee';
|
|||||||
export const Redactable =
|
export const Redactable =
|
||||||
(fieldName: FieldName = 'user'): MethodDecorator =>
|
(fieldName: FieldName = 'user'): MethodDecorator =>
|
||||||
(_target, _propertyName, propertyDescriptor: PropertyDescriptor) => {
|
(_target, _propertyName, propertyDescriptor: PropertyDescriptor) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
const originalMethod = propertyDescriptor.value as Function;
|
const originalMethod = propertyDescriptor.value as Function;
|
||||||
|
|
||||||
type MethodArgs = Array<{ [fieldName: string]: UserLike }>;
|
type MethodArgs = Array<{ [fieldName: string]: UserLike }>;
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
import { Service } from '@n8n/di';
|
import { Container, Service } from '@n8n/di';
|
||||||
|
|
||||||
import { getControllerMetadata } from './controller.registry';
|
import { ControllerRegistryMetadata } from './controller-registry-metadata';
|
||||||
import type { Controller } from './types';
|
import type { Controller } from './types';
|
||||||
|
|
||||||
export const RestController =
|
export const RestController =
|
||||||
(basePath: `/${string}` = '/'): ClassDecorator =>
|
(basePath: `/${string}` = '/'): ClassDecorator =>
|
||||||
(target) => {
|
(target) => {
|
||||||
const metadata = getControllerMetadata(target as unknown as Controller);
|
const metadata = Container.get(ControllerRegistryMetadata).getControllerMetadata(
|
||||||
|
target as unknown as Controller,
|
||||||
|
);
|
||||||
metadata.basePath = basePath;
|
metadata.basePath = basePath;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||||
return Service()(target);
|
return Service()(target);
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
|
import { Container } from '@n8n/di';
|
||||||
import type { RequestHandler } from 'express';
|
import type { RequestHandler } from 'express';
|
||||||
|
|
||||||
import { getRouteMetadata } from './controller.registry';
|
import { ControllerRegistryMetadata } from './controller-registry-metadata';
|
||||||
import type { Controller, Method, RateLimit } from './types';
|
import type { Controller, Method, RateLimit } from './types';
|
||||||
|
|
||||||
interface RouteOptions {
|
interface RouteOptions {
|
||||||
@@ -16,7 +17,10 @@ const RouteFactory =
|
|||||||
(method: Method) =>
|
(method: Method) =>
|
||||||
(path: `/${string}`, options: RouteOptions = {}): MethodDecorator =>
|
(path: `/${string}`, options: RouteOptions = {}): MethodDecorator =>
|
||||||
(target, handlerName) => {
|
(target, handlerName) => {
|
||||||
const routeMetadata = getRouteMetadata(target.constructor as Controller, String(handlerName));
|
const routeMetadata = Container.get(ControllerRegistryMetadata).getRouteMetadata(
|
||||||
|
target.constructor as Controller,
|
||||||
|
String(handlerName),
|
||||||
|
);
|
||||||
routeMetadata.method = method;
|
routeMetadata.method = method;
|
||||||
routeMetadata.path = path;
|
routeMetadata.path = path;
|
||||||
routeMetadata.middlewares = options.middlewares ?? [];
|
routeMetadata.middlewares = options.middlewares ?? [];
|
||||||
@@ -1,12 +1,16 @@
|
|||||||
|
import { Container } from '@n8n/di';
|
||||||
import type { Scope } from '@n8n/permissions';
|
import type { Scope } from '@n8n/permissions';
|
||||||
|
|
||||||
import { getRouteMetadata } from './controller.registry';
|
import { ControllerRegistryMetadata } from './controller-registry-metadata';
|
||||||
import type { Controller } from './types';
|
import type { Controller } from './types';
|
||||||
|
|
||||||
const Scoped =
|
const Scoped =
|
||||||
(scope: Scope, { globalOnly } = { globalOnly: false }): MethodDecorator =>
|
(scope: Scope, { globalOnly } = { globalOnly: false }): MethodDecorator =>
|
||||||
(target, handlerName) => {
|
(target, handlerName) => {
|
||||||
const routeMetadata = getRouteMetadata(target.constructor as Controller, String(handlerName));
|
const routeMetadata = Container.get(ControllerRegistryMetadata).getRouteMetadata(
|
||||||
|
target.constructor as Controller,
|
||||||
|
String(handlerName),
|
||||||
|
);
|
||||||
routeMetadata.accessScope = { scope, globalOnly };
|
routeMetadata.accessScope = { scope, globalOnly };
|
||||||
};
|
};
|
||||||
|
|
||||||
31
packages/@n8n/decorators/src/shutdown-registry-metadata.ts
Normal file
31
packages/@n8n/decorators/src/shutdown-registry-metadata.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { Service } from '@n8n/di';
|
||||||
|
import { UserError } from 'n8n-workflow';
|
||||||
|
|
||||||
|
import { HIGHEST_SHUTDOWN_PRIORITY, LOWEST_SHUTDOWN_PRIORITY } from './shutdown/constants';
|
||||||
|
import type { ShutdownHandler } from './types';
|
||||||
|
|
||||||
|
@Service()
|
||||||
|
export class ShutdownRegistryMetadata {
|
||||||
|
private handlersByPriority: ShutdownHandler[][] = [];
|
||||||
|
|
||||||
|
register(priority: number, handler: ShutdownHandler) {
|
||||||
|
if (priority < LOWEST_SHUTDOWN_PRIORITY || priority > HIGHEST_SHUTDOWN_PRIORITY) {
|
||||||
|
throw new UserError(
|
||||||
|
`Invalid shutdown priority. Please set it between ${LOWEST_SHUTDOWN_PRIORITY} and ${HIGHEST_SHUTDOWN_PRIORITY}.`,
|
||||||
|
{ extra: { priority } },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.handlersByPriority[priority]) this.handlersByPriority[priority] = [];
|
||||||
|
|
||||||
|
this.handlersByPriority[priority].push(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
getHandlersByPriority(): ShutdownHandler[][] {
|
||||||
|
return this.handlersByPriority;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.handlersByPriority = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
3
packages/@n8n/decorators/src/shutdown/constants.ts
Normal file
3
packages/@n8n/decorators/src/shutdown/constants.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export const LOWEST_SHUTDOWN_PRIORITY = 0;
|
||||||
|
export const DEFAULT_SHUTDOWN_PRIORITY = 100;
|
||||||
|
export const HIGHEST_SHUTDOWN_PRIORITY = 200;
|
||||||
@@ -47,3 +47,14 @@ export interface ControllerMetadata {
|
|||||||
|
|
||||||
export type Controller = Constructable<object> &
|
export type Controller = Constructable<object> &
|
||||||
Record<HandlerName, (...args: unknown[]) => Promise<unknown>>;
|
Record<HandlerName, (...args: unknown[]) => Promise<unknown>>;
|
||||||
|
|
||||||
|
type RouteHandlerFn = () => Promise<void> | void;
|
||||||
|
|
||||||
|
type Class<T = object, A extends unknown[] = unknown[]> = new (...args: A) => T;
|
||||||
|
|
||||||
|
export type ServiceClass = Class<Record<string, RouteHandlerFn>>;
|
||||||
|
|
||||||
|
export interface ShutdownHandler {
|
||||||
|
serviceClass: ServiceClass;
|
||||||
|
methodName: string;
|
||||||
|
}
|
||||||
11
packages/@n8n/decorators/tsconfig.build.json
Normal file
11
packages/@n8n/decorators/tsconfig.build.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"extends": ["./tsconfig.json", "@n8n/typescript-config/tsconfig.build.json"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"rootDir": "src",
|
||||||
|
"outDir": "dist",
|
||||||
|
"tsBuildInfoFile": "dist/build.tsbuildinfo"
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts"],
|
||||||
|
"exclude": ["src/**/__tests__/**"]
|
||||||
|
}
|
||||||
12
packages/@n8n/decorators/tsconfig.json
Normal file
12
packages/@n8n/decorators/tsconfig.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"extends": "@n8n/typescript-config/tsconfig.common.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"rootDir": ".",
|
||||||
|
"types": ["node", "jest"],
|
||||||
|
"baseUrl": "src",
|
||||||
|
"tsBuildInfoFile": "dist/typecheck.tsbuildinfo",
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"emitDecoratorMetadata": true
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts"]
|
||||||
|
}
|
||||||
@@ -93,6 +93,7 @@
|
|||||||
"@n8n/client-oauth2": "workspace:*",
|
"@n8n/client-oauth2": "workspace:*",
|
||||||
"@n8n/config": "workspace:*",
|
"@n8n/config": "workspace:*",
|
||||||
"@n8n/constants": "workspace:^",
|
"@n8n/constants": "workspace:^",
|
||||||
|
"@n8n/decorators": "workspace:*",
|
||||||
"@n8n/di": "workspace:*",
|
"@n8n/di": "workspace:*",
|
||||||
"@n8n/localtunnel": "3.0.0",
|
"@n8n/localtunnel": "3.0.0",
|
||||||
"@n8n/n8n-nodes-langchain": "workspace:*",
|
"@n8n/n8n-nodes-langchain": "workspace:*",
|
||||||
|
|||||||
@@ -3,27 +3,30 @@ jest.mock('@/constants', () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
import type { GlobalConfig } from '@n8n/config';
|
import type { GlobalConfig } from '@n8n/config';
|
||||||
|
import { ControllerRegistryMetadata } from '@n8n/decorators';
|
||||||
|
import { Param } from '@n8n/decorators';
|
||||||
|
import { Get, Licensed, RestController } from '@n8n/decorators';
|
||||||
|
import { Container } from '@n8n/di';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { mock } from 'jest-mock-extended';
|
import { mock } from 'jest-mock-extended';
|
||||||
import { agent as testAgent } from 'supertest';
|
import { agent as testAgent } from 'supertest';
|
||||||
|
|
||||||
import type { AuthService } from '@/auth/auth.service';
|
import type { AuthService } from '@/auth/auth.service';
|
||||||
import { ControllerRegistry, Get, Licensed, RestController } from '@/decorators';
|
import { ControllerRegistry } from '@/controller.registry';
|
||||||
import type { License } from '@/license';
|
import type { License } from '@/license';
|
||||||
import type { SuperAgentTest } from '@test-integration/types';
|
import type { SuperAgentTest } from '@test-integration/types';
|
||||||
|
|
||||||
import { Param } from '../args';
|
|
||||||
|
|
||||||
describe('ControllerRegistry', () => {
|
describe('ControllerRegistry', () => {
|
||||||
const license = mock<License>();
|
const license = mock<License>();
|
||||||
const authService = mock<AuthService>();
|
const authService = mock<AuthService>();
|
||||||
const globalConfig = mock<GlobalConfig>({ endpoints: { rest: 'rest' } });
|
const globalConfig = mock<GlobalConfig>({ endpoints: { rest: 'rest' } });
|
||||||
|
const metadata = Container.get(ControllerRegistryMetadata);
|
||||||
let agent: SuperAgentTest;
|
let agent: SuperAgentTest;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.resetAllMocks();
|
jest.resetAllMocks();
|
||||||
const app = express();
|
const app = express();
|
||||||
new ControllerRegistry(license, authService, globalConfig).activate(app);
|
new ControllerRegistry(license, authService, globalConfig, metadata).activate(app);
|
||||||
agent = testAgent(app);
|
agent = testAgent(app);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { GlobalConfig } from '@n8n/config';
|
import { GlobalConfig } from '@n8n/config';
|
||||||
|
import { OnShutdown } from '@n8n/decorators';
|
||||||
import { Container, Service } from '@n8n/di';
|
import { Container, Service } from '@n8n/di';
|
||||||
import compression from 'compression';
|
import compression from 'compression';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
@@ -11,7 +12,6 @@ import { Logger } from 'n8n-core';
|
|||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import { N8N_VERSION, TEMPLATES_DIR, inDevelopment, inTest } from '@/constants';
|
import { N8N_VERSION, TEMPLATES_DIR, inDevelopment, inTest } from '@/constants';
|
||||||
import * as Db from '@/db';
|
import * as Db from '@/db';
|
||||||
import { OnShutdown } from '@/decorators/on-shutdown';
|
|
||||||
import { ExternalHooks } from '@/external-hooks';
|
import { ExternalHooks } from '@/external-hooks';
|
||||||
import { rawBodyReader, bodyParser, corsMiddleware } from '@/middlewares';
|
import { rawBodyReader, bodyParser, corsMiddleware } from '@/middlewares';
|
||||||
import { send, sendErrorResponse } from '@/response-helper';
|
import { send, sendErrorResponse } from '@/response-helper';
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
import { WorkflowsConfig } from '@n8n/config';
|
import { WorkflowsConfig } from '@n8n/config';
|
||||||
|
import { OnShutdown } from '@n8n/decorators';
|
||||||
import { Service } from '@n8n/di';
|
import { Service } from '@n8n/di';
|
||||||
import { chunk } from 'lodash';
|
import { chunk } from 'lodash';
|
||||||
import {
|
import {
|
||||||
@@ -42,7 +43,6 @@ import {
|
|||||||
} from '@/constants';
|
} from '@/constants';
|
||||||
import type { WorkflowEntity } from '@/databases/entities/workflow-entity';
|
import type { WorkflowEntity } from '@/databases/entities/workflow-entity';
|
||||||
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
|
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
|
||||||
import { OnShutdown } from '@/decorators/on-shutdown';
|
|
||||||
import { executeErrorWorkflow } from '@/execution-lifecycle/execute-error-workflow';
|
import { executeErrorWorkflow } from '@/execution-lifecycle/execute-error-workflow';
|
||||||
import { ExecutionService } from '@/executions/execution.service';
|
import { ExecutionService } from '@/executions/execution.service';
|
||||||
import { ExternalHooks } from '@/external-hooks';
|
import { ExternalHooks } from '@/external-hooks';
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'reflect-metadata';
|
import 'reflect-metadata';
|
||||||
import { GlobalConfig } from '@n8n/config';
|
import { GlobalConfig } from '@n8n/config';
|
||||||
import { LICENSE_FEATURES } from '@n8n/constants';
|
import { LICENSE_FEATURES } from '@n8n/constants';
|
||||||
|
import { ModuleRegistry } from '@n8n/decorators';
|
||||||
import { Container } from '@n8n/di';
|
import { Container } from '@n8n/di';
|
||||||
import { Command, Errors } from '@oclif/core';
|
import { Command, Errors } from '@oclif/core';
|
||||||
import {
|
import {
|
||||||
@@ -19,7 +20,6 @@ import config from '@/config';
|
|||||||
import { N8N_VERSION, N8N_RELEASE_DATE, inDevelopment, inTest } from '@/constants';
|
import { N8N_VERSION, N8N_RELEASE_DATE, inDevelopment, inTest } from '@/constants';
|
||||||
import * as CrashJournal from '@/crash-journal';
|
import * as CrashJournal from '@/crash-journal';
|
||||||
import * as Db from '@/db';
|
import * as Db from '@/db';
|
||||||
import { ModuleRegistry } from '@/decorators/module';
|
|
||||||
import { getDataDeduplicationService } from '@/deduplication';
|
import { getDataDeduplicationService } from '@/deduplication';
|
||||||
import { DeprecationService } from '@/deprecation/deprecation.service';
|
import { DeprecationService } from '@/deprecation/deprecation.service';
|
||||||
import { TestRunnerService } from '@/evaluation.ee/test-runner/test-runner.service.ee';
|
import { TestRunnerService } from '@/evaluation.ee/test-runner/test-runner.service.ee';
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { GlobalConfig } from '@n8n/config';
|
import { GlobalConfig } from '@n8n/config';
|
||||||
import type { BooleanLicenseFeature } from '@n8n/constants';
|
import type { BooleanLicenseFeature } from '@n8n/constants';
|
||||||
|
import { ControllerRegistryMetadata } from '@n8n/decorators';
|
||||||
|
import type { AccessScope, Controller, RateLimit } from '@n8n/decorators';
|
||||||
import { Container, Service } from '@n8n/di';
|
import { Container, Service } from '@n8n/di';
|
||||||
import { Router } from 'express';
|
import { Router } from 'express';
|
||||||
import type { Application, Request, Response, RequestHandler } from 'express';
|
import type { Application, Request, Response, RequestHandler } from 'express';
|
||||||
@@ -15,57 +17,23 @@ import { userHasScopes } from '@/permissions.ee/check-access';
|
|||||||
import type { AuthenticatedRequest } from '@/requests';
|
import type { AuthenticatedRequest } from '@/requests';
|
||||||
import { send } from '@/response-helper'; // TODO: move `ResponseHelper.send` to this file
|
import { send } from '@/response-helper'; // TODO: move `ResponseHelper.send` to this file
|
||||||
|
|
||||||
import type {
|
|
||||||
AccessScope,
|
|
||||||
Controller,
|
|
||||||
ControllerMetadata,
|
|
||||||
HandlerName,
|
|
||||||
RateLimit,
|
|
||||||
RouteMetadata,
|
|
||||||
} from './types';
|
|
||||||
|
|
||||||
const registry = new Map<Controller, ControllerMetadata>();
|
|
||||||
|
|
||||||
export const getControllerMetadata = (controllerClass: Controller) => {
|
|
||||||
let metadata = registry.get(controllerClass);
|
|
||||||
if (!metadata) {
|
|
||||||
metadata = {
|
|
||||||
basePath: '/',
|
|
||||||
middlewares: [],
|
|
||||||
routes: new Map(),
|
|
||||||
};
|
|
||||||
registry.set(controllerClass, metadata);
|
|
||||||
}
|
|
||||||
return metadata;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getRouteMetadata = (controllerClass: Controller, handlerName: HandlerName) => {
|
|
||||||
const metadata = getControllerMetadata(controllerClass);
|
|
||||||
let route = metadata.routes.get(handlerName);
|
|
||||||
if (!route) {
|
|
||||||
route = {} as RouteMetadata;
|
|
||||||
route.args = [];
|
|
||||||
metadata.routes.set(handlerName, route);
|
|
||||||
}
|
|
||||||
return route;
|
|
||||||
};
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class ControllerRegistry {
|
export class ControllerRegistry {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly license: License,
|
private readonly license: License,
|
||||||
private readonly authService: AuthService,
|
private readonly authService: AuthService,
|
||||||
private readonly globalConfig: GlobalConfig,
|
private readonly globalConfig: GlobalConfig,
|
||||||
|
private readonly metadata: ControllerRegistryMetadata,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
activate(app: Application) {
|
activate(app: Application) {
|
||||||
for (const controllerClass of registry.keys()) {
|
for (const controllerClass of this.metadata.controllerClasses) {
|
||||||
this.activateController(app, controllerClass);
|
this.activateController(app, controllerClass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private activateController(app: Application, controllerClass: Controller) {
|
private activateController(app: Application, controllerClass: Controller) {
|
||||||
const metadata = registry.get(controllerClass)!;
|
const metadata = this.metadata.getControllerMetadata(controllerClass);
|
||||||
|
|
||||||
const router = Router({ mergeParams: true });
|
const router = Router({ mergeParams: true });
|
||||||
const prefix = `/${this.globalConfig.endpoints.rest}/${metadata.basePath}`
|
const prefix = `/${this.globalConfig.endpoints.rest}/${metadata.basePath}`
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Get, RestController } from '@/decorators';
|
import { Get, RestController } from '@n8n/decorators';
|
||||||
|
|
||||||
import { ActiveWorkflowRequest } from '@/requests';
|
import { ActiveWorkflowRequest } from '@/requests';
|
||||||
import { ActiveWorkflowsService } from '@/services/active-workflows.service';
|
import { ActiveWorkflowsService } from '@/services/active-workflows.service';
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
AiAskRequestDto,
|
AiAskRequestDto,
|
||||||
AiFreeCreditsRequestDto,
|
AiFreeCreditsRequestDto,
|
||||||
} from '@n8n/api-types';
|
} from '@n8n/api-types';
|
||||||
|
import { Body, Post, RestController } from '@n8n/decorators';
|
||||||
import type { AiAssistantSDK } from '@n8n_io/ai-assistant-sdk';
|
import type { AiAssistantSDK } from '@n8n_io/ai-assistant-sdk';
|
||||||
import { Response } from 'express';
|
import { Response } from 'express';
|
||||||
import { OPEN_AI_API_CREDENTIAL_TYPE } from 'n8n-workflow';
|
import { OPEN_AI_API_CREDENTIAL_TYPE } from 'n8n-workflow';
|
||||||
@@ -13,7 +14,6 @@ import { WritableStream } from 'node:stream/web';
|
|||||||
|
|
||||||
import { FREE_AI_CREDITS_CREDENTIAL_NAME } from '@/constants';
|
import { FREE_AI_CREDITS_CREDENTIAL_NAME } from '@/constants';
|
||||||
import { CredentialsService } from '@/credentials/credentials.service';
|
import { CredentialsService } from '@/credentials/credentials.service';
|
||||||
import { Body, Post, RestController } from '@/decorators';
|
|
||||||
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
|
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
|
||||||
import { AuthenticatedRequest } from '@/requests';
|
import { AuthenticatedRequest } from '@/requests';
|
||||||
import { AiService } from '@/services/ai.service';
|
import { AiService } from '@/services/ai.service';
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Delete, Get, Patch, Post, RestController, GlobalScope } from '@/decorators';
|
import { Delete, Get, Patch, Post, RestController, GlobalScope } from '@n8n/decorators';
|
||||||
|
|
||||||
import { AnnotationTagsRequest } from '@/requests';
|
import { AnnotationTagsRequest } from '@/requests';
|
||||||
import { AnnotationTagService } from '@/services/annotation-tag.service.ee';
|
import { AnnotationTagService } from '@/services/annotation-tag.service.ee';
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { CreateApiKeyRequestDto, UpdateApiKeyRequestDto } from '@n8n/api-types';
|
import { CreateApiKeyRequestDto, UpdateApiKeyRequestDto } from '@n8n/api-types';
|
||||||
|
import { Body, Delete, Get, Param, Patch, Post, RestController } from '@n8n/decorators';
|
||||||
import type { RequestHandler } from 'express';
|
import type { RequestHandler } from 'express';
|
||||||
|
|
||||||
import { Body, Delete, Get, Param, Patch, Post, RestController } from '@/decorators';
|
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { EventService } from '@/events/event.service';
|
import { EventService } from '@/events/event.service';
|
||||||
import { isApiEnabled } from '@/public-api';
|
import { isApiEnabled } from '@/public-api';
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { LoginRequestDto, ResolveSignupTokenQueryDto } from '@n8n/api-types';
|
import { LoginRequestDto, ResolveSignupTokenQueryDto } from '@n8n/api-types';
|
||||||
|
import { Body, Get, Post, Query, RestController } from '@n8n/decorators';
|
||||||
import { isEmail } from 'class-validator';
|
import { isEmail } from 'class-validator';
|
||||||
import { Response } from 'express';
|
import { Response } from 'express';
|
||||||
import { Logger } from 'n8n-core';
|
import { Logger } from 'n8n-core';
|
||||||
@@ -8,7 +9,6 @@ import { AuthService } from '@/auth/auth.service';
|
|||||||
import { RESPONSE_ERROR_MESSAGES } from '@/constants';
|
import { RESPONSE_ERROR_MESSAGES } from '@/constants';
|
||||||
import type { User } from '@/databases/entities/user';
|
import type { User } from '@/databases/entities/user';
|
||||||
import { UserRepository } from '@/databases/repositories/user.repository';
|
import { UserRepository } from '@/databases/repositories/user.repository';
|
||||||
import { Body, Get, Post, Query, RestController } from '@/decorators';
|
|
||||||
import { AuthError } from '@/errors/response-errors/auth.error';
|
import { AuthError } from '@/errors/response-errors/auth.error';
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
|
import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { BinaryDataQueryDto, BinaryDataSignedQueryDto, ViewableMimeTypes } from '@n8n/api-types';
|
import { BinaryDataQueryDto, BinaryDataSignedQueryDto, ViewableMimeTypes } from '@n8n/api-types';
|
||||||
|
import { Get, Query, RestController } from '@n8n/decorators';
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import { JsonWebTokenError } from 'jsonwebtoken';
|
import { JsonWebTokenError } from 'jsonwebtoken';
|
||||||
import { BinaryDataService, FileNotFoundError, isValidNonDefaultMode } from 'n8n-core';
|
import { BinaryDataService, FileNotFoundError, isValidNonDefaultMode } from 'n8n-core';
|
||||||
|
|
||||||
import { Get, Query, RestController } from '@/decorators';
|
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
|
|
||||||
@RestController('/binary-data')
|
@RestController('/binary-data')
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
|
import { Delete, Get, Patch, Post, RestController, GlobalScope } from '@n8n/decorators';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
RESPONSE_ERROR_MESSAGES,
|
RESPONSE_ERROR_MESSAGES,
|
||||||
STARTER_TEMPLATE_NAME,
|
STARTER_TEMPLATE_NAME,
|
||||||
UNKNOWN_FAILURE_REASON,
|
UNKNOWN_FAILURE_REASON,
|
||||||
} from '@/constants';
|
} from '@/constants';
|
||||||
import type { InstalledPackages } from '@/databases/entities/installed-packages';
|
import type { InstalledPackages } from '@/databases/entities/installed-packages';
|
||||||
import { Delete, Get, Patch, Post, RestController, GlobalScope } from '@/decorators';
|
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
|
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
|
||||||
import { EventService } from '@/events/event.service';
|
import { EventService } from '@/events/event.service';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import { Get, RestController } from '@n8n/decorators';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
|
|
||||||
import { Get, RestController } from '@/decorators';
|
|
||||||
import { AuthenticatedRequest } from '@/requests';
|
import { AuthenticatedRequest } from '@/requests';
|
||||||
import { CtaService } from '@/services/cta.service';
|
import { CtaService } from '@/services/cta.service';
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
import { Get, RestController } from '@n8n/decorators';
|
||||||
import { InstanceSettings } from 'n8n-core';
|
import { InstanceSettings } from 'n8n-core';
|
||||||
|
|
||||||
import { ActiveWorkflowManager } from '@/active-workflow-manager';
|
import { ActiveWorkflowManager } from '@/active-workflow-manager';
|
||||||
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
|
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
|
||||||
import { Get, RestController } from '@/decorators';
|
|
||||||
import { OrchestrationService } from '@/services/orchestration.service';
|
import { OrchestrationService } from '@/services/orchestration.service';
|
||||||
|
|
||||||
@RestController('/debug')
|
@RestController('/debug')
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import {
|
|||||||
ResourceMapperFieldsRequestDto,
|
ResourceMapperFieldsRequestDto,
|
||||||
ActionResultRequestDto,
|
ActionResultRequestDto,
|
||||||
} from '@n8n/api-types';
|
} from '@n8n/api-types';
|
||||||
|
import { Post, RestController, Body } from '@n8n/decorators';
|
||||||
import type { INodePropertyOptions, NodeParameterValueType } from 'n8n-workflow';
|
import type { INodePropertyOptions, NodeParameterValueType } from 'n8n-workflow';
|
||||||
|
|
||||||
import { Post, RestController, Body } from '@/decorators';
|
|
||||||
import { AuthenticatedRequest } from '@/requests';
|
import { AuthenticatedRequest } from '@/requests';
|
||||||
import { DynamicNodeParametersService } from '@/services/dynamic-node-parameters.service';
|
import { DynamicNodeParametersService } from '@/services/dynamic-node-parameters.service';
|
||||||
import { getBase } from '@/workflow-execute-additional-data';
|
import { getBase } from '@/workflow-execute-additional-data';
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { PushMessage } from '@n8n/api-types';
|
import type { PushMessage } from '@n8n/api-types';
|
||||||
import type { BooleanLicenseFeature, NumericLicenseFeature } from '@n8n/constants';
|
import type { BooleanLicenseFeature, NumericLicenseFeature } from '@n8n/constants';
|
||||||
import { LICENSE_FEATURES, LICENSE_QUOTAS, UNLIMITED_LICENSE_QUOTA } from '@n8n/constants';
|
import { LICENSE_FEATURES, LICENSE_QUOTAS, UNLIMITED_LICENSE_QUOTA } from '@n8n/constants';
|
||||||
|
import { Patch, Post, RestController } from '@n8n/decorators';
|
||||||
import { Container } from '@n8n/di';
|
import { Container } from '@n8n/di';
|
||||||
import { Request } from 'express';
|
import { Request } from 'express';
|
||||||
import { Logger } from 'n8n-core';
|
import { Logger } from 'n8n-core';
|
||||||
@@ -12,7 +13,6 @@ import { inE2ETests } from '@/constants';
|
|||||||
import { AuthUserRepository } from '@/databases/repositories/auth-user.repository';
|
import { AuthUserRepository } from '@/databases/repositories/auth-user.repository';
|
||||||
import { SettingsRepository } from '@/databases/repositories/settings.repository';
|
import { SettingsRepository } from '@/databases/repositories/settings.repository';
|
||||||
import { UserRepository } from '@/databases/repositories/user.repository';
|
import { UserRepository } from '@/databases/repositories/user.repository';
|
||||||
import { Patch, Post, RestController } from '@/decorators';
|
|
||||||
import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus';
|
import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus';
|
||||||
import type { FeatureReturnType } from '@/license';
|
import type { FeatureReturnType } from '@/license';
|
||||||
import { License } from '@/license';
|
import { License } from '@/license';
|
||||||
|
|||||||
@@ -4,10 +4,19 @@ import {
|
|||||||
ListFolderQueryDto,
|
ListFolderQueryDto,
|
||||||
UpdateFolderDto,
|
UpdateFolderDto,
|
||||||
} from '@n8n/api-types';
|
} from '@n8n/api-types';
|
||||||
|
import {
|
||||||
|
Post,
|
||||||
|
RestController,
|
||||||
|
ProjectScope,
|
||||||
|
Body,
|
||||||
|
Get,
|
||||||
|
Patch,
|
||||||
|
Delete,
|
||||||
|
Query,
|
||||||
|
} from '@n8n/decorators';
|
||||||
import { Response } from 'express';
|
import { Response } from 'express';
|
||||||
import { UserError } from 'n8n-workflow';
|
import { UserError } from 'n8n-workflow';
|
||||||
|
|
||||||
import { Post, RestController, ProjectScope, Body, Get, Patch, Delete, Query } from '@/decorators';
|
|
||||||
import { FolderNotFoundError } from '@/errors/folder-not-found.error';
|
import { FolderNotFoundError } from '@/errors/folder-not-found.error';
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
|
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { AcceptInvitationRequestDto, InviteUsersRequestDto } from '@n8n/api-types';
|
import { AcceptInvitationRequestDto, InviteUsersRequestDto } from '@n8n/api-types';
|
||||||
|
import { Post, GlobalScope, RestController, Body, Param } from '@n8n/decorators';
|
||||||
import { Response } from 'express';
|
import { Response } from 'express';
|
||||||
import { Logger } from 'n8n-core';
|
import { Logger } from 'n8n-core';
|
||||||
|
|
||||||
@@ -7,7 +8,6 @@ import config from '@/config';
|
|||||||
import { RESPONSE_ERROR_MESSAGES } from '@/constants';
|
import { RESPONSE_ERROR_MESSAGES } from '@/constants';
|
||||||
import type { User } from '@/databases/entities/user';
|
import type { User } from '@/databases/entities/user';
|
||||||
import { UserRepository } from '@/databases/repositories/user.repository';
|
import { UserRepository } from '@/databases/repositories/user.repository';
|
||||||
import { Post, GlobalScope, RestController, Body, Param } from '@/decorators';
|
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
|
import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
|
||||||
import { EventService } from '@/events/event.service';
|
import { EventService } from '@/events/event.service';
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
SettingsUpdateRequestDto,
|
SettingsUpdateRequestDto,
|
||||||
UserUpdateRequestDto,
|
UserUpdateRequestDto,
|
||||||
} from '@n8n/api-types';
|
} from '@n8n/api-types';
|
||||||
|
import { Body, Patch, Post, RestController } from '@n8n/decorators';
|
||||||
import { plainToInstance } from 'class-transformer';
|
import { plainToInstance } from 'class-transformer';
|
||||||
import { Response } from 'express';
|
import { Response } from 'express';
|
||||||
import { Logger } from 'n8n-core';
|
import { Logger } from 'n8n-core';
|
||||||
@@ -11,7 +12,6 @@ import { Logger } from 'n8n-core';
|
|||||||
import { AuthService } from '@/auth/auth.service';
|
import { AuthService } from '@/auth/auth.service';
|
||||||
import type { User } from '@/databases/entities/user';
|
import type { User } from '@/databases/entities/user';
|
||||||
import { UserRepository } from '@/databases/repositories/user.repository';
|
import { UserRepository } from '@/databases/repositories/user.repository';
|
||||||
import { Body, Patch, Post, RestController } from '@/decorators';
|
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { InvalidMfaCodeError } from '@/errors/response-errors/invalid-mfa-code.error';
|
import { InvalidMfaCodeError } from '@/errors/response-errors/invalid-mfa-code.error';
|
||||||
import { EventService } from '@/events/event.service';
|
import { EventService } from '@/events/event.service';
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Get, Post, RestController } from '@/decorators';
|
import { Get, Post, RestController } from '@n8n/decorators';
|
||||||
|
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { ExternalHooks } from '@/external-hooks';
|
import { ExternalHooks } from '@/external-hooks';
|
||||||
import { MfaService } from '@/mfa/mfa.service';
|
import { MfaService } from '@/mfa/mfa.service';
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
|
import { Post, RestController } from '@n8n/decorators';
|
||||||
import { Request } from 'express';
|
import { Request } from 'express';
|
||||||
import { readFile } from 'fs/promises';
|
import { readFile } from 'fs/promises';
|
||||||
import get from 'lodash/get';
|
import get from 'lodash/get';
|
||||||
import type { INodeTypeDescription, INodeTypeNameVersion } from 'n8n-workflow';
|
import type { INodeTypeDescription, INodeTypeNameVersion } from 'n8n-workflow';
|
||||||
|
|
||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import { Post, RestController } from '@/decorators';
|
|
||||||
import { NodeTypes } from '@/node-types';
|
import { NodeTypes } from '@/node-types';
|
||||||
|
|
||||||
@RestController('/node-types')
|
@RestController('/node-types')
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Get, RestController } from '@n8n/decorators';
|
||||||
import type { AxiosRequestConfig } from 'axios';
|
import type { AxiosRequestConfig } from 'axios';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { createHmac } from 'crypto';
|
import { createHmac } from 'crypto';
|
||||||
@@ -6,7 +7,6 @@ import { ensureError, jsonStringify } from 'n8n-workflow';
|
|||||||
import type { RequestOptions } from 'oauth-1.0a';
|
import type { RequestOptions } from 'oauth-1.0a';
|
||||||
import clientOAuth1 from 'oauth-1.0a';
|
import clientOAuth1 from 'oauth-1.0a';
|
||||||
|
|
||||||
import { Get, RestController } from '@/decorators';
|
|
||||||
import { OAuthRequest } from '@/requests';
|
import { OAuthRequest } from '@/requests';
|
||||||
|
|
||||||
import { AbstractOAuthController, skipAuthOnOAuthCallback } from './abstract-oauth.controller';
|
import { AbstractOAuthController, skipAuthOnOAuthCallback } from './abstract-oauth.controller';
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { ClientOAuth2Options, OAuth2CredentialData } from '@n8n/client-oauth2';
|
import type { ClientOAuth2Options, OAuth2CredentialData } from '@n8n/client-oauth2';
|
||||||
import { ClientOAuth2 } from '@n8n/client-oauth2';
|
import { ClientOAuth2 } from '@n8n/client-oauth2';
|
||||||
|
import { Get, RestController } from '@n8n/decorators';
|
||||||
import { Response } from 'express';
|
import { Response } from 'express';
|
||||||
import omit from 'lodash/omit';
|
import omit from 'lodash/omit';
|
||||||
import set from 'lodash/set';
|
import set from 'lodash/set';
|
||||||
@@ -9,7 +10,6 @@ import pkceChallenge from 'pkce-challenge';
|
|||||||
import * as qs from 'querystring';
|
import * as qs from 'querystring';
|
||||||
|
|
||||||
import { GENERIC_OAUTH2_CREDENTIALS_WITH_EDITABLE_SCOPE as GENERIC_OAUTH2_CREDENTIALS_WITH_EDITABLE_SCOPE } from '@/constants';
|
import { GENERIC_OAUTH2_CREDENTIALS_WITH_EDITABLE_SCOPE as GENERIC_OAUTH2_CREDENTIALS_WITH_EDITABLE_SCOPE } from '@/constants';
|
||||||
import { Get, RestController } from '@/decorators';
|
|
||||||
import { OAuthRequest } from '@/requests';
|
import { OAuthRequest } from '@/requests';
|
||||||
|
|
||||||
import { AbstractOAuthController, skipAuthOnOAuthCallback } from './abstract-oauth.controller';
|
import { AbstractOAuthController, skipAuthOnOAuthCallback } from './abstract-oauth.controller';
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Post, RestController, GlobalScope } from '@/decorators';
|
import { Post, RestController, GlobalScope } from '@n8n/decorators';
|
||||||
|
|
||||||
import { License } from '@/license';
|
import { License } from '@/license';
|
||||||
import { Publisher } from '@/scaling/pubsub/publisher.service';
|
import { Publisher } from '@/scaling/pubsub/publisher.service';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { DismissBannerRequestDto, OwnerSetupRequestDto } from '@n8n/api-types';
|
import { DismissBannerRequestDto, OwnerSetupRequestDto } from '@n8n/api-types';
|
||||||
|
import { Body, GlobalScope, Post, RestController } from '@n8n/decorators';
|
||||||
import { Response } from 'express';
|
import { Response } from 'express';
|
||||||
import { Logger } from 'n8n-core';
|
import { Logger } from 'n8n-core';
|
||||||
|
|
||||||
@@ -6,7 +7,6 @@ import { AuthService } from '@/auth/auth.service';
|
|||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import { SettingsRepository } from '@/databases/repositories/settings.repository';
|
import { SettingsRepository } from '@/databases/repositories/settings.repository';
|
||||||
import { UserRepository } from '@/databases/repositories/user.repository';
|
import { UserRepository } from '@/databases/repositories/user.repository';
|
||||||
import { Body, GlobalScope, Post, RestController } from '@/decorators';
|
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { EventService } from '@/events/event.service';
|
import { EventService } from '@/events/event.service';
|
||||||
import { validateEntity } from '@/generic-helpers';
|
import { validateEntity } from '@/generic-helpers';
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ import {
|
|||||||
ForgotPasswordRequestDto,
|
ForgotPasswordRequestDto,
|
||||||
ResolvePasswordTokenQueryDto,
|
ResolvePasswordTokenQueryDto,
|
||||||
} from '@n8n/api-types';
|
} from '@n8n/api-types';
|
||||||
|
import { Body, Get, Post, Query, RestController } from '@n8n/decorators';
|
||||||
import { Response } from 'express';
|
import { Response } from 'express';
|
||||||
import { Logger } from 'n8n-core';
|
import { Logger } from 'n8n-core';
|
||||||
|
|
||||||
import { AuthService } from '@/auth/auth.service';
|
import { AuthService } from '@/auth/auth.service';
|
||||||
import { RESPONSE_ERROR_MESSAGES } from '@/constants';
|
import { RESPONSE_ERROR_MESSAGES } from '@/constants';
|
||||||
import { UserRepository } from '@/databases/repositories/user.repository';
|
import { UserRepository } from '@/databases/repositories/user.repository';
|
||||||
import { Body, Get, Post, Query, RestController } from '@/decorators';
|
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
|
import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
|
||||||
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
|
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
|
||||||
|
|||||||
@@ -1,12 +1,4 @@
|
|||||||
import { CreateProjectDto, DeleteProjectDto, UpdateProjectDto } from '@n8n/api-types';
|
import { CreateProjectDto, DeleteProjectDto, UpdateProjectDto } from '@n8n/api-types';
|
||||||
import { combineScopes } from '@n8n/permissions';
|
|
||||||
import type { Scope } from '@n8n/permissions';
|
|
||||||
// eslint-disable-next-line n8n-local-rules/misplaced-n8n-typeorm-import
|
|
||||||
import { In, Not } from '@n8n/typeorm';
|
|
||||||
import { Response } from 'express';
|
|
||||||
|
|
||||||
import type { Project } from '@/databases/entities/project';
|
|
||||||
import { ProjectRepository } from '@/databases/repositories/project.repository';
|
|
||||||
import {
|
import {
|
||||||
Get,
|
Get,
|
||||||
Post,
|
Post,
|
||||||
@@ -19,7 +11,15 @@ import {
|
|||||||
Body,
|
Body,
|
||||||
Param,
|
Param,
|
||||||
Query,
|
Query,
|
||||||
} from '@/decorators';
|
} from '@n8n/decorators';
|
||||||
|
import { combineScopes } from '@n8n/permissions';
|
||||||
|
import type { Scope } from '@n8n/permissions';
|
||||||
|
// eslint-disable-next-line n8n-local-rules/misplaced-n8n-typeorm-import
|
||||||
|
import { In, Not } from '@n8n/typeorm';
|
||||||
|
import { Response } from 'express';
|
||||||
|
|
||||||
|
import type { Project } from '@/databases/entities/project';
|
||||||
|
import { ProjectRepository } from '@/databases/repositories/project.repository';
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||||
import { EventService } from '@/events/event.service';
|
import { EventService } from '@/events/event.service';
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Get, RestController } from '@/decorators';
|
import { Get, RestController } from '@n8n/decorators';
|
||||||
|
|
||||||
import { type AllRoleTypes, RoleService } from '@/services/role.service';
|
import { type AllRoleTypes, RoleService } from '@/services/role.service';
|
||||||
|
|
||||||
@RestController('/roles')
|
@RestController('/roles')
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import { CreateOrUpdateTagRequestDto, RetrieveTagQueryDto } from '@n8n/api-types';
|
import { CreateOrUpdateTagRequestDto, RetrieveTagQueryDto } from '@n8n/api-types';
|
||||||
import { Response } from 'express';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Delete,
|
Delete,
|
||||||
Get,
|
Get,
|
||||||
@@ -11,7 +9,9 @@ import {
|
|||||||
Body,
|
Body,
|
||||||
Param,
|
Param,
|
||||||
Query,
|
Query,
|
||||||
} from '@/decorators';
|
} from '@n8n/decorators';
|
||||||
|
import { Response } from 'express';
|
||||||
|
|
||||||
import { AuthenticatedRequest } from '@/requests';
|
import { AuthenticatedRequest } from '@/requests';
|
||||||
import { TagService } from '@/services/tag.service';
|
import { TagService } from '@/services/tag.service';
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Get, RestController } from '@n8n/decorators';
|
||||||
import type { Request } from 'express';
|
import type { Request } from 'express';
|
||||||
import { access } from 'fs/promises';
|
import { access } from 'fs/promises';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
@@ -5,7 +6,6 @@ import { join } from 'path';
|
|||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import { NODES_BASE_DIR } from '@/constants';
|
import { NODES_BASE_DIR } from '@/constants';
|
||||||
import { CredentialTypes } from '@/credential-types';
|
import { CredentialTypes } from '@/credential-types';
|
||||||
import { Get, RestController } from '@/decorators';
|
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
|
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import { Patch, RestController } from '@n8n/decorators';
|
||||||
import type { NpsSurveyState } from 'n8n-workflow';
|
import type { NpsSurveyState } from 'n8n-workflow';
|
||||||
|
|
||||||
import { Patch, RestController } from '@/decorators';
|
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { NpsSurveyRequest } from '@/requests';
|
import { NpsSurveyRequest } from '@/requests';
|
||||||
import { UserService } from '@/services/user.service';
|
import { UserService } from '@/services/user.service';
|
||||||
|
|||||||
@@ -1,4 +1,14 @@
|
|||||||
import { RoleChangeRequestDto, SettingsUpdateRequestDto } from '@n8n/api-types';
|
import { RoleChangeRequestDto, SettingsUpdateRequestDto } from '@n8n/api-types';
|
||||||
|
import {
|
||||||
|
GlobalScope,
|
||||||
|
Delete,
|
||||||
|
Get,
|
||||||
|
RestController,
|
||||||
|
Patch,
|
||||||
|
Licensed,
|
||||||
|
Body,
|
||||||
|
Param,
|
||||||
|
} from '@n8n/decorators';
|
||||||
import { Response } from 'express';
|
import { Response } from 'express';
|
||||||
import { Logger } from 'n8n-core';
|
import { Logger } from 'n8n-core';
|
||||||
|
|
||||||
@@ -11,16 +21,6 @@ import { ProjectRepository } from '@/databases/repositories/project.repository';
|
|||||||
import { SharedCredentialsRepository } from '@/databases/repositories/shared-credentials.repository';
|
import { SharedCredentialsRepository } from '@/databases/repositories/shared-credentials.repository';
|
||||||
import { SharedWorkflowRepository } from '@/databases/repositories/shared-workflow.repository';
|
import { SharedWorkflowRepository } from '@/databases/repositories/shared-workflow.repository';
|
||||||
import { UserRepository } from '@/databases/repositories/user.repository';
|
import { UserRepository } from '@/databases/repositories/user.repository';
|
||||||
import {
|
|
||||||
GlobalScope,
|
|
||||||
Delete,
|
|
||||||
Get,
|
|
||||||
RestController,
|
|
||||||
Patch,
|
|
||||||
Licensed,
|
|
||||||
Body,
|
|
||||||
Param,
|
|
||||||
} from '@/decorators';
|
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
|
import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
|
||||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Get, Middleware, RestController } from '@n8n/decorators';
|
||||||
import { Response, NextFunction } from 'express';
|
import { Response, NextFunction } from 'express';
|
||||||
import { Logger } from 'n8n-core';
|
import { Logger } from 'n8n-core';
|
||||||
|
|
||||||
@@ -5,7 +6,6 @@ import type { WorkflowStatistics } from '@/databases/entities/workflow-statistic
|
|||||||
import { StatisticsNames } from '@/databases/entities/workflow-statistics';
|
import { StatisticsNames } from '@/databases/entities/workflow-statistics';
|
||||||
import { SharedWorkflowRepository } from '@/databases/repositories/shared-workflow.repository';
|
import { SharedWorkflowRepository } from '@/databases/repositories/shared-workflow.repository';
|
||||||
import { WorkflowStatisticsRepository } from '@/databases/repositories/workflow-statistics.repository';
|
import { WorkflowStatisticsRepository } from '@/databases/repositories/workflow-statistics.repository';
|
||||||
import { Get, Middleware, RestController } from '@/decorators';
|
|
||||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||||
import type { IWorkflowStatisticsDataLoaded } from '@/interfaces';
|
import type { IWorkflowStatisticsDataLoaded } from '@/interfaces';
|
||||||
|
|
||||||
|
|||||||
@@ -5,17 +5,6 @@ import {
|
|||||||
GenerateCredentialNameRequestQuery,
|
GenerateCredentialNameRequestQuery,
|
||||||
} from '@n8n/api-types';
|
} from '@n8n/api-types';
|
||||||
import { GlobalConfig } from '@n8n/config';
|
import { GlobalConfig } from '@n8n/config';
|
||||||
// eslint-disable-next-line n8n-local-rules/misplaced-n8n-typeorm-import
|
|
||||||
import { In } from '@n8n/typeorm';
|
|
||||||
import { Logger } from 'n8n-core';
|
|
||||||
import type { ICredentialDataDecryptedObject } from 'n8n-workflow';
|
|
||||||
import { deepCopy } from 'n8n-workflow';
|
|
||||||
import { z } from 'zod';
|
|
||||||
|
|
||||||
import { SharedCredentials } from '@/databases/entities/shared-credentials';
|
|
||||||
import { ProjectRelationRepository } from '@/databases/repositories/project-relation.repository';
|
|
||||||
import { SharedCredentialsRepository } from '@/databases/repositories/shared-credentials.repository';
|
|
||||||
import * as Db from '@/db';
|
|
||||||
import {
|
import {
|
||||||
Delete,
|
Delete,
|
||||||
Get,
|
Get,
|
||||||
@@ -25,8 +14,21 @@ import {
|
|||||||
Put,
|
Put,
|
||||||
RestController,
|
RestController,
|
||||||
ProjectScope,
|
ProjectScope,
|
||||||
} from '@/decorators';
|
Body,
|
||||||
import { Body, Param, Query } from '@/decorators/args';
|
Param,
|
||||||
|
Query,
|
||||||
|
} from '@n8n/decorators';
|
||||||
|
// eslint-disable-next-line n8n-local-rules/misplaced-n8n-typeorm-import
|
||||||
|
import { In } from '@n8n/typeorm';
|
||||||
|
import { Logger } from 'n8n-core';
|
||||||
|
import { deepCopy } from 'n8n-workflow';
|
||||||
|
import type { ICredentialDataDecryptedObject } from 'n8n-workflow';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
import { SharedCredentials } from '@/databases/entities/shared-credentials';
|
||||||
|
import { ProjectRelationRepository } from '@/databases/repositories/project-relation.repository';
|
||||||
|
import { SharedCredentialsRepository } from '@/databases/repositories/shared-credentials.repository';
|
||||||
|
import * as Db from '@/db';
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
|
import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
|
||||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
export { Body, Query, Param } from './args';
|
|
||||||
export { RestController } from './rest-controller';
|
|
||||||
export { Get, Post, Put, Patch, Delete } from './route';
|
|
||||||
export { Middleware } from './middleware';
|
|
||||||
export { ControllerRegistry } from './controller.registry';
|
|
||||||
export { Licensed } from './licensed';
|
|
||||||
export { GlobalScope, ProjectScope } from './scoped';
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { getControllerMetadata } from './controller.registry';
|
|
||||||
import type { Controller } from './types';
|
|
||||||
|
|
||||||
export const Middleware = (): MethodDecorator => (target, handlerName) => {
|
|
||||||
const metadata = getControllerMetadata(target.constructor as Controller);
|
|
||||||
metadata.middlewares.push(String(handlerName));
|
|
||||||
};
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { PullWorkFolderRequestDto, PushWorkFolderRequestDto } from '@n8n/api-types';
|
import { PullWorkFolderRequestDto, PushWorkFolderRequestDto } from '@n8n/api-types';
|
||||||
import type { SourceControlledFile } from '@n8n/api-types';
|
import type { SourceControlledFile } from '@n8n/api-types';
|
||||||
|
import { Get, Post, Patch, RestController, GlobalScope, Body } from '@n8n/decorators';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import type { PullResult } from 'simple-git';
|
import type { PullResult } from 'simple-git';
|
||||||
|
|
||||||
import { Get, Post, Patch, RestController, GlobalScope, Body } from '@/decorators';
|
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { EventService } from '@/events/event.service';
|
import { EventService } from '@/events/event.service';
|
||||||
import { AuthenticatedRequest } from '@/requests';
|
import { AuthenticatedRequest } from '@/requests';
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { VariableListRequestDto } from '@n8n/api-types';
|
import { VariableListRequestDto } from '@n8n/api-types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Delete,
|
Delete,
|
||||||
Get,
|
Get,
|
||||||
@@ -9,7 +8,8 @@ import {
|
|||||||
Post,
|
Post,
|
||||||
Query,
|
Query,
|
||||||
RestController,
|
RestController,
|
||||||
} from '@/decorators';
|
} from '@n8n/decorators';
|
||||||
|
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||||
import { VariableCountLimitReachedError } from '@/errors/variable-count-limit-reached.error';
|
import { VariableCountLimitReachedError } from '@/errors/variable-count-limit-reached.error';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
import { Get, Post, Patch, RestController, Delete } from '@n8n/decorators';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import assert from 'node:assert';
|
import assert from 'node:assert';
|
||||||
|
|
||||||
import { Get, Post, Patch, RestController, Delete } from '@/decorators';
|
|
||||||
import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
|
import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
|
||||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
|
import { Delete, Get, Post, RestController } from '@n8n/decorators';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { InstanceSettings } from 'n8n-core';
|
import { InstanceSettings } from 'n8n-core';
|
||||||
|
|
||||||
import { TestCaseExecutionRepository } from '@/databases/repositories/test-case-execution.repository.ee';
|
import { TestCaseExecutionRepository } from '@/databases/repositories/test-case-execution.repository.ee';
|
||||||
import { TestRunRepository } from '@/databases/repositories/test-run.repository.ee';
|
import { TestRunRepository } from '@/databases/repositories/test-run.repository.ee';
|
||||||
import { Delete, Get, Post, RestController } from '@/decorators';
|
|
||||||
import { ConflictError } from '@/errors/response-errors/conflict.error';
|
import { ConflictError } from '@/errors/response-errors/conflict.error';
|
||||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||||
import { NotImplementedError } from '@/errors/response-errors/not-implemented.error';
|
import { NotImplementedError } from '@/errors/response-errors/not-implemented.error';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { RestController, Get, Post, Delete, GlobalScope, Licensed } from '@n8n/decorators';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import type {
|
import type {
|
||||||
MessageEventBusDestinationWebhookOptions,
|
MessageEventBusDestinationWebhookOptions,
|
||||||
@@ -5,7 +6,6 @@ import type {
|
|||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { MessageEventBusDestinationTypeNames } from 'n8n-workflow';
|
import { MessageEventBusDestinationTypeNames } from 'n8n-workflow';
|
||||||
|
|
||||||
import { RestController, Get, Post, Delete, GlobalScope, Licensed } from '@/decorators';
|
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { AuthenticatedRequest } from '@/requests';
|
import { AuthenticatedRequest } from '@/requests';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Get, RestController } from '@/decorators';
|
import { Get, RestController } from '@n8n/decorators';
|
||||||
|
|
||||||
import { AuthenticatedRequest } from '@/requests';
|
import { AuthenticatedRequest } from '@/requests';
|
||||||
|
|
||||||
import { EventService } from './event.service';
|
import { EventService } from './event.service';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
import { Redactable } from '@n8n/decorators';
|
||||||
import { Service } from '@n8n/di';
|
import { Service } from '@n8n/di';
|
||||||
import type { IWorkflowBase } from 'n8n-workflow';
|
import type { IWorkflowBase } from 'n8n-workflow';
|
||||||
|
|
||||||
import { Redactable } from '@/decorators/redactable';
|
|
||||||
import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus';
|
import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus';
|
||||||
import { EventService } from '@/events/event.service';
|
import { EventService } from '@/events/event.service';
|
||||||
import type { RelayEventMap } from '@/events/maps/relay.event-map';
|
import type { RelayEventMap } from '@/events/maps/relay.event-map';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { ModuleRegistry } from '@n8n/decorators';
|
||||||
import { Container } from '@n8n/di';
|
import { Container } from '@n8n/di';
|
||||||
import { stringify } from 'flatted';
|
import { stringify } from 'flatted';
|
||||||
import { ErrorReporter, Logger, InstanceSettings, ExecutionLifecycleHooks } from 'n8n-core';
|
import { ErrorReporter, Logger, InstanceSettings, ExecutionLifecycleHooks } from 'n8n-core';
|
||||||
@@ -8,7 +9,6 @@ import type {
|
|||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import { ExecutionRepository } from '@/databases/repositories/execution.repository';
|
import { ExecutionRepository } from '@/databases/repositories/execution.repository';
|
||||||
import { ModuleRegistry } from '@/decorators/module';
|
|
||||||
import { EventService } from '@/events/event.service';
|
import { EventService } from '@/events/event.service';
|
||||||
import { ExternalHooks } from '@/external-hooks';
|
import { ExternalHooks } from '@/external-hooks';
|
||||||
import { Push } from '@/push';
|
import { Push } from '@/push';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
import { Get, Patch, Post, RestController } from '@n8n/decorators';
|
||||||
import type { Scope } from '@n8n/permissions';
|
import type { Scope } from '@n8n/permissions';
|
||||||
|
|
||||||
import type { User } from '@/databases/entities/user';
|
import type { User } from '@/databases/entities/user';
|
||||||
import { Get, Patch, Post, RestController } from '@/decorators';
|
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||||
import { License } from '@/license';
|
import { License } from '@/license';
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
|
import { OnShutdown } from '@n8n/decorators';
|
||||||
import { Service } from '@n8n/di';
|
import { Service } from '@n8n/di';
|
||||||
import { Cipher, Logger } from 'n8n-core';
|
import { Cipher, Logger } from 'n8n-core';
|
||||||
import { jsonParse, type IDataObject, ensureError, UnexpectedError } from 'n8n-workflow';
|
import { jsonParse, type IDataObject, ensureError, UnexpectedError } from 'n8n-workflow';
|
||||||
|
|
||||||
import { SettingsRepository } from '@/databases/repositories/settings.repository';
|
import { SettingsRepository } from '@/databases/repositories/settings.repository';
|
||||||
import { OnShutdown } from '@/decorators/on-shutdown';
|
|
||||||
import { EventService } from '@/events/event.service';
|
import { EventService } from '@/events/event.service';
|
||||||
import { License } from '@/license';
|
import { License } from '@/license';
|
||||||
import { Publisher } from '@/scaling/pubsub/publisher.service';
|
import { Publisher } from '@/scaling/pubsub/publisher.service';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import { Get, Post, RestController, GlobalScope, Middleware } from '@n8n/decorators';
|
||||||
import { Request, Response, NextFunction } from 'express';
|
import { Request, Response, NextFunction } from 'express';
|
||||||
|
|
||||||
import { Get, Post, RestController, GlobalScope, Middleware } from '@/decorators';
|
|
||||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||||
|
|
||||||
import { ExternalSecretsProviders } from './external-secrets-providers.ee';
|
import { ExternalSecretsProviders } from './external-secrets-providers.ee';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import { Get, Post, Put, RestController, GlobalScope } from '@n8n/decorators';
|
||||||
import pick from 'lodash/pick';
|
import pick from 'lodash/pick';
|
||||||
|
|
||||||
import { Get, Post, Put, RestController, GlobalScope } from '@/decorators';
|
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { EventService } from '@/events/event.service';
|
import { EventService } from '@/events/event.service';
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
type BooleanLicenseFeature,
|
type BooleanLicenseFeature,
|
||||||
type NumericLicenseFeature,
|
type NumericLicenseFeature,
|
||||||
} from '@n8n/constants';
|
} from '@n8n/constants';
|
||||||
|
import { OnShutdown } from '@n8n/decorators';
|
||||||
import { Container, Service } from '@n8n/di';
|
import { Container, Service } from '@n8n/di';
|
||||||
import type { TEntitlement, TFeatures, TLicenseBlock } from '@n8n_io/license-sdk';
|
import type { TEntitlement, TFeatures, TLicenseBlock } from '@n8n_io/license-sdk';
|
||||||
import { LicenseManager } from '@n8n_io/license-sdk';
|
import { LicenseManager } from '@n8n_io/license-sdk';
|
||||||
@@ -13,7 +14,6 @@ import { InstanceSettings, Logger } from 'n8n-core';
|
|||||||
|
|
||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import { SettingsRepository } from '@/databases/repositories/settings.repository';
|
import { SettingsRepository } from '@/databases/repositories/settings.repository';
|
||||||
import { OnShutdown } from '@/decorators/on-shutdown';
|
|
||||||
import { LicenseMetricsService } from '@/metrics/license-metrics.service';
|
import { LicenseMetricsService } from '@/metrics/license-metrics.service';
|
||||||
|
|
||||||
import { N8N_VERSION, SETTINGS_LICENSE_CERT_KEY, Time } from './constants';
|
import { N8N_VERSION, SETTINGS_LICENSE_CERT_KEY, Time } from './constants';
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { CommunityRegisteredRequestDto } from '@n8n/api-types';
|
import { CommunityRegisteredRequestDto } from '@n8n/api-types';
|
||||||
|
import { Get, Post, RestController, GlobalScope, Body } from '@n8n/decorators';
|
||||||
import type { AxiosError } from 'axios';
|
import type { AxiosError } from 'axios';
|
||||||
import { InstanceSettings } from 'n8n-core';
|
import { InstanceSettings } from 'n8n-core';
|
||||||
|
|
||||||
import { Get, Post, RestController, GlobalScope, Body } from '@/decorators';
|
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { AuthenticatedRequest, LicenseRequest } from '@/requests';
|
import { AuthenticatedRequest, LicenseRequest } from '@/requests';
|
||||||
import { UrlService } from '@/services/url.service';
|
import { UrlService } from '@/services/url.service';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { ListInsightsWorkflowQueryDto } from '@n8n/api-types';
|
import { ListInsightsWorkflowQueryDto } from '@n8n/api-types';
|
||||||
import type { InsightsSummary, InsightsByTime, InsightsByWorkflow } from '@n8n/api-types';
|
import type { InsightsSummary, InsightsByTime, InsightsByWorkflow } from '@n8n/api-types';
|
||||||
|
import { Get, GlobalScope, Licensed, Query, RestController } from '@n8n/decorators';
|
||||||
|
|
||||||
import { Get, GlobalScope, Licensed, Query, RestController } from '@/decorators';
|
|
||||||
import { AuthenticatedRequest } from '@/requests';
|
import { AuthenticatedRequest } from '@/requests';
|
||||||
|
|
||||||
import { InsightsService } from './insights.service';
|
import { InsightsService } from './insights.service';
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
import type { BaseN8nModule } from '@n8n/decorators';
|
||||||
|
import { N8nModule } from '@n8n/decorators';
|
||||||
import type { ExecutionLifecycleHooks } from 'n8n-core';
|
import type { ExecutionLifecycleHooks } from 'n8n-core';
|
||||||
import { InstanceSettings, Logger } from 'n8n-core';
|
import { InstanceSettings, Logger } from 'n8n-core';
|
||||||
|
|
||||||
import type { BaseN8nModule } from '@/decorators/module';
|
|
||||||
import { N8nModule } from '@/decorators/module';
|
|
||||||
import type { MultiMainSetup } from '@/scaling/multi-main-setup.ee';
|
import type { MultiMainSetup } from '@/scaling/multi-main-setup.ee';
|
||||||
|
|
||||||
import { InsightsService } from './insights.service';
|
import { InsightsService } from './insights.service';
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import type { InsightsSummary } from '@n8n/api-types';
|
import type { InsightsSummary } from '@n8n/api-types';
|
||||||
import type { InsightsDateRange } from '@n8n/api-types/src/schemas/insights.schema';
|
import type { InsightsDateRange } from '@n8n/api-types/src/schemas/insights.schema';
|
||||||
|
import { OnShutdown } from '@n8n/decorators';
|
||||||
import { Service } from '@n8n/di';
|
import { Service } from '@n8n/di';
|
||||||
import { Logger } from 'n8n-core';
|
import { Logger } from 'n8n-core';
|
||||||
import type { ExecutionLifecycleHooks } from 'n8n-core';
|
import type { ExecutionLifecycleHooks } from 'n8n-core';
|
||||||
import type { IRun } from 'n8n-workflow';
|
import type { IRun } from 'n8n-workflow';
|
||||||
|
|
||||||
import { OnShutdown } from '@/decorators/on-shutdown';
|
|
||||||
import { License } from '@/license';
|
import { License } from '@/license';
|
||||||
|
|
||||||
import type { PeriodUnit, TypeUnit } from './database/entities/insights-shared';
|
import type { PeriodUnit, TypeUnit } from './database/entities/insights-shared';
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { PushMessage } from '@n8n/api-types';
|
import type { PushMessage } from '@n8n/api-types';
|
||||||
|
import { OnShutdown } from '@n8n/decorators';
|
||||||
import { Container, Service } from '@n8n/di';
|
import { Container, Service } from '@n8n/di';
|
||||||
import type { Application } from 'express';
|
import type { Application } from 'express';
|
||||||
import { ServerResponse } from 'http';
|
import { ServerResponse } from 'http';
|
||||||
@@ -11,7 +12,6 @@ import { Server as WSServer } from 'ws';
|
|||||||
import { AuthService } from '@/auth/auth.service';
|
import { AuthService } from '@/auth/auth.service';
|
||||||
import { inProduction, TRIMMED_TASK_DATA_CONNECTIONS } from '@/constants';
|
import { inProduction, TRIMMED_TASK_DATA_CONNECTIONS } from '@/constants';
|
||||||
import type { User } from '@/databases/entities/user';
|
import type { User } from '@/databases/entities/user';
|
||||||
import { OnShutdown } from '@/decorators/on-shutdown';
|
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { Publisher } from '@/scaling/pubsub/publisher.service';
|
import { Publisher } from '@/scaling/pubsub/publisher.service';
|
||||||
import { TypedEmitter } from '@/typed-emitter';
|
import { TypedEmitter } from '@/typed-emitter';
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { GlobalConfig } from '@n8n/config';
|
import { GlobalConfig } from '@n8n/config';
|
||||||
|
import { OnShutdown } from '@n8n/decorators';
|
||||||
import { Container, Service } from '@n8n/di';
|
import { Container, Service } from '@n8n/di';
|
||||||
import { ErrorReporter, InstanceSettings, isObjectLiteral, Logger } from 'n8n-core';
|
import { ErrorReporter, InstanceSettings, isObjectLiteral, Logger } from 'n8n-core';
|
||||||
import {
|
import {
|
||||||
@@ -16,7 +17,6 @@ import { ActiveExecutions } from '@/active-executions';
|
|||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import { HIGHEST_SHUTDOWN_PRIORITY, Time } from '@/constants';
|
import { HIGHEST_SHUTDOWN_PRIORITY, Time } from '@/constants';
|
||||||
import { ExecutionRepository } from '@/databases/repositories/execution.repository';
|
import { ExecutionRepository } from '@/databases/repositories/execution.repository';
|
||||||
import { OnShutdown } from '@/decorators/on-shutdown';
|
|
||||||
import { EventService } from '@/events/event.service';
|
import { EventService } from '@/events/event.service';
|
||||||
import { OrchestrationService } from '@/services/orchestration.service';
|
import { OrchestrationService } from '@/services/orchestration.service';
|
||||||
import { assertNever } from '@/utils';
|
import { assertNever } from '@/utils';
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ import {
|
|||||||
N8N_VERSION,
|
N8N_VERSION,
|
||||||
Time,
|
Time,
|
||||||
} from '@/constants';
|
} from '@/constants';
|
||||||
|
import { ControllerRegistry } from '@/controller.registry';
|
||||||
import { CredentialsOverwrites } from '@/credentials-overwrites';
|
import { CredentialsOverwrites } from '@/credentials-overwrites';
|
||||||
import { ControllerRegistry } from '@/decorators';
|
|
||||||
import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus';
|
import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus';
|
||||||
import { EventService } from '@/events/event.service';
|
import { EventService } from '@/events/event.service';
|
||||||
import { LogStreamingEventRelay } from '@/events/relays/log-streaming.event-relay';
|
import { LogStreamingEventRelay } from '@/events/relays/log-streaming.event-relay';
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { ExecutionsConfig } from '@n8n/config';
|
import { ExecutionsConfig } from '@n8n/config';
|
||||||
|
import { OnShutdown } from '@n8n/decorators';
|
||||||
import { Service } from '@n8n/di';
|
import { Service } from '@n8n/di';
|
||||||
import { BinaryDataService, InstanceSettings, Logger } from 'n8n-core';
|
import { BinaryDataService, InstanceSettings, Logger } from 'n8n-core';
|
||||||
import { ensureError } from 'n8n-workflow';
|
import { ensureError } from 'n8n-workflow';
|
||||||
@@ -7,7 +8,6 @@ import { strict } from 'node:assert';
|
|||||||
import { Time } from '@/constants';
|
import { Time } from '@/constants';
|
||||||
import { ExecutionRepository } from '@/databases/repositories/execution.repository';
|
import { ExecutionRepository } from '@/databases/repositories/execution.repository';
|
||||||
import { connectionState as dbConnectionState } from '@/db';
|
import { connectionState as dbConnectionState } from '@/db';
|
||||||
import { OnShutdown } from '@/decorators/on-shutdown';
|
|
||||||
|
|
||||||
import { OrchestrationService } from '../orchestration.service';
|
import { OrchestrationService } from '../orchestration.service';
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { GlobalConfig } from '@n8n/config';
|
import { GlobalConfig } from '@n8n/config';
|
||||||
|
import { Debounce } from '@n8n/decorators';
|
||||||
import { Service } from '@n8n/di';
|
import { Service } from '@n8n/di';
|
||||||
import ioRedis from 'ioredis';
|
import ioRedis from 'ioredis';
|
||||||
import type { Cluster, RedisOptions } from 'ioredis';
|
import type { Cluster, RedisOptions } from 'ioredis';
|
||||||
import { Logger } from 'n8n-core';
|
import { Logger } from 'n8n-core';
|
||||||
|
|
||||||
import { Debounce } from '@/decorators/debounce';
|
|
||||||
import { TypedEmitter } from '@/typed-emitter';
|
import { TypedEmitter } from '@/typed-emitter';
|
||||||
|
|
||||||
import type { RedisClientType } from '../scaling/redis/redis.types';
|
import type { RedisClientType } from '../scaling/redis/redis.types';
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
|
import { ShutdownRegistryMetadata } from '@n8n/decorators';
|
||||||
|
import type { ServiceClass } from '@n8n/decorators/src/types';
|
||||||
import { Container } from '@n8n/di';
|
import { Container } from '@n8n/di';
|
||||||
import { mock } from 'jest-mock-extended';
|
import { mock } from 'jest-mock-extended';
|
||||||
import type { ErrorReporter } from 'n8n-core';
|
import type { ErrorReporter } from 'n8n-core';
|
||||||
import { UnexpectedError } from 'n8n-workflow';
|
import { UnexpectedError } from 'n8n-workflow';
|
||||||
|
|
||||||
import type { ServiceClass } from '@/shutdown/shutdown.service';
|
import { ShutdownService } from '../shutdown.service';
|
||||||
import { ShutdownService } from '@/shutdown/shutdown.service';
|
|
||||||
|
|
||||||
class MockComponent {
|
class MockComponent {
|
||||||
onShutdown() {}
|
onShutdown() {}
|
||||||
@@ -15,9 +16,11 @@ describe('ShutdownService', () => {
|
|||||||
let mockComponent: MockComponent;
|
let mockComponent: MockComponent;
|
||||||
let onShutdownSpy: jest.SpyInstance;
|
let onShutdownSpy: jest.SpyInstance;
|
||||||
const errorReporter = mock<ErrorReporter>();
|
const errorReporter = mock<ErrorReporter>();
|
||||||
|
const shutdownRegistryMetadata = Container.get(ShutdownRegistryMetadata);
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
shutdownService = new ShutdownService(mock(), errorReporter);
|
shutdownRegistryMetadata.clear();
|
||||||
|
shutdownService = new ShutdownService(mock(), errorReporter, shutdownRegistryMetadata);
|
||||||
mockComponent = new MockComponent();
|
mockComponent = new MockComponent();
|
||||||
Container.set(MockComponent, mockComponent);
|
Container.set(MockComponent, mockComponent);
|
||||||
onShutdownSpy = jest.spyOn(mockComponent, 'onShutdown');
|
onShutdownSpy = jest.spyOn(mockComponent, 'onShutdown');
|
||||||
|
|||||||
@@ -1,18 +1,9 @@
|
|||||||
|
import type { ShutdownHandler } from '@n8n/decorators';
|
||||||
|
import { ShutdownRegistryMetadata } from '@n8n/decorators';
|
||||||
import { Container, Service } from '@n8n/di';
|
import { Container, Service } from '@n8n/di';
|
||||||
import { type Class, ErrorReporter } from 'n8n-core';
|
import { ErrorReporter, Logger } from 'n8n-core';
|
||||||
import { Logger } from 'n8n-core';
|
|
||||||
import { assert, UnexpectedError, UserError } from 'n8n-workflow';
|
import { assert, UnexpectedError, UserError } from 'n8n-workflow';
|
||||||
|
|
||||||
import { LOWEST_SHUTDOWN_PRIORITY, HIGHEST_SHUTDOWN_PRIORITY } from '@/constants';
|
|
||||||
|
|
||||||
type HandlerFn = () => Promise<void> | void;
|
|
||||||
export type ServiceClass = Class<Record<string, HandlerFn>>;
|
|
||||||
|
|
||||||
export interface ShutdownHandler {
|
|
||||||
serviceClass: ServiceClass;
|
|
||||||
methodName: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Error reported when a listener fails to shutdown gracefully */
|
/** Error reported when a listener fails to shutdown gracefully */
|
||||||
export class ComponentShutdownError extends UnexpectedError {
|
export class ComponentShutdownError extends UnexpectedError {
|
||||||
constructor(componentName: string, cause: Error) {
|
constructor(componentName: string, cause: Error) {
|
||||||
@@ -26,33 +17,22 @@ export class ComponentShutdownError extends UnexpectedError {
|
|||||||
/** Service responsible for orchestrating a graceful shutdown of the application */
|
/** Service responsible for orchestrating a graceful shutdown of the application */
|
||||||
@Service()
|
@Service()
|
||||||
export class ShutdownService {
|
export class ShutdownService {
|
||||||
private readonly handlersByPriority: ShutdownHandler[][] = [];
|
|
||||||
|
|
||||||
private shutdownPromise: Promise<void> | undefined;
|
private shutdownPromise: Promise<void> | undefined;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
private readonly errorReporter: ErrorReporter,
|
private readonly errorReporter: ErrorReporter,
|
||||||
|
private readonly shutdownRegistry: ShutdownRegistryMetadata,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/** Registers given listener to be notified when the application is shutting down */
|
/** Registers given listener to be notified when the application is shutting down */
|
||||||
register(priority: number, handler: ShutdownHandler) {
|
register(priority: number, handler: ShutdownHandler) {
|
||||||
if (priority < LOWEST_SHUTDOWN_PRIORITY || priority > HIGHEST_SHUTDOWN_PRIORITY) {
|
this.shutdownRegistry.register(priority, handler);
|
||||||
throw new UserError(
|
|
||||||
`Invalid shutdown priority. Please set it between ${LOWEST_SHUTDOWN_PRIORITY} and ${HIGHEST_SHUTDOWN_PRIORITY}.`,
|
|
||||||
{ extra: { priority } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.handlersByPriority[priority]) {
|
|
||||||
this.handlersByPriority[priority] = [];
|
|
||||||
}
|
|
||||||
this.handlersByPriority[priority].push(handler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Validates that all the registered shutdown handlers are properly configured */
|
/** Validates that all the registered shutdown handlers are properly configured */
|
||||||
validate() {
|
validate() {
|
||||||
const handlers = this.handlersByPriority.flat();
|
const handlers = this.shutdownRegistry.getHandlersByPriority().flat();
|
||||||
|
|
||||||
for (const { serviceClass, methodName } of handlers) {
|
for (const { serviceClass, methodName } of handlers) {
|
||||||
if (!Container.has(serviceClass)) {
|
if (!Container.has(serviceClass)) {
|
||||||
@@ -93,7 +73,8 @@ export class ShutdownService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async startShutdown() {
|
private async startShutdown() {
|
||||||
const handlers = Object.values(this.handlersByPriority).reverse();
|
const handlers = Object.values(this.shutdownRegistry.getHandlersByPriority()).reverse();
|
||||||
|
|
||||||
for (const handlerGroup of handlers) {
|
for (const handlerGroup of handlers) {
|
||||||
await Promise.allSettled(
|
await Promise.allSettled(
|
||||||
handlerGroup.map(async (handler) => await this.shutdownComponent(handler)),
|
handlerGroup.map(async (handler) => await this.shutdownComponent(handler)),
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { SamlAcsDto, SamlPreferences, SamlToggleDto } from '@n8n/api-types';
|
import { SamlAcsDto, SamlPreferences, SamlToggleDto } from '@n8n/api-types';
|
||||||
|
import { Get, Post, RestController, GlobalScope, Body } from '@n8n/decorators';
|
||||||
import { Response } from 'express';
|
import { Response } from 'express';
|
||||||
import querystring from 'querystring';
|
import querystring from 'querystring';
|
||||||
import type { PostBindingContext } from 'samlify/types/src/entity';
|
import type { PostBindingContext } from 'samlify/types/src/entity';
|
||||||
import url from 'url';
|
import url from 'url';
|
||||||
|
|
||||||
import { AuthService } from '@/auth/auth.service';
|
import { AuthService } from '@/auth/auth.service';
|
||||||
import { Get, Post, RestController, GlobalScope, Body } from '@/decorators';
|
|
||||||
import { AuthError } from '@/errors/response-errors/auth.error';
|
import { AuthError } from '@/errors/response-errors/auth.error';
|
||||||
import { EventService } from '@/events/event.service';
|
import { EventService } from '@/events/event.service';
|
||||||
import { AuthenticatedRequest, AuthlessRequest } from '@/requests';
|
import { AuthenticatedRequest, AuthlessRequest } from '@/requests';
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { TaskRunnersConfig } from '@n8n/config';
|
import { TaskRunnersConfig } from '@n8n/config';
|
||||||
|
import { OnShutdown } from '@n8n/decorators';
|
||||||
import { Container, Service } from '@n8n/di';
|
import { Container, Service } from '@n8n/di';
|
||||||
import { ErrorReporter, Logger } from 'n8n-core';
|
import { ErrorReporter, Logger } from 'n8n-core';
|
||||||
import { sleep } from 'n8n-workflow';
|
import { sleep } from 'n8n-workflow';
|
||||||
import * as a from 'node:assert/strict';
|
import * as a from 'node:assert/strict';
|
||||||
|
|
||||||
import { OnShutdown } from '@/decorators/on-shutdown';
|
|
||||||
import type { TaskRunnerRestartLoopError } from '@/task-runners/errors/task-runner-restart-loop-error';
|
import type { TaskRunnerRestartLoopError } from '@/task-runners/errors/task-runner-restart-loop-error';
|
||||||
import { TaskBrokerWsServer } from '@/task-runners/task-broker/task-broker-ws-server';
|
import { TaskBrokerWsServer } from '@/task-runners/task-broker/task-broker-ws-server';
|
||||||
import type { TaskRunnerProcess } from '@/task-runners/task-runner-process';
|
import type { TaskRunnerProcess } from '@/task-runners/task-runner-process';
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
import { TaskRunnersConfig } from '@n8n/config';
|
import { TaskRunnersConfig } from '@n8n/config';
|
||||||
|
import { OnShutdown } from '@n8n/decorators';
|
||||||
import { Service } from '@n8n/di';
|
import { Service } from '@n8n/di';
|
||||||
import { Logger } from 'n8n-core';
|
import { Logger } from 'n8n-core';
|
||||||
import * as a from 'node:assert/strict';
|
import * as a from 'node:assert/strict';
|
||||||
import { spawn } from 'node:child_process';
|
import { spawn } from 'node:child_process';
|
||||||
import * as process from 'node:process';
|
import * as process from 'node:process';
|
||||||
|
|
||||||
import { OnShutdown } from '@/decorators/on-shutdown';
|
|
||||||
|
|
||||||
import { forwardToLogger } from './forward-to-logger';
|
import { forwardToLogger } from './forward-to-logger';
|
||||||
import { NodeProcessOomDetector } from './node-process-oom-detector';
|
import { NodeProcessOomDetector } from './node-process-oom-detector';
|
||||||
import { TaskBrokerAuthService } from './task-broker/auth/task-broker-auth.service';
|
import { TaskBrokerAuthService } from './task-broker/auth/task-broker-auth.service';
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { GlobalConfig } from '@n8n/config';
|
import { GlobalConfig } from '@n8n/config';
|
||||||
|
import { OnShutdown } from '@n8n/decorators';
|
||||||
import { Container, Service } from '@n8n/di';
|
import { Container, Service } from '@n8n/di';
|
||||||
import type RudderStack from '@rudderstack/rudder-sdk-node';
|
import type RudderStack from '@rudderstack/rudder-sdk-node';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
@@ -10,7 +11,6 @@ import { ProjectRelationRepository } from '@/databases/repositories/project-rela
|
|||||||
import { ProjectRepository } from '@/databases/repositories/project.repository';
|
import { ProjectRepository } from '@/databases/repositories/project.repository';
|
||||||
import { UserRepository } from '@/databases/repositories/user.repository';
|
import { UserRepository } from '@/databases/repositories/user.repository';
|
||||||
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
|
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
|
||||||
import { OnShutdown } from '@/decorators/on-shutdown';
|
|
||||||
import type { IExecutionTrackProperties } from '@/interfaces';
|
import type { IExecutionTrackProperties } from '@/interfaces';
|
||||||
import { License } from '@/license';
|
import { License } from '@/license';
|
||||||
import { PostHogClient } from '@/posthog';
|
import { PostHogClient } from '@/posthog';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { PaginationDto } from '@n8n/api-types';
|
import { PaginationDto } from '@n8n/api-types';
|
||||||
|
import { RestController, Get, Middleware, Query } from '@n8n/decorators';
|
||||||
import { Request, Response, NextFunction } from 'express';
|
import { Request, Response, NextFunction } from 'express';
|
||||||
|
|
||||||
import { RestController, Get, Middleware, Query } from '@/decorators';
|
|
||||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||||
import { SharedWorkflowNotFoundError } from '@/errors/shared-workflow-not-found.error';
|
import { SharedWorkflowNotFoundError } from '@/errors/shared-workflow-not-found.error';
|
||||||
import { WorkflowHistoryVersionNotFoundError } from '@/errors/workflow-history-version-not-found.error';
|
import { WorkflowHistoryVersionNotFoundError } from '@/errors/workflow-history-version-not-found.error';
|
||||||
|
|||||||
@@ -4,6 +4,19 @@ import {
|
|||||||
TransferWorkflowBodyDto,
|
TransferWorkflowBodyDto,
|
||||||
} from '@n8n/api-types';
|
} from '@n8n/api-types';
|
||||||
import { GlobalConfig } from '@n8n/config';
|
import { GlobalConfig } from '@n8n/config';
|
||||||
|
import {
|
||||||
|
Body,
|
||||||
|
Delete,
|
||||||
|
Get,
|
||||||
|
Licensed,
|
||||||
|
Param,
|
||||||
|
Patch,
|
||||||
|
Post,
|
||||||
|
ProjectScope,
|
||||||
|
Put,
|
||||||
|
Query,
|
||||||
|
RestController,
|
||||||
|
} from '@n8n/decorators';
|
||||||
// eslint-disable-next-line n8n-local-rules/misplaced-n8n-typeorm-import
|
// eslint-disable-next-line n8n-local-rules/misplaced-n8n-typeorm-import
|
||||||
import { In, type FindOptionsRelations } from '@n8n/typeorm';
|
import { In, type FindOptionsRelations } from '@n8n/typeorm';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
@@ -21,19 +34,6 @@ import { SharedWorkflowRepository } from '@/databases/repositories/shared-workfl
|
|||||||
import { TagRepository } from '@/databases/repositories/tag.repository';
|
import { TagRepository } from '@/databases/repositories/tag.repository';
|
||||||
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
|
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
|
||||||
import * as Db from '@/db';
|
import * as Db from '@/db';
|
||||||
import {
|
|
||||||
Body,
|
|
||||||
Delete,
|
|
||||||
Get,
|
|
||||||
Licensed,
|
|
||||||
Param,
|
|
||||||
Patch,
|
|
||||||
Post,
|
|
||||||
ProjectScope,
|
|
||||||
Put,
|
|
||||||
Query,
|
|
||||||
RestController,
|
|
||||||
} from '@/decorators';
|
|
||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
|
import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
|
||||||
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
|
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import { URL } from 'url';
|
|||||||
import { AuthService } from '@/auth/auth.service';
|
import { AuthService } from '@/auth/auth.service';
|
||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import { AUTH_COOKIE_NAME } from '@/constants';
|
import { AUTH_COOKIE_NAME } from '@/constants';
|
||||||
|
import { ControllerRegistry } from '@/controller.registry';
|
||||||
import type { User } from '@/databases/entities/user';
|
import type { User } from '@/databases/entities/user';
|
||||||
import { ControllerRegistry } from '@/decorators';
|
|
||||||
import { License } from '@/license';
|
import { License } from '@/license';
|
||||||
import { rawBodyReader, bodyParser } from '@/middlewares';
|
import { rawBodyReader, bodyParser } from '@/middlewares';
|
||||||
import { PostHogClient } from '@/posthog';
|
import { PostHogClient } from '@/posthog';
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
{ "path": "../@n8n/client-oauth2/tsconfig.build.json" },
|
{ "path": "../@n8n/client-oauth2/tsconfig.build.json" },
|
||||||
{ "path": "../@n8n/config/tsconfig.build.json" },
|
{ "path": "../@n8n/config/tsconfig.build.json" },
|
||||||
{ "path": "../@n8n/constants/tsconfig.build.json" },
|
{ "path": "../@n8n/constants/tsconfig.build.json" },
|
||||||
|
{ "path": "../@n8n/decorators/tsconfig.build.json" },
|
||||||
{ "path": "../@n8n/di/tsconfig.build.json" },
|
{ "path": "../@n8n/di/tsconfig.build.json" },
|
||||||
{ "path": "../@n8n/nodes-langchain/tsconfig.build.json" },
|
{ "path": "../@n8n/nodes-langchain/tsconfig.build.json" },
|
||||||
{ "path": "../@n8n/permissions/tsconfig.build.json" }
|
{ "path": "../@n8n/permissions/tsconfig.build.json" }
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ export * from './binary-data';
|
|||||||
export * from './constants';
|
export * from './constants';
|
||||||
export * from './credentials';
|
export * from './credentials';
|
||||||
export * from './data-deduplication-service';
|
export * from './data-deduplication-service';
|
||||||
export * from './decorators';
|
|
||||||
export * from './encryption';
|
export * from './encryption';
|
||||||
export * from './errors';
|
export * from './errors';
|
||||||
export * from './execution-engine';
|
export * from './execution-engine';
|
||||||
|
|||||||
31
pnpm-lock.yaml
generated
31
pnpm-lock.yaml
generated
@@ -419,6 +419,34 @@ importers:
|
|||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../typescript-config
|
version: link:../typescript-config
|
||||||
|
|
||||||
|
packages/@n8n/decorators:
|
||||||
|
dependencies:
|
||||||
|
'@n8n/constants':
|
||||||
|
specifier: workspace:^
|
||||||
|
version: link:../constants
|
||||||
|
'@n8n/di':
|
||||||
|
specifier: workspace:^
|
||||||
|
version: link:../di
|
||||||
|
'@n8n/permissions':
|
||||||
|
specifier: workspace:^
|
||||||
|
version: link:../permissions
|
||||||
|
lodash:
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 4.17.21
|
||||||
|
n8n-workflow:
|
||||||
|
specifier: workspace:^
|
||||||
|
version: link:../../workflow
|
||||||
|
devDependencies:
|
||||||
|
'@n8n/typescript-config':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../typescript-config
|
||||||
|
'@types/express':
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 5.0.1
|
||||||
|
'@types/lodash':
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 4.14.195
|
||||||
|
|
||||||
packages/@n8n/di:
|
packages/@n8n/di:
|
||||||
dependencies:
|
dependencies:
|
||||||
reflect-metadata:
|
reflect-metadata:
|
||||||
@@ -932,6 +960,9 @@ importers:
|
|||||||
'@n8n/constants':
|
'@n8n/constants':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
version: link:../@n8n/constants
|
version: link:../@n8n/constants
|
||||||
|
'@n8n/decorators':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../@n8n/decorators
|
||||||
'@n8n/di':
|
'@n8n/di':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../@n8n/di
|
version: link:../@n8n/di
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
"dependsOn": [
|
"dependsOn": [
|
||||||
"@n8n/api-types#lint",
|
"@n8n/api-types#lint",
|
||||||
"@n8n/config#lint",
|
"@n8n/config#lint",
|
||||||
|
"@n8n/decorators#lint",
|
||||||
"@n8n/constants#lint",
|
"@n8n/constants#lint",
|
||||||
"@n8n/di#lint",
|
"@n8n/di#lint",
|
||||||
"@n8n/client-oauth2#lint",
|
"@n8n/client-oauth2#lint",
|
||||||
@@ -64,6 +65,7 @@
|
|||||||
"dependsOn": [
|
"dependsOn": [
|
||||||
"@n8n/api-types#test",
|
"@n8n/api-types#test",
|
||||||
"@n8n/config#test",
|
"@n8n/config#test",
|
||||||
|
"@n8n/decorators#test",
|
||||||
"@n8n/di#test",
|
"@n8n/di#test",
|
||||||
"@n8n/client-oauth2#test",
|
"@n8n/client-oauth2#test",
|
||||||
"@n8n/imap#test",
|
"@n8n/imap#test",
|
||||||
|
|||||||
Reference in New Issue
Block a user