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

js-hierarchy

v4.0.2

Published

Proper hierarchy management for Node, Typescript and the Browser.

Downloads

13

Readme

js-hierarchy

Sauce Test Status Travis node npm

Sauce Test Status

Proper hierarchy management for Node, Typescript and the Browser.

Introduction

js-hierarchy enables you to build tree-like data structures and work with them properly. It supports walking in multiple directions, storage of arbitrary data and can be used as a base framework for your special needs.

Installation

npm

Install the module using npm:

npm install --save js-hierarchy

If you're using Typescript, you might want to add the following typings:

npm install @types/bluebird @types/loglevel @types/node --save-dev

Basic usage

Typescript

The module includes the complete type definitions for Typescript applications. Simply install the module and you're ready to go:

import {SimpleNode} from 'js-hierarchy';

let rootNode: SimpleNode = new SimpleNode('nodeName');

Node.js

After installing the module, use it with require():

var hierarchy = require('js-hierarchy');

var rootNode = new hierarchy.SimpleNode('nodeName');

Browser

Install the module and include the browser script:

<script type="text/javascript" src="node_modules/js-hierarchy/browser.min.js"></script>

or use the jsDelivr CDN hosted version:

<script type="text/javascript" src="//cdn.jsdelivr.net/npm/js-hierarchy/browser.min.js"></script>

With this the global namespace will include a "jshierarchy" object:

var rootNode = new jshierarchy.SimpleNode('nodeName');

After that, everything's right as working in Node.js.

Building the hierarchy

The tree-like data structures, that js-hierarchy can build are build up from "Nodes". There can be several implementations of the Node interface, but the simplest one is called "SimpleNode".

Just instantiate it to create a new node and give it a name:

rootNode = new SimpleNode('nodeName');

If a node has no parent, it is considered the "root node". A node can include a number of children, obviously. Simply use the "addChild"- method to add one:

rootNode = new SimpleNode('nodeName');
rootNode.addChild(new SimpleNode('childNodeName'));

Adding the child will automatically set the child's parent to the node it was added to.

Storing arbitrary data

Because nodes without any information aren't quite useful, js-hierarchy supports storing arbitrary data in a key/value manner.

To add a new data to a node, use the method "setData":

rootNode = new SimpleNode('nodeName');
rootNode.setData('mykey', 'myvalue');

You can also directly set the data when instantiating the node:

rootNode = new SimpleNode('nodeName', {'mykey': 'myValue'});

Use "getData" to retrieve node data again later:

rootNode = new SimpleNode('nodeName', {'mykey': 'myValue'});
console.log(rootNode.getData('mykey'));
// will output: myValue

Walking the tree

Most tree-like structures are used to store hierarchical data and walk the tree from one node to the upper, lower or sibling nodes.

The "walk" method of a node will just do that and call a user defined function on each node it encounters. Please note, that only the directions traversing the tree vertically (Down, Up, and RootDown) will call the action on the original node.

rootNode = new SimpleNode('nodeName', {'testkey': 'value'});
childNode = new SimpleNode('childNodeName', {'testkey': 'childvalue'});
childNode.addChild(new SimpleNode('grandChildNodeName', {'testkey': 'grandChildvalue'}));
rootNode.addChild(childNode);

rootNode.walk(Direction.up, (node) => {
    console.log(node.getData('testkey'));
    return Bluebird.resolve();
});
// will output 'value', 'childvalue' and 'grandChildvalue'

Please look at this example tree:

                                    +----------------+
      +                             | grandchild 3.1 |
      |                             +-------^--------+
down  |                                     |
      |                                     |
      |                                     |
      |                                     |
      |     +---------+  +---------+   +----+----+
      v     | child 1 |  | child 2 |   | child 3 |
            +---^-----+  +----^----+   +----^----+
      ^         |             |             |
      |         |             |             |
      |         |   <----+    |   +----->   |
 up   |         |    left     |    right    |
      |         |             |             |
      |         |             |             |
      |         |          +--+---+         |
      +         +----------+ root +---------+
                           +------+

Now, these directions are available:

  • up: Walks through all child nodes. Then to their child nodes and so on until no node is available anymore (from root to child 1-3 to grandchild)
  • down: Walks to the parent node, then the next parent node and so on until the root node is reached. (from grandchild to child 1-3 to root)
  • left: Walks all siblings (the parent node's children) from the current node to the left (children having a smaller array index) until the first node is reached (from child2 to child1)
  • right: Walks all siblings (the parent node's children) from the current node to the right (children having a larger array index) until the last node is reached (from child2 to child3)
  • rootUp: Walks the same way "up" would go, but will only call the action function on its way up. For example, when called from grandchild 3.1, the action function will encounter "root" first, then "child3" and finally "grandchild 3.1".

You can also specify an array of directions, meaning that, after the last node has been reached in the first direction, the next direction is walked and so on.

The walk method runs asynchronously using Promises in the Bluebird implementation.

Thus, the walker returns a fulfilled promise, if every node was walked. Also, the supplied user function has to return a promise.

Extending

If you need a specialized nodes with functions suitable for your usage, you should extend "AbstractNode" and implement "Node". AbstractNode already has all needed features, so you can just concentrate on the needed features without caring about the basic ones.

Please read the API documentation for details.

Building

To test and build this package, simply use grunt:

grunt release

This will run all unit tests and a coverage report.

Contributing

First of all: Thank you for your will to contribute!

To request a new feature or report a bug, please create a github issue.

Pull requests are always welcome!

If you can, please submit a pull request adding the feature or solving the bug you just reported.

While developing for your pull request, please first create a test, that produces your error or checks your new feature, run the test suite using

grunt test

to see them fail. Then, solve the bug or implement the feature and run the tests once again to see them succeed. Please write good tests and keep the coverage up.

We will review the pull request and optionally comment your code and probably ask you to fix one or two things, before we can merge your code.

Browser compatibility tests

Browser compatibility tests are run using SauceLabs. To run them, first add this line to your local hosts file:

127.0.0.1 saucelabs.test

Then, when running grunt browsertest, set these two environment variables:

SAUCE_USERNAME=<your SauceLabs username>
SAUCE_ACCESS_KEY=<your SauceLabs access key>