Skip to content

DSL Cheatsheet

If you want to learn more about a particular part of the DSL, we recommend taking a look at the user guide.

The following section describes the syntax and usage of the DSL blocks:

spec {
  inState<State1>{ // inState is always a "top level" element

    // Handle external "input", called Actions
    on<Action1>{ action, state -> ... } //  Handle an action
    on<Action2>(ExecutionPolicy){ action, state -> ... } //  You can have multiple on<Action> blocks. Optionally specify ExecutionPolicy

    // Do something when you enter the state.
    onEnter{ state -> ... } // Called exactly one time when the given state has been entered
    onEnter{ state -> ... } // You can have multiple onEnter blocks

    // Collect a Flow (from kotlinx.coroutines) as long as the state machine is in the state (see inState<State>)
    collectWhileInstate(flow1) { valueEmitedFromFlow, state -> ... } // stops flow collection when state is left
    collectWhileInstate(flow2) { valueEmitedFromFlow, state -> ... } // You can have multiple collectWhileInstate

    // Effects to do something without changing the state (i.e. logging, analytics, ...)
    onActionEffect<Action1>{ action, state -> ... } // You can have multiple onActionEffect
    onEnterEffect{ state -> ... } // You can have multiple onEnterEffect
    collectWhileInStateEffect(flow1){ valueEmitedFromFlow, state -> ... } // You can have multiple collectWhileInstate

    // Hierarchical state machines
    onEnterStartStateMachine(
      stateMachineFactory = { stateSnapshot : State1  -> OtherStateMachine() },
      stateMapper = { state : State<State1>, otherStateMachineState : OtherState -> ... }
    )
    onActionStartStateMachine<Action1>(
      stateMachineFactory = { action, stateSnapshot : State1 -> OtherStateMachine() },
      stateMapper = { state : State<State1>, otherStateMachineState :OtherState -> ... }
    )
    onEnterStartStateMachine(...) // You can have multiple onEnterStartStateMachine
    onActionStartStateMachine(...) // You can have multiple onActionStartStateMachine

    unitlIdentityChanged({ state.id }) {
      // Everyhting inside this block executes only as long as the "identity" (in this example state.id)
      // doesn't change. When it changes, then the previous executions will be canceled and 
      // this block starts again but with the changed state

      //  you can have multiple of the dsl blocks, i.e. multiple on<Action> blocks and so on.
      on<Action3>{ action, state -> ... } // you can have multiple on<Action>
      onEnter{ state -> ... }
      collectWhileInState(flow){ valueEmitedFromFlow, state -> ... } 
      onActionEffect{ action, state -> ...}
      onEnterEffect{ state -> ... }
      collectWhileInStateEffect(flow){ valueEmitedFromFlow, state -> ... } 
      onEnterStartStateMachine(...)
      onActionStartStateMachine(...)
    }

    // Custom conditions
    condition({ state.someString == "Hello" }){
      // Everything inside this block only executes if the surounding condition is met 
      // and the state machine is in the state as specified by the top level inState<State1>.

      //  You can have each DSL block multiple times, i.e. multiple on<Action> blocks and so on.
      on<Action3>{ action, state -> ... }
      onEnter{ state -> ... }
      collectWhileInState(flow){ valueEmitedFromFlow, state -> ... } 
      onActionEffect{ action, state -> ...}
      onEnterEffect{ state -> ... }
      collectWhileInStateEffect(flow){ valueEmitedFromFlow, state -> ... } 
      onEnterStartStateMachine(...)
      onActionStartStateMachine(...)

      untilIdentityChanged(...) { // version of untilIdentityChanged that is only ran if the condition block is active
        on<Action3>{ action, state -> ... }
        onEnter{ state -> ... }
        collectWhileInState(flow){ valueEmitedFromFlow, state -> ... } 
        onActionEffect{ action, state -> ...}
        onEnterEffect{ state -> ... }
        collectWhileInStateEffect(flow){ valueEmitedFromFlow, state -> ... } 
        onEnterStartStateMachine(...)
        onActionStartStateMachine(...)

        // Please note that you cannot have a condition block inside an untilIdentityChanged block
      }

      // Please note that you cannot have nested conditions inside a condition block
    }
  }

  inState<State2> { ... } // You can have multiple "top level" inState blocks
}