I’m working on a custom n8n node for my service called DataFlow. Right now I have two separate operations: login and file transfer. When I search for DataFlow in the node panel, both operations appear as individual nodes which is not what I want.
I want to achieve the same structure that AWS S3 uses where you have one main node and then you can choose different operations from a dropdown menu. Currently my setup creates separate core nodes (DataFlow Login and DataFlow File Transfer) instead of one unified node.
Here’s my current package.json configuration:
"nodes": {
"main": [
"dist/nodes/main/login.node.js",
"dist/nodes/main/fileTransfer.node.js"
]
}
And here’s my main node structure:
export class DataFlow implements INodeType {
description: INodeTypeDescription = {
displayName: 'DataFlow',
name: 'DataFlow',
icon: 'file:DataFlow.png',
group: ['transform'],
version: 1,
description: 'Handle login and file operations for DataFlow service.',
defaults: {
name: 'DataFlow',
color: '#2E8B57',
},
inputs: ['main'],
outputs: ['main'],
properties: [
{
displayName: 'Action',
name: 'action',
type: 'options',
options: [
{
displayName: 'Login',
name: 'Login',
value: 'Login',
description: 'Login to your DataFlow account',
},
{
displayName: 'Transfer File',
name: 'transferFile',
value: 'transferFile',
description: 'Transfer a file using DataFlow',
},
],
default: 'Login',
description: 'Choose the action to perform',
},
{
displayName: 'Email',
name: 'email',
type: 'string',
default: '',
displayOptions: {
show: {
action: ['Login'],
},
},
description: 'Your email address',
required: true,
},
{
displayName: 'API Key',
name: 'apiKey',
type: 'string',
typeOptions: {
password: true,
},
displayOptions: {
show: {
action: ['Login'],
},
},
default: '',
description: 'Your API key for authentication',
required: true,
},
{
displayName: 'Workspace ID',
name: 'workspaceId',
type: 'string',
displayOptions: {
show: {
action: ['transferFile'],
},
},
default: '',
description: 'ID of the workspace to use.',
},
{
displayName: 'Source Format',
name: 'sourceFormat',
type: 'string',
displayOptions: {
show: {
action: ['transferFile'],
},
},
default: '',
description: 'Format of the source file.',
},
{
displayName: 'Destination Format',
name: 'destinationFormat',
type: 'string',
displayOptions: {
show: {
action: ['transferFile'],
},
},
default: '',
description: 'Format for the destination file.',
},
{
displayName: 'File Data',
name: 'fileData',
type: 'string',
displayOptions: {
show: {
action: ['transferFile'],
},
},
default: '',
placeholder: 'Choose file...',
typeOptions: {
multipleValues: false,
multipleValueButtonText: 'Add File',
},
required: true,
description: 'The file that needs to be transferred.',
},
],
};
}
I tried making separate login.node.ts and transfer.node.ts files and adding them to package.json but that just creates two individual core nodes. What’s the correct way to structure this?