How to create a single n8n node with multiple operations instead of separate nodes?

I’m working on a custom n8n node called ServiceAPI and I want it to work like AWS S3 node where you have one main node with different operations in a dropdown.

Right now when I search for ServiceAPI in the node panel, I see two separate action nodes (login and file-upload). But I want just one node that shows a dropdown to pick between login and file-upload operations.

Here’s my current setup:

package.json structure:

"nodes": {
  "main": [
    "dist/nodes/main/login.node.js",
    "dist/nodes/main/fileUpload.node.js"
  ]
}

My ServiceAPI.node.ts file:

export class ServiceAPI implements INodeType {
  description: INodeTypeDescription = {
    displayName: 'ServiceAPI',
    name: 'ServiceAPI',
    icon: 'file:ServiceAPI.png',
    group: ['transform'],
    version: 1,
    description: 'Login and upload files using this service.',
    defaults: {
      name: 'ServiceAPI',
      color: '#FF6B6B',
    },
    inputs: ['main'],
    outputs: ['main'],
    properties: [
      {
        displayName: 'Action',
        name: 'action',
        type: 'options',
        options: [
          {
            displayName: 'Login',
            name: 'Login',
            value: 'Login',
            description: 'Login to your account',
          },
          {
            displayName: 'File Upload',
            name: 'fileUpload',
            value: 'fileUpload',
            description: 'Upload a file to the service',
          },
        ],
        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: 'Secret Key',
        name: 'secretKey',
        type: 'string',
        typeOptions: {
          password: true,
        },
        displayOptions: {
          show: {
            action: ['Login'],
          },
        },
        default: '',
        description: 'Your secret key',
        required: true,
      },
      {
        displayName: 'Workspace',
        name: 'workspace',
        type: 'string',
        displayOptions: {
          show: {
            action: ['fileUpload'],
          },
        },
        default: '',
        description: 'Name of your workspace.',
      },
      {
        displayName: 'Document Type',
        name: 'documentType',
        type: 'string',
        displayOptions: {
          show: {
            action: ['fileUpload'],
          },
        },
        default: '',
        description: 'Type of document being uploaded.',
      },
      {
        displayName: 'File Data',
        name: 'fileData',
        type: 'string',
        displayOptions: {
          show: {
            action: ['fileUpload'],
          },
        },
        default: '',
        placeholder: 'Choose file...',
        required: true,
        description: 'The file you want to upload.',
      },
    ],
  };
}

I tried making separate login.node.ts and upload.node.ts files but that just gives me two different core nodes. What’s the right way to structure this so I get one node with operation choices?

your package.json is the problem. you’ve got two separate node files registered when you only need one. just point it to your main ServiceAPI.node.js file and delete the other entries. the dropdown logic in your TypeScript is already fine.

Your package.json setup is the problem. You need just one node file listed - get rid of login.node.js and fileUpload.node.js completely. Keep only ServiceAPI.node.ts and make sure package.json points to whatever compiled file it generates. Your TypeScript action dropdown structure looks good for handling different operations. Just add a switch statement (or similar logic) in your ServiceAPI execute method to route functionality based on which action gets selected.

You’re treating this like multiple nodes when it should be one. Your ServiceAPI.node.ts structure looks good, but consolidate everything into that single file and ditch the separate node registrations. Update package.json to point to just your compiled ServiceAPI node. Then handle the different operations in your execute method based on the selected action parameter. The node framework will automatically show your dropdown and display the right fields using your displayOptions config. It’s the same approach official n8n nodes like AWS S3 use.

you’re registering multiple nodes when you only need one. delete those separate login.node.js and fileUpload.node.js files completely. update your package.json to only reference the single ServiceAPI node file. your TypeScript code already has the correct structure with the action dropdown, so that’s not the problem.