Mealy

finite-state machine whose output values are determined both by its current state and the current input

Currently has the following features implemented:

Below an example on how to create a mealy state machine:

// services.js

// mocked data
export const todos = [
    {
        description: 'I am a todo'
    },
    {
        description: 'I am another todo'
    }
]

export const getTodos = filter => data =>
  new Promise((resolve, reject) => {
    // get is an abstraction that could be in a http.js file
    const result = await get(filter || 'notCompleted')
    if (result.status === 200) {
      // MUTATION IS GOING TO HAPPEN INSIDE THE STATE MACHINE
      resolve(result.data)
    } else {
      reject(new Error('Error while getting todo'))
    }
  })
  
export const postTodo = todo => data =>
  new Promise((resolve, reject) => {
    const { id } = todo
    
    // post is an abstraction that could be in a http.js file
    const result = await post(todo)
    
    /**
     * MUTATION IS GOING TO HAPPEN INSIDE THE STATE MACHINE
     * If the todo is saved, let's change the data inside state machine
     * and return it to the state machine in order to be saved
     */
    if (result.status === 201) {
      data.push(result.data)
      resolve(data)
    } else {
      reject(new Error('Error while saving todo'))
    }
  })
  
export const putTodo = todo => data =>
  new Promise((resolve, reject) => {
    const { id } = todo
    
    // put is an abstraction that could be in a http.js file
    const result = await put(todo)
    
    if (result.status === 200) {
      /**
       * MUTATION IS GOING TO HAPPEN INSIDE THE STATE MACHINE
       * If the todo is changed, let's change the data inside state machine
       * and return it to the state machine in order to be saved
       */
      data[id] = result.data
      resolve(data)
    } else {
      reject(new Error('Error while changing todo'))
    }
  })
// store.js

import { MealyStateMachine } from 'status-machina'

/** 
 * The store describes the following:
 * - possible states
 * - possible transitions
 * - example: the first transition from addTodo to listTodos
 */ 
const model = {
  addTodo: {
    listTodos: {},
  },
  changeTodo: {
    listTodos: {},
  },
  listTodos: {
    addTodo: {},
    changeTodo: {},
    listTodos: {},
  },
}

export const store = new MealyStateMachine(model, 'listTodos')
// now only have to bind the functions when we need them

import { addTodo, getTodos, todos } from './services'
import { store } from './store'

// this could be inside a callback
store.states.listTodos.on.outputs = getTodos();

// this could be inside a callback that adds a todo
store.states.addTodo.on.outputs = addTodo(todos[0])
  • every transition has an on property defined, which can hold listeners, callback functions, etc...

  • every state transition is defined inside each state and takes an input keyword into account

  • the transition functions are a curried two parameter function which returns a Promise.

  • listeners are not fired in mealy machines.

  • only the initial state needs to be defined at firsthand.

  • states can be added after the machine has been started.

Last updated

Was this helpful?