Из чего состоит Framework
Framework складывается из исходников, готовых поставок, выпусков, пакетов компонентов продуктов, загрузчика и документации. Здесь — из чего состоит каждая часть и как они связаны.
Исходники и поставки
Framework разрабатывается в одном месте, а проектам отдаётся в виде готовых поставок.
| Репозиторий | Роль | Правится вручную |
|---|---|---|
simai/ui-source |
Исходники: Core, Loader, утилиты, компоненты, Smart-компоненты, порты хоста, их контракты и тесты | Да — единственное место правки |
simai/ui-builder |
Воспроизводимая сборка поставок и пакетов из исходников: инструмент sf-build (см. Сборка пакета: sf-build) |
Да |
simai/ui |
Поставка Framework: ядро, Loader, утилиты, компоненты, Smart-компоненты, правила загрузки (каталог distr/) |
Нет, генерируется |
@simai-studio/ui (npm) |
Тот же выпуск пакетом npm для подключения с CDN: ядро целиком, модули только в сжатой форме (см. Пакет npm) | Нет, издаётся из ui |
simai/ui-doc |
Публичная документация | Да |
Поставка ui содержит всё, что нужно странице. Core (distr/core) —
стили ядра, токены, темы, Loader и общая основа Smart-компонентов
(core/js/smart-base.js: одна на страницу, её используют все Smart-компоненты). Рядом лежат
утилиты (distr/utility), компоненты (distr/component), правила загрузки
(distr/rule) и Smart-компоненты (distr/smart). Smart-компоненты без Core не
работают.
Поставка ui получается только сборкой из исходников. Её не правят руками:
следующая сборка всё равно перезапишет правку.
Каждый выпуск ui издан и пакетом npm @simai-studio/ui; его версия
получается из времени коммита выпуска, а выпуск определяет коммит (см. Пакет npm).
Smart-компоненты, которые нужны одному продукту, в эти репозитории не входят: продукт хранит и поставляет их сам (см. Пакеты компонентов продуктов).
Выпуск
Поставка ui издаётся выпусками. Выпуск — одна сборка поставки, которая
проверена целиком: ядро, утилиты, компоненты и Smart-компоненты вместе. У
каждого выпуска есть идентификатор вида ui-<ревизия>, где ревизия — первые
12 знаков коммита сборки в ui, и запись о выпуске
contracts/releases/ui-<ревизия>.lock.json. Идентификатор выпуска — не тег
git: в адресах и закреплении проекта используется полный коммит из записи о
выпуске (см. Выпуск и запись о выпуске).
Проект закрепляет выпуск целиком. Ветка main и слово latest — не релиз:
они меняются без предупреждения. Подробно о поставке, выпусках и обновлении —
см. Что такое поставка, Версии: как закрепить выпуск и Как обновить проект.
Пакеты компонентов продуктов
Компонент живёт у своего владельца. Framework содержит универсальные
компоненты — те, что подходят любому проекту. Smart-компоненты, которые нужны
одному продукту, в том числе составные, хранит и поставляет этот продукт.
Такой набор называется пакетом продукта. Действующий пакет продукта —
larena: четыре элемента sf-table, sf-data-view, sf-property-view и
sf-admin-menu (описаны в справочнике Smart-компонентов). Его исходник —
папка components репозитория simai/larena-ui, открытая по лицензии
Apache-2.0. Пакет соответствует стандарту
simai.component-package (см. Пакет компонентов (simai.component-package)) и расширяет Framework только через
объявленные точки расширения (см. Принципы, принцип 8).
Действующее издание стандарта — 1.1.1; оно закрепляет схему манифеста 2.5.0.
Издание 1.0.0 закрепляло схему 2.2.0 и осталось в истории; требования те же.
Как устроен пакет продукта:
-
Где лежит исходник. В папке UI-репозитория продукта: в корне репозитория или в любой вложенной папке. Папка устроена так же, как исходники Framework:
src/smart/<папка>/— по папке на компонент (точка входаindex.js, правило загрузкиrule.js, манифестsmart.manifest.json, шаблоны и стили — как у компонентов Framework, см. Из чего состоит),tests/— тесты пакета. Сборка берёт из папки пакета толькоsrc/,tests/иdocs/. Пакет с одним компонентом целиком:acme-ui/ framework.lock.json ревизия Framework, к которой привязан пакет sf-build.config.json настройки сборки src/smart/acme-counter/ index.js класс компонента rule.js правило загрузки smart.manifest.json манифест js/templates/default.js встроенный шаблон js/templates/default.css стили шаблона tests/acme-counter.test.mjs тесты пакетаЧто пишется в каждом файле — ниже на этой странице, в Устройство компонента и в Манифест.
-
Импорты и стили. Компонент импортирует Framework относительными путями, как компоненты самого Framework. Базовый класс — экспорт по умолчанию модуля
smart-base, остальное — именованные экспорты:import SfBaseElement from '../../core/js/smart-base'; import {pageText} from '../../core/js/page-language'; import {html} from 'lit';Запись
import {SfBaseElement} from '../../core/js/smart-base'не работает: сборка проходит, но класс в модуле не определён, и элемент не регистрируется. Сборка кладёт пакет поверх исходников Framework, поэтому относительные пути разрешаются. Модули общей основы —litс его директивами,smart-base,page-language,position,control-spacing— в сборку компонента не попадают: на странице компонент берёт их из общей основы Smart-компонентов (см. Общая основа Smart-компонентов). Остальные импорты сборка включает в файл компонента.Стили компонента лежат рядом с шаблоном (
js/templates/default.css), шаблон импортирует их (import './default.css'), а правило объявляетcss: true; сборка выдаёт их файлом<папка>/css/<папка>.css. Стили пишутся в каскадных слоях Framework, как у его Smart-компонентов: оформление — в@layer sf.components, состояния — в@layer sf.states(см. Каскадные слои). -
К чему привязан. Файл
framework.lock.jsonв корне папки пакета закрепляет точную ревизию исходников Framework. Компоненты пакета опираются на базовый класс, вспомогательные модули и рендереры полей именно этой ревизии. Файл пакета не может заменить файл Framework: пакет только добавляет к нему.{ "schema": "simai.framework.product-package-source-lock.v1", "package": "shop", "source": { "repository": "simai/ui-source", "revision": "3029d8abda3899f055d91e1599e1c19a969e4369" } }schema— точно эта строка;source.repository— всегдаsimai/ui-source;source.revision— полный коммит исходников, из которых собран выбранный выпуск Framework (полеbuild_inputs.source.commitзаписи о выпуске, см. Выпуск и запись о выпуске; в примере — ревизия выпускаui-106d5901f8c3).packageнеобязателен; если он есть, он совпадает с именем пакета в сборке. Других полей сборка не читает. -
Правило компонента. Файл
src/smart/<папка>/rule.jsзаписывает ровно одно правилоcl-<папка>простыми данными, без регулярных выражений, функций и поляpackage:SF.RuleLoader['cl-catalog'] = { tags: ['shop-catalog'], type: 'smart', mode: 'smart', js: true, css: true, relation: [{name: 'cl-icons'}, {name: 'cl-pagination'}], };В
relationперечисляют всё, что компонент рисует из Framework: Smart- компоненты (cl-iconsдля тега<sf-icon>) и обычные компоненты, классы которых стоят в его шаблоне (buttonsдляsf-button,iconsдля классовsf-icon). Имя каждого правила — полеnameвdistr/rule/rule.jsonвыпуска. Без такой связи стили обычного компонента загружаются, только если он уже есть на странице: на пустой странице кнопки пакета остаются без оформления.Пропущенную связь находит сама сборка:
sf-build packageиsf-build verify packageперечисляют в предупреждениях каждый элемент Framework, который компонент рисует без связи с его правилом (тег в шаблоне, элемент изcreateElementилиSF.create, описаниеcomponent: {type: …}), и называют связь, которую нужно добавить. Элемент, который компонент загружает сам черезSF.Loader.ensureSmartElementLoaded, предупреждения не вызывает. Предупреждение сборку не останавливает.Из этих файлов сборка создаёт общий файл правил пакета (см. Пакеты компонентов).
-
Имена элементов. Новый элемент пакета получает префикс владельца, а не
sf-:shop-catalog, а неsf-catalog. Loader загружает любой тег, который перечислен в правиле пакета; тег без префиксаsf-может занять только правило пакета, поэтому имена Framework остаются за Framework. Компонент, перенесённый из Framework в пакет, сохраняет имя сsf-(см. Пакет компонентов (simai.component-package)): поэтому элементы пакетаlarenaназываютсяsf-table,sf-data-view,sf-property-viewиsf-admin-menu. Папку компонента называют так же, как тег, с префиксом владельца (acme-counter): правило пакета называется по папке (cl-acme-counter) и тогда не совпадёт с правилом Framework. -
Тесты.
sf-buildтесты пакета не запускает. Пакет прогоняет свои тесты и браузерные пробы на закреплённой ревизии и на своей сборке до её использования: деревоwave-1/overlayрабочего каталога сборки (его сохраняют параметры--workspaceи--keep-workspace, см. Сборка пакета:sf-build) — это исходники Framework с наложеннымиsrc/,tests/иdocs/пакета, и тесты пакета читают в нём те же пути, что и тесты Framework. Тесты пишутся, как тесты Framework, файламиtests/*.test.mjsдля встроенного средства запуска Node.js. Вwave-1/overlayкаталогtests/содержит и тесты Framework, поэтому файлы пакета передают явно, по их общему началу имени:node --test tests/acme-*.test.mjs. Манифесты пакета проверяетnode scripts/sf-contract.mjs buildв том же дереве: код 0 означает, что все манифесты соответствуют схеме. Зависимости вwave-1/overlayуже установлены сборкой: тесты иsf-contractзапускаются там без установки. Самый короткий тест пакета проверяет его манифест:// tests/acme-counter.test.mjs import test from 'node:test'; import assert from 'node:assert/strict'; import {readFileSync} from 'node:fs'; test('acme-counter declares its tag', () => { const manifest = JSON.parse(readFileSync('src/smart/acme-counter/smart.manifest.json', 'utf8')); assert.equal(manifest.custom_element, 'acme-counter'); }); -
Как собирается. Инструмент сборки Framework
sf-build(репозиторийui-builder, см. Сборка пакета:sf-build) накладывает папку пакета на закреплённую ревизию исходников и собирает пакет дважды; обе сборки обязаны совпасть побайтно. Результат — каталогsmart/: по каталогу на компонент (<папка>/js/<папка>.jsи, если у компонента есть стили,<папка>/css/<папка>.css, а рядом сжатые.min.jsи.min.css, которые Loader берёт по умолчанию) и файл правил пакетаrule.js. Собранные файлы получаются только сборкой и вручную не правятся. -
Как поставляется. Продукт кладёт собранный каталог
smart/в свою поставку и отдаёт его вместе с тем выпуском Framework, на котором пакет собран. Отдельного репозитория со сборками нет, и собранные файлы в git не хранятся: сборку пакетаlarenaприносит поставка Larena или выпуск репозиторияsimai/larena-ui, а какой выпуск Framework ей нужен, называет её квитанция (см. «Пакетlarenaдля проекта без Larena»). На странице пакет подключается как пакет компонентов Loader под именем продукта:SF_BOOT_CONFIG.packages.<имя> = {base: '<путь>/smart'}. Файл правил<base>/rule.jsLoader загружает сам (см. Пакеты компонентов). Путьbaseстраница получает от развёртывания: сценарий выкладки кладёт каталогsmart/под путём с ревизией пакета из квитанции (package_source.revision) и записывает этот путь в настройку страницы или в шаблон, который выводитSF_BOOT_CONFIG, — так путь и квитанция меняются вместе. -
Квитанция пакета. Каждая сборка пакета сопровождается квитанцией, по которой проект закрепляет пакет (описание квитанции — ниже).
-
Лицензия. Компоненты пакета распространяются по лицензии продукта. Framework (
ui) распространяется по лицензии Apache 2.0 (см. Принципы).
Квитанция пакета — файл package-receipt.json. Имя формата
simai.framework.product-package-receipt записано в поле schema_id (не
schema), старшая версия — в поле schema_version. Она записывает, что
собрано, поверх чего, чем и с каким результатом:
| Поле | Что записано |
|---|---|
package |
Имя пакета |
loader |
Как объявить пакет на странице: SF_BOOT_CONFIG.packages.<имя>.base, каталог smart, файл правил smart/rule.js |
package_source |
Репозиторий, ревизия и путь папки пакета, git-дерево этой папки |
framework |
Ревизия исходников Framework и выпуск ui-<ревизия>, собранный из неё (null, если такого выпуска нет) |
builder |
Ревизия сборщика и признак чистого рабочего дерева |
node |
Версия Node.js, на которой шла сборка |
output |
Число файлов, контрольная сумма списка всех файлов (manifest_sha256), имя и контрольная сумма архива package-<имя>.tar (archive_sha256) |
required_files |
Файлы, которые обязаны быть на месте: файл правил, скрипт каждого компонента и его стили, если правило их объявляет; у каждого — SHA-256 и размер |
inventory |
Число компонентов и правил; для каждого тега — правило, папка, наличие JS и CSS, связи |
package_reference |
Результат сверки со справкой о пакете в выпуске Framework — объект {path, release, status}, где status — agrees, absent, no-release или not-checked. absent — обычное значение для нового пакета, справки о котором в выпуске Framework нет; сборка при этом только предупреждает |
files |
SHA-256 и размер каждого файла пакета |
claims |
production_ready: false: квитанция не объявляет пакет готовым к промышленной эксплуатации |
Сборку и квитанцию выполняет одна команда sf-build package: она собирает
пакет дважды, выписывает квитанцию и кладёт в выходной каталог собранный
каталог smart/, package-receipt.json и детерминированный архив
package-<имя>.tar (см. Сборка пакета: sf-build).
Что важно заметить:
- Квитанция выписывается только для сборки, которая прошла проверку и совпала побайтно в обоих проходах.
- С параметром
--uiквитанция дополнительно сверяет пакет с выпуском Framework: каждая связь правила пакета ведёт к правилу пакета или выпуска, ни один тег пакета не совпадает с тегом Framework, а справка о пакете в выпуске (distr/core/contracts/packages/<имя>.package.json), если она есть, совпадает с правилами пакета. Отсутствие справки — предупреждение, а не ошибка. - Проект закрепляет выпуск Framework и пакет вместе (см. Версии: как закрепить выпуск). В своей
записи он хранит из квитанции
package,package_source.revision,framework.release,output.manifest_sha256(илиoutput.archive_sha256) и контрольные суммыrequired_files; проверка проекта сверяет с ними файлы, которые отдаёт сервер. - Чтобы перевести пакет на новый выпуск Framework, сначала выходит выпуск
Framework; затем
framework.lock.jsonпакета указывает на ревизию исходников этого выпуска, пакет проходит свои тесты, собирается заново и получает новую квитанцию.
Что остаётся во Framework: порты хоста и их наборы проверок, рендереры полей и части редактора композиции. Компонент продукта работает с данными через публичный порт Framework (см. Порт хоста и Порты и наборы проверок), поэтому приложение реализует и проверяет свой хост по открытому контракту.
Сборка пакета: sf-build
sf-build — инструмент, которым собираются Framework и пакеты
компонентов. Он лежит в репозитории ui-builder и состоит из командной
строки (bin/sf-build.js) и Node API (libs/api.js). Командная строка
только разбирает параметры и вызывает те же функции API, поэтому оба способа
дают один и тот же результат.
Доступ. Репозитории ui-builder и ui-source открыты и
распространяются по лицензии Apache 2.0, как и поставка ui. Сборка пакета
требует обе рабочие копии (см. «Условия запуска» ниже). Пакет собирается из
открытых исходников для выпусков, начиная с ui-82fc0ba882ba: их ревизии
исходников лежат в simai/ui-source. Ревизии более ранних выпусков хранятся
в закрытом архиве истории исходников, и пакет под такой выпуск собирается
только с доступом к нему, который даёт команда Framework.
sf-build проверяет устройство пакета, правила, воспроизводимость и
квитанцию. Манифесты компонентов он не проверяет: соответствие манифеста схеме
2.5.0, которую закрепляет стандарт пакета (требование manifest-conforms, см. Пакет компонентов (simai.component-package)) держат тесты пакета.
Команды
| Команда | Что делает | Что кладёт в --out |
|---|---|---|
sf-build package |
Собирает пакет дважды поверх ревизии исходников Framework, закреплённой в framework.lock.json, сравнивает обе сборки и выписывает квитанцию |
smart/…, package-receipt.json, package-<имя>.tar |
sf-build framework |
Собирает Core, компоненты, утилиты и Smart-компоненты из рабочей копии ui-source дважды и сравнивает обе сборки |
core/, component/, utility/, smart/ и отчёт build-report.json |
sf-build verify package, sf-build verify framework |
Только двойная сборка и сравнение | Ничего; параметр --workspace сохраняет обе сборки |
sf-build receipt --report <report.json> |
Выписывает квитанцию для уже проверенной сборки пакета по её отчёту | С --out — то же, что sf-build package |
sf-build --help перечисляет все параметры. Основные из них:
--config, --name, --package-root, --package-revision,
--package-repository, --ui-source, --ui, --out, --replace-out,
--workspace, --keep-workspace, --json.
Файл настроек sf-build.config.json
Продукт хранит рядом с папкой пакета или в корне репозитория файл
sf-build.config.json (формат simai.sf-build.config, файл схемы
schemas/sf-build.config.v1.schema.json в ui-builder). Пример собирает
пакет acme из папки resources/ui:
{
"schema": "simai.sf-build.config.v1",
"package": { "name": "acme", "kind": "components", "path": "resources/ui" },
"framework": { "source": "../ui-source" },
"out": "public/vendor/acme-ui"
}
| Поле | Обязательно | Что задаёт |
|---|---|---|
schema |
да | Имя формата simai.sf-build.config с меткой версии, как в примере (см. Имена и версии) |
package.name |
да | Имя пакета: ключ в SF_BOOT_CONFIG.packages и имя, которое регистрирует файл правил. Строчные латинские буквы, цифры и дефис; начинается с буквы |
package.kind |
да | Вид пакета: components — пакет компонентов |
package.path |
нет | Папка пакета (framework.lock.json и src/smart/<папка>/). По умолчанию — каталог файла настроек |
package.revision |
нет | Коммит репозитория пакета, который собирается. По умолчанию HEAD. Сборка читает только закоммиченные файлы, а не рабочее дерево |
package.repository |
нет | Идентификатор репозитория для квитанции, например simai/acme. По умолчанию берётся из удалённого репозитория origin на GitHub |
framework.source |
нет | Рабочая копия ui-source, в которой есть ревизия из framework.lock.json пакета |
framework.ui |
нет | Рабочая копия ui: квитанция называет выпуск, собранный из закреплённой ревизии, и сверяет с ним пакет. Выпуск ищется по записям о выпусках в рабочем дереве, поэтому копия стоит на коммите, где запись уже есть, — на текущей ветке main (см. Выпуск и запись о выпуске) |
out |
нет | Выходной каталог |
workspace |
нет | Каталог для двух сборок; при каждом запуске новый. Лежит вне ui-builder, вне репозитория пакета и вне ui-source. По умолчанию — временный каталог |
Правила файла настроек:
- других полей схема не принимает: файл с лишним полем отклоняется;
- относительные пути отсчитываются от каталога, в котором лежит файл;
- параметр командной строки или API важнее переменной окружения
(
SF_BUILD_UI_SOURCE,SF_BUILD_UI), а переменная окружения важнее файла. Так сборка на сервере указывает свои рабочие копии, не меняя файл; - без
--configкомандыpackageиverify packageберутsf-build.config.jsonиз текущего каталога, если он там есть.
Выходной каталог --out
--out (или поле out) — каталог, куда кладётся результат. Для пакета там
оказываются:
smart/— собранные компоненты (smart/<папка>/js/<папка>.js,smart/<папка>/css/<папка>.css) и файл правилsmart/rule.js. Этот каталог страница объявляет какSF_BOOT_CONFIG.packages.<имя>.base(см. Пакеты компонентов);package-receipt.json— квитанция пакета (см. Пакеты компонентов продуктов);package-<имя>.tar— детерминированный архив той же сборки.
Правила выходного каталога:
- результат собирается рядом во временном каталоге, перепроверяется по
контрольным суммам квитанции и только после этого занимает место
--out; - непустой
--outзаменяется только с параметром--replace-outи только если в нём лежит файл, который кладёт самsf-build(package-receipt.jsonилиbuild-report.json). Каталог, которыйsf-buildне создавал, не удаляется; --outне может содержать сборщик, папку пакета или рабочую копиюui-sourceи не может лежать в рабочем каталоге сборки;- рабочий каталог
--workspaceещё не существует и лежит внеui-builder, вне всего репозитория пакета и внеui-source. Каталог внутри репозитория пакета (например,build/рядом с исходником) отклоняется с кодом2(USAGE) и сообщением:workspace root must be outside the builder, the package repository and ui-source; sf-build packageтребует--outили--workspace. Без--outсборка и квитанция остаются в рабочем каталоге;- временный рабочий каталог удаляется после успешного запуска, который
положил результат в
--out, и сохраняется после ошибки для разбора.
Результат --json
С параметром --json команда печатает в стандартный вывод один JSON-документ
в формате simai.sf-build.result. Node API возвращает тот же объект. Без
--json команда пишет ход работы в поток ошибок и краткий итог в конце.
| Поле | Что значит для вызывающей сборки |
|---|---|
status |
PASS или FAIL — единственный признак успеха |
exit_code |
Код завершения (таблица ниже) |
error |
null при успехе; иначе {code, message} — причина отказа |
out.runtime |
Путь к <out>/smart: его продукт отдаёт как SF_BOOT_CONFIG.packages.<имя>.base |
out.receipt |
Путь к <out>/package-receipt.json: его продукт закрепляет |
out.archive |
Путь к архиву package-<имя>.tar |
output.manifest_sha256, output.archive_sha256 |
Контрольные суммы списка файлов и архива — те же, что в квитанции |
framework.release |
Выпуск Framework, собранный из закреплённой ревизии, или null, если он не определён |
package_reference |
Результат сверки со справкой о пакете в выпуске (см. Пакеты компонентов) |
warnings |
Предупреждения, которые не остановили сборку |
Коды завершения
| Код | Что произошло | error.code |
|---|---|---|
0 |
Собрано, обе сборки совпали, квитанция выписана, результат положен | — |
1 |
Сборка не прошла или сборки различаются | BUILD_FAILED, NOT_REPRODUCIBLE, OUTPUT_MISMATCH |
2 |
Ошибка параметров, файла настроек или выходного каталога | USAGE, CONFIG_INVALID, KIND_NOT_SUPPORTED, OUT_CONFLICT, WORKSPACE_CONFLICT |
3 |
Квитанция отклонила пакет: он расходится с выпуском Framework | RECEIPT_REFUSED |
4 |
Окружение не подходит | UNSUPPORTED_NODE, TOOL_MISSING, BUILDER_NOT_A_CHECKOUT |
Node API
Модуль <ui-builder>/libs/api.js экспортирует функции buildPackage,
verifyPackage, buildFramework, verifyFramework, writeReceipt,
loadConfig и validateConfig, а также EXIT_CODES, RESULT_SCHEMA и
SfBuildError. Имена параметров — параметры командной строки в
верблюжьей записи: packageRoot, packageRevision, packageRepository,
uiSource, ui, out, replaceOut, workspace, keepWorkspace; кроме
них — config, cwd (основа относительных путей), env и
onProgress(message). Пример собирает пакет из сценария сборки продукта на Node.js
(модуль ES, файл build-ui.mjs):
import sfBuild from '/path/to/ui-builder/libs/api.js';
const result = await sfBuild.buildPackage({
config: 'sf-build.config.json',
out: 'public/vendor/acme-ui',
replaceOut: true,
onProgress: (message) => console.error(message),
});
if (result.status !== 'PASS') {
throw new Error(`${result.error.code}: ${result.error.message}`);
}
Что важно заметить: функция не бросает исключение при ожидаемом отказе —
ошибке сборки, отклонённой квитанции или неверном параметре. Она возвращает
объект с status: "FAIL", поэтому сборка продукта проверяет status.
Как сборка продукта вызывает sf-build
Сборка продукта вызывает sf-build одним из двух способов:
- из своего сценария сборки — командой
node <ui-builder>/bin/sf-build.js package --replace-out --json, запущенной в каталоге сsf-build.config.json; результат читается из стандартного вывода как JSON; - из своего кода на Node.js — через
buildPackage(пример выше).
После успешной сборки продукт отдаёт каталог out.runtime как
SF_BOOT_CONFIG.packages.<имя>.base рядом с выпуском Framework, который
называет квитанция, и закрепляет квитанцию out.receipt вместе с выпуском
(см. Версии: как закрепить выпуск).
Условия запуска
sf-buildзапускается из рабочей копии репозиторияui-builder, полученной черезgit cloneили лежащей рядом локально, с установленными зависимостями (yarn install --frozen-lockfile). Инструмент записывает в каждый отчёт коммит сборщика; копия без.gitотклоняется с кодомBUILDER_NOT_A_CHECKOUT;- сборщик закрепляют, как выпуск: выпуск Framework собран коммитом
ui-builderиз поляbuild_inputs.builder.commitсвоей записи о выпуске (см. Выпуск и запись о выпуске), и пакет к этому выпуску собирают тем же коммитом или более новым; квитанция записывает коммит в полеbuilder; - нужны Node.js версии 20.19.0 или новее и
git; - квитанцию выписывает
python3: он нужен командамpackageиreceipt; - сборке пакета нужна рабочая копия
ui-source, в которой есть ревизия, закреплённая вframework.lock.jsonпакета (--ui-source,SF_BUILD_UI_SOURCEилиframework.source); - каждая из двух сборок устанавливает зафиксированные зависимости сборщика заново, поэтому нужен кеш Yarn или доступ к сети.
Пакет темы
Кроме пакета компонентов sf-build собирает пакет темы — свои цвета сайта или
продукта, посчитанные так же, как Framework считает собственные. Пакет темы —
папка с двумя файлами:
framework.lock.json— ревизияui-source, чьи правила темы берутся, как у пакета компонентов;theme.json—{"schema": "simai.framework.theme-source", "schema_version": 1}и либоcolor(#rgbили#rrggbb), либоhueиchroma; необязательныеselector(по умолчанию:root) иpalettes— свои{hue, chroma}для отдельных палитр (primary,secondary,tertiary,neutral,error,warning,success,info).
{"schema": "simai.framework.theme-source", "schema_version": 1, "color": "#2e7d32", "selector": ":root"}
Сборка — модуль src/core/js/theme-palette.js закреплённой ревизии, тот же
расчёт, что у генератора темы: дважды, с
побайтным сравнением. Результат в --out:
| Файл | Что в нём |
|---|---|
theme/theme.css |
одно правило переменных темы под selector |
theme/theme.json |
тема целиком: каждая палитра и её тона |
theme-receipt.json |
квитанция simai.framework.theme-receipt: из чего собрано и хеши файлов |
node <ui-builder>/bin/sf-build.js package --kind theme \
--package-root brand-theme --package-revision <коммит> \
--ui-source <ui-source> --out build/brand-theme --json
Вид пакета задают --kind theme или package.kind: "theme" в
sf-build.config.json. Проект подключает theme/theme.css после core.css.
Пакет larena для проекта без Larena
Каждая сборка пакета larena публикуется выпуском открытого репозитория
simai/larena-ui: выпуск
называется larena- и первыми двенадцатью знаками коммита пакета. В выпуске
три файла: архив package-larena.tar, его SHA-256 в
package-larena.tar.sha256 и квитанция package-receipt.json, которая
называет выпуск Framework, рядом с которым пакет работает. Сборку для своего
выпуска Framework выбирают по квитанции: подходит выпуск репозитория, в
квитанции которого framework.release равно выпуску проекта. Проект без
Larena берёт пакет оттуда:
commit=5f33ba576aebde377d5195ec71836eb4430aa84d
tag="larena-${commit:0:12}"
gh release download "$tag" --repo simai/larena-ui \
--pattern 'package-larena.tar*' --pattern package-receipt.json
shasum -a 256 -c package-larena.tar.sha256
mkdir -p "public/assets/larena/$commit"
tar -xf package-larena.tar -C "public/assets/larena/$commit"
Без gh те же файлы скачиваются по адресу
https://github.com/simai/larena-ui/releases/download/<выпуск>/<файл>.
Архив разворачивает папку smart/; её адрес и объявляют на странице:
SF_BOOT_CONFIG.packages.larena = {base: '/assets/larena/<коммит пакета>/smart'}.
Если SHA-256 не совпадает, архив не разворачивают.
Ту же сборку можно воспроизвести из исходников командой sf-build package при
тех же условиях запуска: архив получится байт в байт тем же, и его SHA-256
совпадёт с опубликованным. Нужны три открытых репозитория на закреплённых
ревизиях: simai/ui-builder (сборщик; установка зависимостей и команда — в
его README), simai/ui-source (исходники
Framework на ревизии, которую закрепляет components/framework.lock.json
пакета, для этого выпуска — 3029d8abda3899f055d91e1599e1c19a969e4369) и simai/larena-ui
(исходник пакета).
Пример воспроизведения — для выпуска ui-106d5901f8c3; <ui-builder>, <ui-source> и <ui> —
пути к рабочим копиям, <ui> стоит на текущей ветке main.
-
Сборка. Папка пакета —
componentsрепозиторияsimai/larena-ui, ревизия — коммит пакета, собранного для выпуска (см. Выпуск и запись о выпуске):Сборщик стоит на коммите, которым собран пакет (поле сборщика в его квитанции); он может быть новее сборщика выпуска Framework. Для этого пакета —
git -C <ui-builder> checkout 7d57d9b45549e7f6b7bc4e615ccf80a3f35cedc3.git clone https://github.com/simai/larena-ui.git git -C larena-ui checkout 5f33ba576aebde377d5195ec71836eb4430aa84d node <ui-builder>/bin/sf-build.js package --name larena \ --package-root larena-ui/components \ --package-revision 5f33ba576aebde377d5195ec71836eb4430aa84d \ --package-repository simai/larena-ui \ --ui-source <ui-source> --ui <ui> --out build/larena --json -
Проверка квитанции. Команда завершается с кодом
0иstatus: "PASS". Вbuild/larena/package-receipt.jsonполеframework.releaseравноui-106d5901f8c3,package_source.revision— коммиту из шага 1, аpackage_reference.status—agrees. -
Подключение. Каталог
build/larena/smartкладут в публичную папку проекта под путём с коммитом пакета, напримерpublic/assets/larena/5f33ba576aebde377d5195ec71836eb4430aa84d/smart/, и объявляют доcore.js:window.SF_BOOT_CONFIG = { packages: {larena: {base: '/assets/larena/5f33ba576aebde377d5195ec71836eb4430aa84d/smart'}}, };В файл блокировки проекта переписывают
output.manifest_sha256из квитанции этой сборки (см. Версии).
Loader
Loader — модуль Core, который подключается вместе с core.js (отдельного
файла загрузчика проекту подключать не нужно). После запуска он доступен как
SF.Loader и делает три вещи:
- находит на странице классы утилит и компонентов и теги Smart-компонентов — по правилам загрузки из поставки;
- загружает только нужные модули, по умолчанию в сжатом виде: класс
sf-buttonподтягивает компонент кнопки, тег<sf-button>— Smart-кнопку, её зависимости и общую основу Smart-компонентов; - следит за страницей и подгружает то, что появилось позже, например после ответа сервера.
Где лежат файлы, Loader узнаёт из глобальной переменной window.sfPath
(каталог distr/ поставки), заданной до core.js; Smart-компоненты он берёт
из <sfPath>/smart/. Поведение загрузки настраивается объектом
window.SF_BOOT_CONFIG; в нём же объявляются пакеты компонентов, например
пакет продукта (см. Пакеты компонентов продуктов). Все настройки и их значения по умолчанию — см. Глобальные настройки;
как Loader находит и загружает модули — Как работает Loader; пакеты компонентов — Пакеты компонентов.
Документация
Документация (ui-doc) — сайт с руководством и тремя справочниками:
утилиты, компоненты, Smart-компоненты. Руководство объясняет, справочники
перечисляют точные классы, настройки и события. Документация привязана к
конкретному выпуску поставки и проверяет, что её страницы не отстали от кода. Для
ИИ сайт публикует машиночитаемый индекс ai.json и Markdown-версии страниц.