Skip to content

Контракт манифеста (v1)

Манифест задаётся в ryntExtensionViteConfig({ manifest }) и попадает в dist/manifest.json.

При сборке и загрузке лаунчер парсит манифест и валидирует contributes.rynt (схема v1 без requiresRegistries).

Обязательные и общие поля

ПолеОписание
idСтабильный id (@rynt/my-pack)
name, version, descriptionМетаданные (version может подтянуться из package.json при сборке)
mainEntry после сборки (index.js)
engines.ryntSemver-диапазон версии лаунчера
extensionApiВерсия контракта платформы: "1" (целое, не semver). См. 08-extension-api-versioning.md
versionSemver пакета (релиз, автообновление с каталога)

extensionApi

json
{
  "extensionApi": "1"
}
  • Одна поддерживаемая версия API: 1. В коде хоста: EXTENSION_API_VERSION = 1.
  • Не использовать ^1.0.0 / 1.0.0 — только major как строка.
  • Политика: API только расширяется, обратная совместимость сохраняется; лаунчер обновляется чаще расширений.
  • Проверка в лаунчере мягкая: required <= host → грузим; required > host → предупреждение (опционально не грузим в strict); отсутствие поля → считаем "1".
  • Подробнее и автообновление расширений по version: 08-extension-api-versioning.md.

extensionDependencies

json
{
  "extensionDependencies": {
    "@rynt/chats-calls": "^0.0.1"
  }
}
  • Ключ — manifest.id зависимости.
  • Значение — semver range; лаунчер проверяет совместимость с установленной версией зависимости.
  • Задаёт порядок выполнения setup (топологическая сортировка + проверка циклов).

Важно для 0.0.x: ^0.0.1 означает >=0.0.1 <0.0.2 (только патч внутри той же «минорной» тройки). Версия зависимости 0.0.2 такой диапазон не удовлетворяет. Для «0.0.1 и любой более новой 0.0.x» используйте >=0.0.1 или явный ^0.0.2.

Дополнительно резолвер может добавить implied зависимости: если расширение в extendsRegistries ссылается на чужой registryId, владелец должен загрузиться раньше (см. 03-launcher-resolution.md).

contributes.rynt.declaresRegistries

Реестры, которые создаёт это расширение (для себя и для других).

json
{
  "contributes": {
    "rynt": {
      "declaresRegistries": [
        {
          "id": "@rynt/chats-calls.message-types",
          "title": "Типы сообщений чата",
          "description": "Тело сообщения по ключу payload.type"
        }
      ]
    }
  }
}
ПолеОбязательноОписание
idдаregistryId (уникален среди declares в одном манифесте)
titleнетДля каталога / UI
descriptionнетДля каталога / UI

Не путать с пополнением: объявление не означает, что расширение не будет писать в свой же реестр (владелец часто регистрирует ключи text, build, … в setup).

contributes.rynt.extendsRegistries

Реестры, которые расширение пополняет, и какими ключами (для резолва, каталога и кнопки «установить слот»).

Формат (группировка по registryId):

json
{
  "contributes": {
    "rynt": {
      "extendsRegistries": [
        {
          "registryId": "@rynt/chats-calls.message-types",
          "keys": ["demo_ping"]
        },
        {
          "registryId": "core.nav",
          "keys": ["chats.main"]
        }
      ]
    }
  }
}
Правило валидации
registryId непустой
keys — массив, минимум один элемент
ключи уникальны внутри одного объекта
один registryId не дублируется в массиве extendsRegistries

Семантика: «это расширение заявляет, что при установке оно заполнит указанные слоты». Фактическая запись в runtime — через register в setup; расхождение манифест ↔ runtime — предупреждение в dev (не блокер в лаунчере).

requiresRegistries

Удалено из v1. Не использовать и не поддерживать в парсере. Используйте только extendsRegistries.

Примеры тестовых расширений

@rynt/chats-calls

  • declaresRegistries: @rynt/chats-calls.message-types, @rynt/chats-calls.input-toolbar
  • extendsRegistries: те же реестры с ключами встроенных типов + core.page / core.nav / …

@rynt/chats-message-sample

json
{
  "extensionDependencies": {
    "@rynt/chats-calls": "^0.0.1"
  },
  "contributes": {
    "rynt": {
      "extendsRegistries": [
        {
          "registryId": "@rynt/chats-calls.message-types",
          "keys": ["demo_ping"]
        },
        {
          "registryId": "@rynt/chats-calls.input-toolbar",
          "keys": ["demo_ping"]
        }
      ]
    }
  }
}

@rynt/optifine-marketplace

Только расширяет встроенный реестр (без declaresRegistries):

json
{
  "contributes": {
    "rynt": {
      "extendsRegistries": [
        {
          "registryId": "core.modProvider",
          "keys": ["optifine"]
        }
      ]
    }
  }
}

Соответствует коду: useModProviderRegistry().register('optifine', provider, …).

@rynt/quilt-loader / @rynt/json-editor

json
{
  "extendsRegistries": [
    { "registryId": "core.loader", "keys": ["quilt"] }
  ]
}
json
{
  "extendsRegistries": [
    { "registryId": "core.fileEditor", "keys": ["@rynt/json-editor/editor"] }
  ]
}

(точные строки ключей должны совпадать с register(...) в setup.)

Нормализация при загрузке

После parseRyntManifestJson:

  1. applyValidatedRyntContributesToManifest(manifest) — в discovery лаунчера и при emit dist/manifest.json в @rynt/extension-build.
  2. При ошибке — расширение не загружается / не публикуется в каталог.