{"id":20757599,"url":"https://github.com/dodevops/js-hierarchy","last_synced_at":"2026-04-13T20:32:03.300Z","repository":{"id":57283244,"uuid":"102191699","full_name":"dodevops/js-hierarchy","owner":"dodevops","description":"Proper hierarchy management for Node, Typescript and the Browser.","archived":false,"fork":false,"pushed_at":"2018-08-09T07:59:32.000Z","size":253,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-10-20T08:40:21.772Z","etag":null,"topics":["browser","hierarchy","javascript","node","tree","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/js-hierarchy","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dodevops.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-MIT","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-09-02T11:23:19.000Z","updated_at":"2024-12-31T18:52:23.000Z","dependencies_parsed_at":"2022-09-17T13:54:13.684Z","dependency_job_id":null,"html_url":"https://github.com/dodevops/js-hierarchy","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/dodevops/js-hierarchy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dodevops%2Fjs-hierarchy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dodevops%2Fjs-hierarchy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dodevops%2Fjs-hierarchy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dodevops%2Fjs-hierarchy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dodevops","download_url":"https://codeload.github.com/dodevops/js-hierarchy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dodevops%2Fjs-hierarchy/sbom","scorecard":{"id":349491,"data":{"date":"2025-08-11","repo":{"name":"github.com/dodevops/js-hierarchy","commit":"55ead0f3ae32750054692643e41d60ef18b17f77"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE-MIT:0","Info: FSF or OSI recognized license: MIT License: LICENSE-MIT:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-18T07:57:44.117Z","repository_id":57283244,"created_at":"2025-08-18T07:57:44.117Z","updated_at":"2025-08-18T07:57:44.117Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31770718,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-13T20:17:16.280Z","status":"ssl_error","status_checked_at":"2026-04-13T20:17:08.216Z","response_time":93,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["browser","hierarchy","javascript","node","tree","typescript"],"created_at":"2024-11-17T09:43:21.306Z","updated_at":"2026-04-13T20:32:03.259Z","avatar_url":"https://github.com/dodevops.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# js-hierarchy\n\n[![TestingBot Test Status](https://testingbot.com/buildstatus/190e841358e8e595f6f7c007e8196dd4)](https://testingbot.com/builds/190e841358e8e595f6f7c007e8196dd4?auth=2e97049df058e9e19afeb9815cfbd92f)\n[![Travis](https://img.shields.io/travis/dodevops/js-hierarchy.svg)](https://travis-ci.org/dodevops/js-hierarchy)\n[![node](https://img.shields.io/node/v/js-hierarchy.svg)](https://www.npmjs.com/package/js-hierarchy)\n[![npm](https://img.shields.io/npm/v/js-hierarchy.svg)](https://www.npmjs.com/package/js-hierarchy)\n\n[![TestingBot Test Status](https://testingbot.com/buildmatrix/190e841358e8e595f6f7c007e8196dd4)](https://testingbot.com/builds/190e841358e8e595f6f7c007e8196dd4?auth=2e97049df058e9e19afeb9815cfbd92f)\n\nProper hierarchy management for Node, Typescript and the Browser.\n\n## Introduction\n\njs-hierarchy enables you to build tree-like data structures and work\nwith them properly. It supports walking in multiple directions,\nstorage of arbitrary data and can be used as a base framework for\nyour special needs.\n\n## Installation\n\n### npm\n\nInstall the module using npm:\n\n    npm install --save js-hierarchy\n\nIf you're using Typescript, you might want to add the following typings:\n\n    npm install @types/bluebird @types/loglevel @types/node --save-dev\n\n## Basic usage\n\n### Typescript\n\nThe module includes the complete type definitions for Typescript\napplications. Simply install the module and you're ready to go:\n\n```typescript\nimport {SimpleNode} from 'js-hierarchy';\n\nlet rootNode: SimpleNode = new SimpleNode('nodeName');\n```\n\n### Node.js\n\nAfter installing the module, use it with require():\n\n```javascript\nvar hierarchy = require('js-hierarchy');\n\nvar rootNode = new hierarchy.SimpleNode('nodeName');\n```\n\n### Browser\n\nInstall the module and include the browser script:\n\n```html\n\u003cscript type=\"text/javascript\" src=\"node_modules/js-hierarchy/browser.min.js\"\u003e\u003c/script\u003e\n```\n\nor use the jsDelivr CDN hosted version:\n```html\n\u003cscript type=\"text/javascript\" src=\"//cdn.jsdelivr.net/npm/js-hierarchy/browser.min.js\"\u003e\u003c/script\u003e\n```\n\nWith this the global namespace will include a \"jshierarchy\" object:\n\n```javascript\nvar rootNode = new jshierarchy.SimpleNode('nodeName');\n```\n\nAfter that, everything's right as working in Node.js.\n\n## Building the hierarchy\n\nThe tree-like data structures, that js-hierarchy can build are build\nup from \"Nodes\". There can be several implementations of the Node\ninterface, but the simplest one is called \"SimpleNode\".\n\nJust instantiate it to create a new node and give it a name:\n\n```javascript\nrootNode = new SimpleNode('nodeName');\n```\n\nIf a node has no parent, it is considered the \"root node\". A node can\ninclude a number of children, obviously. Simply use the \"addChild\"-\nmethod to add one:\n\n```javascript\nrootNode = new SimpleNode('nodeName');\nrootNode.addChild(new SimpleNode('childNodeName'));\n```\n\nAdding the child will automatically set the child's parent to\nthe node it was added to.\n\n## Storing arbitrary data\n\nBecause nodes without any information aren't quite useful, js-hierarchy\nsupports storing arbitrary data in a key/value manner.\n\nTo add a new data to a node, use the method \"setData\":\n\n```javascript\nrootNode = new SimpleNode('nodeName');\nrootNode.setData('mykey', 'myvalue');\n```\n\nYou can also directly set the data when instantiating the node:\n\n```javascript\nrootNode = new SimpleNode('nodeName', {'mykey': 'myValue'});\n```\n\nUse \"getData\" to retrieve node data again later:\n\n```javascript\nrootNode = new SimpleNode('nodeName', {'mykey': 'myValue'});\nconsole.log(rootNode.getData('mykey'));\n// will output: myValue\n```\n\n## Walking the tree\n\nMost tree-like structures are used to store hierarchical data\nand walk the tree from one node to the upper, lower or sibling nodes.\n\nThe \"walk\" method of a node will just do that and call a user\ndefined function on each node it encounters. Please note, that only the\ndirections traversing the tree vertically (Down, Up, and RootDown)\nwill call the action on the original node.\n\n```javascript\nrootNode = new SimpleNode('nodeName', {'testkey': 'value'});\nchildNode = new SimpleNode('childNodeName', {'testkey': 'childvalue'});\nchildNode.addChild(new SimpleNode('grandChildNodeName', {'testkey': 'grandChildvalue'}));\nrootNode.addChild(childNode);\n\nrootNode.walk(Direction.up, (node) =\u003e {\n    console.log(node.getData('testkey'));\n    return Bluebird.resolve();\n});\n// will output 'value', 'childvalue' and 'grandChildvalue'\n```\n\nPlease look at this example tree:\n\n```\n                                    +----------------+\n      +                             | grandchild 3.1 |\n      |                             +-------^--------+\ndown  |                                     |\n      |                                     |\n      |                                     |\n      |                                     |\n      |     +---------+  +---------+   +----+----+\n      v     | child 1 |  | child 2 |   | child 3 |\n            +---^-----+  +----^----+   +----^----+\n      ^         |             |             |\n      |         |             |             |\n      |         |   \u003c----+    |   +-----\u003e   |\n up   |         |    left     |    right    |\n      |         |             |             |\n      |         |             |             |\n      |         |          +--+---+         |\n      +         +----------+ root +---------+\n                           +------+\n```\n\nNow, these directions are available:\n\n* up: Walks through all child nodes. Then to their child nodes and\n  so on until no node is available anymore (from root to child 1-3\n  to grandchild)\n* down: Walks to the parent node, then the next parent node and so on\n  until the root node is reached. (from grandchild to child 1-3 to root)\n* left: Walks all siblings (the parent node's children) from the current\n  node to the left (children having a smaller array index) until the\n  first node is reached (from child2 to child1)\n* right: Walks all siblings (the parent node's children) from the current\n  node to the right (children having a larger array index) until the\n  last node is reached (from child2 to child3)\n* rootUp: Walks the same way \"up\" would go, but will only call the action\n  function on its way up. For example, when called from grandchild 3.1, the\n  action function will encounter \"root\" first, then \"child3\" and finally\n  \"grandchild 3.1\".\n\nYou can also specify an array of directions, meaning that, after the\nlast node has been reached in the first direction, the next direction\nis walked and so on.\n\nThe walk method runs asynchronously using [Promises](https://promisesaplus.com/)\nin the [Bluebird implementation](http://bluebirdjs.com/docs/getting-started.html).\n\nThus, the walker returns a fulfilled promise, if every node was walked. Also, the\nsupplied user function has to return a promise.\n\n## Extending\n\nIf you need a specialized nodes with functions suitable for your\nusage, you should extend \"AbstractNode\" and implement \"Node\".\nAbstractNode already has all needed features, so you can just\nconcentrate on the needed features without caring about the basic\nones.\n\nPlease read the\n[API documentation](https://dodevops.github.io/js-hierarchy/doc/) for details.\n\n## Building\n\nTo test and build this package, simply use grunt:\n\n    grunt release\n\nThis will run all unit tests and a coverage report.\n\n## Contributing\n\nFirst of all: Thank you for your will to contribute!\n\nTo request a new feature or report a bug, please\ncreate a github issue.\n\nPull requests are always welcome!\n\nIf you can, please submit a pull request adding the feature\nor solving the bug you just reported.\n\nWhile developing for your pull request, please first create a test, that\nproduces your error or checks your new feature, run the test suite\nusing\n\n    grunt test\n\nto see them fail. Then, solve the bug or implement the feature and\nrun the tests once again to see them succeed. Please write good tests\nand keep the coverage up.\n\nWe will review the pull request and optionally comment your code\nand probably ask you to fix one or two things, before we can merge\nyour code.\n\n## Browser compatibility tests\n\nBrowser compatibility tests are run using SauceLabs. To run them,\nfirst add this line to your local hosts file:\n\n    127.0.0.1 saucelabs.test\n\nThen, when running ```grunt browsertest```, set these two environment\nvariables:\n\n    SAUCE_USERNAME=\u003cyour SauceLabs username\u003e\n    SAUCE_ACCESS_KEY=\u003cyour SauceLabs access key\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdodevops%2Fjs-hierarchy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdodevops%2Fjs-hierarchy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdodevops%2Fjs-hierarchy/lists"}