Skip to Content
👋 Добро пожаловать в документацию lite-fsm!
Пакеты@lite-fsm/graph

@lite-fsm/graph

@lite-fsm/graph строит статическое описание машин lite-fsm. Пакет читает TypeScript-код, находит createMachine и MachineManager, собирает граф состояний, переходов, событий, эффектов и связей между машинами.

Пакет нужен для анализа, визуализации, автоматических проверок и инструментов для конечных автоматов. Он не запускает приложение, не вызывает пользовательские reducer, effect и guard-условия и не выполняет пользовательский код.

Пакет находится в alpha-версии.

Установка

npm install --save-dev @lite-fsm/graph

Импорты

import { analyzeLiteFsmGraph, compileLiteFsmGraph, compileLiteFsmGraphProject, selectMachineGraph, } from "@lite-fsm/graph"; import { createGraphSimulator } from "@lite-fsm/graph/simulator"; import { buildGraphVisualizerModel } from "@lite-fsm/graph/view-model";
ИмпортНазначение
@lite-fsm/graphКомпилятор, компилятор проекта, выбор машины, анализатор и основные типы графа
@lite-fsm/graph/simulatorСимуляция событий поверх готового графа
@lite-fsm/graph/view-modelМодель данных для интерфейса визуализации

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

Основной результат работы пакета — LiteFsmGraphDocument.

type LiteFsmGraphDocument = { version: "lite-fsm.graph/v1"; source: GraphSource; machines: LiteFsmGraphMachine[]; managers: LiteFsmGraphManager[]; diagnostics: GraphDiagnostic[]; };

Документ содержит:

  • machines — найденные машины, их состояния, переходы, reducer-ветки и события из effects.
  • managers — найденные MachineManager и ключи, под которыми машины подключены к менеджеру.
  • diagnostics — сообщения компилятора о неполном, неоднозначном или неподдержанном коде.
  • source — сведения об исходнике: язык, имя файла, список файлов проекта и хеш (hash), если он доступен.

LiteFsmGraphDocument — обычные данные. Его можно сериализовать в JSON, сохранить в файл, передать в визуализатор или использовать в тестах.

Общий поток работы

import { analyzeLiteFsmGraph, compileLiteFsmGraph } from "@lite-fsm/graph"; import { createGraphSimulator } from "@lite-fsm/graph/simulator"; const compiled = compileLiteFsmGraph(source, { filename: "store/machines/order.ts", }); const analysis = analyzeLiteFsmGraph(compiled.document); const simulator = createGraphSimulator(compiled.document); const started = simulator.start(); if (!started.ok) { console.log(started.diagnostics); } console.log(compiled.document.machines); console.log(analysis.diagnostics);

Обычно работа делится на три шага:

  1. Компилятор строит граф из исходного кода.
  2. Анализатор проверяет готовый граф и возвращает дополнительные сообщения.
  3. Симулятор проходит по событиям и показывает, какие переходы сработают.

Компилятор одного файла

compileLiteFsmGraph(source, options?) принимает строку с исходным кодом и возвращает LiteFsmGraphResult.

import { compileLiteFsmGraph } from "@lite-fsm/graph"; const result = compileLiteFsmGraph(source, { filename: "store/machines/toggle.ts", language: "ts", parser: "static", maxMachines: 10, }); for (const machine of result.document.machines) { console.log(machine.id, machine.initialState); }

Компилятор извлекает из статически читаемого кода:

  • состояния из config;
  • переходы из config;
  • переходы, которые reducer записывает в state;
  • события, которые effects отправляют через transition;
  • initialState;
  • initialContext в виде JSON, если значение можно безопасно прочитать;
  • связи между MachineManager и машинами;
  • координаты исходного кода для состояний, переходов и сообщений.

Компилятор не исполняет reducer-ы и effects. Если цель перехода или условие зависит от значения времени выполнения, граф получает частичную информацию и диагностическое сообщение. Это поведение важно: анализ остается безопасным и не требует запускать приложение.

