Перейти к содержанию
Mercury
Русский
Дизайн книга
Меню
Русский

Hypergraph, ядро управления состоянием

Планировщик и исполнитель графа, который пакетно выполняет связи модели до состояния покоя, без промежуточных несогласованных значений, с изолированными областями состояния (scope), эффектами (effect) и единым интерфейсом наблюдения.

Hypergraph — ядро управления состоянием Mercury: пакет @fiberfx/hypergraph версии 4.0.0 без зависимостей. Модель — граф единиц Hypergraph (unit), который выполняет ядро.

Что такое Hypergraph

Hypergraph — планировщик и исполнитель графа. Он пакетно выполняет связи модели до состояния покоя, без промежуточных несогласованных значений, с изолированными областями, эффектами и единым интерфейсом наблюдения. Его отличают три свойства:

  • По замыслу за идентичность отвечает компилятор. У каждой единицы есть стабильный идентификатор sid и описание структуры (shape), чтобы хранилище (store) можно было снова найти после правки, при серверном рендеринге или в другой среде выполнения. Сегодня проход компилятора, назначающий sid, обрабатывает только вызовы прежнего фасада, а не Hypergraph. Поэтому у единицы Hypergraph есть sid лишь тогда, когда вы задали его сами; без этого она получает идентификатор времени выполнения api:<n>, пока её не именует компилятор. Пока компилятор не выдаёт и описания структуры, ядро определяет структуру каждого хранилища по его начальному значению.
  • Связи представлены данными. Единицы и рёбра модели образуют граф, который загружает ядро, поэтому браузер, сервер и тест могут выполнять одно и то же описание.
  • Семантика задана тестовыми векторами. Требуемое поведение ядра описано 467 векторами проверки соответствия, объединёнными в 19 семейств. Каждая среда выполнения, содержащая область состояния, запускает те же файлы; утверждение о соответствии опирается на результат этих проверок.

Имена API

  • Единицы называются по своему виду: store, event и effect — хранилище, событие (event) и эффект. Эффект принимает обработчик напрямую.
  • Связи: sample — единый примитив композиции. combine объединяет обновления своих источников через барьер. Его дополняют split, attach, merge и restore, а также методы единиц on, reset, map, filter, filterMap и prepend.
  • Области состояния: fork создаёт изолированную область, allSettled выполняет в ней работу, а scopeBind привязывает к ней функцию. snapshot возвращает кадр состояния (frame) со структурой каждого значения; apply приводит область к состоянию кадра; diff описывает изменения между двумя кадрами; dispose завершает работу области.
  • Наблюдение: watch(unit, fn, {scope}) принадлежит своему поколению. При замене графа модели наблюдатели старого поколения завершаются вместе с ним.
  • Виды: kindOf возвращает store, event, effect, scope либо ничего.
import { event, store } from "@fiberfx/hypergraph";

const increment = event<number>();
export const $count = store(0, { name: "$count" }).on(increment, (count, by) => count + by);

Пути экспорта

  • @fiberfx/hypergraph: единицы, связи, кадры состояния области и типы.
  • @fiberfx/hypergraph/node: nodeCarrier, сохраняющий контекст области состояния через await на сервере JavaScript. Он вынесен в отдельную точку входа, чтобы браузерный код не импортировал серверные модули.
  • @fiberfx/hypergraph/inspect: inspect и describe, а также типы Observation, Declaration, Kind и ResetReason.

Ещё два пути пока запланированы и не экспортируются: /hyperscript — интеграция с Mercury Hyperscript (useUnit, Provider), и /hmr — горячая замена.

Что происходит при правке в mx dev

Когда mx dev начнёт доставлять замену, сохранение правки модели будет заменять её граф, а не перезагружать страницу. Если изменились только тела функций, замена выполняется на месте: область состояния, её значения и выполняющийся эффект сохраняются. Любая другая правка загружает новое поколение графа, переносит каждое хранилище с совпадающими sid и структурой, а затем завершает старое поколение вместе с его наблюдателями.

