I’m working on an n8n custom node for my company and I’m stuck. Right now, I have two action nodes (authenticate and upload file) that show up separately when I search for the company in the node panel. But what I really want is to have these actions grouped under one main node, like how S3 does it.
Here’s what I’ve tried:
- I set up my
main.node.ts file with authentication and file upload logic
- In my
package.json, I listed both action nodes under the “main” key
- I even tried making separate files for each action (auth.node.ts and upload.node.ts)
But no luck. I either get two separate core nodes or a dropdown that doesn’t quite work right.
Can someone help me figure out the correct structure to achieve this? I want users to be able to select my company node and then choose between authenticate and upload file actions, all within the same node.
Here’s a simplified version of my current setup:
class CompanyNode {
description = {
name: 'Company',
properties: [
{
name: 'action',
type: 'options',
options: [
{ name: 'Auth', value: 'auth' },
{ name: 'Upload', value: 'upload' }
]
},
// Other properties based on selected action
]
}
// Methods for auth and upload
}
Any ideas on how to restructure this to get the desired result?
hey flyingeagle, i think i got a solution for ya. try using the loadOptions method in ur description object. it lets u dynamically load properties based on the selected action. somethin like this:
loadOptions: {
async getProperties(this, loadOptionsDependencies) {
const action = loadOptionsDependencies.action;
if (action === 'auth') {
return [/* auth properties */];
} else if (action === 'upload') {
return [/* upload properties */];
}
}
}
hope this helps!
I’ve encountered similar challenges with n8n custom nodes. One approach that’s worked well is implementing a ‘Resource’ dropdown in addition to the ‘Action’ selection. This setup mimics how many official n8n nodes are structured.
Here’s a basic outline:
class CompanyNode {
description = {
displayName: 'Company',
name: 'company',
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
options: [
{ name: 'Authentication', value: 'auth' },
{ name: 'File', value: 'file' },
],
default: 'auth',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'file'
]
}
},
options: [
{ name: 'Upload', value: 'upload' }
],
default: 'upload',
}
]
};
async execute() {
const resource = this.getNodeParameter('resource', 0);
const operation = this.getNodeParameter('operation', 0);
if (resource === 'auth') {
return this.handleAuth();
} else if (resource === 'file' && operation === 'upload') {
return this.handleFileUpload();
}
}
}
This structure allows for easy expansion with additional resources and operations in the future.
As someone who’s wrestled with custom n8n nodes before, I totally get your frustration. Here’s what worked for me:
Instead of separate files, try consolidating everything into a single file structure. Use a switch statement in your execute method to handle different actions. Something like:
async execute() {
const action = this.getNodeParameter('action', 0) as string;
switch (action) {
case 'auth':
return await this.authenticate();
case 'upload':
return await this.uploadFile();
default:
throw new Error(`The action "${action}" is not supported.`);
}
}
Then define your authenticate() and uploadFile() methods within the same class. This approach keeps everything neatly packaged under one node while still allowing for multiple actions.
Don’t forget to update your description object to include all possible parameters for both actions. The loadOptions method suggested earlier is crucial for dynamically showing relevant fields.
Lastly, make sure your node.json file correctly references this consolidated structure. With these tweaks, you should see a single node with a dropdown for actions, just like the S3 node.