> ## Documentation Index
> Fetch the complete documentation index at: https://help.teable.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Запуск сценарію

> Виконуйте власний JavaScript у захищеній пісочниці для логіки, що виходить за межі вбудованих дій

<Tip>
  Наполегливо рекомендуємо створювати автоматизації за допомогою дії «Запуск сценарію», оскільки вона охоплює всі типи дій, зокрема ті, які інакше довелося б створювати вручну. Просто опишіть свої вимоги ШІ в чаті.

  Зверніть увагу: якщо ви додасте дії вручну, ШІ надалі не розпізнаватиме й не змінюватиме їх.
</Tip>

Дія «Запуск сценарію» дає змогу писати власний JavaScript для обробки логіки, якої не охоплюють вбудовані дії. Ви можете перетворювати дані, викликати зовнішні API, виконувати обчислення, реалізовувати умовне розгалуження тощо — усе в захищеному середовищі пісочниці.

Сценарії отримують дані з попередніх кроків через об’єкт `input` і передають результати наступним крокам через функцію `output.set()`.

## Коли використовувати «Запуск сценарію», а коли — вбудовані дії

| Сценарій використання                        | Використовувати вбудовані дії        | Використовувати «Запуск сценарію»                             |
| -------------------------------------------- | ------------------------------------ | ------------------------------------------------------------- |
| Створення, оновлення або отримання записів   | Так                                  | Лише якщо навколо операції потрібна складна логіка            |
| Надсилання простого електронного листа       | Так                                  | Ні                                                            |
| Виклик однієї кінцевої точки API             | Так (HTTP-запит)                     | Лише якщо відповідь потрібно обробляти складним способом      |
| Перетворення даних між кроками               | Іноді                                | Так — якщо потрібна умовна логіка, цикли або робота з рядками |
| Аналіз складних структур JSON                | Ні                                   | Так                                                           |
| Обчислення дат, форматування чисел           | Ні                                   | Так                                                           |
| Послідовний виклик кількох API з логікою     | Незручно за допомогою вбудованих дій | Так                                                           |
| Реалізація бізнес-правил із багатьма умовами | Непрактично                          | Так                                                           |

Зазвичай використовуйте вбудовані дії, якщо вони відповідають вашим потребам. Використовуйте «Запуск сценарію», коли потрібні власна логіка, перетворення даних або складна взаємодія з API.

## Середовище

| Властивість          | Значення                                                 |
| -------------------- | -------------------------------------------------------- |
| Мова                 | JavaScript (ES6+), підтримується `await` верхнього рівня |
| Середовище виконання | Захищена пісочниця з тайм-аутом 60 секунд                |
| Модулі               | CommonJS (`require()`), підтримуються пакети npm         |
| Мережа               | HTTP-запити через `fetch()`                              |

## Як налаштувати

1. Додайте до робочого процесу дію **Запуск сценарію**.
2. Відкриється редактор сценарію з порожнім полотном. Напишіть тут код JavaScript.
3. Сценарій може читати дані з попередніх кроків через об’єкт `input` (див. нижче).
4. Використовуйте `output.set(key, value)`, щоб передавати результати наступним крокам.
5. (Необов’язково) Додайте залежності npm на панелі налаштувань, якщо сценарію потрібні зовнішні бібліотеки.
6. Натисніть **Перевірити**, щоб запустити сценарій із реальними даними останнього виконання тригера.
7. Перегляньте тестовий результат і журнали консолі, щоб переконатися, що сценарій працює правильно.
8. Збережіть дію.

## Читання вхідних даних

Об’єкт `input` містить дані з усіх попередніх кроків робочого процесу. Кожен крок визначається ідентифікатором дії.

### Структура вхідних даних

```javascript theme={null}
// input — це об’єкт із ключами-ідентифікаторами дій
// Кожен ключ містить результат відповідного кроку

const actionIds = Object.keys(input);
// Приклад actionIds: ["triggerStep1", "actionStep2", "actionStep3"]
```

### Отримання даних тригера (полів запису)

```javascript theme={null}
const actionIds = Object.keys(input);
const triggerData = input[actionIds[0]]; // Перший запис зазвичай є тригером

// Для тригерів на основі записів (створено, оновлено, натиснуто кнопку, надіслано форму):
const recordId = triggerData.record.id;
const fields = triggerData.record.fields;

// Доступ до певних полів за ідентифікатором поля
const customerName = fields.fldXXXXXXX;  // Замініть фактичним ідентифікатором поля
const orderAmount = fields.fldYYYYYYY;
```

