0.0.1 • Published 4 years ago

explaining v0.0.1

Weekly downloads
1
License
MIT
Repository
-
Last release
4 years ago

Why this package ?

Configuring a state machine using the Object Configuration Pattern is straightfoward. But there is some flaws to it:

  • it lacks to provide meaning to the code, therefore, regression can and will happen.
  • it's long to read, reading JSON is very different from code reading.
  • composition is hard to achieve
  • techincal debt is hight.

Using the Builder Pattern to create this object is what we need. This abstraction can

  • Autocomplete, Dynamic Typing and improved API discovery 👌.
  • Easy to compose with any JS code to help you configure your machine.
  • Ability to quickly have a clear view of all the different states of the machine.
  • Write the same machine with fewer lines of code.
  • Increase Maintainability: Easier to read and understand ( because of the fluent API ).
  • Ability to organize the code in a way that makes the more sense to you, and not to the machine.
  • Integrates with all the js/ts tools you already have

Examples

Example: Sequence Pattern:

const machineConfig = Machine.Builder(machine => {
  const nodes = ['node-1', 'node-2', 'node-3', 'node-4];
  
  machine.states(nodes).forEach((state, index, nodes) => {
   const nextTarget = nodes[index + 1] || nodes[0];
   const prevTarget = nodes[index - 1] || nodes[nodes.length - 1];
   
   state.on('NEXT').target(nextTarget)
    .on('PREVIOUS').target(prevTarget);
   
  })
})

// SAME AS:

const machineConfig = {
  initial: 'node-1',
  states: {
    'node-1': {
      type: 'atomic',
      on: {
        NEXT: 'node-2',
        PREVIOUS: 'node-4',
      },
    },
    'node-2': {
      type: 'atomic',
      on: {
        NEXT: 'node-3',
        PREVIOUS: 'node-1',
      },
    },
    'node-3': {
      type: 'atomic',
      on: {
        NEXT: 'node-4',
        PREVIOUS: 'node-2',
      },
    },
    'node-4': {
      type: 'atomic',
      on: {
        NEXT: 'node-1',
        PREVIOUS: 'node-3',
      },
    },
  },
}

Example 2: Simple State With Event Handler

const machineConfig = Machine.Builder(state => {
  state.atomic('initialState')
    .onEach(['TAP', 'CLICK', 'LONGPRESS'])
      .if('IS_ACTIVE').do('SET_INACTIVE')
      .if('IS_INACTIVE').do('SET_ACTIVE')
})

// SAME AS:

const machineConfig = {
  initial: 'initialState',
  states: {
    'initialState': {
      type: 'atomic',
      on: {
        TAP: [{
          cond: 'IS_ACTIVE',
          action: 'SET_INACTIVE',
        }, {
          cond: 'IS_INACTIVE',
          action: 'SET_ACTIVE',
        }],
        CLICK: [{
          cond: 'IS_ACTIVE',
          action: 'SET_INACTIVE',
        }, {
          cond: 'IS_INACTIVE',
          action: 'SET_ACTIVE',
        }],
        LONGPRESS: [{
          cond: 'IS_ACTIVE',
          action: 'SET_INACTIVE',
        }, {
          cond: 'IS_INACTIVE',
          action: 'SET_ACTIVE',
        }],
      },
    },
  },
}

Example 3: Transiant State

const machineConfig = Machine.Builder(state => {
  state.switch('transiant-example')
    .case('GUARD1').target('TARGET1')
    .case('GUARD1').target('TARGET2')
    .default('TARGET3')
})

const machineConfig = {
  initial: 'transiant-example',
  states: {
    'transiant-example': {
      type: 'atomic',
      on: {
        '': [
          {
            cond: 'GUARD1',
            target: 'TARGET1',
          },
          {
            cond: 'GUARD1',
            target: 'TARGET2',
          },
          {
            target: 'TARGET3',
          },
        ],
      },
    },
  },
}

What has been Done ✅

  • support for custom actions
  • support for activities
  • automatic intial state definition
  • support for compound states
  • support for parallel state
  • ability to use xstate object
  • add remove functions
  • ... a lot of other things
0.0.1

4 years ago