Обзор узла Code
Выполняйте JavaScript или TypeScript прямо внутри workflow, когда ни один встроенный узел не подходит.
Обзор узла Code
Узел Code запускает короткий фрагмент JavaScript или TypeScript как шаг workflow. Это аварийный люк для ситуаций, когда язык шаблонов в сопоставлении полей не выражает того, что нужно, и никакое действие коннектора тоже не подходит — место, где можно преобразовать данные, вычислить производное значение или выбрать элемент из массива перед передачей результата следующему узлу.
Он намеренно узкий. Узел Code не делает HTTP-вызовов, не трогает файловую систему и не хранит состояние между запусками. Считайте его чистой функцией от inputs к выходному значению.
Когда за ним тянуться
Используйте узел Code, когда:
- Вам нужна логика, которую язык шаблонов не выражает, — условия, работа со строками сложнее простого доступа по пути, арифметика над несколькими полями, выбор элемента массива.
- Нужна утилита из встроенных помощников: работа с датами через
dayjs, UUID,pick/omit/groupBy/keyBy/uniqByнад массивом, кодирование в base64 или хеш (sha256по умолчанию). - Нужна заказная форма данных — уплощение, переименование, объединение полей нескольких узлов выше по потоку в один объект, — которой не даёт ни одно действие коннектора.
Когда использовать не стоит
- Чтобы вызвать внешний HTTP API — узел Code не умеет делать сетевые вызовы. Используйте коннектор HTTP Request или подходящее действие коннектора, если оно есть.
- Для простого сопоставления полей — если нужно просто передать
trigger.emailв следующий шаг, сделайте это прямо в инспекторе. Не оборачивайте это в код. - Для чего-либо, что требует состояния за пределами запуска — никаких БД, кэшей, файлов. Каждое выполнение начинается с нуля. Если нужна долговременная хранимость — используйте коннектор.
Модель песочницы
Каждое выполнение узла Code порождает собственный V8-изолят через isolated-vm. Это не vm2, не модуль Node vm и не worker thread — это полностью отдельная V8-куча без общей памяти.
Значения по умолчанию берутся из DEFAULT_SANDBOX_CONFIG в:
- Лимит памяти: 64 МБ на выполнение.
- Таймаут по настенным часам: 30 секунд. Это тот же таймаут шага в 30 с, что использует остальной исполнитель, — при превышении шаг падает.
- Свежий изолят на каждый вызов: песочница создаётся в
createCodeSandbox()и утилизируется сразу после возврата из узла. Никакое состояние не переживает вызовы. Переменная, «установленная» в одном запуске, исчезает в следующем.
Что заблокировано
Бутстрап-скрипт удаляет следующие глобалы перед запуском вашего кода:
fetch— никакого HTTP.setTimeout,setInterval,setImmediate,clearTimeout,clearInterval,clearImmediate— никаких таймеров. Нельзя сделать задержку или опрос.process,require,import, файловая система, сеть — ничего из этого в изоляте и не было. Загрузчика модулей нет. Нельзя сделатьrequire("lodash")или динамическийimport()чего-либо.
Если написать await fetch(...) или setTimeout(...), шаг упадёт с ReferenceError. Обхода внутри узла Code нет; выносите сетевые вызовы в действие HTTP Request выше по потоку и пробрасывайте результат через сопоставление полей.
Что доступно
Внутри изолята вам даются:
console.log/.warn/.error/.info/.debug— всё захватывается. Первые 1000 строк логов на выполнение записываются на запуск и логируются один раз в конце шага подconsoleLogs. Всё, что сверх 1000 строк, отбрасывается молча.__utils— пояс с помощниками, доступный двумя способами (выбирайте тот, что читается лучше):- Как глобал:
__utils.uuid(),__utils.dayjs(...),__utils.hash("foo"). - Как второй аргумент вашей функции:
function run(inputs, utils) { utils.uuid(); }. Обработчик всегда вызывает с[inputs, null], а песочница подменяет второй слот на__utilsнепосредственно перед вызовом. - Стандартный JS — всё, что идёт с V8:
JSON,Math,Date,Object,Array,Map,Set,Promise.Bufferне предоставляется.
Полный список утилит и сигнатуры функций — в reference.mdx.
Минимальный пример
Каждый узел Code определяет одну именованную функцию. Исполнитель находит её, просматривая (по порядку) export default function <name>, function run или первую именованную функцию в исходнике. По соглашению — run.
Дан триггер вебхука, срабатывающий с { name, email }; построим нормализованное отображаемое имя и передадим его дальше:
function run(inputs: { name: string; email: string }, utils) {
const name = (inputs.name ?? "").trim();
const email = inputs.email.toLowerCase();
const display = name.length > 0
? `${name} <${email}>`
: email;
return {
display,
emailNormalized: email,
contactId: utils.hash(email), // стабильный id из email
};
}Подключите его в инспекторе, сопоставив name с {{trigger.name}} и email с {{trigger.email}}. Возвращаемое значение — весь объект — становится выходом узла Code. Нижестоящие узлы адресуют поля как {{code_1.display}}, {{code_1.contactId}} и т. д.
Функция может быть async или возвращать Promise; песочница его дождётся. Аннотации типов TypeScript снимаются на входе в обработчик нативным stripTypeScriptTypes из Node 24, поэтому : string и : Record<string, any> писать можно — но не ждите полноценной проверки типов уровня TS, только синтаксическое срезание.
Связанное
- Справочник — полный API: обнаружение функции-входа, контракт I/O, сигнатуры утилит, лимиты.
- Миграция с n8n — проекция концепций узла Code/Function из n8n на Triggo.
- Сопоставление полей — язык шаблонов
{{...}}для передачи данных в узел Code.