export interface Node { id : string ; parent ? : Node ; data ? : any ; children : Node [ ] ; } export default class Tree { private root : Node | undefined ; private nodeIds : string [ ] = [ ] ; constructor ( root ? ) { if ( root ) this . root = root ; } bfs = ( cb ) : Node | undefined => { if ( ! this . root ) { return ; } const queue = [ ] ; queue . push ( this . root ) ; while ( queue . length ) { const node = queue . shift ( ) as Node ; if ( cb ( node ) ) { return node ; } if ( node . children . length ) { queue . push ( ... node . children ) ; } } } ; getRoot = ( ) : Node | undefined => { return this . root ; } ; getNode = ( id ) : Node | undefined => { const result = this . bfs ( ( node ) => { return node . id === id ; } ) ; return result ; } ; private addRoot = ( id , data ? ) => { this . root = { id , data , children : [ ] , } ; this . root . parent = this . root ; this . nodeIds . push ( id ) ; } ; addNode = ( conf ) => { const { parentId , id , data } = conf ; if ( ! this . root ) { this . addRoot ( id , data ) ; return ; } let parent ; if ( ! parentId ) { const index = Math . floor ( Math . random ( ) * this . nodeIds . length ) ; parent = this . getNode ( this . nodeIds [ index ] ) ; } else { parent = this . getNode ( parentId ) ; } if ( ! parent ) { console . error ( `Parent node doesn't exist!` ) ; return ; } this . nodeIds . push ( id ) ; parent . children . push ( { id , data , parent , children : [ ] , } ) ; } ; }