### Отримання даних із кроку «Отримати записи»

```javascript theme={null}
const actionIds = Object.keys(input);
const getRecordsData = input[actionIds[1]]; // Наприклад, другий крок

const records = getRecordsData.records;
records.forEach(record => {
  console.log(record.id, record.fields.fldName);
});
```

### Отримання даних із результатів інших дій

```javascript theme={null}
const actionIds = Object.keys(input);
const previousOutput = input[actionIds[2]]; // Результат третього кроку
// Структура залежить від результату цієї дії
```

<Tip>Під час тестування використовуйте `console.log(JSON.stringify(input, null, 2))`, щоб побачити точну структуру вхідних даних. Це найшвидший спосіб зрозуміти, які дані доступні.</Tip>

## Запис вихідних даних

Використовуйте `output.set(key, value)`, щоб зробити дані доступними наступним крокам. Можна задати кілька ключів.

```javascript theme={null}
// Задайте прості значення
output.set("status", "success");
output.set("count", 42);

// Задайте об’єкти
output.set("result", {
  name: "Аліса",
  score: 95,
  passed: true
});

// Задайте масиви
output.set("items", [
  { id: 1, name: "Елемент A" },
  { id: 2, name: "Елемент B" }
]);
```

Кожен заданий ключ стає окремою змінною, на яку наступні кроки можуть посилатися через засіб вибору змінних **+**. Наприклад, якщо викликати `output.set("status", "success")`, наступний крок зможе посилатися на `status` у результаті цього сценарію.

## Налагодження за допомогою console.log

Під час розробки використовуйте `console.log()` для перевірки даних і відстеження перебігу виконання. Результат журналу з’являється на панелі тестування після натискання **Перевірити**.

```javascript theme={null}
const actionIds = Object.keys(input);
console.log("Ідентифікатори дій:", actionIds);

const data = input[actionIds[0]];
console.log("Дані тригера:", JSON.stringify(data, null, 2));

// Запишіть проміжні результати до журналу
const processed = data.record.fields.fldName.toUpperCase();
console.log("Оброблене ім’я:", processed);

output.set("name", processed);
```

Журнали консолі видимі лише під час тестування — вони не з’являються в історії виробничих запусків. Активно використовуйте їх під час створення сценарію.

## Керування пакетами npm

У сценаріях можна використовувати пакети npm. Оголосіть залежності на панелі налаштувань:

```json theme={null}
[
  { "name": "lodash", "version": "4.17.21" },
  { "name": "dayjs", "version": "1.11.10" }
]
```

Потім використовуйте їх у сценарії за допомогою `require()`:

```javascript theme={null}
const _ = require("lodash");
const dayjs = require("dayjs");

const actionIds = Object.keys(input);
const records = input[actionIds[0]].records;

const grouped = _.groupBy(records, r => r.fields.fldCategory);
const today = dayjs().format("YYYY-MM-DD");

output.set("grouped", grouped);
output.set("date", today);
```

<Tip>За можливості віддавайте перевагу вбудованим можливостям JavaScript, а не пакетам npm. Сучасний JavaScript має багато вбудованих засобів — `Array.map()`, `Array.filter()`, `Object.entries()`, шаблонні літерали, деструктурування тощо. Додавайте пакети npm лише тоді, коли вони дають істотну користь.</Tip>

## Вбудовані змінні

| Змінна                         | Опис                                                                                       |
| ------------------------------ | ------------------------------------------------------------------------------------------ |
| `process.env.AUTOMATION_TOKEN` | Токен Bearer для виклику API Teable. Область дії обмежена дозволами поточної автоматизації |
| `process.env.PUBLIC_ORIGIN`    | Базова URL-адреса вашого екземпляра Teable (наприклад, `https://app.teable.io`)            |

### Безпека: область дії AUTOMATION\_TOKEN

`AUTOMATION_TOKEN` автоматично створюється для кожного запуску автоматизації. Він має ті самі дозволи, що й автор автоматизації, а його область дії обмежена поточним виконанням. Основне:

* Він може отримувати доступ до будь-якої таблиці, доступної автору автоматизації.
* Він дійсний лише протягом виконання сценарію (тайм-аут 60 секунд).
* Не передавайте цей токен зовнішнім системам — він призначений для виклику API Teable із вашого сценарію.

