perf(core): Skip init for unlicensed modules (#16311)

This commit is contained in:
Iván Ovejero
2025-06-13 11:49:38 +02:00
committed by GitHub
parent 3864f0e1c1
commit cb81826cf1
6 changed files with 43 additions and 19 deletions

View File

@@ -19,7 +19,7 @@ describe('@BackendModule decorator', () => {
initialize() {}
}
const registeredModules = Array.from(moduleMetadata.getModules());
const registeredModules = moduleMetadata.getEntries().map((entry) => entry.class);
expect(registeredModules).toContain(TestModule);
expect(registeredModules).toHaveLength(1);
@@ -41,7 +41,7 @@ describe('@BackendModule decorator', () => {
initialize() {}
}
const registeredModules = Array.from(moduleMetadata.getModules());
const registeredModules = moduleMetadata.getEntries().map((entry) => entry.class);
expect(registeredModules).toContain(FirstModule);
expect(registeredModules).toContain(SecondModule);
@@ -53,7 +53,7 @@ describe('@BackendModule decorator', () => {
@BackendModule()
class TestModule {}
const registeredModules = Array.from(moduleMetadata.getModules());
const registeredModules = moduleMetadata.getEntries().map((entry) => entry.class);
expect(registeredModules).toContain(TestModule);
expect(registeredModules).toHaveLength(1);
@@ -69,7 +69,7 @@ describe('@BackendModule decorator', () => {
}
}
const registeredModules = Array.from(moduleMetadata.getModules());
const registeredModules = moduleMetadata.getEntries().map((entry) => entry.class);
expect(registeredModules).toContain(TestModule);
@@ -87,7 +87,7 @@ describe('@BackendModule decorator', () => {
@BackendModule()
class SecondModule {}
const registeredModules = Array.from(moduleMetadata.getModules());
const registeredModules = moduleMetadata.getEntries().map((entry) => entry.class);
expect(registeredModules).toContain(FirstModule);
expect(registeredModules).toContain(SecondModule);

View File

@@ -1,16 +1,21 @@
import { Service } from '@n8n/di';
import type { ModuleClass } from './module';
import type { LicenseFlag, ModuleClass } from './module';
type ModuleEntry = {
class: ModuleClass;
licenseFlag?: LicenseFlag;
};
@Service()
export class ModuleMetadata {
private readonly modules: Set<ModuleClass> = new Set();
private readonly modules: Map<string, ModuleEntry> = new Map();
register(module: ModuleClass) {
this.modules.add(module);
register(moduleName: string, moduleEntry: ModuleEntry) {
this.modules.set(moduleName, moduleEntry);
}
getModules() {
return this.modules.keys();
getEntries() {
return [...this.modules.values()];
}
}

View File

@@ -1,3 +1,4 @@
import type { LICENSE_FEATURES } from '@n8n/constants';
import { Container, Service, type Constructable } from '@n8n/di';
import { ModuleMetadata } from './module-metadata';
@@ -24,9 +25,16 @@ export interface ModuleInterface {
export type ModuleClass = Constructable<ModuleInterface>;
export const BackendModule = (): ClassDecorator => (target) => {
Container.get(ModuleMetadata).register(target as unknown as ModuleClass);
export type LicenseFlag = (typeof LICENSE_FEATURES)[keyof typeof LICENSE_FEATURES];
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return Service()(target);
};
export const BackendModule =
(opts?: { licenseFlag: LicenseFlag }): ClassDecorator =>
(target) => {
Container.get(ModuleMetadata).register(target.name, {
class: target as unknown as ModuleClass,
licenseFlag: opts?.licenseFlag,
});
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return Service()(target);
};