Компилятор проекта

compileLiteFsmGraphProject(options) строит граф по входному TypeScript-файлу проекта. Этот режим используется CLI-командой lite-fsm export-graph.

import { compileLiteFsmGraphProject, type LiteFsmGraphProjectHost } from "@lite-fsm/graph"; const host: LiteFsmGraphProjectHost = { readSource(fileName) { return readFile(fileName); }, resolveModule({ fromFileName, moduleSpecifier }) { return resolveImport(fromFileName, moduleSpecifier); }, }; const result = compileLiteFsmGraphProject({ entryFileName: "/repo/store/index.ts", projectRoot: "/repo", host, });

Проектный компилятор работает через LiteFsmGraphProjectHost. Сам пакет не читает файловую систему напрямую: вызывающий код передает функции чтения файла и разрешения импортов.

Этот режим нужен, когда MachineManager находится в одном файле, а машины импортируются из других файлов. Компилятор проходит только по файлам, которые нужны для найденного менеджера, раскрывает поддерживаемые именованные экспорты и собирает список файлов в result.files.

result.files показывает роль каждого файла:

РольЗначение
entryвходной файл проекта
machineфайл с найденной машиной
barrelфайл с повторными экспортами
helperфайл с локальной оберткой над API lite-fsm

Если проектный компилятор не может прочитать файл, разрешить импорт или однозначно определить карту машин, он возвращает диагностику вместо исключения.

Выбор машины

selectMachineGraph(document, selector?) выбирает одну машину из готового документа.

import { selectMachineGraph } from "@lite-fsm/graph"; const selected = selectMachineGraph(document, { exportName: "orderMachine", }); if (selected.ok) { console.log(selected.machine.states); } else { console.log(selected.diagnostics); }

Выберите машину по index, id, variableName, exportName, ключу в менеджере или паре managerId + managerKey. Если выбор неоднозначен или машина не найдена, функция возвращает ok: false и диагностические сообщения.

Анализатор

analyzeLiteFsmGraph(document, options?) запускает проверки поверх уже построенного графа.

import { analyzeLiteFsmGraph } from "@lite-fsm/graph"; const analysis = analyzeLiteFsmGraph(document, { rules: ["unknown-target", "unreachable-state", "effect-event-acceptance"], scope: { kind: "document" }, strict: true, }); for (const diagnostic of analysis.diagnostics) { console.log(diagnostic.code, diagnostic.message); }

Анализатор не меняет document. Он возвращает отдельный список сообщений, чтобы инструменты могли показывать ошибки компиляции и результаты анализа раздельно.

Доступные правила:

ПравилоЧто проверяет
unknown-targetпереход или reducer ссылается на неизвестную цель
unreachable-stateобычное состояние недостижимо из initialState по переходам config
dead-end-stateдостижимое обычное состояние не имеет исходящих переходов config
actor-template-shapeactor template объявлен без корректного __INIT, terminal states или публичных служебных состояний
reducer-config-consistencyreducer пишет состояние для события, которое не принимает config, или пишет неизвестную цель
effect-event-acceptanceeffect отправляет событие, которое не принимает ни одна машина в выбранной области анализа
wildcard-shadowingпереход конкретного состояния перекрывает wildcard-переход с тем же событием

По умолчанию анализатор запускает все правила для всего документа. Через rules можно оставить только нужные проверки. Через scope можно ограничить анализ одной машиной или одним менеджером. В режиме strict: true часть сообщений, которые обычно имеют уровень info, возвращаются с уровнем warning.

Симулятор

Симулятор работает с готовым LiteFsmGraphDocument и показывает, как событие проходит через граф. Он не вызывает пользовательский reducer или effect. Вместо этого он использует данные, которые уже есть в графе: состояния, переходы, события effects и статически известные изменения состояния.

