Reacting to the same action in different ways due to what happened in the past may be a challenge.
Rosmaro is a framework for writing functions like this:
({state, action}) => ({state, result})
Check out the Rosmaro documentation at rosmaro.js.org!
Get Rosmaro using npm: npm i rosmaro
.
Rosmaro places great emphasis on two programming paradigms:
- Visual programming - changes of behavior are drawn using the Rosmaro visual editor.
- Functional programming - the whole model is a pure function built out of pure functions and pure data.
First, you draw a graph. Then, you assign functional code to its nodes.
It gives you:
- Automata-based dispatch - actions are dispatched to handlers based on the current node of the state machine. There's no need to check the current state.
- The right model for the job - the behavior-related state is expressed by a state machine, while the data-related state lives in a dictionary.
- Existing tooling - it's easy to use with redux and redux-saga.
Rosmaro models support:
- Node multiplication - a node may be multiplied using a function of the context.
- Reuse and composition - models may be included within other models.
- Lenses - thanks to Ramda lenses the shape and size of your data-related state may be easily adjusted.
- Orthogonal regions - multiple regions may be active at the same time. One of the ways to avoid state explosion.
- Subgraphs - nodes of state machines may contain other state machines.
-
Use the Rosmaro visual editor to draw a state machine.
-
Write some functional code.
This example makes use of the rosmaro-binding-utils package.
const Frog = handler({
INTRODUCE_YOURSELF: () => "Ribbit! Ribbit!",
});
const Prince = handler({
INTRODUCE_YOURSELF: () => "I am The Prince of Rosmaro!",
EAT: ({action}) => action.dish === 'pizza' ? {arrow: 'ate a pizza'} : undefined
});
- Enjoy your
({state, action}) => ({state, result})
function!
[
{type: 'INTRODUCE_YOURSELF'}, // 'I am The Prince of Rosmaro!'
{type: 'EAT', dish: 'yakisoba'}, // undefined
{type: 'INTRODUCE_YOURSELF'}, // 'I am The Prince of Rosmaro!'
{type: 'EAT', dish: 'pizza'}, // undefined
{type: 'INTRODUCE_YOURSELF'} // 'Ribbit! Ribbit!'
].forEach(action => console.log(
({state} = model({state, action})).result.data
));
The complete code of this example can be found on GitHub.
- A JavaScript framework for functions of state and action
- What did we lose when we moved to Redux?
- Dynamic orthogonal regions in state machines
- Decomposing the TodoMVC app with state diagrams
- An overview of the Rosmaro-TodoMVC app codebase
- Testing the TodoMVC app
- State management in JavaScript: data-related state and behavior-related state
- Bunny App a wizard implemented in Rosmaro, React, Redux and Redux-Saga.
- TodoMVC the famous TodoMVC demo app
- bool-less-todo a todo app implemented without boolean values and without variables
- rosmaro-snabbdom-starter - a zero configuration Rosmaro Snabbdom starter.
- rosmaro-redux - connects Rosmaro, Redux and Redux-Saga.
- rosmaro-react - connects Rosmaro and React.
- rosmaro-binding-utils - makes writing simple Rosmaro handlers easier.
- rosmaro-tools - CLI tooling for Rosmaro.
- rosmaro-testing-library - testing utilities for Rosmaro.
Rosmaro is licensed under the MIT license.