Документация Triggo
Конструктор workflow

Сопоставление полей

Как ссылаться на значения предыдущих шагов с помощью выражений {{template}}.

Сопоставление полей

Почти каждому узлу нужны значения откуда-то ещё — из полезной нагрузки триггера, из выхода предыдущего действия, из вложенного поля на три уровня вниз в JSON-ответе. Сопоставление полей — это способ пробросить такие значения во входы узла.

В Triggo есть небольшой язык шаблонов вида {{source.path.to.value}}. Вы пишете такие выражения в любом текстовом поле инспектора; исполнитель разрешает их во время запуска, обращаясь к актуальным выходам узлов-предков.

Синтаксис

Разделитель — двойные фигурные скобки: {{... }}. Внутри — путь, разделённый точками. Реализация находится в.

Существуют два режима разрешения, выбираемые автоматически:

  • Whole-value — всё поле ввода — это одно выражение, например {{trigger.email}}. Разрешённое значение возвращается как есть, с сохранением типа. Число остаётся числом, массив — массивом, объект — объектом.
  • Inline — выражение встроено в большую строку, например Hello {{trigger.name}}!. Каждое выражение разрешается и приводится к строке в окружающем тексте. null и undefined превращаются в пустую строку.

Обращение к триггеру

Триггер особенный — у него зарезервированный корневой ключ:

{{trigger.field}}

Под капотом исполнитель хранит выход каждого узла по его node ID. Когда вы пишете {{trigger...}}, резолвер сначала ищет буквальный ключ trigger, а если его нет, использует первый ключ, начинающийся с trigger (например, trigger_1). Это позволяет писать {{trigger.email}} независимо от того, как холст назвал узел триггера внутри себя.

Обращение к предыдущему шагу

Любой другой узел адресуется по его node ID — тому самому ID, который холст присваивает при добавлении узла:

{{action_1.id}}
{{http_request_2.body.status}}

Откройте узел в инспекторе, чтобы увидеть его ID. Подборщик сопоставления полей в UI сам вставляет эти идентификаторы, так что вручную писать их приходится редко.

Обращение к вложенным значениям

Пути — это обычная точечная нотация. Каждый сегмент после корня трактуется как ключ объекта:

{{trigger.contact.email}}
{{action_1.customer.address.city}}

Обход null-безопасен в том смысле, что возвращает undefined, как только любой сегмент отсутствует или не является объектом, — он не бросает исключение. См. traversePath в field-mapper.

Несколько вещей, которых нет в языке:

  • Синтаксиса индекса массива. Нет {{items.0.name}} или {{items[0].name}}. Резолвер делит путь по . и трактует каждый сегмент как ключ объекта, поэтому числовые сегменты работают только если базовое значение — объект с таким числовым ключом (в виде строки). Чтобы выбрать элемент из массива, используйте Code node.
  • Optional chaining (?.), null coalescing (??), значений по умолчанию — не поддерживаются. Отсутствующий путь разрешается в undefined, и всё.
  • Вызовов функций, фильтров и выражений — в языке шаблонов нет операторов. Если нужны toUpperCase(), slice(), арифметика или условная логика — используйте Code node.

Приведение типов

Когда выражение подставляется во вход коннектора, исполнитель приводит разрешённое значение к объявленному типу свойства. Правила лежат в — одна стратегия на тип свойства:

  • NUMBER — если уже число, проходит без изменений. Иначе Number(value); бросает VALIDATION_ERROR, если результат NaN. Так {{trigger.age}}, возвращающий строку "25", становится 25.
  • CHECKBOX — булевы значения проходят. Строки "true" / "1" (без учёта регистра) → true; "false" / "0"false. Всё остальное бросает VALIDATION_ERROR.
  • SHORT_TEXT — всегда String(value). Числа, булевы, даже объекты становятся строковым представлением.
  • LONG_TEXT — то же, что SHORT_TEXT: String(value).
  • ARRAY — массивы проходят. Строка парсится как JSON и принимается, если парсится в массив; иначе бросается ошибка. Нестроковые и немассивные значения проходят без изменений (коннектор получает то, что есть).
  • OBJECT — объекты проходят (включая null, так как typeof null === "object"). Строки парсятся как JSON; результат должен быть ненулевым объектом, иначе бросается ошибка. Нестроковые и необъектные значения проходят без изменений.
  • DROPDOWN, DYNAMIC_DROPDOWN, OAUTH2, SECRET_TEXT, DATE_TIME — идентичность. Значение передаётся нетронутым; парсинг — ответственность коннектора.

