Спецификация FAPL 1.0¶
Эта страница задаёт каркас FAPL 1.0 (Frontend Architecture & Process Language): какие поля есть у модуля, как устроены три слоя и какой документ считается согласованным. Зачем язык собран именно так и как его читать агенту, написано в обзоре.
Статус
Версия 1.0 — каркас. Он фиксирует форму документа, три слоя и пример модуля аутентификации. Парсер, рантайм и привязка к React, Vue или Angular в эту версию не входят.
Файл¶
| Правило | Значение |
|---|---|
| Кодировка | UTF-8 |
| Расширение | .fapl.yaml |
| Синтаксис | YAML |
| Версия YAML | 1.2. Ключ карты событий пишется как "on", чтобы парсер YAML 1.1 не превратил его в булево значение |
| Комментарии | Строки, начинающиеся с #, смысла для языка не несут |
Корень файла — одно отображение. Порядок ключей в тексте: version, module, description, components, workflows, services. Порядок для машины не значим; для человека он совпадает с порядком чтения технического задания.
Идентификатор — непустая строка из латиницы, цифр и _, первый символ не цифра: ^[A-Za-z_][A-Za-z0-9_]*$.
Документ модуля¶
| Поле | Обязательность | Форма |
|---|---|---|
version | обязан присутствовать | Строка "1.0" |
module | обязан присутствовать | Непустая строка, имя модуля |
description | может отсутствовать | Строка для человека |
components | обязан присутствовать | Список компонентов, возможно пустой |
workflows | обязан присутствовать | Отображение «имя процесса → процесс», хотя бы один процесс |
services | обязан присутствовать | Отображение «имя сервиса → сервис», список может быть пустым |
Имена процессов — ключи workflows. Имена сервисов — ключи services. Оба набора подчиняются правилу идентификатора.
Компоненты¶
Элемент списка components описывает страницу или компонент интерфейса.
| Поле | Обязательность | Форма |
|---|---|---|
name | обязан присутствовать | Идентификатор, уникальный среди компонентов модуля |
type | обязан присутствовать | Page или Component |
route | обязан у Page, у Component отсутствует | Строка маршрута, начинается с / |
children | может отсутствовать | Непустой список имён компонентов того же модуля |
inputs | может отсутствовать | Непустой список входов |
outputs | может отсутствовать | Непустой список выходов |
Вход:
| Поле | Обязательность | Форма |
|---|---|---|
name | обязан присутствовать | Идентификатор, уникальный среди входов этого компонента |
type | обязан присутствовать | Выражение типа |
Выход:
| Поле | Обязательность | Форма |
|---|---|---|
name | обязан присутствовать | Идентификатор, уникальный среди выходов этого компонента |
action | обязан присутствовать | Действие |
Page — экран с маршрутом. Component — вложенная часть экрана. Имя из children указывает на другой элемент того же списка components.
В примере LoginView — страница /login, её ребёнок — LoginForm. Выход формы onSubmit связан с процессом строкой AuthWorkflow.startLogin.
Процессы¶
Процесс — конечный автомат.
| Поле | Обязательность | Форма |
|---|---|---|
description | может отсутствовать | Строка |
initial_state | обязан присутствовать | Имя состояния из states этого процесса |
states | обязан присутствовать | Отображение «имя состояния → состояние», хотя бы одно |
Состояние:
| Поле | Обязательность | Форма |
|---|---|---|
type | обязан у конечного состояния | Единственное допустимое значение — Final |
entry | может быть у неконечного состояния | Одна ссылка. Выполняется при входе в состояние |
on | обязан у неконечного состояния | Отображение «имя события → переход» |
Конечное состояние содержит только type: Final. Ключей on и entry у него нет.
У состояния есть либо type: Final, либо непустая карта on.
Переход:
| Поле | Обязательность | Форма |
|---|---|---|
target | обязан присутствовать | Имя состояния того же процесса |
payload | может отсутствовать | Выражение типа полезной нагрузки события |
action | может отсутствовать | Действие, выполняется вместе с переходом |
Имя события уникально в карте on своего состояния. Одинаковое имя события в разных состояниях — разные переходы.
Порядок для одного события такой: при входе в исходное состояние выполняется его entry, если он есть; когда приходит событие, выполняется action перехода и процесс оказывается в target.
В примере AuthWorkflow стартует в Idle. Событие SUBMIT_FORM несёт email и pass и ведёт в Validating. На входе в Validating вызывается локальное действие executeValidation. На входе в RequestingApi вызывается AuthService.login.
stateDiagram-v2
[*] --> Idle
Idle --> Validating: SUBMIT_FORM
Validating --> RequestingApi: VALIDATION_SUCCESS
Validating --> Idle: VALIDATION_FAIL
RequestingApi --> Authenticated: API_SUCCESS
RequestingApi --> Idle: API_ERROR
Authenticated --> [*] Сервисы¶
Сервис — набор методов, к которым обращается фронтенд.
| Поле | Обязательность | Форма |
|---|---|---|
methods | обязан присутствовать | Непустой список методов |
Метод:
| Поле | Обязательность | Форма |
|---|---|---|
name | обязан присутствовать | Идентификатор, уникальный среди методов этого сервиса |
async | может отсутствовать | Булево. Отсутствие поля означает синхронный метод. true — вызов асинхронный |
params | обязан присутствовать | Выражение типа аргументов |
returns | обязан присутствовать | Выражение типа успешного результата |
error | может отсутствовать | Выражение типа ошибки |
AuthService.login в примере асинхронный. Аргументы — email и pass. Успех — token и вложенный user. Ошибка — code и message.
Типы¶
Выражение типа — либо скаляр, либо отображение «поле → выражение типа».
Скаляры версии 1.0:
| Имя | Смысл |
|---|---|
String | Строка |
ID | Идентификатор сущности |
Других скаляров в 1.0 нет. Вложенность объектов не ограничена. Имена полей — идентификаторы.
Здесь token и name — строки, user — объект, id — идентификатор.
Ссылки и действия¶
Ссылка — идентификатор либо два идентификатора через точку.
| Запись | Куда указывает |
|---|---|
executeValidation | Локальное действие модуля. Отдельного реестра таких имён в 1.0 нет: имя само является объявлением |
AuthService.login | Метод login сервиса AuthService. Оба имени обязаны существовать |
AuthWorkflow.startLogin | Символ процесса AuthWorkflow. Процесс обязан существовать. Символ после точки может не совпадать с именем события |
Действие — одна ссылка или непустой список ссылок. Список выполняется в порядке записи. В примере переход API_SUCCESS выполняет saveToken, затем redirectToDashboard.
Привязка выхода и имя события
В каноническом примере выход onSubmit ссылается на AuthWorkflow.startLogin, а переход из Idle слушает событие SUBMIT_FORM. Каркас считает это допустимым: символ после точки — имя привязки, а не обязанное совпасть событие. В задании генератору нужно прямо сказать, какое событие шлёт выход. Для этого примера onSubmit шлёт SUBMIT_FORM.
Согласованность¶
Помимо JSON Schema, документ обязан выполнять правила ниже. Схема их не выражает: они связывают разные части файла.
- Имена компонентов модуля попарно различны.
- Каждое имя в
childrenесть средиnameкомпонентов. initial_stateесть среди ключейstatesтого же процесса.targetкаждого перехода есть среди ключейstatesтого же процесса.- Если ссылка начинается с имени сервиса и точки, после точки стоит имя метода этого сервиса.
- Если ссылка начинается с имени процесса и точки, такой процесс в модуле есть.
- Имена методов одного сервиса попарно различны.
- Имена входов одного компонента попарно различны. То же для выходов.
flowchart LR
LoginView["LoginView /login"] --> LoginForm
LoginForm -->|onSubmit| AuthWorkflow
AuthWorkflow -->|AuthService.login| AuthService Пример¶
Канонический файл: auth-module.fapl.yaml.
Описание модуля упоминает регистрацию и вход. Автомат примера раскладывает вход: состояния Idle, Validating, RequestingApi, Authenticated.
JSON Schema¶
Синтаксис документа проверяет схема fapl-1.0.schema.json (JSON Schema, draft 2020-12). Её идентификатор — https://bnd.by/fapl/examples/fapl-1.0.schema.json.
Схема проверяет набор полей, перечисления Page, Component, Final, String, ID, форму ссылок и запрет route у Component. Правила из раздела «Согласованность» применяются отдельным шагом после схемы.
Текст схемы
| fapl-1.0.schema.json | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | |
За пределами 1.0¶
Следующие вещи каркас сознательно оставляет снаружи, чтобы документ модуля оставался описанием поведения:
- исполняемый парсер и рантайм автомата;
- поля хуков React, стора Vue и любого другого фреймворка;
- TypeScript DSL с теми же сущностями;
- системная инструкция агента — её черновик лежит в обзоре, к грамматике языка она не относится;
- скалярные типы кроме
StringиID; - сценарий регистрации: строка
descriptionпримера его называет, отдельного автомата у него нет.