Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

simple-tree-utils

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

simple-tree-utils - npm Package Compare versions

Comparing version 0.0.7 to 1.0.0

.netlify/state.json

91

dist/browser-bundle.js

@@ -24,4 +24,13 @@ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.treeUtils = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){

exports.TreeUtils = void 0;
/**
* Default name of unique identifier property in nodes
*/
const DEFAULT_ID_PROP = 'id';
/**
* Default name of parent identifier property in nodes
*/
const DEFAULT_PARENT_ID_PROP = 'parentId';
/**
* Default name of property where child nodes are stored
*/
const DEFAULT_CHILDREN_PROP = 'children';

@@ -32,2 +41,6 @@ /**

class TreeUtils {
/**
* Constructor of class
* @param config - to configure class, if configuration option is omitted, default one is used
*/
constructor(config) {

@@ -40,3 +53,3 @@ this.idProp = (config === null || config === void 0 ? void 0 : config.idProp) || DEFAULT_ID_PROP;

* Convert list to tree like structure
* @param list list of objects (object need to have id and parentId)
* @param list list of objects, objects need to have id (as you configured, or 'id' by default) and parentId property (as you configured, or 'parentId' by default)
* @param parentId id of parent node

@@ -51,3 +64,3 @@ */

* Convert tree like structure to list
* @param tree tree of objects (object need to have child property and parentId)
* @param tree tree of objects, objects need to have children (as you configured, or 'children' by default) and parentId property (as you configured, or 'parentId' by default)
* @param parentId

@@ -65,5 +78,21 @@ */

}
/**
* Method to find node in tree structure by given id
* @param tree - tree structure to search in
* @param id - identifier of node
* @returns found node
*/
findTreeNodeById(tree, id) {
return this.findTreeNode(tree, item => item[this.idProp] === id);
}
/**
* Method to find node in tree structure by given callback function
* @param tree - tree structure to search in
* @param fn - callback function to find node
* @returns found node
* @example
* ```ts
* utils.findTreeNode(tree, item => item.id === myId);
* ```
*/
findTreeNode(tree, fn) {

@@ -76,2 +105,12 @@ const node = tree.find(item => fn(item));

}
/**
* Method to find all nodes in tree structure by given callback function
* @param tree - tree structure to search in
* @param fn - callback function to find all nodes
* @returns all found nodes
* @example
* ```ts
* utils.findAllTreeNodes(tree, item => item.id === myId);
* ```
*/
findAllTreeNodes(tree, fn) {

@@ -81,2 +120,7 @@ const nodes = tree.filter(item => fn(item));

}
/**
* Method to delete node in tree by given id (mutable operation!)
* @param tree - tree structure for node deleting
* @param id - identifier of node to delete
*/
deleteNode(tree, id) {

@@ -89,2 +133,8 @@ const index = tree.findIndex(item => item[this.idProp] == id);

}
/**
* Method to add new node to tree (mutable operation!)
* @param tree - tree structure for node adding
* @param parentId - identifier of parent node, null if new node should be on root level
* @param childData - data of new node
*/
addNode(tree, parentId, childData) {

@@ -102,2 +152,8 @@ if (parentId == null) {

}
/**
* Method to update node by id with given data in tree (mutable operation!)
* @param tree - tree structure for node editing
* @param id - identifier of node to be updated
* @param data - new data of node (you should also pass children if you want to keep it)
*/
editNode(tree, id, data) {

@@ -111,2 +167,8 @@ const index = tree.findIndex(item => item[this.idProp] == id);

}
/**
* Method to find all children nodes of given node in tree structure
* @param tree - tree structure to search in
* @param id - identifier of node
* @returns all found children nodes
*/
findAllChildrenNodes(tree, id) {

@@ -119,2 +181,8 @@ const node = this.findTreeNodeById(tree, id);

}
/**
* Helper method to recursively get all children nodes of given node in tree structure
* @param node - we want to get all of its children
* @returns all found children nodes
* @private
*/
getChildrenNodes(node) {

@@ -126,2 +194,8 @@ return [

}
/**
* Method to find all parents of given node in tree structure
* @param tree - tree structure to search in
* @param id - identifier of node
* @returns all found parent nodes
*/
findAllParentNodes(tree, id) {

@@ -136,2 +210,9 @@ const parents = [];

}
/**
* Method to find parent of given node in tree structure
* @param tree - tree structure to search in
* @param id - identifier of node
* @param parent - parent node, if we found something (for recursion only)
* @returns found parent node
*/
findNodeParent(tree, id, parent = null) {

@@ -144,2 +225,8 @@ const node = tree.find(item => item[this.idProp] === id);

}
/**
* Helper method to deep clone object
* @param obj - object to be cloned
* @private
* @returns deep cloned object
*/
static deepCopy(obj) {

@@ -146,0 +233,0 @@ return JSON.parse(JSON.stringify(obj));

@@ -1,4 +0,16 @@

interface IConfig {
/**
* IConfig interface for configuring whole class during instantiating
*/
export interface IConfig {
/**
* Name of unique identifier property in nodes
*/
idProp?: string;
/**
* Name of parent identifier property in nodes
*/
parentIdProp?: string;
/**
* Name of property where child nodes are stored
*/
childrenProp?: string;

@@ -10,9 +22,22 @@ }

export declare class TreeUtils {
/**
* Name of unique identifier property in nodes (default value is `id`)
*/
private readonly idProp;
/**
* Name of parent identifier property in nodes (default value is `parentId`)
*/
private readonly parentIdProp;
/**
* Name of property where child nodes are stored (default value is `children`)
*/
private readonly childrenProp;
/**
* Constructor of class
* @param config - to configure class, if configuration option is omitted, default one is used
*/
constructor(config?: IConfig);
/**
* Convert list to tree like structure
* @param list list of objects (object need to have id and parentId)
* @param list list of objects, objects need to have id (as you configured, or 'id' by default) and parentId property (as you configured, or 'parentId' by default)
* @param parentId id of parent node

@@ -23,18 +48,91 @@ */

* Convert tree like structure to list
* @param tree tree of objects (object need to have child property and parentId)
* @param tree tree of objects, objects need to have children (as you configured, or 'children' by default) and parentId property (as you configured, or 'parentId' by default)
* @param parentId
*/
tree2List(tree: any[], parentId?: any): any[];
/**
* Method to find node in tree structure by given id
* @param tree - tree structure to search in
* @param id - identifier of node
* @returns found node
*/
findTreeNodeById(tree: any[], id: any): any;
/**
* Method to find node in tree structure by given callback function
* @param tree - tree structure to search in
* @param fn - callback function to find node
* @returns found node
* @example
* ```ts
* utils.findTreeNode(tree, item => item.id === myId);
* ```
*/
findTreeNode(tree: any[], fn: (item: any) => boolean): any;
/**
* Method to find all nodes in tree structure by given callback function
* @param tree - tree structure to search in
* @param fn - callback function to find all nodes
* @returns all found nodes
* @example
* ```ts
* utils.findAllTreeNodes(tree, item => item.id === myId);
* ```
*/
findAllTreeNodes(tree: any[], fn: (item: any) => boolean): any;
/**
* Method to delete node in tree by given id (mutable operation!)
* @param tree - tree structure for node deleting
* @param id - identifier of node to delete
*/
deleteNode(tree: any[], id: any): any;
/**
* Method to add new node to tree (mutable operation!)
* @param tree - tree structure for node adding
* @param parentId - identifier of parent node, null if new node should be on root level
* @param childData - data of new node
*/
addNode(tree: any[], parentId: any, childData: any): void;
/**
* Method to update node by id with given data in tree (mutable operation!)
* @param tree - tree structure for node editing
* @param id - identifier of node to be updated
* @param data - new data of node (you should also pass children if you want to keep it)
*/
editNode(tree: any[], id: any, data: any): void;
/**
* Method to find all children nodes of given node in tree structure
* @param tree - tree structure to search in
* @param id - identifier of node
* @returns all found children nodes
*/
findAllChildrenNodes(tree: any[], id: any): any[];
/**
* Helper method to recursively get all children nodes of given node in tree structure
* @param node - we want to get all of its children
* @returns all found children nodes
* @private
*/
private getChildrenNodes;
/**
* Method to find all parents of given node in tree structure
* @param tree - tree structure to search in
* @param id - identifier of node
* @returns all found parent nodes
*/
findAllParentNodes(tree: any[], id: any): any[];
/**
* Method to find parent of given node in tree structure
* @param tree - tree structure to search in
* @param id - identifier of node
* @param parent - parent node, if we found something (for recursion only)
* @returns found parent node
*/
findNodeParent(tree: any[], id: any, parent?: any): any;
/**
* Helper method to deep clone object
* @param obj - object to be cloned
* @private
* @returns deep cloned object
*/
private static deepCopy;
}
export {};

@@ -16,4 +16,13 @@ "use strict";

exports.TreeUtils = void 0;
/**
* Default name of unique identifier property in nodes
*/
const DEFAULT_ID_PROP = 'id';
/**
* Default name of parent identifier property in nodes
*/
const DEFAULT_PARENT_ID_PROP = 'parentId';
/**
* Default name of property where child nodes are stored
*/
const DEFAULT_CHILDREN_PROP = 'children';

@@ -24,2 +33,6 @@ /**

class TreeUtils {
/**
* Constructor of class
* @param config - to configure class, if configuration option is omitted, default one is used
*/
constructor(config) {

@@ -32,3 +45,3 @@ this.idProp = (config === null || config === void 0 ? void 0 : config.idProp) || DEFAULT_ID_PROP;

* Convert list to tree like structure
* @param list list of objects (object need to have id and parentId)
* @param list list of objects, objects need to have id (as you configured, or 'id' by default) and parentId property (as you configured, or 'parentId' by default)
* @param parentId id of parent node

@@ -43,3 +56,3 @@ */

* Convert tree like structure to list
* @param tree tree of objects (object need to have child property and parentId)
* @param tree tree of objects, objects need to have children (as you configured, or 'children' by default) and parentId property (as you configured, or 'parentId' by default)
* @param parentId

@@ -57,5 +70,21 @@ */

}
/**
* Method to find node in tree structure by given id
* @param tree - tree structure to search in
* @param id - identifier of node
* @returns found node
*/
findTreeNodeById(tree, id) {
return this.findTreeNode(tree, item => item[this.idProp] === id);
}
/**
* Method to find node in tree structure by given callback function
* @param tree - tree structure to search in
* @param fn - callback function to find node
* @returns found node
* @example
* ```ts
* utils.findTreeNode(tree, item => item.id === myId);
* ```
*/
findTreeNode(tree, fn) {

@@ -68,2 +97,12 @@ const node = tree.find(item => fn(item));

}
/**
* Method to find all nodes in tree structure by given callback function
* @param tree - tree structure to search in
* @param fn - callback function to find all nodes
* @returns all found nodes
* @example
* ```ts
* utils.findAllTreeNodes(tree, item => item.id === myId);
* ```
*/
findAllTreeNodes(tree, fn) {

@@ -73,2 +112,7 @@ const nodes = tree.filter(item => fn(item));

}
/**
* Method to delete node in tree by given id (mutable operation!)
* @param tree - tree structure for node deleting
* @param id - identifier of node to delete
*/
deleteNode(tree, id) {

@@ -81,2 +125,8 @@ const index = tree.findIndex(item => item[this.idProp] == id);

}
/**
* Method to add new node to tree (mutable operation!)
* @param tree - tree structure for node adding
* @param parentId - identifier of parent node, null if new node should be on root level
* @param childData - data of new node
*/
addNode(tree, parentId, childData) {

@@ -94,2 +144,8 @@ if (parentId == null) {

}
/**
* Method to update node by id with given data in tree (mutable operation!)
* @param tree - tree structure for node editing
* @param id - identifier of node to be updated
* @param data - new data of node (you should also pass children if you want to keep it)
*/
editNode(tree, id, data) {

@@ -103,2 +159,8 @@ const index = tree.findIndex(item => item[this.idProp] == id);

}
/**
* Method to find all children nodes of given node in tree structure
* @param tree - tree structure to search in
* @param id - identifier of node
* @returns all found children nodes
*/
findAllChildrenNodes(tree, id) {

@@ -111,2 +173,8 @@ const node = this.findTreeNodeById(tree, id);

}
/**
* Helper method to recursively get all children nodes of given node in tree structure
* @param node - we want to get all of its children
* @returns all found children nodes
* @private
*/
getChildrenNodes(node) {

@@ -118,2 +186,8 @@ return [

}
/**
* Method to find all parents of given node in tree structure
* @param tree - tree structure to search in
* @param id - identifier of node
* @returns all found parent nodes
*/
findAllParentNodes(tree, id) {

@@ -128,2 +202,9 @@ const parents = [];

}
/**
* Method to find parent of given node in tree structure
* @param tree - tree structure to search in
* @param id - identifier of node
* @param parent - parent node, if we found something (for recursion only)
* @returns found parent node
*/
findNodeParent(tree, id, parent = null) {

@@ -136,2 +217,8 @@ const node = tree.find(item => item[this.idProp] === id);

}
/**
* Helper method to deep clone object
* @param obj - object to be cloned
* @private
* @returns deep cloned object
*/
static deepCopy(obj) {

@@ -138,0 +225,0 @@ return JSON.parse(JSON.stringify(obj));

5

package.json
{
"name": "simple-tree-utils",
"version": "0.0.7",
"version": "1.0.0",
"description": "Tree utils library.",

@@ -17,3 +17,4 @@ "keywords": [],

"lint:fix": "npx eslint ./src --fix",
"docs": "npx typedoc src/index.ts",
"docs": "npx typedoc src/main.ts",
"deploy": "npm run docs && netlify deploy --dir=docs --prod",
"publish": "npm run build && npm publish"

@@ -20,0 +21,0 @@ },

@@ -1,11 +0,104 @@

# Tree utils
Tree utils library.
[![npm version](https://badge.fury.io/js/simple-tree-utils.svg)](https://badge.fury.io/js/simple-tree-utils)
[![CircleCI](https://circleci.com/gh/Raiper34/simple-tree-utils.svg?style=shield)](https://circleci.com/gh/Raiper34/simple-tree-utils)
[![Coverage Status](https://coveralls.io/repos/github/Raiper34/simple-tree-utils/badge.svg?branch=main)](https://coveralls.io/github/Raiper34/simple-tree-utils?branch=main)
![npm bundle size](https://img.shields.io/bundlephobia/min/simple-tree-utils)
![NPM](https://img.shields.io/npm/l/simple-tree-utils)
[![docs](https://badgen.net/badge/docs/online/orange)](https://simple-tree-utils.netlify.app)
[![](https://data.jsdelivr.com/v1/package/npm/simple-tree-utils/badge?style=rounded)](https://www.jsdelivr.com/package/npm/simple-tree-utils)
# Simple Tree Utils
Simple Tree Utils is the library to convert and manipulate with tree-like structures.
Library provides converter from an array of objects to trees like structure and vice versa,
and also methods to manipulate that tree and/or search in that tree.
It is created because I needed to convert the array of objects into a tree to visualize in
[**Angular tree component**](https://www.npmjs.com/package/@circlon/angular-tree-component).
Surely there are plenty of similar libraries, but I think all of them work with their own
models/classes, I needed to use my own data without no extra instantiating,
or adding extra methods/properties into the working model.
# Instalation
`npm install simple-tree-utils --save`
Install library using npm `npm install simple-tree-utils --save` and import main class
into your code base `import {TreeUtils} from 'simple-tree-utils';` .
# Usage
todo
First instantiate class with config, or without config.
```ts
const treeUtils = new TreeUtils(); // without config, default values are used (id as idProp, parentId as parentIdProp, children as childrenProp)
const treeUtils2 = new TreeUtils({
idProp: 'id', // the key of a unique identifier for an object (source object)
parentIdProp: 'parentId', // the key of a unique parent identifier (source object)
childrenProp: 'children', // the key, where child nodes are stored (destination object tree)
});
```
After instantiation, you can use tree utils. You can convert the array of the following objects into a tree using `list2Tree` method as following
```ts
const items = [
{id: 1, parentId: null, name: 'Node 1'},
{id: 2, parentId: null, name: 'Node 2'},
{id: 3, parentId: 1, name: 'Node 3'},
{id: 4, parentId: 1, name: 'Node 4'},
{id: 5, parentId: 2, name: 'Node 5'},
{id: 6, parentId: 3, name: 'Node 6'},
];
const output = treeUtils.list2Tree(items);
```
then the output of lift2Tree will be
```ts
const tree = [
{
id: 1, parentId: null, name: 'Node 1', children: [
{
id: 3, parentId: 1, name: 'Node 3', children: [
{id: 6, parentId: 3, name: 'Node 6', children: []},
]
},
{id: 4, parentId: 1, name: 'Node 4', children: []},
]
},
{
id: 2, parentId: null, name: 'Node 2', children: [
{id: 5, parentId: 2, name: 'Node 5', children: []},
]
},
];
```
When you got a structure like the above, you can use all the following methods:
| **Name** | Desription | Signature |
| ---- | ---------- | --------- |
| **addNode** | Method to add new node to tree (mutable operation!) | `addNode(tree: any[], parentId: any, childData: any): void` |
| **deleteNode** | Method to delete node in tree by given id (mutable operation!) | `deleteNode(tree: any[], id: any): any` |
| **editNode** | Method to update node by id with given data in tree (mutable operation!) | `editNode(tree: any[], id: any, data: any): void` |
| **findAllChildrenNodes** | Method to find all children nodes of given node in tree structure | `findAllChildrenNodes(tree: any[], id: any): any[]` |
| **findAllParentNodes** | Method to find all parents of given node in tree structure | `findAllParentNodes(tree: any[], id: any): any[]` |
| **findAllTreeNodes** | Method to find all nodes in tree structure by given callback function | `findAllTreeNodes(tree: any[], fn: ((item: any) => boolean)): any` |
| **findNodeParent** | Method to find parent of given node in tree structure | `findNodeParent(tree: any[], id: any, parent?: any): any` |
| **findTreeNode** | Method to find node in tree structure by given callback function | `findTreeNode(tree: any[], fn: ((item: any) => boolean)): any` |
| **findTreeNodeById** | Method to find node in tree structure by given id | `findTreeNodeById(tree: any[], id: any): any` |
For example, we can find node by giving callback
```ts
const node = treeUtils.findTreeNode(tree, item => item.id === 2);
```
If you need a list again, you can convert the tree back to a list using `treeUtils.tree2List` method
```ts
treeUtils.tree2List(tree);
```
# Documentation
For more details and complete documentation check: https://simple-tree-utils.netlify.app/
# Usage in browser
You can also use this library in the browser without compiling using jsDelivr.
Import script into HTML file, and you can access classes through the global `treeUtils` object.
```html
<script src="https://cdn.jsdelivr.net/npm/simple-tree-utils@1/dist/browser-bundle.min.js"></script>
<script>
const utils = new treeUtils.TreeUtils();
const tree = utils.list2Tree(items);
</script>
```
# License
MIT
MIT
/* eslint-disable @typescript-eslint/no-explicit-any */
interface IConfig {
/**
* IConfig interface for configuring whole class during instantiating
*/
export interface IConfig {
/**
* Name of unique identifier property in nodes
*/
idProp?: string,
/**
* Name of parent identifier property in nodes
*/
parentIdProp?: string,
/**
* Name of property where child nodes are stored
*/
childrenProp?: string,
}
/**
* Default name of unique identifier property in nodes
*/
const DEFAULT_ID_PROP = 'id';
/**
* Default name of parent identifier property in nodes
*/
const DEFAULT_PARENT_ID_PROP = 'parentId';
/**
* Default name of property where child nodes are stored
*/
const DEFAULT_CHILDREN_PROP = 'children';

@@ -18,6 +39,19 @@

/**
* Name of unique identifier property in nodes (default value is `id`)
*/
private readonly idProp: string;
/**
* Name of parent identifier property in nodes (default value is `parentId`)
*/
private readonly parentIdProp: string;
/**
* Name of property where child nodes are stored (default value is `children`)
*/
private readonly childrenProp: string;
/**
* Constructor of class
* @param config - to configure class, if configuration option is omitted, default one is used
*/
constructor(config?: IConfig) {

@@ -31,3 +65,3 @@ this.idProp = config?.idProp || DEFAULT_ID_PROP;

* Convert list to tree like structure
* @param list list of objects (object need to have id and parentId)
* @param list list of objects, objects need to have id (as you configured, or 'id' by default) and parentId property (as you configured, or 'parentId' by default)
* @param parentId id of parent node

@@ -46,3 +80,3 @@ */

* Convert tree like structure to list
* @param tree tree of objects (object need to have child property and parentId)
* @param tree tree of objects, objects need to have children (as you configured, or 'children' by default) and parentId property (as you configured, or 'parentId' by default)
* @param parentId

@@ -61,2 +95,8 @@ */

/**
* Method to find node in tree structure by given id
* @param tree - tree structure to search in
* @param id - identifier of node
* @returns found node
*/
findTreeNodeById(tree: any[], id: any): any {

@@ -66,2 +106,12 @@ return this.findTreeNode(tree, item => item[this.idProp] === id);

/**
* Method to find node in tree structure by given callback function
* @param tree - tree structure to search in
* @param fn - callback function to find node
* @returns found node
* @example
* ```ts
* utils.findTreeNode(tree, item => item.id === myId);
* ```
*/
findTreeNode(tree: any[], fn: (item: any) => boolean): any {

@@ -77,2 +127,12 @@ const node = tree.find(item => fn(item));

/**
* Method to find all nodes in tree structure by given callback function
* @param tree - tree structure to search in
* @param fn - callback function to find all nodes
* @returns all found nodes
* @example
* ```ts
* utils.findAllTreeNodes(tree, item => item.id === myId);
* ```
*/
findAllTreeNodes(tree: any[], fn: (item: any) => boolean): any {

@@ -85,2 +145,7 @@ const nodes = tree.filter(item => fn(item));

/**
* Method to delete node in tree by given id (mutable operation!)
* @param tree - tree structure for node deleting
* @param id - identifier of node to delete
*/
deleteNode(tree: any[], id: any): any {

@@ -94,2 +159,8 @@ const index = tree.findIndex(item => item[this.idProp] == id);

/**
* Method to add new node to tree (mutable operation!)
* @param tree - tree structure for node adding
* @param parentId - identifier of parent node, null if new node should be on root level
* @param childData - data of new node
*/
addNode(tree: any[], parentId: any, childData: any): void {

@@ -108,2 +179,8 @@ if (parentId == null) {

/**
* Method to update node by id with given data in tree (mutable operation!)
* @param tree - tree structure for node editing
* @param id - identifier of node to be updated
* @param data - new data of node (you should also pass children if you want to keep it)
*/
editNode(tree: any[], id: any, data: any): void {

@@ -118,2 +195,8 @@ const index = tree.findIndex(item => item[this.idProp] == id);

/**
* Method to find all children nodes of given node in tree structure
* @param tree - tree structure to search in
* @param id - identifier of node
* @returns all found children nodes
*/
findAllChildrenNodes(tree: any[], id: any): any[] {

@@ -127,2 +210,8 @@ const node = this.findTreeNodeById(tree, id);

/**
* Helper method to recursively get all children nodes of given node in tree structure
* @param node - we want to get all of its children
* @returns all found children nodes
* @private
*/
private getChildrenNodes(node: any): any[] {

@@ -135,2 +224,8 @@ return [

/**
* Method to find all parents of given node in tree structure
* @param tree - tree structure to search in
* @param id - identifier of node
* @returns all found parent nodes
*/
findAllParentNodes(tree: any[], id: any): any[] {

@@ -146,2 +241,9 @@ const parents = [];

/**
* Method to find parent of given node in tree structure
* @param tree - tree structure to search in
* @param id - identifier of node
* @param parent - parent node, if we found something (for recursion only)
* @returns found parent node
*/
findNodeParent(tree: any[], id: any, parent: any = null): any {

@@ -157,2 +259,8 @@ const node = tree.find(item => item[this.idProp] === id);

/**
* Helper method to deep clone object
* @param obj - object to be cloned
* @private
* @returns deep cloned object
*/
private static deepCopy(obj: any): any {

@@ -159,0 +267,0 @@ return JSON.parse(JSON.stringify(obj));

@@ -5,8 +5,8 @@ import {TreeUtils} from "../src";

const LIST_MOCK_ITEMS = [
{id: 1, parentId: null, name: 'Node 1'},
{id: 2, parentId: null, name: 'Node 2'},
{id: 3, parentId: 1, name: 'Node 3'},
{id: 4, parentId: 1, name: 'Node 4'},
{id: 5, parentId: 2, name: 'Node 5'},
{id: 6, parentId: 3, name: 'Node 6'},
{customId: 1, parentCustomId: null, name: 'Node 1'},
{customId: 2, parentCustomId: null, name: 'Node 2'},
{customId: 3, parentCustomId: 1, name: 'Node 3'},
{customId: 4, parentCustomId: 1, name: 'Node 4'},
{customId: 5, parentCustomId: 2, name: 'Node 5'},
{customId: 6, parentCustomId: 3, name: 'Node 6'},
];

@@ -16,14 +16,14 @@

{
id: 1, parentId: null, name: 'Node 1', children: [
customId: 1, parentCustomId: null, name: 'Node 1', customChildren: [
{
id: 3, parentId: 1, name: 'Node 3', children: [
{id: 6, parentId: 3, name: 'Node 6', children: []},
customId: 3, parentCustomId: 1, name: 'Node 3', customChildren: [
{customId: 6, parentCustomId: 3, name: 'Node 6', customChildren: []},
]
},
{id: 4, parentId: 1, name: 'Node 4', children: []},
{customId: 4, parentCustomId: 1, name: 'Node 4', customChildren: []},
]
},
{
id: 2, parentId: null, name: 'Node 2', children: [
{id: 5, parentId: 2, name: 'Node 5', children: []},
customId: 2, parentCustomId: null, name: 'Node 2', customChildren: [
{customId: 5, parentCustomId: 2, name: 'Node 5', customChildren: []},
]

@@ -33,6 +33,16 @@ },

const treeUtils = new TreeUtils();
const treeUtils = new TreeUtils({
idProp: 'customId',
parentIdProp: 'parentCustomId',
childrenProp: 'customChildren',
});
describe('Tree utils methods', () => {
it('should setup converter with defaults when parameter is not provided', () => {
const treeUtils = new TreeUtils();
expect(treeUtils.list2Tree([{id: 1, parentId: null, name: 'Node 1'}]))
.toEqual([{id: 1, parentId: null, name: 'Node 1', children: []}]);
});
it('should convert list to tree', () => {

@@ -43,10 +53,18 @@ expect(treeUtils.list2Tree(LIST_MOCK_ITEMS)).toEqual(TREE_MOCK_ITEMS);

it('should convert tree to list', () => {
expect(treeUtils.tree2List(TREE_MOCK_ITEMS).sort((a: any, b: any) => a.id - b.id)).toEqual(LIST_MOCK_ITEMS);
expect(treeUtils.tree2List(TREE_MOCK_ITEMS).sort((a: any, b: any) => a.customId - b.customId)).toEqual(LIST_MOCK_ITEMS);
});
it('should find node by given id', () => {
expect(treeUtils.findTreeNodeById(TREE_MOCK_ITEMS, 6)).toEqual({id: 6, parentId: 3, name: 'Node 6', children: []});
it('should find node by given customId', () => {
expect(treeUtils.findTreeNodeById(TREE_MOCK_ITEMS, 6)).toEqual({customId: 6, parentCustomId: 3, name: 'Node 6', customChildren: []});
});
it('should delete node by given id', () => {
it('should not fail, when children prop is missing', () => {
const input = [
{customId: 1, parentCustomId: null, name: 'Node 1'}
]
expect(treeUtils.findTreeNodeById(input, 6)).toBeNull();
expect(treeUtils.findNodeParent(input, 6)).toBeNull();
});
it('should delete node by given customId', () => {
const mock = JSON.parse(JSON.stringify(TREE_MOCK_ITEMS));

@@ -56,12 +74,12 @@ treeUtils.deleteNode(mock, 6);

{
id: 1, parentId: null, name: 'Node 1', children: [
customId: 1, parentCustomId: null, name: 'Node 1', customChildren: [
{
id: 3, parentId: 1, name: 'Node 3', children: []
customId: 3, parentCustomId: 1, name: 'Node 3', customChildren: []
},
{id: 4, parentId: 1, name: 'Node 4', children: []},
{customId: 4, parentCustomId: 1, name: 'Node 4', customChildren: []},
]
},
{
id: 2, parentId: null, name: 'Node 2', children: [
{id: 5, parentId: 2, name: 'Node 5', children: []},
customId: 2, parentCustomId: null, name: 'Node 2', customChildren: [
{customId: 5, parentCustomId: 2, name: 'Node 5', customChildren: []},
]

@@ -73,15 +91,15 @@ },

it('should add node to parent with given id', () => {
it('should add node to parent with given customId', () => {
const mock = JSON.parse(JSON.stringify(TREE_MOCK_ITEMS));
treeUtils.addNode(mock, 4, {id: 7, parentId: 4, name: 'Node 7', children: []});
treeUtils.addNode(mock, 4, {customId: 7, parentCustomId: 4, name: 'Node 7', customChildren: []});
const out = [
{
id: 1, parentId: null, name: 'Node 1', children: [
customId: 1, parentCustomId: null, name: 'Node 1', customChildren: [
{
id: 3, parentId: 1, name: 'Node 3', children: [
{id: 6, parentId: 3, name: 'Node 6', children: []}
customId: 3, parentCustomId: 1, name: 'Node 3', customChildren: [
{customId: 6, parentCustomId: 3, name: 'Node 6', customChildren: []}
]
},
{id: 4, parentId: 1, name: 'Node 4', children: [
{id: 7, parentId: 4, name: 'Node 7', children: []}
{customId: 4, parentCustomId: 1, name: 'Node 4', customChildren: [
{customId: 7, parentCustomId: 4, name: 'Node 7', customChildren: []}
]},

@@ -91,4 +109,4 @@ ]

{
id: 2, parentId: null, name: 'Node 2', children: [
{id: 5, parentId: 2, name: 'Node 5', children: []},
customId: 2, parentCustomId: null, name: 'Node 2', customChildren: [
{customId: 5, parentCustomId: 2, name: 'Node 5', customChildren: []},
]

@@ -100,21 +118,22 @@ },

it('should edit node of given id by given data', () => {
it('should add node to root', () => {
const mock = JSON.parse(JSON.stringify(TREE_MOCK_ITEMS));
treeUtils.editNode(mock, 5, {id: 5, parentId: 2, name: 'Node 5 edited', children: []});
treeUtils.addNode(mock, null, {customId: 7, parentCustomId: 4, name: 'Node 7', customChildren: []});
const out = [
{
id: 1, parentId: null, name: 'Node 1', children: [
customId: 1, parentCustomId: null, name: 'Node 1', customChildren: [
{
id: 3, parentId: 1, name: 'Node 3', children: [
{id: 6, parentId: 3, name: 'Node 6', children: []}
customId: 3, parentCustomId: 1, name: 'Node 3', customChildren: [
{customId: 6, parentCustomId: 3, name: 'Node 6', customChildren: []}
]
},
{id: 4, parentId: 1, name: 'Node 4', children: []},
{customId: 4, parentCustomId: 1, name: 'Node 4', customChildren: []},
]
},
{
id: 2, parentId: null, name: 'Node 2', children: [
{id: 5, parentId: 2, name: 'Node 5 edited', children: []},
customId: 2, parentCustomId: null, name: 'Node 2', customChildren: [
{customId: 5, parentCustomId: 2, name: 'Node 5', customChildren: []},
]
},
{customId: 7, parentCustomId: 4, name: 'Node 7', customChildren: []}
]

@@ -124,5 +143,28 @@ expect(mock).toEqual(out);

it('should edit node of given customId by given data', () => {
const mock = JSON.parse(JSON.stringify(TREE_MOCK_ITEMS));
treeUtils.editNode(mock, 5, {customId: 5, parentCustomId: 2, name: 'Node 5 edited', customChildren: []});
const out = [
{
customId: 1, parentCustomId: null, name: 'Node 1', customChildren: [
{
customId: 3, parentCustomId: 1, name: 'Node 3', customChildren: [
{customId: 6, parentCustomId: 3, name: 'Node 6', customChildren: []}
]
},
{customId: 4, parentCustomId: 1, name: 'Node 4', customChildren: []},
]
},
{
customId: 2, parentCustomId: null, name: 'Node 2', customChildren: [
{customId: 5, parentCustomId: 2, name: 'Node 5 edited', customChildren: []},
]
},
]
expect(mock).toEqual(out);
});
it('should find parent of node', () => {
const mock = JSON.parse(JSON.stringify(TREE_MOCK_ITEMS));
expect(treeUtils.findNodeParent(mock, 6).id).toBe(3);
expect(treeUtils.findNodeParent(mock, 6).customId).toBe(3);
expect(treeUtils.findNodeParent(mock, 1)).toBeNull();

@@ -133,21 +175,26 @@ });

const mock = JSON.parse(JSON.stringify(TREE_MOCK_ITEMS));
expect(treeUtils.findAllParentNodes(mock, 6).map((item: any) => item.id)).toEqual([1, 3]);
expect(treeUtils.findAllParentNodes(mock, 4).map((item: any) => item.id)).toEqual([1]);
expect(treeUtils.findAllParentNodes(mock, 5).map((item: any) => item.id)).toEqual([2]);
expect(treeUtils.findAllParentNodes(mock, 1).map((item: any) => item.id)).toEqual([]);
expect(treeUtils.findAllParentNodes(mock, 6).map((item: any) => item.customId)).toEqual([1, 3]);
expect(treeUtils.findAllParentNodes(mock, 4).map((item: any) => item.customId)).toEqual([1]);
expect(treeUtils.findAllParentNodes(mock, 5).map((item: any) => item.customId)).toEqual([2]);
expect(treeUtils.findAllParentNodes(mock, 1).map((item: any) => item.customId)).toEqual([]);
});
it('should find ALL children of node', () => {
it('should find ALL customChildren of node', () => {
const mock = JSON.parse(JSON.stringify(TREE_MOCK_ITEMS));
expect(treeUtils.findAllChildrenNodes(mock, 1).map((item: any) => item.id)).toEqual([3, 4, 6]);
expect(treeUtils.findAllChildrenNodes(mock, 2).map((item: any) => item.id)).toEqual([5]);
expect(treeUtils.findAllChildrenNodes(mock, 5).map((item: any) => item.id)).toEqual([]);
expect(treeUtils.findAllChildrenNodes(mock, 1).map((item: any) => item.customId)).toEqual([3, 4, 6]);
expect(treeUtils.findAllChildrenNodes(mock, 2).map((item: any) => item.customId)).toEqual([5]);
expect(treeUtils.findAllChildrenNodes(mock, 5).map((item: any) => item.customId)).toEqual([]);
});
it('should not find ALL customChildren of nonexisting node', () => {
const mock = JSON.parse(JSON.stringify(TREE_MOCK_ITEMS));
expect(treeUtils.findAllChildrenNodes(mock, 666).map((item: any) => item.customId)).toEqual([]);
});
it('should find ALL nodes that match callback', () => {
const mock = JSON.parse(JSON.stringify(TREE_MOCK_ITEMS));
expect(treeUtils.findAllTreeNodes(mock, item => item.id % 2 === 0).map((item: any) => item.id)).toEqual([2, 4, 6]);
expect(treeUtils.findAllTreeNodes(mock, item => item.id % 3 === 0).map((item: any) => item.id)).toEqual([3, 6]);
expect(treeUtils.findAllTreeNodes(mock, item => item.name.includes('Node')).map((item: any) => item.id)).toEqual([1, 2, 3, 4, 6, 5]);
expect(treeUtils.findAllTreeNodes(mock, item => item.customId % 2 === 0).map((item: any) => item.customId)).toEqual([2, 4, 6]);
expect(treeUtils.findAllTreeNodes(mock, item => item.customId % 3 === 0).map((item: any) => item.customId)).toEqual([3, 6]);
expect(treeUtils.findAllTreeNodes(mock, item => item.name.includes('Node')).map((item: any) => item.customId)).toEqual([1, 2, 3, 4, 6, 5]);
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc