Yantrix is a TypeScript framework that provides a set of tools to create robust and self-documented functional applications by code generation. The business logic is represented by declarative, event-driven finite state machines, while the application state is an Anemic Domain Model, making it great a counterpart to any traditional state manager like Redux, while allowing devs to focus on describing contracts and workflows, rather than writing and debugging the actual code.
Lends itself perfectly to Architecture-as-Code paradigm and no-code/less-code tools for developers, like n8n.
To install Yantrix end-to-end command line tool, you can use NPM, Yarn or PNPM:
npm install @yantrix/cli
# or
yarn add @yantrix/cli
# or
pnpm install @yantrix/cli
If your main language is TypeScript, you may prefer to install all available APIs or list only those you require
pnpm install yantrix
npm install @yantrix/automata @yantrix/utils @yantrix/yantrix-parser
Basically, you turn diagrams into a code module in required language
yantrix codegen --outfile ../yantrix-generated.ts --language TypeScript --className SampleFSM --eval "A-->B"
stateDiagram-v2
[*] --> INIT: RESET (optionsList)
note left of [*]
#( items = [], selectedIndex = 0 }
end note
INIT --> CLOSED: RESET (optionsList)
CLOSED --> OPEN: OPEN
OPEN --> CLOSED: CLOSE
OPEN --> SELECTED: SELECT (index)
SELECTED --> CLOSED: CLOSE
note right of INIT
+Init
+ByPass
#{ items, selectedIndex } <= sortBy($optionsList, 'id'), 0
end note
note left of CLOSED
subscribe/click => OPEN
emit/dropdownClose
end note
note left of SELECTED
#{ selectedIndex } <= (index)
emit/selected (index) <= #{ selectedIndex }
subscribe/selected CLOSE
end note
note right of OPEN
emit/dropdownOpen
subscribe/click SELECT (index)
subscribe/clickOutside CLOSE
end note
+Init
marks that INIT is the initialState
of theFSM
.+ByPass
also implies that transition through thisState
is synchronous#{items, selectedIndex}
describes a shape ofContext
for allStates
.items
is the list of dropdown values, andselectedIndex
stores currently selected item. Without extra expressions these values are copied from the precedingContext
#{items=[], selectedIndex = 0}
sets the initial value for thatContext
#{items, selectedIndex} <= sortBy($optionsList, 'id'), 0
fills bothContext
properties fromPayload
:items
is a sortedoptionsList
property, assuming it's a List of Objects that have property ofid
.selectedIndex
is set to 0, when the options list is updated
subscribe/click => OPEN
in CLOSED state produces OPENAction
on incomingclick
Event
, which transitions theFSM
into OPEN state- likewise,
subscribe/click SELECT (index)
produces SELECTAction
and passesindex
property fromEvent Meta
to itsPayload
, which transitions theFSM
into the SELECTEDState
subscribe/clickOutside => CLOSE
produces a CLOSEAction
to return the dropdown to the originalState
(CLOSED)- Both CLOSED and OPEN
States
emit correspondingEvents
, that are pipelined intoEvent Bus
and connect the component to others. - SELECTED is a transitional
State
: whileemit/selected (index) <= #{ selectedIndex }
lets theEvent Bus
know which item was selected, at the same timesubscribe/selected => CLOSE
transitions theFSM
back to CLOSEDState
via CLOSEAction
. It behaves similar to INITState
– theFSM
goes through it. However, unlike that case, here it will emitEvent
and wait for its settlement before it runs further processing.
See Contributing