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

hibe

v0.0.6

Published

Lightweight data framework implementing eventual immutability paradigm

Downloads

2

Readme

Hibe - Immutable data without pain

tl;dr hibe is a library to create immutable data objects/graphs through a 'mutable' api. Changes can be observed and objects can be serialized/de-serialized to JSON data.

Key features

Core concept

Hibe has been primarily designed to work in uni-directional dataflow contexts (cf. flux or redux). In this architecture, User Interface updates are triggered by state changes - and state changes are triggered through actions (in other words UI elements never refresh themselves directly).

Unidirectional-data-flow

This model is composed of 2 main sequences:

  • a read-only sequence that occurs after state changes to trigger UI view updates. In this sequence, data should be ideally immutable as it gives a very simple way to avoid recalculating pieces that haven't changed on the UI side.
  • a (mostly)write-only sequence that occurs during the action processing. In this sequence, having mutable data is convenient as actions can be written through very straightforward and maintainable code.

Hibe allows exactly that: have immutable objects that provide a mutable api to create new versions of those objects. To be more precise, only the last version of a hibe object can be virtually mutated. In this respect, hibe objects behave as if they were eventually immutable.

Let's imagine a very simple example to concretely illustrate what it means.

// Todo data for http://todomvc.com/examples/vanillajs/
@Data()
export class Todo {
    @value() description = "";   // description of the todo task
    @value() completed = false;  // is the task completed?
    @value() editing = false;    // is the task being edited?
}

let todo = new Todo();

The Todo class in the previous code snippet models an item in the todo mvc application. The todo instance is immutable - but it can still be virtually updated like this:

todo.description = "Call Marge";
todo.completed = true;
console.log(todo.description); // print "Call Marge"
console.log(todo.completed);   // print true

When this code is run hibe implicitly creates a new version for the todo object and redirects all read/write operation to it - so that todo is unchanged, even though it seems mutable from the developer's perspective.

Before micro-task

Of course this would be pointless if the new version remained hidden. In practice hibe triggers a micro-task (used by Promises ) to asynchronously spawn the new versions as soon as the 'mutation sequence' ends.

When the new version has spawn, the code will behave as follows:

console.log(todo.description); // print "" -> value before mutation
console.log(todo.completed);   // print false

todo = latestVersion(todo);    // latestVersion is a hibe utility function that return the latest version of a dataset
console.log(todo.description); // print "Call Marge" -> value after mutation
console.log(todo.completed);   // print true

After micro-task

You may wonder how the application can get notified of the micro-task result. There are actually 2 ways:

  • either by watching a data object
watch(todo, (newTodo: Todo) => {
    // a new version of todo has been spawn
    todo = newTodo;
    // let's refresh the UI...
})
  • or by explicitly waiting for the micro-task through a promise
todo = await mutationComplete(todo);
// the new todo version is now accessible

(note: for advanced cases a synchronous API is also available - cf. commitMutations())

Of course, more complex (directed acyclic) graphs can be created:

// TodoApp structure for http://todomvc.com/examples/vanillajs/
@Data()
export class TodoApp {
    @value() newEntry = "";
    @data(list(Todo)) list: Todo[];
    @value() filter = "ALL";
}

Hibe objects (aka. datasets) also support @computed properties to expose values that are calculated from other properties (and that will not be recalculated if its dependencies don't change):

// TodoApp structure for http://todomvc.com/examples/vanillajs/
@Data()
export class TodoApp {
    @value() newEntry = "";
    @data(list(Todo)) list: Todo[];
    @value() filter = "ALL";

    // return an array of Todo sorted according to the filter property
    @computed() get listView(): Todo[] {
        if (this.filter === "ALL") {
            return this.list;
        } else {
            let isComplete = (this.filter === "COMPLETED");
            return this.list.filter(item => item.completed === isComplete);
        }
    }

    // return the number of items that are not completed    
    @computed() get itemsLeft(): number {
        let itemsLeft = 0;
        this.list.forEach(item => {
            itemsLeft += item.completed ? 0 : 1;
        });
        return itemsLeft;
    }
}

Using hibe

Hibe can be installed from npm:

npm i hibe

Compiling hibe on your machine

Simply install yarn - then run

yarn install
yarn build-hive

This will generate a hibe.js in a dist folder.

To run tests:

yarn test

License

Apache V2.0