### Виклик API Teable

```javascript theme={null}
const base = process.env.PUBLIC_ORIGIN + "/api";
const token = process.env.AUTOMATION_TOKEN;

// Приклад: отримання записів із таблиці
const res = await fetch(`${base}/table/tblXXXXXXX/record?take=10`, {
  headers: {
    Authorization: `Bearer ${token}`,
    "Content-Type": "application/json"
  }
});

const data = await res.json();
console.log("Отримані записи:", data);
output.set("records", data);
```

### Виклик ШІ зі сценарію

`POST /api/automation/runtime/ai` надсилає запит моделі ШІ вашої Бази. База визначається з контексту автоматизації, тому її ідентифікатор не потрібен. Тіло приймає `prompt`, а також необов’язкові `attachments`, `modelKey`, `temperature` й `outputType`; відповідь має формат `{ "message": ... }`.

Вкладення — це елементи `{ url, mimetype, name }`, до 10 на один виклик, кожен розміром до 20 МБ і з часом завантаження до 30 секунд; підтримуються зображення, PDF і документи Office. Стандартна модель чату може не читати зображення та подібні вкладення, тому під час надсилання файлів передавайте `modelKey`. Кожен виклик витрачає кредити.

## Обробка помилок

Завжди обгортайте ризиковані операції в блоки try/catch, щоб робочий процес міг належно обробляти помилки:

```javascript theme={null}
try {
  const res = await fetch("https://api.example.com/data");
  
  if (!res.ok) {
    throw new Error(`API повернув ${res.status}: ${res.statusText}`);
  }
  
  const data = await res.json();
  output.set("success", true);
  output.set("data", data);
} catch (error) {
  console.log("Помилка:", error.message);
  output.set("success", false);
  output.set("error", error.message);
}
```

Без обробки помилок невдалий виклик fetch або неочікуваний формат даних призведе до аварійного завершення сценарію, і наступні кроки не отримають результату.

## Повний приклад: обробка й маршрутизація звернень до служби підтримки

```javascript theme={null}
const actionIds = Object.keys(input);
const record = input[actionIds[0]].record;

const subject = record.fields.fldSubject || "";
const body = record.fields.fldBody || "";
const email = record.fields.fldEmail || "";

// Проста маршрутизація за ключовими словами
const text = (subject + " " + body).toLowerCase();

let category = "Загальне";
let priority = "Звичайний";

if (text.includes("оплата") || text.includes("рахунок") || text.includes("платіж")) {
  category = "Оплата";
} else if (text.includes("помилка") || text.includes("збій") || text.includes("аварія")) {
  category = "Технічна проблема";
  priority = "Високий";
} else if (text.includes("скасувати") || text.includes("повернення")) {
  category = "Обліковий запис";
  priority = "Високий";
}

// Перевірте, чи належить клієнт до категорії VIP
const vipDomains = ["bigcorp.com", "enterprise.io"];
const domain = email.split("@")[1] || "";
if (vipDomains.includes(domain)) {
  priority = "Терміновий";
}

output.set("category", category);
output.set("priority", priority);
output.set("isVIP", vipDomains.includes(domain));
```

## Поради

* **Почніть із console.log.** Створюючи новий сценарій, спочатку запишіть до журналу весь об’єкт `input`, щоб зрозуміти його структуру.
* **Зосереджуйте сценарії на одному завданні.** Краще добре виконати одне завдання, ніж умістити в одному сценарії кілька. За потреби створіть послідовність із кількох дій «Запуск сценарію».
* **Пам’ятайте про 60-секундний тайм-аут.** Тривалі операції (обробка великого обсягу даних, багато послідовних викликів API) можуть перевищити тайм-аут. Розділяйте великі завдання на менші частини.
* **Перевіряйте з реальними даними.** Панель тестування використовує фактичні дані останнього виконання тригера, забезпечуючи реалістичні результати.
* **Обробляйте відсутні дані.** Використовуйте стандартні значення (оператор `||`) для полів, які можуть бути порожніми або undefined.

## Пов’язані матеріали

* [Генерування за допомогою ШІ](/uk/basic/automation/actions/ai/ai-generate) — завдання ШІ на основі запитів, які не потребують власного коду
* [HTTP-запит](/uk/basic/automation/actions/logic/http-request) — прості виклики API, які не потребують сценаріїв
