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

bouton

v0.7.2

Published

A framework to build your reactive library

Downloads

18

Readme

bouton.js

build status Code Climate

A framework to build your reactive library. It provides a basic feature set for your reactive library:

  • asynchronous
  • error handling
  • back pressure
  • operator extension
  • source extension

The kernel of "bouton.js" is a "Node" or we can called it a "Bouton". See the following diagram: (Isn't it looks like a button? in french: "bouton")

bouton.js

It has a bidirectional data flow:

[signal flow]  : push(signal) -> Node -> send(signal) -> push(signal) -> Node
[command flow] : Node <- pull(cmd) <- request(cmd) <- Node <- pull(cmd)

The signal/data flow is called "downstream", the command flow is called "upstream".

By chaining Node together you can build your stream like what RxJS, bacon.js and highland.js do.

bouton.js ships with a small set of operators and signal generator, and provides a very simple API for you to extend you own operator and signal source.

To understand how bouton.js works, see the tutorial: Implement a JavaScript reactive programming library

I haven't provided many operators in this library yet (In progress). The idea of this library is to let you customize the library on your own way. You can build your own reactive programming library with your own set of operators.

Node / Bouton

Node is the basic and only data structure in bouton.js. Both your data source and operator are inherited from it.

From Node's internal point of view: it handles the received signal with onReceive(), and send() signal to downstream node. It also handles the request made by downstream with onRequest(), and makes a request() to upstream.

From external point of view: You can push() a signal to a node, and observe the signal emitted by the node with observe(). You can make a request with pull(). And observe the request made by the node by using observe().

See document : Node

Example

In browser

// fromDOMEvent is an active source
bouton.fromDOMEvent("click", document.getElementById("btn"))
  .throttle(500)
  .map(v => 1)
  .scan(0, (a, b) => a + b) // count the clicks
  .act(console.log);

In node.js

const bouton = require("bouton").default();
bouton.asList([1, 2, 3]) // asList is a passive source
  .map(v => {
    console.log(v);
    return v;
  })
  .sink(); // back pressure, drive the stream

build

  1. build nodejs library
npm run build
  1. pack web modules

developer version version, will generate build/bouton.js

npm run webpack

production version, will generate build/bouton.min.js

npm run webpack-prod

API

Sources

More sources coming soon

- bouton.just(value)

A source with only one signal in it.

- bouton.asList(array)

Turn an array to a signal source. It is a passive source : you need a sink operator to drive the stream

- bouton.fromDOMEvent(event, element)

Works in browser. send DOM event to the stream. This is an active source, you don't need a sink to drive it.


Operators

More operators coming soon

- stream.act((signal) => void)

Make side effect with the signal, send the original signal to the stream

- stream.done(() => void)

Handle END signal

- stream.errors(error, rethrow)

Handle errors occurred on upstream. use rethrow to resend signal/error to stream.

- stream.map((signal) => signal)

transform signal to another form

- stream.scan((state, add) => sum)

handle signal with a state

- stream.sink()

drive stream with a passive source

- stream.throttle(ms)

Only allow one signal pass in ms millisecond.

Utils

- bouton.addOperator(name, operator)

add a new operator. An operator is a function which returns a Node instance.

For example:

bouton.addOperator("count", (initCount) => {
  class CountNode extends bouton.Node {
    constructor(options, eventemitter) {
      super(options, eventemitter);
      this.initCount = this.options;
    }

    onSignal(signal) {
      this.initCount++;
      this.send(this.initCount);
    }
  }

  return new CountNode(initCount);
});

bouton.asList(["a", "b", "c"])
  .count(10)
  .act(console.log)
  .sink();

// output
// 11
// 12
// 13

- bouton.addOperators(operators)

add multiple operators, accept a map of name:operator pair as argument

- bouton.addSource(name, source)

register a source function.

- bouton.addSources(sources)

register multiple sources. accept a map of name:source pair as argument

- bouton.default()

register the default operators and sources.

const bouton = require("bouton").default();