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

reckon-js

v0.1.14

Published

Event-based, immutable state container for javascript apps with cursors and views

Downloads

20

Readme

Reckon JS Build Status npm version

Reckon JS is an event-based, immutable state container for javascript apps. Reckon manages state as Facebook Immutable objects. Reckon provides cursors, views and scoped events so that a single Reckon instance can be used for all state in an application.

Table of Contents

TodoMVC Example

Demo

The crux of this ReackonJS+React example is under examples/todomvc-react/js and view the demo application running here

Check out app.js for the starting point of the application, and the react components are in the '.jsx' files. The bundle.js is the compiled version of the code.

This is based on the TodoMVC template

Basic Example

Try it here

import Reckon from 'reckon-js';

let reckon = new Reckon({
    fruits:['apple','pear','banana'],
    veges:['carrot','broccoli','celery']
});

let fruitCursor = reckon.select('fruits');
let fruitJoinView = fruitCursor.addView('Fruit join', fruits => fruits.join());

fruitJoinView.onUpdate(newFruitJoin=>{
    console.log("New fruit join: "+newFruitJoin);
});

fruitCursor.on('ADD_A_FRUIT', name => {
    fruitCursor.update(fruitState => fruitState.push(name));
});

fruitCursor.emit('ADD_A_FRUIT','mandarin');
fruitCursor.emit('ADD_A_FRUIT','grape');

// output:
// New fruit join: apple,pear,banana,mandarin
// New fruit join: apple,pear,banana,mandarin,grape

Installation

To install stable version if you are using npm package manager

npm install reckon-js --save

Guide

The Reckon Object

Create a reckon object with your initial state

let reckon = new Reckon({
    fruits: [
        'apple',
        'pear'
    ],
    veges: [
        'tomato',
        'cucumber'
    ]
});

The state is made immutable with Immutable JS. Get back the state like this

let state = reckon.get();
state.get('fruits').get(0); //returns 'apple'

The reckon object doubles up as a cursor; you can use it like a cursor on the whole tree. See the next section for how cursors work

Cursors

Cursors are used to manipulate a particular part of the state. Let's say we just want to deal with the fruits

let fruitsCursor = reckon.select('fruits');
fruitsCursor.get(); //returns ['apple','pear'] as an ImmutableJS wrapper

You can change the data through immutable updates, like this

fruitsCursor.update(currentState => {
    return currentState.push('mandarin').set(1,'banana');
});
fruitsCursor.get(); //returns ['apple','banana','mandarin'] as immutable

For the full list of immutable opertions refer to the ImmutableJS Documentation.

Reckon Object Cursor

The reckon object doubles up as a cursor on the whole state. For example, these two statements are equivelant

reckon.get()
reckon.select([]).get()

In fact you can treat the reckon object as a root cursor in all respects.

Events

You can fire events on a cursor, and you can listen to events on the cursor.

fruitsCursor.on('ADD_FRUIT_EVENT', (data,fruits) => {
    return fruits.concat(data);
});

fruitsCursor.emit('ADD_FRUIT_EVENT', ['orange','grapefruit']);

If your event listener returns anything, it is used to replace the current cursors state.

Updates

You could use an event listener and emit an event in order to update your state. But sometimes you just want to do an update. Here's a shortcut to simply update the state, under the covers it still fires events to do the update

myCursor.update(state=>{
    return state.remove(3).concat([4,5,6]);
});

You can also listen for updates on the cursor. This will fire when anything in the cursors state changes, regardless of which cursor made the change

myCursor.onUpdate( (newState,oldState) => {
    //do some stuff
});

Anything you return will be ignored though, so you don't end up with an infinite loop.

Filters

If you add a listener to a cursor, by default it listens ONLY to events fired on that cursor. However, what if you want to listen to events higher up the state tree, or lower down on the state tree?

import {filterTypes} from 'reckon-js';
...
let fruitSelect = reckon.select('fruit[0]');

fruitSelect.on('SCOPED_EVENT',()=>{
    //this will be called because we passed the SUPER filter
},filterTypes.SUPER);

reckon.emit('SCOPED_EVENT');

The list of filters are:

  • CURRENT (default) - listens to events fired on the same cursor, at the same path in the tree
  • SUB - anything equal to or below on the state tree
  • SUPER - anything equal to or above on the state tree
  • ANY - listens to all events
  • ROOT - events emitted only on the top of the tree
  • SUB_EXCLUSIVE - listens to events strictly below the current cursor
  • SUPER_EXCLUSIVE - listens to events strictly above the current cursor
  • AFFECTED - anything where a change to the state in that cursor could affect the current cursor. i.e. anything above, below or the same as the current cursor

Views

Views are simple functions that you add to a listener to expose a certain view of the data. You can also listen to updates on the view for when the output of the function changes.

let reckon = new Reckon({
    fruit:'apple'
});

let view = reckon.addView('fruit_view',data=>data.get('fruit'));
view.onUpdate(data=>{
    //data (which is returned by the view) will now be 'pear'
});

reckon.update(()=>{
    return {
        fruit:'pear'
    };
});

Undo and redo

You can go forward and backward in states by using reckon.undo() and reckon.redo()

This must be enabled when you create a reckon object in order to set the maximum number of states to remember (note that it only remembers the state changes to save on space). e.g.

let reckon = new Reckon({
    state:'state-1'
},{
    maxHistory:1000 //maximum number of undo's to store
});

reckon.update(state=>'state-2');
reckon.undo();
// State now contains 'state-1'
reckon.redo();
// State now contains 'state-2'

Note that updates are fired on all changes, including undo/redo.

Credit

Reckon is influenced by and takes cues from the following projects and programming paradigms:

Contributions

Contributions are greatly appreciated, whether you're new to JS or experienced there are tasks available. Feel free to get in touch.

Issues and feature requests are also welcome here.

License

MIT