Кабинет

#Как устроен пакет

Пакет (в панели — «решение») — устанавливаемая единица функциональности. Одним нажатием он приносит на сайт справочники, модули, вёрстку, маршруты, права, пункты меню и обработчики событий.

Пакет — это не папка с файлами, которую надо куда-то положить. Это манифест — описание того, что должно появиться на сайте, — плюс, если нужно, файлы с логикой.

#Из чего состоит

packages/e-commerce/
  manifest.json      обязателен — описание решения
  src/               логика: обработчики маршрутов и событий
  README.md

Большинству решений хватает одного manifest.json. Решения «Портфолио», «Отзывы», «Вопросы и ответы», «Блок» — это только манифест: справочник, модуль и вёрстка, без единой строки кода.

#Манифест целиком

{
  "name": "Формы",
  "code": "form",
  "version": "1.9.0",
  "description": "Конструктор форм: поля, обязательность, действия после отправки.",
  "author": "Wacis",
  "core_version": ">=1.0.0",
  "dependencies": [],

  "dictionaries": [ … ],
  "modules":      [ … ],
  "routes":       [ … ],
  "permissions":  [ … ],
  "admin_menu":   [ … ],
  "listeners":    { … },
  "assets":       [ … ]
}
КлючЧто описывает
codeимя решения: латиница, цифры, дефис. Точка нельзя
versionровно три числа: 1.9.0. Растить при каждой выкладке
core_versionограничение по версии ядра — со знаком
dependenciesкоды решений, без которых это не работает
dictionariesсправочники и их поля
modulesмодули и их вёрстка
routesадреса, которые решение обрабатывает
permissionsправа доступа
admin_menuсвои пункты меню панели
listenersподписки на события
assetsфайлы стилей и скриптов
Частая ошибка

core_version без знака означает точное совпадение: "1.0.0" читается как «работает ровно на ядре 1.0.0», и решение не встанет ни на одно сегодняшнее. Почти всегда имеется в виду ">=1.0.0".

Подробный разбор каждого ключа — Манифест по частям.

#Что делает установщик

По шагам, в этом порядке:

  1. читает и проверяет манифест;
  2. сверяет core_version с версией ядра сайта;
  3. проверяет dependencies — недостающие ставит первыми;
  4. накатывает миграции решения;
  5. заводит справочники и их поля;
  6. вторым проходом связывает поля-выборки со справочниками;
  7. заводит модули с вёрсткой — в двух копиях: рабочей и исходной;
  8. регистрирует маршруты;
  9. регистрирует права;
  10. добавляет пункты меню;
  11. подключает слушателей событий;
  12. записывает установленную версию;
  13. включает решение.
Важно

На любом шаге может случиться отказ — тогда всё сделанное отменяется в обратном порядке. Это не общие слова: установка делает CREATE TABLE, а его нельзя откатить обычной транзакцией базы, поэтому установщик ведёт свой список сделанного и обратные действия к нему.

#Что установщик делает бережно

Три правила, о которые чаще всего спотыкаются авторы решений.

Чужой справочник не переписывается. Если справочник с таким именем уже есть, решение его не трогает — но недостающие поля добавляет. Иначе решение вставало бы «успешно», а его блок рисовал пустоту.

Тип поля молча не меняется. Разошёлся тип у существующего поля — меняют, только если хранилище то же (Текст → Выбор). Иначе предупреждают и не трогают: превращение текста в число обнулило бы часть значений.

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

#Что даёт связка решений

Решения соединяются не прямыми вызовами, а событиями. Так устроены crm-form, crm-ecommerce, crm-task-manager:

Формы          → событие  form.submitted
CRM и формы    → слушает  form.submitted → создаёт заявку
CRM            → событие  crm.lead.created
Задачи по CRM  → слушает  crm.lead.created → создаёт задачу

Поэтому «Формы» работают без CRM, а CRM — без задач. Ставите связку — появляется связь; снимаете — остальное продолжает работать.

Подробно — События.

#Дальше

#Что чаще всего идёт не так

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

«Установка отказала: „Модулю X нужен справочник Y, а его нет“». В манифесте модуль объявлен раньше своего справочника либо имя справочника написано с ошибкой. Справочники заводятся до модулей, но только те, что перечислены в этом же манифесте.

«Решение не встаёт: не подходит версия ядра». В core_version записано точное число вместо ограничения. Нужно ">=1.0.0", а не "1.0.0".

«Сняли решение — пропали данные». Значит снимали с отметкой «Удалить и справочники с содержимым». Обычное снятие данные оставляет.