Null-безопасность повсеместно: если разрешённое значение — null или undefined, приведение пропускается и сырое null/undefined передаётся как есть. Отсутствующее поле никогда не бросает ошибку на этапе приведения — обычно оно падает позже, когда коннектор валидирует обязательные входы.

Экранирование

Механизма экранирования для литеральных {{ или }} нет. Регулярное выражение — \{\{([^}]+)\}\}: любая пара двойных скобок с не-} содержимым внутри считается шаблоном. Вывести в тексте литерал {{foo}} нельзя; если это действительно нужно, соберите строку в Code node и верните её оттуда.

На практике это практически никогда не случается — входы workflow это значения, а не исходник шаблонов.

Отсутствующие пути

Это намеренное поведение, о котором стоит знать:

  • Неизвестный корневой ключ → undefined. Если вы пишете {{tyop.field}}, а узла с ID tyop не было, выражение разрешается в undefined. Резолвер не ищет подходящий ключ в остальных данных. Это сознательно — так опечатки и сломанные ссылки всплывают, а не подхватывают случайное значение.
  • Неизвестный вложенный сегмент → undefined. Проход по отсутствующему ключу или через null даёт undefined.
  • Inline-шаблоны приводят undefined к "". Так Hello {{trigger.unknown}}! отрендерится как Hello !.
  • Whole-value-шаблоны сохраняют undefined. Сопоставление поля, всё значение которого — {{trigger.unknown}}, пробрасывает undefined, и (по правилам приведения выше) приведение его пропускает. Ошибка обычно всплывает на валидации обязательных полей на границе коннектора.

Глобального фолбэка и автопоиска нет. Если вы адресуете узел, не являющийся предком текущего, получаете undefined.

Частые ошибки

  1. Голые имена полей не работают. {{email}} выглядит естественно, но разрешается в undefined, если только нет узла с ID email. Почти всегда имеется в виду {{trigger.email}} или {{some_action.email}}. Корневой сегмент — это node ID, а не имя поля.
  2. Опечатки молча возвращают undefined. {{trigger_1.emial}} (переставлены буквы) возвращает undefined, что в inline-контексте становится "". Если ниже по потоку узел отправляет пустую строку там, где должно быть значение, начните с проверки написания пути.
  3. Числа из некоторых источников приходят строками. Тела вебхуков, URL-параметры и поля форм часто приходят строками. Свойства типа NUMBER приводят их за вас; SHORT_TEXT — нет (нечего приводить). Но если вы пишете условие против {{trigger.body.count}}, ожидая целочисленного сравнения, помните: сырое значение может быть "25", а не 25. Операторы условий это учитывают, но своя логика в Code node должна тоже.
  4. Нет индексации массива. {{list_rows_1.rows.0.name}} не вытаскивает первую строку — он ищет ключ, буквально называемый "0", на rows. Массивы результатов требуют Loop node или Code node для выбора элементов.
  5. Ссылка на соседнюю ветвь. Узел видит выходы только своих предков в DAG. Ссылка {{other_branch.result}} на узел в параллельной ветви, которая ещё не запускалась, разрешится в undefined. Если нужны данные из другой ветви, сначала объедините ветви.

Смотрите также

On this page