Разработка кастомных нод для n8n

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Разработка кастомных нод для n8n
Средняя
~3-5 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1214
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    852
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    823
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    815

Разработка кастомных нод для n8n

Когда встроенных нод n8n недостаточно, разрабатываются custom nodes — TypeScript-пакеты, которые добавляются в инсталляцию n8n и работают как нативные ноды в редакторе.

Структура кастомной ноды

my-n8n-nodes/
├── nodes/
│   └── MyService/
│       ├── MyService.node.ts   # Основная нода
│       ├── MyService.node.json # Мета-данные
│       └── myservice.svg       # Иконка
├── credentials/
│   └── MyServiceApi.credentials.ts
├── package.json
└── tsconfig.json

package.json

{
  "name": "n8n-nodes-myservice",
  "version": "1.0.0",
  "description": "n8n nodes for MyService API",
  "main": "index.js",
  "n8n": {
    "n8nNodesApiVersion": 1,
    "credentials": ["dist/credentials/MyServiceApi.credentials.js"],
    "nodes": ["dist/nodes/MyService/MyService.node.js"]
  },
  "devDependencies": {
    "n8n-workflow": "*",
    "typescript": "^5.0.0"
  }
}

Credentials

// credentials/MyServiceApi.credentials.ts
import { ICredentialType, INodeProperties } from 'n8n-workflow';

export class MyServiceApi implements ICredentialType {
  name = 'myServiceApi';
  displayName = 'MyService API';
  documentationUrl = 'https://docs.myservice.com/api';

  properties: INodeProperties[] = [
    {
      displayName: 'API Key',
      name: 'apiKey',
      type: 'string',
      typeOptions: { password: true },
      default: '',
    },
    {
      displayName: 'Base URL',
      name: 'baseUrl',
      type: 'string',
      default: 'https://api.myservice.com/v1',
    },
  ];
}

Основная нода

// nodes/MyService/MyService.node.ts
import {
  IExecuteFunctions,
  INodeExecutionData,
  INodeType,
  INodeTypeDescription,
  NodeApiError,
} from 'n8n-workflow';

export class MyService implements INodeType {
  description: INodeTypeDescription = {
    displayName: 'MyService',
    name: 'myService',
    icon: 'file:myservice.svg',
    group: ['transform'],
    version: 1,
    description: 'Interact with MyService API',
    defaults: { name: 'MyService' },
    inputs: ['main'],
    outputs: ['main'],
    credentials: [
      { name: 'myServiceApi', required: true }
    ],
    properties: [
      {
        displayName: 'Resource',
        name: 'resource',
        type: 'options',
        options: [
          { name: 'Contact', value: 'contact' },
          { name: 'Deal', value: 'deal' },
        ],
        default: 'contact',
      },
      {
        displayName: 'Operation',
        name: 'operation',
        type: 'options',
        displayOptions: { show: { resource: ['contact'] } },
        options: [
          { name: 'Create', value: 'create', action: 'Create a contact' },
          { name: 'Get', value: 'get', action: 'Get a contact' },
          { name: 'Update', value: 'update', action: 'Update a contact' },
        ],
        default: 'create',
      },
      {
        displayName: 'Email',
        name: 'email',
        type: 'string',
        displayOptions: {
          show: { resource: ['contact'], operation: ['create'] }
        },
        default: '',
        required: true,
      },
    ],
  };

  async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
    const items = this.getInputData();
    const returnData: INodeExecutionData[] = [];

    const credentials = await this.getCredentials('myServiceApi');
    const resource = this.getNodeParameter('resource', 0) as string;
    const operation = this.getNodeParameter('operation', 0) as string;

    for (let i = 0; i < items.length; i++) {
      try {
        let responseData: unknown;

        if (resource === 'contact' && operation === 'create') {
          const email = this.getNodeParameter('email', i) as string;

          responseData = await this.helpers.request({
            method: 'POST',
            url: `${credentials.baseUrl}/contacts`,
            headers: {
              'Authorization': `Bearer ${credentials.apiKey}`,
              'Content-Type': 'application/json',
            },
            body: { email },
            json: true,
          });
        }

        returnData.push({ json: responseData as object });
      } catch (error) {
        if (this.continueOnFail()) {
          returnData.push({ json: { error: error.message }, pairedItem: i });
          continue;
        }
        throw new NodeApiError(this.getNode(), error);
      }
    }

    return [returnData];
  }
}

Установка кастомной ноды

# В директории n8n
npm install /path/to/my-n8n-nodes
# или из npm registry
npm install n8n-nodes-myservice
# docker-compose: монтирование кастомных нод
volumes:
  - ./custom-nodes:/home/node/.n8n/custom
environment:
  N8N_CUSTOM_EXTENSIONS: "/home/node/.n8n/custom"

Сроки

Кастомная нода с 2–3 операциями + credentials — 2–4 дня. Сложная нода с polling trigger, пагинацией, binary data — 1–2 недели.