Для каждого хранилища, которое не перенесено, указывается причина:

  • removed — удалено: ни одно хранилище нового графа не использует его sid;
  • shape changed — изменилась структура: тот же sid присутствует с другой структурой; указываются обе структуры;
  • renamed — переименовано: только подсказка, которая никогда не применяется автоматически; возникает, если ровно одно удалённое и одно новое хранилище имеют одинаковое имя;
  • positional — позиционный идентификатор: ключ получен из положения в файле, а после изменения файла это не доказывает, что хранилище осталось тем же.

Хранилище, объявленное только в новом графе, помечается new — новое: оно начинает с исходного значения, ничего не потеряно, поэтому это информационное сообщение, а не сброс.

Главы

Читайте их по порядку: каждая опирается на предыдущие.

  • Единицы: store, event и effect. Модель состоит из трёх видов единиц, названных по видам, которые записаны в графе. Хранилище содержит значение, событие передаёт данные, эффект запускает обработчик и завершается.
  • Связи: от единиц к графу. Связи объединяют единицы в граф. sample — примитив композиции; combine соединяет хранилища через барьер; split, attach, merge и restore дополняют набор.
  • Области состояния: создать, завершить работу, передать. Область — изолированная копия состояния модели для серверного запроса, теста или корня на странице. Её кадры содержат каждое значение по sid, вместе со структурой, поэтому кадр из одной сборки можно применить в другой.
  • Наблюдение: watch, inspect, describe. Два способа наблюдать модель. watch вызывает функцию при обновлениях единицы; inspect в отдельной точке входа — единый интерфейс для инструментов, где каждое обновление, пропуск, ошибка, объявление, запуск эффекта и сброс представлены наблюдением.
  • Виды, перенос контекста и ошибки. Три небольших механизма, обеспечивающих корректную работу модели. kindOf отличает единицу от области состояния, переносчик контекста сохраняет область через await, а каждый отказ представлен HypergraphError с одинаковым для всех сред выполнения кодом.
  • Горячая замена. Правка модели должна сохранять состояние, которое вы видели, и точно сообщать, что сохранить не удалось. Hypergraph принимает решение для каждого хранилища по sid и структуре и указывает причину потери каждого значения.
  • Серверный рендеринг: область на каждый запрос. На сервере множество запросов одновременно используют одну модель. Каждый получает собственную область состояния, дожидается завершения её работы и передаёт значения браузеру кадром с ключами sid; клиент применяет его к своей области.
  • Тестирование модели: область на каждый тест. Тест — это область состояния. Создайте её, задайте нужные тесту обработчики эффектов, запустите работу через allSettled и прочитайте результат из значений области или наблюдений. Тестовые векторы соответствия выражают тот же подход в данных.
  • Большие модели: структура и идентичность. Реальная модель состоит из многих модулей, множества хранилищ и нескольких эффектов. Правила ядра об идентичности, производных единицах и областях состояния определяют организацию модели: она должна тестироваться в отдельной области, передаваться кадром состояния и переживать правки.
  • Итоговая работа: передача и восстановление модели. Весь курс в одном файле и одном тесте. Постройте модель из экспортов, запустите её в области состояния, получите кадр, приведите новую область к этому кадру и докажите, что состояния совпадают.

Переход с Effector

Если вы знаете Effector, руководство сопоставит знакомые понятия с Hypergraph: где находится каждое понятие, какие имена изменились и какие исчезли. Effector выведен из использования; здесь он нигде не импортируется.

  • Переход с Effector. Большая часть знаний пригодится. Единицы называются по своему виду, область состояния обменивается кадрами, а некоторые имена Effector удалены окончательно.
  • Единицы и связи. Конструкторы переименованы, а связи — нет. sample остаётся единым примитивом композиции.
  • Области состояния и тестирование. fork, allSettled и scopeBind остаются на своих местах. Теперь из области передаётся кадр состояния.
  • Фреймворки после effector-react. У Mercury один слой представления — Hyperscript. Его интеграция с Hypergraph появится следующим шагом; пока компонент читает хранилище через уже существующий хук Hyperscript.

Что реализовано

Ядро, его API и механизм замены реализованы внутри @fiberfx/hypergraph. Версия 4.0.0 доступна в npm с 2026-11-05. mx dev пока не доставляет замену: это следующий шаг, а до него правка модели перезагружает страницу.