Записи реестра

Запись реестра — это способ, которым бэкенд Wippy объявляет фронтенд-артефакт: либо микрофронтенд-приложение, либо переиспользуемый веб-компонент, чтобы Web Host мог обнаружить и раздать его. Этот документ описывает контракт между _index.yaml модуля, блоком wippy в его package.json и файлом wippy-meta.json, который их связывает.

Про настройку модуля wippy/views, который обрабатывает эти записи во время выполнения, см. Views.

Что такое запись реестра

Каждый фронтенд-артефакт объявляется как registry.entry в _index.yaml модуля. Маркер kind: registry.entry сообщает реестру Wippy, что эта запись несёт метаданные, потребляемые другими модулями, а не определяет напрямую Lua-компонент.

Частая ошибка: view.page и view.component — это не значения kind. Всегда пишите kind: registry.entry, а тип фронтенд-артефакта указывайте в meta.type. kind: view.page и kind: view.component — некорректные формы.

Минимально корректная форма:

- name: main
  kind: registry.entry
  meta:
    type: view.page
version: "1.0"
namespace: app.views

entries:
  - name: main
    kind: registry.entry
    meta:
      type: view.page
      name: main
      title: Admin Panel
      icon: tabler:layout-dashboard
      order: 0
      announced: true
      secure: false
      url: /app
      base_path: app/main
      entry_point: app.html
      mountRoute: /home/:part(.*)*

Блок meta — это то, что читает wippy/views. Поле meta.type различает два поддерживаемых вида артефактов.

Дискриминатор meta.type

Значение Смысл
view.page Микрофронтенд-приложение (полноценное SPA), отображаемое в iframe внутри Web Host
view.component Веб-компонент (пользовательский элемент), который можно встроить в любое место страницы

Все остальные поля meta интерпретируются в контексте этого типа. Поля, применимые к одному типу и неприменимые к другому, описаны на справочных страницах по типам (view.page, view.component).

Маркер specification

Каждый фронтенд-пакет, участвующий в реестре, объявляет "specification": "wippy-component-1.0" на верхнем уровне своего package.json. Эта строка — рукопожатие, сообщающее Wippy (и инструментам), что пакет следует контракту wippy-component: у него есть блок wippy известной формы и он собран с помощью @wippy-fe/vite-plugin.

{
  "name": "@wippy/app-main",
  "version": "1.0.0",
  "specification": "wippy-component-1.0",
  "wippy": { ... }
}

Наличие specification не меняет поведение во время выполнения, но wippy/views использует его при валидации записей, загруженных из реестра.

Контракт wippy-meta.json

@wippy-fe/vite-plugin выпускает файл wippy-meta.json рядом со собранным бандлом. Этот файл — канонический источник истины для рантайм-метаданных артефакта: схемы props, схемы событий, заголовка, иконки и настроек инъекции прокси.

Короткий ответ для агентов и инструментов:

  • Кто его выпускает: wippyPagePlugin() для приложений view.page и wippyComponentPlugin() для веб-компонентов view.component.
  • Кто его пишет: никто не пишет wippy-meta.json вручную; vite-плагин генерирует его из package.json.
  • Кто его потребляет: wippy/views читает его из корня раздаваемого бандла при построении дескрипторов страниц/компонентов и ответов API.
  • Что делает YAML: _index.yaml остаётся авторитетным для политики развёртывания и для любого поля, которое он явно переопределяет.

Когда wippy/views загружает registry.entry, он читает wippy-meta.json из корня раздаваемого бандла артефакта. Для страниц этот корень — url + base_path страницы; для веб-компонентов текущие записи раздают компонент напрямую из url. YAML всегда побеждает: _index.yaml имеет приоритет для каждого объявленного в нём поля. wippy-meta.json предоставляет значения по умолчанию, которые читает wippy/views, когда для данного поля нет переопределения в YAML. Поля политики развёртывания — announced, secure, url, mountRoute и base_path — должны задаваться в _index.yaml, поскольку выражают решения оператора, а не авторство компонента; поверхности для их описания в package.json/wippy-meta.json не существует. (base_path учитывается и для страниц, и для компонентов; текущие записи компонентов из app-template его просто опускают.)

