npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

stating

v0.4.1

Published

Build a state machine-ish function executor

Downloads

4

Readme

stating

Build Status Dependency Status npm version Coverage Status

Build a state machine with simple function nodes.

Each node is a function so it's also an action for the "state".

Each node specifies the next node, or nodes, which allows for dynamically specifying state transitions.

It's a malleable state machine. Others may add new nodes at any time, and, it's also possible to add nodes both "before" and "after" other nodes which may override a node or alter where it transitions to.

You may supply a node to run next which hasn't been added to the stating instance. Or, provide a function you just generated.

Install

npm install stating --save

Examples

See /examples for some runnable examples.

  1. strings/counter
  2. strings/counter-direct
  3. buffers/json
  4. transforms/math
  5. ~~objects/messages~~
  6. strings/json

Usage

// returns a builder function
var buildNodes = require('stating')

// build a new nodes for us to configure
var nodes = buildNodes()

// add a "node", which is a function with an id
nodes.add('someId', function (control, N) {

  // do something with the @input / context.input
  // it's the object provided to process()

  if (/* things are okay, move to the next node */)
    control.next(n.nextId)
  else
    control.fail('there was a problem')
})

nodes.add('nextId', function (control, N) {
  // do something ... and then tell it to move back to the first node
  control.next(N.someId)
})

// Alternate way to add nodes as an object:
nodes.addAll({
  someId: function (control, N) {
    // same as the function used above
  },

  nextId: function (control, N) {
    // same as the function used above
  }
})

// first added node is the 'start' node by default.
//   OR:
// set it explicitly:
nodes.start('someId')

// Alter flow with before/after nodes by specifying which nodes should
// be targeted and which nodes should be applied. works as it reads.
// simple examples, do one before, or after, the specified one:

// will configure 'valid' to run before 'assign' does.
// this means any time any node says to switch to 'assign'
// then the 'valid' node will be run.
nodes.before('assign').run('valid')

// will configure 'some' to run after 'change'.
// this will configure 'some' to run after the 'change' node.
// any time any node says to run 'change' then 'some'
// will be run after it.
nodes.after('change').run('some')

// these mean the same except they target more functions at once.
// these are convenience functions to easily target many nodes.

// this will make all three "blah" nodes run before 'id1' and 'id2'.
// so, any time any node says to run either 'id1' or 'id2'
// it will run all three "blah" nodes *first*.
nodes.before('id1', 'id2').run('blah1', 'blah2', 'blah3')

// same as the before, except, run them after.
nodes.after('diff id', 'id2', 'id3').run('blah4', 'blah5', 'blah6')

// A. For Object inputs:
// create an executor prepared to process objects.
var executor = nodes.objects()

// then provide objects via process()
executor.process({some:'input object'})

// B. For String inputs:
// create an executor prepared to process string.
var executor = nodes.strings()

// then provide strings via process()
executor.process('some input')

// C. For Transforms:
// default transform has string input and object output.
// so, writableObjectMode is false and,
// readableObjectMode is true.
var transform = nodes.transform()

// change from the default with options:
var transform = nodes.transform({
  // example of changing to string/buffer output
  readableObjectMode: false

  // example: enforce Buffer instead of string.
  decodeStrings: true,
})

someSource.pipe(transform).pipe(someTarget);


// Add an event emitter to the `control` each node
// will receive when called.

// set options' `events` to true to use the events.EventEmitter
var options = { events:true }

// or, set your own event emitter instance:
var options = { events: yourEventEmitter }

// then create the usual executor with the options...
var executor = nodes.objects(options)
var executor = nodes.strings(options)

Future

First, finalize how Stating/Control handle nodes and the internal execution queue.

Then, it's all about adding builders/helpers to create the nodes supplied to a Stating instance. See @stating/builder for a start.

For example, look at the JSON example nodes for true, false, and null. All that for a static string. I'm sure I could make a builder to help make nodes like that. I did: @stating/string-plugin.

Also, nodes like the "element" and "element ," for reading an array, which work together as the first and the repeater, could be made via a helper by telling it what is wanted each time and what the separator is.

There's more. I plan to add those later as packages in the stating scope.

Feel free to suggest some or contribute some to the scope.

The hideous "initializer functions" thing is gone in 0.4.0. Yay.

MIT License