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 🙏

© 2026 – Pkg Stats / Ryan Hefner

friar

v0.0.4

Published

An Rx.js wrapper for simple applications

Readme

Rx FRP Library - Readme

This is a simple utility library that bridges Rx streams into a simple Functional Reactive workflow for integration with React or other view libraries.

The library exposes an FRP style with a single application state. Events are encapsulated and transformed into functions which operate and return a new state onto a 'state' stream that can be subscribed to and rendered in various ways.

The guts of the library are: The dispatch() function, and the makeApp() factory function which returns an application object with a lightweight API composed of three primary methods: source, sink, and start.

The library also exposes several utility functions for working with the application object and Rx streams.

import {makeApp} from 'lib/framework.js';

var myApp = makeApp();

Sources and Sinks

Sources and sinks both refer to Rx streams; Sources encapsulate interface events, while sinks encapsulate the side effects caused by those events. A source is a stream that can be dispatch()ed to, which is mapped into another Rx stream that is consumed by the application.

dispatch() is a function which takes a Source stream and emits arguments to it. Using the Rx map function, we can turn a source into a sink by passing in a curried function which accepts state as its first argument, e.g.

var mySource = myApp.source();
var mySink   = mySource.map(function(state, anArgument) { ... });

A makeSink function is exposed which will automatically curry the supplied function.

import {makeSink} from 'lib/framework.js';

var myFunction = function(state, anArgument) {
    ...
};

var mySource = myApp.source();
var mySink   = mySource.map(makeSink(myFunction));

Once a sink stream is created, expose it to the application through the sink function.

myApp.sink(mySink);

dispatch() emits arguments to the source stream which are curried into the sink stream's given function. This results in a stream of functions that accept state and return a new state. The following diagram visualizes the process:

Sources and Sinks

How Sinks are Combined

All of the sinks registered to the application are combined into a single Rx stream.

Combining Sinks

The resultant stream is equivalent to emitting state-modifying functions on a single stream that can be subscribed to. From there, the state can be modified in a non-destructive way using the Rx.Observable.scan() function, which is similar to functionally composing every emitted state modification function as they arrive.

Determining State

Using the State

Once all of the sinks have been registered, the application state can be subscribed to by calling start(), which accepts an initial state and a subscribe function, e.g.

myApp.start(myInitialState, function(state) {
    // Do stuff with the current state
})

Example

The following is a simple app that will increment a counter.

import * as framework from './js/lib/framework.js';

function addSomeNumber(state, number) {
    state.counter += number; return state;
}

var app                 = framework.makeApp();
var addSomeNumberSource = app.source();
var addSomeNumberSink   = addSomeNumberSource.map(framework.makeSink(addSomeNumber));
    app.sink(addSomeNumberSink);
    
app.start({counter: 0}, function(state) {
    console.log(state);
});

framework.dispatch(addSomeNumberSource, 1);
framework.dispatch(addSomeNumberSource, 5);
framework.dispatch(addSomeNumberSource, 0);
setTimeout(function() {
    framework.dispatch(addSomeNumberSource, 2);
}, 500);

/*
Outputs:
{ counter: 0 } <- Initial State
{ counter: 1 }
{ counter: 6 }
{ counter: 6 }
{ counter: 8 } <- 500 ms Later
*/