@lite-fsm/cli
@lite-fsm/cli предоставляет команду lite-fsm для работы с проектом из терминала. В alpha-версии пакет умеет создавать React starter-проекты, добавлять автоматы в generated store, строить project graph по TypeScript-файлам проекта и запускать локальный Visualizer с готовой graph-сессией.
Команды create и add-machine пишут файлы проекта. Команды export-graph и visualize используют @lite-fsm/graph: находят MachineManager, определяют автоматы, переданные в этот менеджер, строят граф состояний, переходов, reducer-веток и событий effects. CLI не запускает приложение и не выполняет пользовательский код.
Пакет находится в alpha-версии.
Установка
npm install --save-dev @lite-fsm/cliПосле установки доступна команда lite-fsm.
Для одноразового запуска без установки в проект можно использовать npx @lite-fsm/cli ....
Команды
| Команда | Назначение |
|---|---|
create | Создать Next.js или Vite React starter, уже подключенный к lite-fsm |
add-machine | Добавить доменный автомат в generated src/store |
export-graph | Построить project graph и записать JSON export document |
visualize | Построить project graph, поднять локальный Visualizer и открыть graph-сессию проекта |
Быстрый старт с нуля
npx @lite-fsm/cli create my-app --template vite
cd my-app
npx @lite-fsm/cli add-machine user-session
npm run devЭтот сценарий создаёт starter с базовым автоматом app, затем добавляет отдельный автомат userSession. Для Next.js используйте --template next.
Команда create
lite-fsm create my-app --template vitecreate создаёт React starter на базе Vite или Next.js и добавляет готовый lite-fsm store под src/store. Проект получает @lite-fsm/core, @lite-fsm/react, @lite-fsm/middleware, immer, typed helper createMachine, React hooks и минимальный автомат app.
Команда вызывает framework scaffold (create-vite или create-next-app), патчит entrypoint приложения, добавляет FSMContextProvider, настраивает alias @/* и по умолчанию устанавливает зависимости.
Примеры:
lite-fsm create my-app --template next
lite-fsm create . --template next
lite-fsm create my-app --template vite --css none
lite-fsm create apps/demo --template vite --package-manager pnpm --no-install<project-name> должен быть относительным путём внутри текущей директории или . для генерации в текущую директорию. Для новых директорий родительская директория должна существовать, а целевая директория — отсутствовать.
Опции create
| Опция | Обязательна | Назначение |
|---|---|---|
<project-name> | Да | Относительная директория проекта, например my-app, apps/demo или . |
--template <next|vite> | Да | Framework starter: Next.js App Router или Vite React |
--css <tailwind|none> | Нет | CSS preset; по умолчанию tailwind |
--package-manager <pnpm|npm|yarn|bun> | Нет | Package manager для scaffold, install и next steps; по умолчанию npm |
--install / --no-install | Нет | Установить зависимости после генерации или пропустить install; по умолчанию install включен |
Generated store
create добавляет одинаковую структуру store для Next.js и Vite:
src/store/
create-machine.ts
deps.ts
hooks.ts
index.ts
types.ts
machines/app.tssrc/store/index.ts экспортирует machines, makeStore, AppState, AppStore, hooks и типы. Автомат app принимает событие DO_INIT и показывает минимальный паттерн: общий AppEvents, typed createMachine, MachineManager с immerMiddleware и dependencies через manager.setDependencies(...).
Команда add-machine
lite-fsm add-machine user-sessionadd-machine запускается из корня проекта, созданного через lite-fsm create. Команда создаёт файл автомата, регистрирует его в src/store/index.ts и добавляет namespace событий в src/store/types.ts.
Для user-session результат выглядит так:
src/store/machines/user-session.ts
src/store/index.ts
src/store/types.tsНовый автомат экспортируется как userSession, а стартовое событие получает имя DO_USER_SESSION_INIT.
Команда принимает имена в kebab-case, snake_case и camelCase:
| Ввод | Файл | Export | Событие |
|---|---|---|---|
user-session | user-session.ts | userSession | DO_USER_SESSION_INIT |
user_session | user-session.ts | userSession | DO_USER_SESSION_INIT |
userSession | user-session.ts | userSession | DO_USER_SESSION_INIT |
checkout | checkout.ts | checkout | DO_CHECKOUT_INIT |
add-machine рассчитан на generated store shape из lite-fsm create: должны существовать src/store/create-machine.ts, src/store/index.ts, src/store/types.ts и src/store/machines. Если store был сильно переписан, CLI вернёт diagnostic и попросит обновить регистрацию вручную.
Опции add-machine
| Опция | Обязательна | Назначение |
|---|---|---|
<name> | Да | Имя автомата: ASCII kebab-case, snake_case или camelCase, начинается с буквы |
Команда export-graph
lite-fsm export-graph --entry store/index.ts --out lite-fsm.graph.json --tsconfig tsconfig.jsonexport-graph строит проектный граф и записывает JSON-файл. Это основной способ подготовить данные для визуализатора, проверок и собственных инструментов анализа.
Команда принимает входной TypeScript-файл, ищет в нем выбранный MachineManager(...), затем проходит по импортам, которые нужны для автоматов этого менеджера.
Минимальный пример
// store/index.ts
import { MachineManager, createMachine } from "@lite-fsm/core";
export const lamp = createMachine({
config: {
off: { SWITCH: "on" },
on: { SWITCH: "off" },
},
initialState: "off",
initialContext: {},
});
export const manager = MachineManager({ lamp });lite-fsm export-graph --entry store/index.ts --out lite-fsm.graph.jsonРезультат будет записан в lite-fsm.graph.json.
Опции export-graph
| Опция | Обязательна | Назначение |
|---|---|---|
--entry <path> | Да | Входной TypeScript-файл, где виден выбранный MachineManager(...) |
--out <path> | Да | Путь к JSON-файлу, который нужно записать |
--tsconfig <path> | Нет | Явный tsconfig.json для разрешения импортов |
--include-source | Нет | Добавить исходный текст найденных файлов в JSON |
Значение --out - не поддерживается. Здесь - — это не пустой путь, а специальное значение, которое в некоторых CLI означает «вывести результат в терминал». lite-fsm export-graph так не работает: передайте обычный путь к файлу, например --out lite-fsm.graph.json.
Входной файл
--entry указывает на файл, от которого начинается обход проекта. Обычно это файл, где создается основной MachineManager.
Поддерживаемый вариант:
import { MachineManager } from "@lite-fsm/core";
import { auth } from "./machines/auth";
import { profile } from "./machines/profile";
export const manager = MachineManager({
auth,
profile,
});CLI ожидает, что карта автоматов в MachineManager читается статически: через объект, локальную константу, поддерживаемые именованные импорты или повторные экспорты. Если карта строится динамически, команда вернёт диагностику о неполном статическом анализе.
На этом этапе проектный обход рассчитан на .ts файлы. Импорты с неподдерживаемым расширением попадают в диагностику.
Работа с tsconfig
lite-fsm export-graph --entry src/store/index.ts --out graph.json --tsconfig tsconfig.jsonЕсли --tsconfig передан явно, CLI использует именно этот файл. Если файл не найден или содержит ошибку, команда завершится с ошибкой.
Если --tsconfig не передан, CLI ищет ближайший tsconfig.json от папки входного файла вверх по дереву каталогов. Если файл найден, команда использует его compilerOptions, включая baseUrl и paths.
Если tsconfig.json не найден, CLI использует настройки разрешения импортов по умолчанию и добавляет информационную диагностику LFC_TSCONFIG_NOT_FOUND в export document.
Включение исходников
lite-fsm export-graph --entry store/index.ts --out lite-fsm.graph.json --include-sourceБез --include-source JSON содержит только граф, список найденных файлов, их роли и хеши. Исходный текст файлов в результат не попадает.
С --include-source команда добавляет sources.files[]:
{
"sources": {
"files": [
{
"fileName": "store/index.ts",
"language": "ts",
"hash": "abc",
"text": "import { MachineManager } from \"@lite-fsm/core\";"
}
]
}
}Эта опция полезна для интерфейсов, которые показывают граф вместе с исходным кодом. Для публичных артефактов включайте ее осознанно: JSON будет содержать текст файлов проекта.
Команда visualize
lite-fsm visualize --entry store/index.tsvisualize строит project graph, создает локальную сессию и запускает встроенный Visualizer на 127.0.0.1. По умолчанию команда использует порт 3030, открывает браузер, печатает URL вида http://127.0.0.1:3030/?session=... и держит процесс запущенным до SIGINT или SIGTERM.
Команда не записывает JSON-файл. Graph document передается Visualizer-у через локальный API с session token из URL, а исходники читаются по запросу только для файлов, которые попали в текущий graph document.
Опции visualize
| Опция | Обязательна | Назначение |
|---|---|---|
--entry <path> | Да | Входной TypeScript-файл, где виден выбранный MachineManager(...) |
--tsconfig <path> | Нет | Явный tsconfig.json для разрешения импортов |
--port <number> | Нет | Порт локального сервера; по умолчанию 3030, допустимы значения от 1 до 65535 |
--no-open | Нет | Не открывать браузер автоматически; команда только напечатает URL локальной сессии |
Если порт занят, static artifact Visualizer-а отсутствует или браузер не удалось открыть, команда завершится с CLI diagnostic и кодом выхода 1. С --no-open browser opener полностью пропускается: URL можно открыть вручную, пока процесс lite-fsm visualize продолжает работать.
Локальная сессия visualize
Успешный запуск создает session token и открывает Visualizer с query parameter session. Token нужен локальному API:
GET /api/session?token=<token>
GET /api/source?token=<token>&fileName=<project-relative-file>/api/session возвращает project graph export document, capabilities локального host-а, entry path и project root. /api/source возвращает текст только для файлов из текущего graph document. Абсолютные пути, .., неизвестные файлы и измененные после сборки graph-файлы отклоняются.
Graph diagnostics не блокируют запуск visualize, если graph document удалось построить: Visualizer открывается, чтобы показать найденные проблемы. Blocking CLI diagnostics, например некорректный explicit tsconfig, останавливают запуск сервера.
Формат export document
export-graph записывает JSON-файл в формате lite-fsm.project-graph-export/v1. visualize использует тот же export document внутри локальной сессии и возвращает его через /api/session.
type LiteFsmProjectGraphExportDocument = {
version: "lite-fsm.project-graph-export/v1";
createdBy: {
package: "@lite-fsm/cli";
version: string;
};
entry: {
path: string;
tsconfigPath?: string;
};
graph: LiteFsmGraphDocument;
files: LiteFsmGraphProjectFile[];
diagnostics: CliDiagnostic[];
sources?: LiteFsmProjectGraphSourceBundle;
};Основные поля:
version— версия формата экспортируемого документа.createdBy— пакет и версия CLI, который создал файл.entry— входной файл и использованныйtsconfig, если он был найден или передан явно.graph— граф@lite-fsm/graphс автоматами, менеджерами, переходами и diagnostics компилятора.files— найденные файлы проекта, их роли и хеши.diagnostics— сообщения CLI.sources— исходный текст файлов, только если передан--include-source.
При export-graph JSON записывается в стабильном порядке ключей и заканчивается переводом строки. Такой формат подходит для сравнения файлов в тестах и проверках.
Роли файлов
files[] показывает, зачем файл попал в граф:
| Роль | Значение |
|---|---|
entry | входной файл из --entry |
machine | файл с найденным автоматом |
barrel | файл с повторными экспортами |
helper | файл с локальной оберткой над API lite-fsm |
Роли помогают визуализатору и собственным инструментам объяснить, откуда взялся каждый автомат.
Диагностика
Диагностика CLI использует коды LFC_* и находится в верхнем поле diagnostics.
Диагностика компилятора графа использует коды LFG_* и остается внутри graph.diagnostics. При выводе в терминал команда показывает оба набора сообщений, но в JSON они разделены.
Такое разделение важно:
diagnosticsописывает запуск CLI: параметры,tsconfig, чтение файлов, запись результата.graph.diagnosticsописывает сам граф: неподдержанные формы кода, проблемы поиска автоматов, ошибки компиляции графа.
Коды CLI:
| Код | Значение |
|---|---|
LFC_INVALID_OPTIONS | неверные или неполные параметры команды |
LFC_TSCONFIG_NOT_FOUND | tsconfig.json не найден |
LFC_TSCONFIG_INVALID | tsconfig.json не прочитан или содержит ошибку |
LFC_GRAPH_PROJECT_FAILED | граф проекта не удалось построить |
LFC_NO_MACHINES_EXPORTED | в графе нет автоматов, подключенных к менеджеру |
LFC_SOURCE_BUNDLE_FILE_UNREADABLE | файл нельзя встроить через --include-source |
LFC_VISUALIZER_STATIC_MISSING | static artifact Visualizer-а не найден |
LFC_VISUALIZER_PORT_UNAVAILABLE | порт локального Visualizer-а занят |
LFC_VISUALIZER_SERVER_FAILED | локальный server Visualizer-а не стартовал |
LFC_VISUALIZER_OPEN_FAILED | браузер не удалось открыть автоматически |
LFC_CREATE_TARGET_EXISTS | целевой путь для create уже существует |
LFC_CREATE_TARGET_PARENT_MISSING | родительская директория для create не найдена |
LFC_CREATE_SCAFFOLD_FAILED | framework scaffold завершился ошибкой |
LFC_CREATE_INSTALL_FAILED | install dependencies завершился ошибкой |
LFC_CREATE_PATCH_FAILED | generated project не удалось пропатчить |
LFC_CREATE_VALIDATION_FAILED | generated project не прошёл финальную проверку |
LFC_ADD_MACHINE_STORE_NOT_FOUND | generated src/store не найден или не прочитан |
LFC_ADD_MACHINE_CONFLICT | добавляемый автомат конфликтует с текущим store |
LFC_ADD_MACHINE_PATCH_FAILED | index.ts или types.ts не удалось обновить |
LFC_WRITE_FAILED | файл проекта или итоговый JSON нельзя записать |
Поведение при ошибках
Команды возвращают код выхода 0, если нет CLI diagnostics с серьезностью error. visualize при успешном запуске держит процесс активным и завершает его с кодом 0 после SIGINT или SIGTERM.
Команды возвращают код выхода 1, если есть хотя бы одна blocking CLI error.
create завершается с ошибкой, когда:
- не передан
<project-name>или--template; - имя проекта является абсолютным путём, содержит
..или указывает на уже существующий target, кроме.для текущей директории; - родительская директория target-а не существует;
- framework scaffold, install, patching или финальная validation завершаются ошибкой.
add-machine завершается с ошибкой, когда:
- не передан
<name>или имя нельзя преобразовать в безопасный JS identifier; - команда запущена не из generated проекта с
src/store; - файл автомата, import, key в
machinesили member вAppEventsуже существуют; src/store/index.tsилиsrc/store/types.tsне соответствуют ожидаемому generated shape.
export-graph не пишет частичный JSON, когда:
- не передан
--entryили--out; --outравен-;- явный
--tsconfigне найден или некорректен; - компилятор графа вернул блокирующие diagnostics;
- в найденном менеджере нет автоматов;
- не удалось прочитать файл для
--include-source; - не удалось записать итоговый файл.
visualize не стартует server, когда:
- не передан
--entry; --portне является целым числом от1до65535;- explicit
--tsconfigне найден или некорректен; - graph build не вернул document;
- static artifact Visualizer-а отсутствует в пакете CLI;
- порт занят или local server не стартовал;
- browser opener завершился ошибкой, если не передан
--no-open.
Что использовать дальше
Project graph, подготовленный CLI, можно:
- открыть через
lite-fsm visualizeбез ручного JSON-файла; - записать в JSON и открыть в визуализаторе;
- хранить как артефакт проверки;
- сравнивать в тестах;
- передавать собственным инструментам анализа;
- использовать вместе с
@lite-fsm/graph/view-model.
Для программного построения графа без терминальной команды используйте @lite-fsm/graph.