import { createMachineGraphSimulator } from "@lite-fsm/graph/simulator"; const simulator = createMachineGraphSimulator(document, "checkout"); const started = simulator.start(); if (!started.ok) { console.log(started.reason, started.diagnostics); } const result = simulator.send({ event: { type: "START", payload: { source: "button" } }, }); if (result.ok) { console.log(result.snapshot.slices); console.log(result.step.consumed); }

Симулятор умеет:

  • стартовать документ, менеджер или выбранные машины;
  • возвращать текущий снимок через getSnapshot();
  • показывать доступные переходы через getAvailableTransitions();
  • показывать события, которые могут быть отправлены effects, через getSuggestedEmissions();
  • отправлять внешнее событие через send();
  • отправлять событие из конкретного перехода через sendFromTransition();
  • отправлять событие из конкретного effect через sendFromEmission();
  • фиксировать ручной выбор перехода через choose().

Снимок симуляции содержит slices, текущие состояния, контекст, историю шагов, потребленные переходы, предложенные события effects и диагностику. Снимок неизменяемый: его можно безопасно передавать в интерфейс или хранить для сравнения.

Если одно событие подходит сразу под несколько переходов, поведение задает branchPolicy:

ПолитикаПоведение
manualсимулятор возвращает choice-required, а вызывающий код выбирает переход через choose()
origin-explicit-default-othersесли событие отправлено из конкретного перехода и у этой же машины есть несколько вариантов, симулятор попросит выбрать вариант вручную; для остальных машин выберет первый подходящий переход
deterministic-firstвыбирается первый подходящий переход в стабильном порядке

Для сложной логики передайте evaluationPolicy. Она позволяет вызывающему коду выбрать переход и обновить контекст без запуска настоящего reducer-а.

Модель для визуализации

@lite-fsm/graph/view-model строит готовые структуры для интерфейсов. Этот слой не зависит от React и DOM.

import { buildGraphVisualizerModel, buildMachineFlowModel, buildMachineWorkbenchModel, } from "@lite-fsm/graph/view-model"; const model = buildGraphVisualizerModel(document, { analysisDiagnostics: analysis.diagnostics, }); const machine = document.machines[0]; if (machine) { const workbench = buildMachineWorkbenchModel(machine); const flow = buildMachineFlowModel({ model, machineId: machine.id, }); }

Модель визуализации включает:

  • краткие сведения о машинах и менеджерах;
  • группировку по типам событий: какие машины отправляют событие и какие машины его принимают;
  • строки для состояний, переходов, reducer-веток, effects и диагностики;
  • ссылки на исходный код;
  • наложение данных симуляции: текущее состояние, доступные переходы, предложенные события и недавно выполненные строки.

Этот слой нужен приложениям вроде визуализатора: они получают готовые данные для списков, схем и панели выбранной машины.

Ограничения

@lite-fsm/graph намеренно строит статическую картину. Он не заменяет тесты поведения во время выполнения и не доказывает, что reducer или effect корректно работают при любых данных.

Важно учитывать:

  • динамические значения могут быть отмечены как dynamic, unknown или диагностикой;
  • пользовательский код не выполняется;
  • анализатор проверяет структуру графа, а не бизнес-правила приложения;
  • симулятор работает по данным графа и пользовательским политикам, а не по настоящему коду времени выполнения.

Когда использовать

Используйте @lite-fsm/graph, если нужно:

  • экспортировать граф машин в JSON;
  • построить визуализатор или внутренний инструмент анализа;
  • проверить недостижимые состояния и неизвестные цели переходов;
  • изучить, какие события производят effects и какие машины их принимают;
  • написать тесты, которые проверяют структуру машин без запуска приложения;
  • симулировать сценарии переходов на уровне графа.

Для экспорта графа проекта начните с CLI: @lite-fsm/cli. Для точного описания сигнатур смотрите Graph API.

Связанные разделы

Last updated on