fix(core): Fix node exclusion on the frontend types (#12544)

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™ 2025-01-10 15:13:31 +01:00 committed by GitHub
parent 68da9bb164
commit b2cbed9865
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 32 additions and 42 deletions

View file

@ -80,8 +80,8 @@ export abstract class DirectoryLoader {
constructor( constructor(
readonly directory: string, readonly directory: string,
protected readonly excludeNodes: string[] = [], protected excludeNodes: string[] = [],
protected readonly includeNodes: string[] = [], protected includeNodes: string[] = [],
) {} ) {}
abstract packageName: string; abstract packageName: string;
@ -121,13 +121,12 @@ export abstract class DirectoryLoader {
this.addCodex(tempNode, filePath); this.addCodex(tempNode, filePath);
const nodeType = tempNode.description.name; const nodeType = tempNode.description.name;
const fullNodeType = `${this.packageName}.${nodeType}`;
if (this.includeNodes.length && !this.includeNodes.includes(fullNodeType)) { if (this.includeNodes.length && !this.includeNodes.includes(nodeType)) {
return; return;
} }
if (this.excludeNodes.includes(fullNodeType)) { if (this.excludeNodes.includes(nodeType)) {
return; return;
} }
@ -151,7 +150,7 @@ export abstract class DirectoryLoader {
if (currentVersionNode.hasOwnProperty('executeSingle')) { if (currentVersionNode.hasOwnProperty('executeSingle')) {
throw new ApplicationError( throw new ApplicationError(
'"executeSingle" has been removed. Please update the code of this node to use "execute" instead.', '"executeSingle" has been removed. Please update the code of this node to use "execute" instead.',
{ extra: { nodeType: fullNodeType } }, { extra: { nodeType } },
); );
} }
} else { } else {
@ -430,9 +429,25 @@ export class CustomDirectoryLoader extends DirectoryLoader {
* e.g. /nodes-base or community packages. * e.g. /nodes-base or community packages.
*/ */
export class PackageDirectoryLoader extends DirectoryLoader { export class PackageDirectoryLoader extends DirectoryLoader {
packageJson: n8n.PackageJson = this.readJSONSync('package.json'); packageJson: n8n.PackageJson;
packageName = this.packageJson.name; packageName: string;
constructor(directory: string, excludeNodes: string[] = [], includeNodes: string[] = []) {
super(directory, excludeNodes, includeNodes);
this.packageJson = this.readJSONSync('package.json');
this.packageName = this.packageJson.name;
this.excludeNodes = this.extractNodeTypes(excludeNodes);
this.includeNodes = this.extractNodeTypes(includeNodes);
}
private extractNodeTypes(fullNodeTypes: string[]) {
return fullNodeTypes
.map((fullNodeType) => fullNodeType.split('.'))
.filter(([packageName]) => packageName === this.packageName)
.map(([_, nodeType]) => nodeType);
}
override async loadAll() { override async loadAll() {
const { n8n } = this.packageJson; const { n8n } = this.packageJson;
@ -524,9 +539,8 @@ export class LazyPackageDirectoryLoader extends PackageDirectoryLoader {
if (this.includeNodes.length) { if (this.includeNodes.length) {
const allowedNodes: typeof this.known.nodes = {}; const allowedNodes: typeof this.known.nodes = {};
for (const fullNodeType of this.includeNodes) { for (const nodeType of this.includeNodes) {
const [packageName, nodeType] = fullNodeType.split('.'); if (nodeType in this.known.nodes) {
if (packageName === this.packageName && nodeType in this.known.nodes) {
allowedNodes[nodeType] = this.known.nodes[nodeType]; allowedNodes[nodeType] = this.known.nodes[nodeType];
} }
} }
@ -538,11 +552,8 @@ export class LazyPackageDirectoryLoader extends PackageDirectoryLoader {
} }
if (this.excludeNodes.length) { if (this.excludeNodes.length) {
for (const fullNodeType of this.excludeNodes) { for (const nodeType of this.excludeNodes) {
const [packageName, nodeType] = fullNodeType.split('.'); delete this.known.nodes[nodeType];
if (packageName === this.packageName) {
delete this.known.nodes[nodeType];
}
} }
this.types.nodes = this.types.nodes.filter( this.types.nodes = this.types.nodes.filter(

View file

@ -235,10 +235,7 @@ describe('DirectoryLoader', () => {
return JSON.stringify({}); return JSON.stringify({});
} }
if (path.endsWith('types/nodes.json')) { if (path.endsWith('types/nodes.json')) {
return JSON.stringify([ return JSON.stringify([{ name: 'node1' }, { name: 'node2' }]);
{ name: 'n8n-nodes-testing.node1' },
{ name: 'n8n-nodes-testing.node2' },
]);
} }
if (path.endsWith('types/credentials.json')) { if (path.endsWith('types/credentials.json')) {
return JSON.stringify([]); return JSON.stringify([]);
@ -254,7 +251,7 @@ describe('DirectoryLoader', () => {
node1: { className: 'Node1', sourcePath: 'dist/Node1/Node1.node.js' }, node1: { className: 'Node1', sourcePath: 'dist/Node1/Node1.node.js' },
}); });
expect(loader.types.nodes).toHaveLength(1); expect(loader.types.nodes).toHaveLength(1);
expect(loader.types.nodes[0].name).toBe('n8n-nodes-testing.node1'); expect(loader.types.nodes[0].name).toBe('node1');
expect(classLoader.loadClassInIsolation).not.toHaveBeenCalled(); expect(classLoader.loadClassInIsolation).not.toHaveBeenCalled();
}); });
@ -274,10 +271,7 @@ describe('DirectoryLoader', () => {
return JSON.stringify({}); return JSON.stringify({});
} }
if (path.endsWith('types/nodes.json')) { if (path.endsWith('types/nodes.json')) {
return JSON.stringify([ return JSON.stringify([{ name: 'node1' }, { name: 'node2' }]);
{ name: 'n8n-nodes-testing.node1' },
{ name: 'n8n-nodes-testing.node2' },
]);
} }
if (path.endsWith('types/credentials.json')) { if (path.endsWith('types/credentials.json')) {
return JSON.stringify([]); return JSON.stringify([]);
@ -314,10 +308,7 @@ describe('DirectoryLoader', () => {
return JSON.stringify({}); return JSON.stringify({});
} }
if (path.endsWith('types/nodes.json')) { if (path.endsWith('types/nodes.json')) {
return JSON.stringify([ return JSON.stringify([{ name: 'node1' }, { name: 'node2' }]);
{ name: 'n8n-nodes-testing.node1' },
{ name: 'n8n-nodes-testing.node2' },
]);
} }
if (path.endsWith('types/credentials.json')) { if (path.endsWith('types/credentials.json')) {
return JSON.stringify([]); return JSON.stringify([]);
@ -333,7 +324,7 @@ describe('DirectoryLoader', () => {
node2: { className: 'Node2', sourcePath: 'dist/Node2/Node2.node.js' }, node2: { className: 'Node2', sourcePath: 'dist/Node2/Node2.node.js' },
}); });
expect(loader.types.nodes).toHaveLength(1); expect(loader.types.nodes).toHaveLength(1);
expect(loader.types.nodes[0].name).toBe('n8n-nodes-testing.node2'); expect(loader.types.nodes[0].name).toBe('node2');
expect(classLoader.loadClassInIsolation).not.toHaveBeenCalled(); expect(classLoader.loadClassInIsolation).not.toHaveBeenCalled();
}); });
}); });
@ -654,18 +645,6 @@ describe('DirectoryLoader', () => {
expect(nodeWithIcon.description.icon).toBeUndefined(); expect(nodeWithIcon.description.icon).toBeUndefined();
}); });
it('should skip node if included in excludeNodes', () => {
const loader = new CustomDirectoryLoader(directory, ['CUSTOM.node1']);
const filePath = 'dist/Node1/Node1.node.js';
loader.loadNodeFromFile(filePath);
expect(loader.nodeTypes).toEqual({});
expect(loader.known.nodes).toEqual({});
expect(loader.types.nodes).toEqual([]);
expect(loader.loadedNodes).toEqual([]);
});
it('should skip node if not in includeNodes', () => { it('should skip node if not in includeNodes', () => {
const loader = new CustomDirectoryLoader(directory, [], ['CUSTOM.other']); const loader = new CustomDirectoryLoader(directory, [], ['CUSTOM.other']);
const filePath = 'dist/Node1/Node1.node.js'; const filePath = 'dist/Node1/Node1.node.js';