# Функции

> Серверный код проекта: кто может звать функцию, открытые функции, вебхуки, расписания, логи и квота минут.

> Оглавление всей документации: https://docs.getxflow.com/llms.txt

Функция это серверный код проекта: читает и пишет [базу](https://docs.getxflow.com/platform/database.md), ходит во
внешние сервисы. Приложения получают данные только через функции, одни на все приложения
проекта.

## Код, выкатка и откат

Функция это папка `functions/<имя>/` в корне проекта с `index.ts` (или `index.js`,
`index.mjs`). Имя: строчные латинские буквы, цифры и дефис, до 41 символа, например
`send-mail`. Зависимости в корневом `package.json`.

```bash
xflow deploy functions -m "что изменилось"
```

Выкатывает функции со списком зовущих. Публикации нет: все приложения работают с новым кодом
сразу после выкатки.

| Действие | Команда |
|---|---|
| Список выкаток | `xflow deployments functions` |
| Вернуть прежнюю ревизию | `xflow deploy functions --revision N -m "почему"` |
| Без папки проекта | `--project <id>` у тех же команд |

Откат возвращает и код, и списки зовущих. Функция, папку которой удалили, при выкатке
необратимо удаляется вместе с ключами и расписаниями, поэтому выкатка сначала спрашивает
подтверждение.

## Кто может звать функцию

Зовущих перечисляют в корневом `xflow.json`, в `functions.<имя>.callers`:

```json
{
  "projectId": "…",
  "functions": {
    "list-slots": { "callers": ["zapis", "priem"] },
    "book-slot":  { "callers": ["zapis"] }
  }
}
```

Зовущий это папка приложения этого проекта: `apps/zapis` пишется как `"zapis"`. Другое имя
выкатка отклоняет. [Страница](https://docs.getxflow.com/platform/pages.md) зовущим не бывает.

Приложение зовёт функцию по своему адресу `/_fn/<имя>` через
`xflow.functions.invoke('book-slot', { body })` из шаблона, без адресов и ключей в коде.
Приложение не из списка получает 404 `not_bound`. Функция без зовущих (нет в `functions` или
`"callers": []`) недоступна приложениям, её запускают расписание, вебхук или человек.

## Открытая функция

Функция открыта, если среди её зовущих есть приложение с уровнем «Любой по ссылке». Это не
настройка, а следствие списка зовущих и уровня приложения. `xflow deploy functions` пишет об
этом отдельной строкой, `xflow functions list` и интерфейс помечают её `open`.

Открытую функцию может вызвать любой человек в интернете, без вашего приложения:

- каждый входящий параметр проверяется в коде функции;
- функция отдаёт только нужное этому вызову, без чужих строк и служебных полей;
- скрытый адрес, проверка `Origin` и токен в коде приложения не защищают;
- каждую минуту работы оплачивает организация.

Платформа ограничивает частоту вызовов `/_fn` с одного адреса. Вход и права пользователей
публичного приложения делает само приложение, см. [Вход в публичном приложении](https://docs.getxflow.com/develop/public-signin.md).

## Вебхуки и вызов из другой функции

Внешний сервис (платёжная система, бот, CRM) зовёт функцию по адресу
`https://fn.xflowpage.ru/<projectId>/<имя>` с ключом функции в заголовке `X-Function-Key` или
в параметре `?key=`. Ключи выпускает человек на экране функции, вкладка «Доступ», CLI и агент ключей не выпускают.
У функции не больше двух ключей: второй нужен, чтобы заменить первый без перерыва.

Функция зовёт другую функцию проекта по тому же адресу через `process.env.XFLOW_FN_URL` с
заголовком `X-Server-Key` из `process.env.XFLOW_SERVER_KEY`.

## Расписания

```bash
xflow schedules set report "0 3 ? * * *" --payload '{"mode":"full"}'
```

Запускает `report` каждый день в 03:00 по UTC. В выражении шесть полей, ровно одно из полей
«день месяца» и «день недели» равно `?`. Функцию нужно выкатить заранее.

| Команда | Что делает |
|---|---|
| `xflow schedules list` | расписания проекта |
| `xflow schedules set <функция> "<cron>"` | завести расписание; с тем же cron меняет тело, с другим добавляет ещё одно |
| `xflow schedules rm <функция> ["<cron>"]` | снять одно расписание или все расписания функции |

Сколько расписаний у организации (по всем проектам) и как часто они могут идти, задаёт тариф.

## Ручной вызов и логи

| Команда | Что делает |
|---|---|
| `xflow functions invoke report --data '{"a":1}'` | вызывает функцию от вашего имени и печатает тело ответа, на 4xx и 5xx завершается с ошибкой. Флаги `--data-file body.json`, `--method GET`. Работает и без зовущих в `callers` |
| `xflow functions logs report` | падения и ответы 5xx со стеком и выводом консоли: последние 10, `--limit N` для большего, хранятся 200. Успешные вызовы не записываются |
| `xflow functions list` | адрес вебхука, пометка `open`, последний вызов и последняя ошибка каждой функции |

Падение при запуске модуля, превышение времени или памяти в логи не попадает: его видно в
выводе `invoke`. Человек видит ошибки на экране функции, вкладка «Ошибки».

## Минуты и остановка

Квота минут общая на организацию: её тратят все приложения, вебхуки и расписания. Когда
минуты кончились или подписка не оплачена, функции и расписания всей организации
останавливаются, вызовы получают 403 `functions_stopped`. Предел на одно выполнение тоже
задаёт тариф, он применяется со следующей выкатки функций. Подробно:
[Тарифы и лимиты](https://docs.getxflow.com/platform/billing.md).