Напротив, entry_point задаётся автором фронтенда и переопределяется в YAML. Он запекается в wippy-meta.json из блока wippy пакета — wippy.path для страниц (который @wippy-fe/vite-plugin требует; его отсутствие заставляет плагин выбросить wippy.path is required for a page package) либо wippy.tagName/browser для компонентов. Поле meta.entry_point в _index.yaml — необязательное переопределение поверх этого авторского значения по умолчанию для конкретного развёртывания; это не поле, существующее только в YAML.

Такое разделение означает, что автор компонента один раз описывает метаданные отображения в блоке wippy файла package.json, а vite-плагин запекает их в wippy-meta.json во время сборки как авторские значения по умолчанию. Оператор, развёртывающий компонент, задаёт маршрутизацию и политику доступа в YAML и может переопределить там же любое поле уровня отображения.

Общие поля

Эти поля присутствуют в блоке meta как для записей view.page, так и для view.component.

Поле Тип По умолчанию Описание
type string view.page или view.component (обязательно)
name string имя записи Идентификатор, используемый в ответах API
title string Человекочитаемое отображаемое имя
icon string Ссылка Iconify, например tabler:layout-dashboard
announced boolean Управляет видимостью в API списков; семантика зависит от типа (см. ниже)
secure boolean false Требует аутентификации для доступа
url string Базовый префикс URL для раздачи статических файлов (origin CDN или локальный путь монтирования)
entry_point string index.html / index.js Имя входного файла внутри статической директории

Семантика announced по типам

Флаг announced имеет разные последствия в зависимости от meta.type:

  • view.page: определяет, появляется ли страница в боковой панели навигации (GET /api/public/pages/list). Установка announced: false скрывает страницу из навигации, но страница по-прежнему загружается при прямом обращении. Это допустимый приём для встроенных или вспомогательных страниц.

  • view.component: управляет включением в GET /api/public/components/list. Если announced: false, компонент полностью исключается из этой конечной точки, а значит Web Host никогда не вставляет его тег скрипта и customElements.get(tagName) остаётся undefined. Для компонентов, которым нужна автозагрузка, требуется announced: true — подробности см. в view.component.

Как комбинируются поля раздачи

Для микрофронтенд-приложений три поля складываются в HTML-URL, который загружает Web Host:

<url>/<base_path>/<entry_point>

Например, при url: /app, base_path: app/main, entry_point: app.html хост запрашивает /app/app/main/app.html.

Разделение между base_path и entry_point сделано намеренно. Web Host вставляет <url>/<base_path>/ в загружаемую страницу как HTML-тег <base>, который определяет, как браузер разрешает все относительные URL внутри этой страницы. Входной файл может лежать в поддиректории базы — важно лишь, чтобы база указывала на общий корень, от которого относительно достижимы все ресурсы.

Например, если бандл имеет такую структуру:

static/
  shared/
    vendor.js
  app/
    index.html    ← entry_point: app/index.html
    app.js

и index.html ссылается на ../shared/vendor.js, то base_path должен указывать на static/ (директорию, содержащую и app/, и shared/), а не на app/. Установка base_path: app привела бы к тому, что ../shared/vendor.js разрешился бы за пределами раздаваемой директории и вернул 404.

В обычном случае, когда все ресурсы лежат рядом с входным файлом, base_path и директория, содержащая entry_point, находятся на одном уровне, поэтому различие незаметно. Оно имеет значение только тогда, когда бандл разделяет ресурсы между соседними директориями.

Для веб-компонентов хост составляет раздаваемый URL точно так же:

<url>/<base_path>/<entry_point>

Текущие записи компонентов из app-template опускают base_path, но он поддерживается и складывается тем же образом (<url>/<base_path>/<entry_point>) — поэтому в этих записях URL сворачивается до <url>/<entry_point>. Отличие от страниц в том, что компонент вставляется как <script type="module">, а не получает собственный вставленный HTML-тег <base>.