{"version":3,"file":"index.mjs","sources":["../src/Array2Tree.ts"],"sourcesContent":["// src/Array2Tree.ts\r\nimport { TreeNode } from './types';\r\n\r\nexport class Array2Tree {\r\n  private myId: number = 0;\r\n\r\n  /**\r\n   * Convert array to tree structure with $children property\r\n   * @param arrIn Array of objects with id and parent relationship\r\n   * @param idKey Primary key field name\r\n   * @param parentKey Foreign key field name that links to primary key\r\n   * @param startWith Starting value for tree calculation\r\n   * @param level Current level of tree structure\r\n   * @returns Tree array with $children, $level, and $is_leaf properties\r\n   * \r\n   * @example\r\n   * const tree = new Array2Tree();\r\n   * const result = tree.array2Tree(arr, \"id\", \"parent_id\", null);\r\n   */\r\n  array2Tree<T extends Record<string, any>>(\r\n    arrIn: T[],\r\n    idKey: string,\r\n    parentKey: string,\r\n    startWith: any = null,\r\n    level: number = 1\r\n  ): TreeNode<T>[] | undefined {\r\n    const myLevel = level;\r\n    \r\n    const roots = arrIn.filter(x =>\r\n      (x[parentKey] === startWith) ||\r\n      (startWith == null && x[parentKey] == undefined) ||\r\n      (startWith == undefined && x[parentKey] == null) ||\r\n      (startWith == undefined && x[parentKey] == '')\r\n    );\r\n\r\n    if (roots && roots.length > 0) {\r\n      roots.forEach(el => {\r\n        (el as TreeNode<T>).$level = myLevel;\r\n        (el as TreeNode<T>).$children = this.array2Tree(arrIn, idKey, parentKey, el[idKey], myLevel + 1) || [];\r\n      });\r\n      return roots as TreeNode<T>[];\r\n    } else {\r\n      const leafChildren = arrIn.find(x => x[idKey] === startWith);\r\n      if (leafChildren) {\r\n        (leafChildren as TreeNode<T>).$is_leaf = 1;\r\n      }\r\n      return undefined;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Create tree with Oracle-like sorting order\r\n   * Returns tree order from root, branch, leaf\r\n   * @param arrIn Input array with id and parent_id structure\r\n   * @param idKey ID key field name\r\n   * @param parentKey Parent key field name\r\n   * @param startWith Starting value (optional)\r\n   * @param level Tree depth (auto-generated, optional)\r\n   * @param arrOut Output array (auto-generated)\r\n   * @param parentIndex Parent index (auto-generated)\r\n   * @returns New array sorted in tree order like Oracle's CONNECT BY\r\n   * \r\n   * @example\r\n   * const tree = new Array2Tree();\r\n   * const result = tree.array2SortByTree(arr, \"id\", \"parent_id\", null);\r\n   */\r\n  array2SortByTree<T extends Record<string, any>>(\r\n    arrIn: T[],\r\n    idKey: string,\r\n    parentKey: string,\r\n    startWith: any = null,\r\n    level: number = 1,\r\n    arrOut: TreeNode<T>[] = [],\r\n    parentIndex?: string\r\n  ): TreeNode<T>[] {\r\n    const arrReturns = arrOut;\r\n    const myLevel = level;\r\n\r\n    if (arrIn && arrIn.length >= arrReturns.length && idKey && parentKey) {\r\n      const parents = arrIn.filter(obj =>\r\n        (obj[parentKey] === startWith) ||\r\n        (startWith == null && obj[parentKey] == undefined) ||\r\n        (startWith == undefined && obj[parentKey] == null) ||\r\n        (startWith == undefined && obj[parentKey] == '')\r\n      );\r\n\r\n      if (parents && parents.length > 0) {\r\n        parents.forEach((el, idx) => {\r\n          const node = el as TreeNode<T>;\r\n          node.$level = myLevel;\r\n          node.$index = idx + 1;\r\n          node.$tree_index = (parentIndex ? parentIndex + '.' : '') + node.$index;\r\n          arrReturns.push(node);\r\n          \r\n          this.array2SortByTree(arrIn, idKey, parentKey, el[idKey], myLevel + 1, arrReturns, node.$tree_index);\r\n        });\r\n      } else {\r\n        // This is a leaf node\r\n        const objCur = arrReturns.find(obj => (obj[idKey] === startWith));\r\n        if (objCur) objCur.$is_leaf = 1;\r\n      }\r\n    }\r\n\r\n    return arrReturns;\r\n  }\r\n\r\n  /**\r\n   * Auto-sum weights (used for summing from child level to parent level in tree structure)\r\n   * @param arrIn Array with id and parent structure\r\n   * @param idKey Primary key field name\r\n   * @param parentKey Parent key field name\r\n   * @param weightKey Weight field name for summing from leaf to root\r\n   * @param startWith Starting value for tree creation\r\n   * @param level Starting level for tree\r\n   * @param rootWeight Sum for root from leaf\r\n   * @param arrOut Output array\r\n   * @param parentIndex Output index like tree format 1.1.1, 1.2.1...\r\n   * @returns New array sorted in tree order with weight calculations\r\n   * \r\n   * @example\r\n   * const tree = new Array2Tree();\r\n   * const result = tree.array2SortAndWeight(arr, \"id\", \"parent_id\", \"weight\", null);\r\n   */\r\n  array2SortAndWeight<T extends Record<string, any>>(\r\n    arrIn: T[],\r\n    idKey: string,\r\n    parentKey: string,\r\n    weightKey: string,\r\n    startWith: any = null,\r\n    level: number = 1,\r\n    rootWeight: number = 1,\r\n    arrOut: TreeNode<T>[] = [],\r\n    parentIndex?: string\r\n  ): TreeNode<T>[] {\r\n    const arrReturns = arrOut;\r\n    const myLevel = level;\r\n\r\n    if (arrIn && arrIn.length >= arrReturns.length) {\r\n      const parents = arrIn.filter(obj =>\r\n        (obj[parentKey] === startWith) ||\r\n        (startWith == null && obj[parentKey] == undefined) ||\r\n        (startWith == undefined && obj[parentKey] == null)\r\n      );\r\n\r\n      if (parents && parents.length > 0) {\r\n        // Calculate sum of weights for same level\r\n        const sumWeight = parents.reduce((sum, obj) => sum + (obj[weightKey] || 0), 0);\r\n        \r\n        parents.forEach((el, idx) => {\r\n          const node = el as TreeNode<T>;\r\n          \r\n          // Record total weight of same level components\r\n          node.$sum_weight = sumWeight;\r\n          // Component weight percentage\r\n          node.$weight_percent = (el[weightKey] || 0) / sumWeight;\r\n          // Parent weight percentage\r\n          node.$parent_weight_percent = rootWeight;\r\n          // Root weight percentage\r\n          node.$root_weight_percent = node.$parent_weight_percent * node.$weight_percent;\r\n          \r\n          node.$level = myLevel;\r\n          node.$index = idx + 1;\r\n          node.$tree_index = (parentIndex ? parentIndex + '.' : '') + node.$index;\r\n          \r\n          arrReturns.push(node);\r\n          \r\n          this.array2SortAndWeight(\r\n            arrIn, idKey, parentKey, weightKey, el[idKey], \r\n            myLevel + 1, node.$root_weight_percent, arrReturns, node.$tree_index\r\n          );\r\n        });\r\n      } else {\r\n        // This is a leaf node\r\n        const objCur = arrReturns.find(obj => (obj[idKey] === startWith));\r\n        if (objCur) objCur.$is_leaf = 1;\r\n      }\r\n    }\r\n\r\n    return arrReturns;\r\n  }\r\n\r\n  /**\r\n   * Convert tree structure to flat array with parent-child relationship\r\n   * @param treeIn Tree structure array\r\n   * @param keyNameOfSubs Key name for children field (e.g., \"subs\" or \"children\")\r\n   * @param parentValue Initial value for $parent_id field\r\n   * @param level Starting level\r\n   * @returns Flat array with $id and $parent_id fields\r\n   * \r\n   * @example\r\n   * const tree = new Array2Tree();\r\n   * const result = tree.tree2Array(treeIn, \"children\");\r\n   */\r\n  tree2Array<T extends Record<string, any>>(\r\n    treeIn: T[],\r\n    keyNameOfSubs: string,\r\n    parentValue: number | null = null,\r\n    level: number = 1\r\n  ): TreeNode<T>[] {\r\n    const myLevel = level;\r\n    let roots: TreeNode<T>[] = [];\r\n\r\n    treeIn.forEach((el) => {\r\n      const node = { ...el } as TreeNode<T>;\r\n      node.$id = ++this.myId;\r\n      node.$parent_id = parentValue;\r\n      roots.push(node);\r\n      \r\n      if (el[keyNameOfSubs]) {\r\n        const subs = JSON.parse(JSON.stringify(el[keyNameOfSubs]));\r\n        delete node[keyNameOfSubs];\r\n        const subTree = this.tree2Array(subs, keyNameOfSubs, this.myId, myLevel + 1);\r\n        roots = roots.concat(subTree);\r\n      }\r\n    });\r\n\r\n    return roots;\r\n  }\r\n\r\n  /**\r\n   * Reset internal ID counter\r\n   */\r\n  resetIdCounter(): void {\r\n    this.myId = 0;\r\n  }\r\n}"],"names":["Array2Tree","arrIn","idKey","parentKey","startWith","level","myLevel","roots","x","el","leafChildren","arrOut","parentIndex","arrReturns","parents","obj","idx","node","objCur","weightKey","rootWeight","sumWeight","sum","treeIn","keyNameOfSubs","parentValue","subs","subTree"],"mappings":"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"}