Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
node-state
Advanced tools
Node-State is intended as a rough port of the Akka FSM module available for Scala. While other FSM implementation exist for Node, none seemed to offer the flexibility and the clear DSL offered by Akka. This project is an attempt at bringing that to the Node/CoffeeScript world.
npm install node-state
Node-State has three main concepts: States, Events, and Transitions. At any one time, a state-machine will be in one of several pre-defined states. Each state has one or more events that it will listen for and respond to until transitioning to the next state. Transitions are special events that occur in between moving from one state to the next. Transitions can be used to set-up initial data for a new state, intercept a transition and redirect to another state, or handle loic that may not necessarily belong in a specific state.
State machines use CoffeeScript's class and inheritance system, and should inherit from NodeState. While it is certainly possible to implement this inheritance using plain javascript, that is beyond the scope of this documentation, and is not recommended.
class MyStateMachine extends NodeState
states:
A:
Enter: (data) ->
@goto 'B', { key: 'new data'}
B:
Enter: (data) ->
@raise 'MyCustomEvent', data
MyCustomEvent: (data) ->
#do something
In the example above, we've created a new state machine with 2 states: A and B. The keys under each state are the names of events to which the state will respond. All states by default will listen for an Enter event, which is called automatically upon entering the new state. In the Enter event of state A, we see the @goto method. @goto will unregister event listeners for state A, and enter state B. The second argument to @goto is data to be passed to the next state. Upon entering state B, we see the @raise method. @raise raises an event which will be responded to by the current state, if an appropriate event has been registered. Again, the second argument may be used to pass new data to the next event handler. In both @raise and @goto, the second argument is optional. Omitting it will pass along the data received by the current event handler.
class MyStateMachine extends NodeState
states:
A:
Enter: (data) ->
@goto 'B', { key: 'new data'}
B:
Enter: (data) ->
@goto 'C'
C:
Enter: (data) ->
@goto 'D'
D:
Enter: (data) ->
transitions:
A:
B: (data, callback) ->
#do setup for new state
'*':
A: (data, callback) ->
D: (data, callback) ->
'*': (data, callback) ->
C:
'*': (data, callback) ->
Above, we have defined transitions from A -> B, * -> A, * -> D, * -> *, and C -> *. The * is a wildcard, it means "any state". There are a few important things to note about transitions. First, they are called in between states, that is after all event handlers have been unregistered from the previous state, but before registering new handlers and entering the next state. Second, only the single most applicable transition will be called, not all matching transitions. Order of precedence, from most to least important, is as follows:
A -> B
'*' -> B
A -> '*'
'*' -> '*'
The NodeState constructor supports an optional configuration object, which supports 3 properties.
autostart
- Defaults to false
. This parameter determines whether the state machine should automatically activate and enter the initial state, or if it should wait for the start() method to be called.initial_data
- Defaults to an empty object ( {} ). Use this to specify any data that might be needed by the initial state.initial_state
- The name of the first state that the machine should enter. By default, this will be the name of the first state defined in the states list.sync_goto
- when you issue goto
the new state's Enter function is called syncrhonously, in the current run-loop iterationfsm = new MyStateMachine
autostart: true
initial_data: 'I can be data of any type, but default to {}'
initial_state: 'B'
Note that any of the following methods can be called from outside of the state machine by replacing @
(the CoffeeScript shortcut for this
) with a reference to the state machine. example:
class MyStateMachine extends NodeState
states:
A:
Enter: (data) ->
@goto 'B', { key: 'new data'}
B:
Enter: (data) ->
@goto 'C'
fsm = new MyStateMachine
fsm.start()
fsm.wait 300
fsm.stop()
@goto(state_name, [data])
- Described previously, this signals the state machine to begin transitioning from the current state to state_name. @goto takes an optional data argument to send new data to the next state.
@raise(event_name, [data])
- Described previously, this raises an event with the name specified by event_name, and optionally passes new data to that event handler. Note that @raise does not cause a change in state, and only the active state's event handlers can respond to the event that has been raised.
@wait(timeout_milliseconds, [data])
- Sleeps for the specified timeout_milliseconds before raising the WaitTimeout event. WaitTimeout's event handler is defined slightly differently than most, as it has an additional parameter for the timeout value.
class MyStateMachine extends NodeState
states:
A:
Enter: (data) ->
@wait 300, { key: 'new data'}
WaitTimeout: (timeout, data) ->
console.log timeout
B:
Enter: (data) ->
#do something
@unwait
- Cancels the current wait operation. Usually, the combination of @wait/@unwait is used if you are waiting a specified time period for other events to come in. @unwait
would be used once you've received an event of interest and no longer want to respond to the timer.
@start
- Kicks off the transition to the initial state.
@stop
- Unregisters all event handlers for the state machine, effectively turning it off. In the future, pre- and post-stop event hooks may be added to allow for additional cleanup during shutdown.
sync_goto
option to constructorFAQs
A finite state machine (FSM) implementation for node.js
The npm package node-state receives a total of 9,243 weekly downloads. As such, node-state popularity was classified as popular.
We found that node-state demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.