@okutils/array-to-tree 0.0.3-b → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -106,18 +106,16 @@ export interface ArrayToTreeOptions {
106
106
  childrenId?: string;
107
107
  customId?: string;
108
108
  parentId?: string;
109
- rootId?: string;
110
109
  allowSelfAsParent?: boolean;
111
110
  }
112
111
  ```
113
112
 
114
- | Option | Type | Default | Description |
115
- | ------------------- | --------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
116
- | `customId` | `string` | `'id'` | Specifies the field name for the unique identifier of a node. |
117
- | `parentId` | `string` | `'parentId'` | Specifies the field name for associating with the parent node. |
118
- | `childrenId` | `string` | `'children'` | Specifies the field name for the array of child nodes in the generated tree. |
119
- | `allowSelfAsParent` | `boolean` | `false` | Whether to allow a node's `parentId` to be equal to its own `id`. |
120
- | `rootId` | `string` | `'__ARRAY_TO_TREE_VIRTUAL_ROOT_ID__'` | An internal virtual root ID, which usually does not need to be changed. The `parentId` of root nodes should be `null`, `undefined`, or an empty string `""`. |
113
+ | Option | Type | Default | Description |
114
+ | ------------------- | --------- | ------------ | ---------------------------------------------------------------------------- |
115
+ | `customId` | `string` | `'id'` | Specifies the field name for the unique identifier of a node. |
116
+ | `parentId` | `string` | `'parentId'` | Specifies the field name for associating with the parent node. |
117
+ | `childrenId` | `string` | `'children'` | Specifies the field name for the array of child nodes in the generated tree. |
118
+ | `allowSelfAsParent` | `boolean` | `false` | Whether to allow a node's `parentId` to be equal to its own `id`. |
121
119
 
122
120
  #### Example: Using Custom Fields
123
121
 
package/README.zh-CN.md CHANGED
@@ -106,18 +106,16 @@ export interface ArrayToTreeOptions {
106
106
  childrenId?: string;
107
107
  customId?: string;
108
108
  parentId?: string;
109
- rootId?: string;
110
109
  allowSelfAsParent?: boolean;
111
110
  }
112
111
  ```
113
112
 
114
- | 选项 | 类型 | 默认值 | 描述 |
115
- | ------------------- | --------- | ------------------------------------- | --------------------------------------------------------------------------------------------------- |
116
- | `customId` | `string` | `'id'` | 指定节点唯一标识的字段名。 |
117
- | `parentId` | `string` | `'parentId'` | 指定关联父节点的字段名。 |
118
- | `childrenId` | `string` | `'children'` | 指定生成的树中用于存放子节点数组的字段名。 |
119
- | `allowSelfAsParent` | `boolean` | `false` | 是否允许一个节点的 `parentId` 等于它自身的 `id`。 |
120
- | `rootId` | `string` | `'__ARRAY_TO_TREE_VIRTUAL_ROOT_ID__'` | 内部使用的虚拟根 ID,通常不需要修改。根节点的 `parentId` 应为 `null`、`undefined` 或空字符串 `""`。 |
113
+ | 选项 | 类型 | 默认值 | 描述 |
114
+ | ------------------- | --------- | ------------ | ------------------------------------------------- |
115
+ | `customId` | `string` | `'id'` | 指定节点唯一标识的字段名。 |
116
+ | `parentId` | `string` | `'parentId'` | 指定关联父节点的字段名。 |
117
+ | `childrenId` | `string` | `'children'` | 指定生成的树中用于存放子节点数组的字段名。 |
118
+ | `allowSelfAsParent` | `boolean` | `false` | 是否允许一个节点的 `parentId` 等于它自身的 `id`。 |
121
119
 
122
120
  #### 示例:使用自定义字段
123
121
 
@@ -1,2 +1,2 @@
1
- "use strict";class r extends Error{constructor(r){super(r),this.name="ArrayToTreeError"}}const t=(r,t)=>{const e=t.split(/[.[\]]/g);let n=r;for(const r of e){if(null===n)return null;if(void 0===n)return null;const t=r.replace(/['"]/g,"");""!==t.trim()&&(n=n[t])}return void 0===n?null:n},e=(r,n,o,s)=>Array.isArray(n)?n.map(n=>{const a={...n},d=t(n,o),c=null!=d?r[d]:void 0;return c&&(a[s]=e(r,c,o,s)),a}):[];exports.ArrayToTreeError=r,exports.arrayToTree=(n,o)=>{const s=(r=>({allowSelfAsParent:(r=r??{}).allowSelfAsParent??!1,childrenId:r.childrenId??"children",customId:r.customId??"id",parentId:r.parentId??"parentId",rootId:r.rootId??"__ARRAY_TO_TREE_VIRTUAL_ROOT_ID__"}))(o);if(!Array.isArray(n))throw new r("Expected an array but got an invalid argument.");const a=((e,n)=>{const o={};for(const s of e){const e=t(s,n.customId);if(null!=e&&Object.hasOwn(o,e))throw new r(`Duplicate node id "${e}" detected.`);o[e]=s}const s=new Set;return e.reduce((e,a)=>{const d=t(a,n.customId);let c=t(a,n.parentId);if(c===d){if(!n.allowSelfAsParent)throw new r(`Node "${d}" cannot be its own parent (self reference found).`);c=n.rootId}if(null!=d&&!s.has(d)){const e=new Set([d]);let a=c;for(;a&&a!==n.rootId&&!s.has(a);){if(e.has(a)){const t=[...e,a].join(" -> ");throw new r(`Cycle detected in parent chain: ${t}`)}e.add(a);const s=o[a];if(!s)break;a=t(s,n.parentId)}for(const r of e)s.add(r)}return c&&Object.hasOwn(o,c)||(c=n.rootId),Object.hasOwn(e,c)?e[c].push(a):e[c]=[a],e},{})})(n,s);return e(a,a[s.rootId],s.customId,s.childrenId)};
1
+ "use strict";class r extends Error{constructor(r){super(r),this.name="ArrayToTreeError"}}const t=(r,t)=>{const e=t.split(/[.[\]]/g);let n=r;for(const r of e){if(null===n)return null;if(void 0===n)return null;const t=r.replace(/['"]/g,"");""!==t.trim()&&(n=n[t])}return void 0===n?null:n},e=(r,n,o,s)=>Array.isArray(n)?n.map(n=>{const a={...n},c=t(n,o),d=null!=c?r[c]:void 0;return d&&(a[s]=e(r,d,o,s)),a}):[];exports.ArrayToTreeError=r,exports.arrayToTree=(n,o)=>{const s=(r=>{const t=r??{};return{allowSelfAsParent:t.allowSelfAsParent??!1,childrenId:t.childrenId??"children",customId:t.customId??"id",parentId:t.parentId??"parentId",rootId:Symbol("root")}})(o);if(!Array.isArray(n))throw new r("Expected an array but got an invalid argument.");const a=((e,n)=>{const o={};for(const s of e){const e=t(s,n.customId);if(null!=e&&Object.hasOwn(o,e))throw new r(`Duplicate node id "${e}" detected.`);o[e]=s}const s=new Set;return e.reduce((e,a)=>{const c=t(a,n.customId);let d=t(a,n.parentId);if(d===c){if(!n.allowSelfAsParent)throw new r(`Node "${c}" cannot be its own parent (self reference found).`);d=n.rootId}if(null!=c&&!s.has(c)){const e=new Set([c]);let a=d;for(;null!=a&&a!==n.rootId&&!s.has(a);){if(e.has(a)){const t=[...e,a].join(" -> ");throw new r(`Cycle detected in parent chain: ${t}`)}e.add(a);const s=o[a];if(!s)break;a=t(s,n.parentId)}for(const r of e)s.add(r)}return null!=d&&Object.hasOwn(o,d)||(d=n.rootId),Object.hasOwn(e,d)?e[d].push(a):e[d]=[a],e},{})})(n,s);return e(a,a[s.rootId],s.customId,s.childrenId)};
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../../../src/errors/array-to-tree-error.ts","../../../../src/internal/get.ts","../../../../src/internal/create-tree.ts","../../../../src/utils/array-to-tree.ts","../../../../src/internal/resolve-options.ts","../../../../src/internal/group-by-parents.ts"],"sourcesContent":["export class ArrayToTreeError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ArrayToTreeError\";\n }\n}\n","/**\n * This code is modified from the radash project.\n * @see https://github.com/sodiray/radash\n */\nexport const get = (value: any, path: string) => {\n const segments = path.split(/[.[\\]]/g);\n let current: any = value;\n for (const key of segments) {\n if (current === null) return null;\n if (current === undefined) return null;\n const dequoted = key.replace(/['\"]/g, \"\");\n if (dequoted.trim() === \"\") continue;\n current = current[dequoted];\n }\n if (current === undefined) return null;\n return current;\n};\n","import { get } from \"./get\";\n\nexport const createTree = (\n grouped: Record<string, any[]>,\n rootNodes: any[],\n customId: string,\n childrenProperty: string,\n) => {\n if (!Array.isArray(rootNodes)) {\n return [];\n }\n\n return rootNodes.map((node) => {\n const newNode = { ...node };\n const nodeId = get(node, customId);\n const children = nodeId != null ? grouped[nodeId] : undefined;\n if (children) {\n newNode[childrenProperty] = createTree(\n grouped,\n children,\n customId,\n childrenProperty,\n );\n }\n return newNode;\n });\n};\n","import { ArrayToTreeError } from \"../errors\";\nimport { createTree, groupByParents, resolveOptions } from \"../internal\";\nimport type {\n ArrayToTreeOptions,\n NormalizedArrayToTreeOptions,\n} from \"../types\";\n\nexport const arrayToTree = (\n data: Record<string, any>[],\n options?: ArrayToTreeOptions,\n) => {\n const normalizeOptions = resolveOptions(\n options,\n ) as NormalizedArrayToTreeOptions;\n\n if (!Array.isArray(data)) {\n throw new ArrayToTreeError(\n \"Expected an array but got an invalid argument.\",\n );\n }\n\n const grouped = groupByParents(data, normalizeOptions);\n\n return createTree(\n grouped,\n grouped[normalizeOptions.rootId],\n normalizeOptions.customId,\n normalizeOptions.childrenId,\n );\n};\n","import type { ArrayToTreeOptions } from \"../types\";\n\nexport const resolveOptions = (\n options?: ArrayToTreeOptions,\n): Required<ArrayToTreeOptions> => {\n options = options ?? {};\n return {\n allowSelfAsParent: options.allowSelfAsParent ?? false,\n childrenId: options.childrenId ?? \"children\",\n customId: options.customId ?? \"id\",\n parentId: options.parentId ?? \"parentId\",\n rootId: options.rootId ?? \"__ARRAY_TO_TREE_VIRTUAL_ROOT_ID__\",\n };\n};\n","import { ArrayToTreeError } from \"../errors\";\nimport type { NormalizedArrayToTreeOptions } from \"../types\";\nimport { get } from \"./get\";\n\nexport const groupByParents = (\n array: Record<string, any>[],\n options: NormalizedArrayToTreeOptions,\n) => {\n const arrayById: Record<string, any> = {};\n\n // 第一次遍历:构建索引并检测重复 id\n for (const item of array) {\n const key = get(item, options.customId);\n if (key != null && Object.hasOwn(arrayById, key)) {\n throw new ArrayToTreeError(`Duplicate node id \"${key}\" detected.`);\n }\n arrayById[key] = item;\n }\n\n const safe = new Set<any>();\n\n return array.reduce<Record<string, any[]>>((grouped, item) => {\n const id = get(item, options.customId);\n let parentId = get(item, options.parentId);\n\n // 1. 先处理自指节点\n if (parentId === id) {\n if (!options.allowSelfAsParent) {\n throw new ArrayToTreeError(\n `Node \"${id}\" cannot be its own parent (self reference found).`,\n );\n }\n parentId = options.rootId;\n }\n\n if (id != null && !safe.has(id)) {\n const path = new Set<any>([id]);\n let cursor = parentId;\n\n while (cursor && cursor !== options.rootId) {\n if (safe.has(cursor)) {\n break;\n }\n if (path.has(cursor)) {\n const cyclePath = [...path, cursor].join(\" -> \");\n throw new ArrayToTreeError(\n `Cycle detected in parent chain: ${cyclePath}`,\n );\n }\n path.add(cursor);\n\n const parentNode = arrayById[cursor];\n if (!parentNode) {\n break;\n }\n cursor = get(parentNode, options.parentId);\n }\n for (const n of path) safe.add(n);\n }\n\n if (!parentId || !Object.hasOwn(arrayById, parentId)) {\n parentId = options.rootId;\n }\n\n if (Object.hasOwn(grouped, parentId)) {\n grouped[parentId].push(item);\n } else {\n grouped[parentId] = [item];\n }\n return grouped;\n }, {});\n};\n"],"names":["ArrayToTreeError","Error","constructor","message","super","this","name","get","value","path","segments","split","current","key","undefined","dequoted","replace","trim","createTree","grouped","rootNodes","customId","childrenProperty","Array","isArray","map","node","newNode","nodeId","children","data","options","normalizeOptions","allowSelfAsParent","childrenId","parentId","rootId","resolveOptions","array","arrayById","item","Object","hasOwn","safe","Set","reduce","id","has","cursor","cyclePath","join","add","parentNode","n","push","groupByParents"],"mappings":"aAAM,MAAOA,UAAyBC,MACpC,WAAAC,CAAYC,GACVC,MAAMD,GACNE,KAAKC,KAAO,kBACd,ECAK,MAAMC,EAAM,CAACC,EAAYC,KAC9B,MAAMC,EAAWD,EAAKE,MAAM,WAC5B,IAAIC,EAAeJ,EACnB,IAAK,MAAMK,KAAOH,EAAU,CAC1B,GAAgB,OAAZE,EAAkB,OAAO,KAC7B,QAAgBE,IAAZF,EAAuB,OAAO,KAClC,MAAMG,EAAWF,EAAIG,QAAQ,QAAS,IACd,KAApBD,EAASE,SACbL,EAAUA,EAAQG,GACpB,CACA,YAAgBD,IAAZF,EAA8B,KAC3BA,GCbIM,EAAa,CACxBC,EACAC,EACAC,EACAC,IAEKC,MAAMC,QAAQJ,GAIZA,EAAUK,IAAKC,IACpB,MAAMC,EAAU,IAAKD,GACfE,EAASrB,EAAImB,EAAML,GACnBQ,EAAqB,MAAVD,EAAiBT,EAAQS,QAAUd,EASpD,OARIe,IACFF,EAAQL,GAAoBJ,EAC1BC,EACAU,EACAR,EACAC,IAGGK,IAfA,kDCFgB,CACzBG,EACAC,KAEA,MAAMC,ECTsB,CAC5BD,IAGO,CACLE,mBAFFF,EAAUA,GAAW,CAAA,GAEQE,oBAAqB,EAChDC,WAAYH,EAAQG,YAAc,WAClCb,SAAUU,EAAQV,UAAY,KAC9Bc,SAAUJ,EAAQI,UAAY,WAC9BC,OAAQL,EAAQK,QAAU,sCDAHC,CACvBN,GAGF,IAAKR,MAAMC,QAAQM,GACjB,MAAM,IAAI9B,EACR,kDAIJ,MAAMmB,EEjBsB,EAC5BmB,EACAP,KAEA,MAAMQ,EAAiC,CAAA,EAGvC,IAAK,MAAMC,KAAQF,EAAO,CACxB,MAAMzB,EAAMN,EAAIiC,EAAMT,EAAQV,UAC9B,GAAW,MAAPR,GAAe4B,OAAOC,OAAOH,EAAW1B,GAC1C,MAAM,IAAIb,EAAiB,sBAAsBa,gBAEnD0B,EAAU1B,GAAO2B,CACnB,CAEA,MAAMG,EAAO,IAAIC,IAEjB,OAAON,EAAMO,OAA8B,CAAC1B,EAASqB,KACnD,MAAMM,EAAKvC,EAAIiC,EAAMT,EAAQV,UAC7B,IAAIc,EAAW5B,EAAIiC,EAAMT,EAAQI,UAGjC,GAAIA,IAAaW,EAAI,CACnB,IAAKf,EAAQE,kBACX,MAAM,IAAIjC,EACR,SAAS8C,uDAGbX,EAAWJ,EAAQK,MACrB,CAEA,GAAU,MAANU,IAAeH,EAAKI,IAAID,GAAK,CAC/B,MAAMrC,EAAO,IAAImC,IAAS,CAACE,IAC3B,IAAIE,EAASb,EAEb,KAAOa,GAAUA,IAAWjB,EAAQK,SAC9BO,EAAKI,IAAIC,IAD6B,CAI1C,GAAIvC,EAAKsC,IAAIC,GAAS,CACpB,MAAMC,EAAY,IAAIxC,EAAMuC,GAAQE,KAAK,QACzC,MAAM,IAAIlD,EACR,mCAAmCiD,IAEvC,CACAxC,EAAK0C,IAAIH,GAET,MAAMI,EAAab,EAAUS,GAC7B,IAAKI,EACH,MAEFJ,EAASzC,EAAI6C,EAAYrB,EAAQI,SACnC,CACA,IAAK,MAAMkB,KAAK5C,EAAMkC,EAAKQ,IAAIE,EACjC,CAWA,OATKlB,GAAaM,OAAOC,OAAOH,EAAWJ,KACzCA,EAAWJ,EAAQK,QAGjBK,OAAOC,OAAOvB,EAASgB,GACzBhB,EAAQgB,GAAUmB,KAAKd,GAEvBrB,EAAQgB,GAAY,CAACK,GAEhBrB,GACN,CAAA,IFjDaoC,CAAezB,EAAME,GAErC,OAAOd,EACLC,EACAA,EAAQa,EAAiBI,QACzBJ,EAAiBX,SACjBW,EAAiBE"}
1
+ {"version":3,"file":"index.cjs","sources":["../../../../src/errors/array-to-tree-error.ts","../../../../src/internal/get.ts","../../../../src/internal/create-tree.ts","../../../../src/utils/array-to-tree.ts","../../../../src/internal/resolve-options.ts","../../../../src/internal/group-by-parents.ts"],"sourcesContent":["export class ArrayToTreeError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ArrayToTreeError\";\n }\n}\n","/**\n * This code is modified from the radash project.\n * @see https://github.com/sodiray/radash\n */\nexport const get = (value: any, path: string) => {\n const segments = path.split(/[.[\\]]/g);\n let current: any = value;\n for (const key of segments) {\n if (current === null) return null;\n if (current === undefined) return null;\n const dequoted = key.replace(/['\"]/g, \"\");\n if (dequoted.trim() === \"\") continue;\n current = current[dequoted];\n }\n if (current === undefined) return null;\n return current;\n};\n","import { get } from \"./get\";\n\nexport const createTree = (\n grouped: Record<string, any[]>,\n rootNodes: any[],\n customId: string,\n childrenProperty: string,\n) => {\n if (!Array.isArray(rootNodes)) {\n return [];\n }\n\n return rootNodes.map((node) => {\n const newNode = { ...node };\n const nodeId = get(node, customId);\n const children = nodeId != null ? grouped[nodeId] : undefined;\n if (children) {\n newNode[childrenProperty] = createTree(\n grouped,\n children,\n customId,\n childrenProperty,\n );\n }\n return newNode;\n });\n};\n","import { ArrayToTreeError } from \"../errors\";\nimport { createTree, groupByParents, resolveOptions } from \"../internal\";\nimport type {\n ArrayToTreeOptions,\n NormalizedArrayToTreeOptions,\n} from \"../types\";\n\nexport const arrayToTree = (\n data: Record<string, any>[],\n options?: ArrayToTreeOptions,\n) => {\n const normalizeOptions = resolveOptions(\n options,\n ) as NormalizedArrayToTreeOptions;\n\n if (!Array.isArray(data)) {\n throw new ArrayToTreeError(\n \"Expected an array but got an invalid argument.\",\n );\n }\n\n const grouped = groupByParents(data, normalizeOptions);\n\n return createTree(\n grouped,\n grouped[normalizeOptions.rootId],\n normalizeOptions.customId,\n normalizeOptions.childrenId,\n );\n};\n","import type {\n ArrayToTreeOptions,\n NormalizedArrayToTreeOptions,\n} from \"../types\";\n\nexport const resolveOptions = (\n options?: ArrayToTreeOptions,\n): NormalizedArrayToTreeOptions => {\n const resolved = options ?? {};\n return {\n allowSelfAsParent: resolved.allowSelfAsParent ?? false,\n childrenId: resolved.childrenId ?? \"children\",\n customId: resolved.customId ?? \"id\",\n parentId: resolved.parentId ?? \"parentId\",\n rootId: Symbol(\"root\"),\n };\n};\n","import { ArrayToTreeError } from \"../errors\";\nimport type { NormalizedArrayToTreeOptions } from \"../types\";\nimport { get } from \"./get\";\n\nexport const groupByParents = (\n array: Record<string, any>[],\n options: NormalizedArrayToTreeOptions,\n) => {\n const arrayById: Record<string, any> = {};\n\n // 第一次遍历:构建索引并检测重复 id\n for (const item of array) {\n const key = get(item, options.customId);\n if (key != null && Object.hasOwn(arrayById, key)) {\n throw new ArrayToTreeError(`Duplicate node id \"${key}\" detected.`);\n }\n arrayById[key] = item;\n }\n\n const safe = new Set<any>();\n\n return array.reduce<Record<string, any[]>>((grouped, item) => {\n const id = get(item, options.customId);\n let parentId = get(item, options.parentId);\n\n // 1. 先处理自指节点\n if (parentId === id) {\n if (!options.allowSelfAsParent) {\n throw new ArrayToTreeError(\n `Node \"${id}\" cannot be its own parent (self reference found).`,\n );\n }\n parentId = options.rootId;\n }\n\n if (id != null && !safe.has(id)) {\n const path = new Set<any>([id]);\n let cursor = parentId;\n\n while (cursor != null && cursor !== options.rootId) {\n if (safe.has(cursor)) {\n break;\n }\n if (path.has(cursor)) {\n const cyclePath = [...path, cursor].join(\" -> \");\n throw new ArrayToTreeError(\n `Cycle detected in parent chain: ${cyclePath}`,\n );\n }\n path.add(cursor);\n\n const parentNode = arrayById[cursor];\n if (!parentNode) {\n break;\n }\n cursor = get(parentNode, options.parentId);\n }\n for (const n of path) safe.add(n);\n }\n\n if (parentId == null || !Object.hasOwn(arrayById, parentId)) {\n parentId = options.rootId;\n }\n\n if (Object.hasOwn(grouped, parentId)) {\n grouped[parentId].push(item);\n } else {\n grouped[parentId] = [item];\n }\n return grouped;\n }, {});\n};\n"],"names":["ArrayToTreeError","Error","constructor","message","super","this","name","get","value","path","segments","split","current","key","undefined","dequoted","replace","trim","createTree","grouped","rootNodes","customId","childrenProperty","Array","isArray","map","node","newNode","nodeId","children","data","options","normalizeOptions","resolved","allowSelfAsParent","childrenId","parentId","rootId","Symbol","resolveOptions","array","arrayById","item","Object","hasOwn","safe","Set","reduce","id","has","cursor","cyclePath","join","add","parentNode","n","push","groupByParents"],"mappings":"aAAM,MAAOA,UAAyBC,MACpC,WAAAC,CAAYC,GACVC,MAAMD,GACNE,KAAKC,KAAO,kBACd,ECAK,MAAMC,EAAM,CAACC,EAAYC,KAC9B,MAAMC,EAAWD,EAAKE,MAAM,WAC5B,IAAIC,EAAeJ,EACnB,IAAK,MAAMK,KAAOH,EAAU,CAC1B,GAAgB,OAAZE,EAAkB,OAAO,KAC7B,QAAgBE,IAAZF,EAAuB,OAAO,KAClC,MAAMG,EAAWF,EAAIG,QAAQ,QAAS,IACd,KAApBD,EAASE,SACbL,EAAUA,EAAQG,GACpB,CACA,YAAgBD,IAAZF,EAA8B,KAC3BA,GCbIM,EAAa,CACxBC,EACAC,EACAC,EACAC,IAEKC,MAAMC,QAAQJ,GAIZA,EAAUK,IAAKC,IACpB,MAAMC,EAAU,IAAKD,GACfE,EAASrB,EAAImB,EAAML,GACnBQ,EAAqB,MAAVD,EAAiBT,EAAQS,QAAUd,EASpD,OARIe,IACFF,EAAQL,GAAoBJ,EAC1BC,EACAU,EACAR,EACAC,IAGGK,IAfA,kDCFgB,CACzBG,EACAC,KAEA,MAAMC,ECNsB,CAC5BD,IAEA,MAAME,EAAWF,GAAW,CAAA,EAC5B,MAAO,CACLG,kBAAmBD,EAASC,oBAAqB,EACjDC,WAAYF,EAASE,YAAc,WACnCd,SAAUY,EAASZ,UAAY,KAC/Be,SAAUH,EAASG,UAAY,WAC/BC,OAAQC,OAAO,UDHQC,CACvBR,GAGF,IAAKR,MAAMC,QAAQM,GACjB,MAAM,IAAI9B,EACR,kDAIJ,MAAMmB,EEjBsB,EAC5BqB,EACAT,KAEA,MAAMU,EAAiC,CAAA,EAGvC,IAAK,MAAMC,KAAQF,EAAO,CACxB,MAAM3B,EAAMN,EAAImC,EAAMX,EAAQV,UAC9B,GAAW,MAAPR,GAAe8B,OAAOC,OAAOH,EAAW5B,GAC1C,MAAM,IAAIb,EAAiB,sBAAsBa,gBAEnD4B,EAAU5B,GAAO6B,CACnB,CAEA,MAAMG,EAAO,IAAIC,IAEjB,OAAON,EAAMO,OAA8B,CAAC5B,EAASuB,KACnD,MAAMM,EAAKzC,EAAImC,EAAMX,EAAQV,UAC7B,IAAIe,EAAW7B,EAAImC,EAAMX,EAAQK,UAGjC,GAAIA,IAAaY,EAAI,CACnB,IAAKjB,EAAQG,kBACX,MAAM,IAAIlC,EACR,SAASgD,uDAGbZ,EAAWL,EAAQM,MACrB,CAEA,GAAU,MAANW,IAAeH,EAAKI,IAAID,GAAK,CAC/B,MAAMvC,EAAO,IAAIqC,IAAS,CAACE,IAC3B,IAAIE,EAASd,EAEb,KAAiB,MAAVc,GAAkBA,IAAWnB,EAAQM,SACtCQ,EAAKI,IAAIC,IADqC,CAIlD,GAAIzC,EAAKwC,IAAIC,GAAS,CACpB,MAAMC,EAAY,IAAI1C,EAAMyC,GAAQE,KAAK,QACzC,MAAM,IAAIpD,EACR,mCAAmCmD,IAEvC,CACA1C,EAAK4C,IAAIH,GAET,MAAMI,EAAab,EAAUS,GAC7B,IAAKI,EACH,MAEFJ,EAAS3C,EAAI+C,EAAYvB,EAAQK,SACnC,CACA,IAAK,MAAMmB,KAAK9C,EAAMoC,EAAKQ,IAAIE,EACjC,CAWA,OATgB,MAAZnB,GAAqBO,OAAOC,OAAOH,EAAWL,KAChDA,EAAWL,EAAQM,QAGjBM,OAAOC,OAAOzB,EAASiB,GACzBjB,EAAQiB,GAAUoB,KAAKd,GAEvBvB,EAAQiB,GAAY,CAACM,GAEhBvB,GACN,CAAA,IFjDasC,CAAe3B,EAAME,GAErC,OAAOd,EACLC,EACAA,EAAQa,EAAiBK,QACzBL,EAAiBX,SACjBW,EAAiBG"}
@@ -1,2 +1,2 @@
1
- class t extends Error{constructor(t){super(t),this.name="ArrayToTreeError"}}const r=(t,r)=>{const e=r.split(/[.[\]]/g);let n=t;for(const t of e){if(null===n)return null;if(void 0===n)return null;const r=t.replace(/['"]/g,"");""!==r.trim()&&(n=n[r])}return void 0===n?null:n},e=(t,n,o,d)=>Array.isArray(n)?n.map(n=>{const s={...n},c=r(n,o),a=null!=c?t[c]:void 0;return a&&(s[d]=e(t,a,o,d)),s}):[],n=(n,o)=>{const d=(t=>({allowSelfAsParent:(t=t??{}).allowSelfAsParent??!1,childrenId:t.childrenId??"children",customId:t.customId??"id",parentId:t.parentId??"parentId",rootId:t.rootId??"__ARRAY_TO_TREE_VIRTUAL_ROOT_ID__"}))(o);if(!Array.isArray(n))throw new t("Expected an array but got an invalid argument.");const s=((e,n)=>{const o={};for(const d of e){const e=r(d,n.customId);if(null!=e&&Object.hasOwn(o,e))throw new t(`Duplicate node id "${e}" detected.`);o[e]=d}const d=new Set;return e.reduce((e,s)=>{const c=r(s,n.customId);let a=r(s,n.parentId);if(a===c){if(!n.allowSelfAsParent)throw new t(`Node "${c}" cannot be its own parent (self reference found).`);a=n.rootId}if(null!=c&&!d.has(c)){const e=new Set([c]);let s=a;for(;s&&s!==n.rootId&&!d.has(s);){if(e.has(s)){const r=[...e,s].join(" -> ");throw new t(`Cycle detected in parent chain: ${r}`)}e.add(s);const d=o[s];if(!d)break;s=r(d,n.parentId)}for(const t of e)d.add(t)}return a&&Object.hasOwn(o,a)||(a=n.rootId),Object.hasOwn(e,a)?e[a].push(s):e[a]=[s],e},{})})(n,d);return e(s,s[d.rootId],d.customId,d.childrenId)};export{t as ArrayToTreeError,n as arrayToTree};
1
+ class t extends Error{constructor(t){super(t),this.name="ArrayToTreeError"}}const r=(t,r)=>{const n=r.split(/[.[\]]/g);let e=t;for(const t of n){if(null===e)return null;if(void 0===e)return null;const r=t.replace(/['"]/g,"");""!==r.trim()&&(e=e[r])}return void 0===e?null:e},n=(t,e,o,s)=>Array.isArray(e)?e.map(e=>{const c={...e},d=r(e,o),l=null!=d?t[d]:void 0;return l&&(c[s]=n(t,l,o,s)),c}):[],e=(e,o)=>{const s=(t=>{const r=t??{};return{allowSelfAsParent:r.allowSelfAsParent??!1,childrenId:r.childrenId??"children",customId:r.customId??"id",parentId:r.parentId??"parentId",rootId:Symbol("root")}})(o);if(!Array.isArray(e))throw new t("Expected an array but got an invalid argument.");const c=((n,e)=>{const o={};for(const s of n){const n=r(s,e.customId);if(null!=n&&Object.hasOwn(o,n))throw new t(`Duplicate node id "${n}" detected.`);o[n]=s}const s=new Set;return n.reduce((n,c)=>{const d=r(c,e.customId);let l=r(c,e.parentId);if(l===d){if(!e.allowSelfAsParent)throw new t(`Node "${d}" cannot be its own parent (self reference found).`);l=e.rootId}if(null!=d&&!s.has(d)){const n=new Set([d]);let c=l;for(;null!=c&&c!==e.rootId&&!s.has(c);){if(n.has(c)){const r=[...n,c].join(" -> ");throw new t(`Cycle detected in parent chain: ${r}`)}n.add(c);const s=o[c];if(!s)break;c=r(s,e.parentId)}for(const t of n)s.add(t)}return null!=l&&Object.hasOwn(o,l)||(l=e.rootId),Object.hasOwn(n,l)?n[l].push(c):n[l]=[c],n},{})})(e,s);return n(c,c[s.rootId],s.customId,s.childrenId)};export{t as ArrayToTreeError,e as arrayToTree};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../../../src/errors/array-to-tree-error.ts","../../../../src/internal/get.ts","../../../../src/internal/create-tree.ts","../../../../src/utils/array-to-tree.ts","../../../../src/internal/resolve-options.ts","../../../../src/internal/group-by-parents.ts"],"sourcesContent":["export class ArrayToTreeError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ArrayToTreeError\";\n }\n}\n","/**\n * This code is modified from the radash project.\n * @see https://github.com/sodiray/radash\n */\nexport const get = (value: any, path: string) => {\n const segments = path.split(/[.[\\]]/g);\n let current: any = value;\n for (const key of segments) {\n if (current === null) return null;\n if (current === undefined) return null;\n const dequoted = key.replace(/['\"]/g, \"\");\n if (dequoted.trim() === \"\") continue;\n current = current[dequoted];\n }\n if (current === undefined) return null;\n return current;\n};\n","import { get } from \"./get\";\n\nexport const createTree = (\n grouped: Record<string, any[]>,\n rootNodes: any[],\n customId: string,\n childrenProperty: string,\n) => {\n if (!Array.isArray(rootNodes)) {\n return [];\n }\n\n return rootNodes.map((node) => {\n const newNode = { ...node };\n const nodeId = get(node, customId);\n const children = nodeId != null ? grouped[nodeId] : undefined;\n if (children) {\n newNode[childrenProperty] = createTree(\n grouped,\n children,\n customId,\n childrenProperty,\n );\n }\n return newNode;\n });\n};\n","import { ArrayToTreeError } from \"../errors\";\nimport { createTree, groupByParents, resolveOptions } from \"../internal\";\nimport type {\n ArrayToTreeOptions,\n NormalizedArrayToTreeOptions,\n} from \"../types\";\n\nexport const arrayToTree = (\n data: Record<string, any>[],\n options?: ArrayToTreeOptions,\n) => {\n const normalizeOptions = resolveOptions(\n options,\n ) as NormalizedArrayToTreeOptions;\n\n if (!Array.isArray(data)) {\n throw new ArrayToTreeError(\n \"Expected an array but got an invalid argument.\",\n );\n }\n\n const grouped = groupByParents(data, normalizeOptions);\n\n return createTree(\n grouped,\n grouped[normalizeOptions.rootId],\n normalizeOptions.customId,\n normalizeOptions.childrenId,\n );\n};\n","import type { ArrayToTreeOptions } from \"../types\";\n\nexport const resolveOptions = (\n options?: ArrayToTreeOptions,\n): Required<ArrayToTreeOptions> => {\n options = options ?? {};\n return {\n allowSelfAsParent: options.allowSelfAsParent ?? false,\n childrenId: options.childrenId ?? \"children\",\n customId: options.customId ?? \"id\",\n parentId: options.parentId ?? \"parentId\",\n rootId: options.rootId ?? \"__ARRAY_TO_TREE_VIRTUAL_ROOT_ID__\",\n };\n};\n","import { ArrayToTreeError } from \"../errors\";\nimport type { NormalizedArrayToTreeOptions } from \"../types\";\nimport { get } from \"./get\";\n\nexport const groupByParents = (\n array: Record<string, any>[],\n options: NormalizedArrayToTreeOptions,\n) => {\n const arrayById: Record<string, any> = {};\n\n // 第一次遍历:构建索引并检测重复 id\n for (const item of array) {\n const key = get(item, options.customId);\n if (key != null && Object.hasOwn(arrayById, key)) {\n throw new ArrayToTreeError(`Duplicate node id \"${key}\" detected.`);\n }\n arrayById[key] = item;\n }\n\n const safe = new Set<any>();\n\n return array.reduce<Record<string, any[]>>((grouped, item) => {\n const id = get(item, options.customId);\n let parentId = get(item, options.parentId);\n\n // 1. 先处理自指节点\n if (parentId === id) {\n if (!options.allowSelfAsParent) {\n throw new ArrayToTreeError(\n `Node \"${id}\" cannot be its own parent (self reference found).`,\n );\n }\n parentId = options.rootId;\n }\n\n if (id != null && !safe.has(id)) {\n const path = new Set<any>([id]);\n let cursor = parentId;\n\n while (cursor && cursor !== options.rootId) {\n if (safe.has(cursor)) {\n break;\n }\n if (path.has(cursor)) {\n const cyclePath = [...path, cursor].join(\" -> \");\n throw new ArrayToTreeError(\n `Cycle detected in parent chain: ${cyclePath}`,\n );\n }\n path.add(cursor);\n\n const parentNode = arrayById[cursor];\n if (!parentNode) {\n break;\n }\n cursor = get(parentNode, options.parentId);\n }\n for (const n of path) safe.add(n);\n }\n\n if (!parentId || !Object.hasOwn(arrayById, parentId)) {\n parentId = options.rootId;\n }\n\n if (Object.hasOwn(grouped, parentId)) {\n grouped[parentId].push(item);\n } else {\n grouped[parentId] = [item];\n }\n return grouped;\n }, {});\n};\n"],"names":["ArrayToTreeError","Error","constructor","message","super","this","name","get","value","path","segments","split","current","key","undefined","dequoted","replace","trim","createTree","grouped","rootNodes","customId","childrenProperty","Array","isArray","map","node","newNode","nodeId","children","arrayToTree","data","options","normalizeOptions","allowSelfAsParent","childrenId","parentId","rootId","resolveOptions","array","arrayById","item","Object","hasOwn","safe","Set","reduce","id","has","cursor","cyclePath","join","add","parentNode","n","push","groupByParents"],"mappings":"AAAM,MAAOA,UAAyBC,MACpC,WAAAC,CAAYC,GACVC,MAAMD,GACNE,KAAKC,KAAO,kBACd,ECAK,MAAMC,EAAM,CAACC,EAAYC,KAC9B,MAAMC,EAAWD,EAAKE,MAAM,WAC5B,IAAIC,EAAeJ,EACnB,IAAK,MAAMK,KAAOH,EAAU,CAC1B,GAAgB,OAAZE,EAAkB,OAAO,KAC7B,QAAgBE,IAAZF,EAAuB,OAAO,KAClC,MAAMG,EAAWF,EAAIG,QAAQ,QAAS,IACd,KAApBD,EAASE,SACbL,EAAUA,EAAQG,GACpB,CACA,YAAgBD,IAAZF,EAA8B,KAC3BA,GCbIM,EAAa,CACxBC,EACAC,EACAC,EACAC,IAEKC,MAAMC,QAAQJ,GAIZA,EAAUK,IAAKC,IACpB,MAAMC,EAAU,IAAKD,GACfE,EAASrB,EAAImB,EAAML,GACnBQ,EAAqB,MAAVD,EAAiBT,EAAQS,QAAUd,EASpD,OARIe,IACFF,EAAQL,GAAoBJ,EAC1BC,EACAU,EACAR,EACAC,IAGGK,IAfA,GCFEG,EAAc,CACzBC,EACAC,KAEA,MAAMC,ECTsB,CAC5BD,IAGO,CACLE,mBAFFF,EAAUA,GAAW,CAAA,GAEQE,oBAAqB,EAChDC,WAAYH,EAAQG,YAAc,WAClCd,SAAUW,EAAQX,UAAY,KAC9Be,SAAUJ,EAAQI,UAAY,WAC9BC,OAAQL,EAAQK,QAAU,sCDAHC,CACvBN,GAGF,IAAKT,MAAMC,QAAQO,GACjB,MAAM,IAAI/B,EACR,kDAIJ,MAAMmB,EEjBsB,EAC5BoB,EACAP,KAEA,MAAMQ,EAAiC,CAAA,EAGvC,IAAK,MAAMC,KAAQF,EAAO,CACxB,MAAM1B,EAAMN,EAAIkC,EAAMT,EAAQX,UAC9B,GAAW,MAAPR,GAAe6B,OAAOC,OAAOH,EAAW3B,GAC1C,MAAM,IAAIb,EAAiB,sBAAsBa,gBAEnD2B,EAAU3B,GAAO4B,CACnB,CAEA,MAAMG,EAAO,IAAIC,IAEjB,OAAON,EAAMO,OAA8B,CAAC3B,EAASsB,KACnD,MAAMM,EAAKxC,EAAIkC,EAAMT,EAAQX,UAC7B,IAAIe,EAAW7B,EAAIkC,EAAMT,EAAQI,UAGjC,GAAIA,IAAaW,EAAI,CACnB,IAAKf,EAAQE,kBACX,MAAM,IAAIlC,EACR,SAAS+C,uDAGbX,EAAWJ,EAAQK,MACrB,CAEA,GAAU,MAANU,IAAeH,EAAKI,IAAID,GAAK,CAC/B,MAAMtC,EAAO,IAAIoC,IAAS,CAACE,IAC3B,IAAIE,EAASb,EAEb,KAAOa,GAAUA,IAAWjB,EAAQK,SAC9BO,EAAKI,IAAIC,IAD6B,CAI1C,GAAIxC,EAAKuC,IAAIC,GAAS,CACpB,MAAMC,EAAY,IAAIzC,EAAMwC,GAAQE,KAAK,QACzC,MAAM,IAAInD,EACR,mCAAmCkD,IAEvC,CACAzC,EAAK2C,IAAIH,GAET,MAAMI,EAAab,EAAUS,GAC7B,IAAKI,EACH,MAEFJ,EAAS1C,EAAI8C,EAAYrB,EAAQI,SACnC,CACA,IAAK,MAAMkB,KAAK7C,EAAMmC,EAAKQ,IAAIE,EACjC,CAWA,OATKlB,GAAaM,OAAOC,OAAOH,EAAWJ,KACzCA,EAAWJ,EAAQK,QAGjBK,OAAOC,OAAOxB,EAASiB,GACzBjB,EAAQiB,GAAUmB,KAAKd,GAEvBtB,EAAQiB,GAAY,CAACK,GAEhBtB,GACN,CAAA,IFjDaqC,CAAezB,EAAME,GAErC,OAAOf,EACLC,EACAA,EAAQc,EAAiBI,QACzBJ,EAAiBZ,SACjBY,EAAiBE"}
1
+ {"version":3,"file":"index.mjs","sources":["../../../../src/errors/array-to-tree-error.ts","../../../../src/internal/get.ts","../../../../src/internal/create-tree.ts","../../../../src/utils/array-to-tree.ts","../../../../src/internal/resolve-options.ts","../../../../src/internal/group-by-parents.ts"],"sourcesContent":["export class ArrayToTreeError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ArrayToTreeError\";\n }\n}\n","/**\n * This code is modified from the radash project.\n * @see https://github.com/sodiray/radash\n */\nexport const get = (value: any, path: string) => {\n const segments = path.split(/[.[\\]]/g);\n let current: any = value;\n for (const key of segments) {\n if (current === null) return null;\n if (current === undefined) return null;\n const dequoted = key.replace(/['\"]/g, \"\");\n if (dequoted.trim() === \"\") continue;\n current = current[dequoted];\n }\n if (current === undefined) return null;\n return current;\n};\n","import { get } from \"./get\";\n\nexport const createTree = (\n grouped: Record<string, any[]>,\n rootNodes: any[],\n customId: string,\n childrenProperty: string,\n) => {\n if (!Array.isArray(rootNodes)) {\n return [];\n }\n\n return rootNodes.map((node) => {\n const newNode = { ...node };\n const nodeId = get(node, customId);\n const children = nodeId != null ? grouped[nodeId] : undefined;\n if (children) {\n newNode[childrenProperty] = createTree(\n grouped,\n children,\n customId,\n childrenProperty,\n );\n }\n return newNode;\n });\n};\n","import { ArrayToTreeError } from \"../errors\";\nimport { createTree, groupByParents, resolveOptions } from \"../internal\";\nimport type {\n ArrayToTreeOptions,\n NormalizedArrayToTreeOptions,\n} from \"../types\";\n\nexport const arrayToTree = (\n data: Record<string, any>[],\n options?: ArrayToTreeOptions,\n) => {\n const normalizeOptions = resolveOptions(\n options,\n ) as NormalizedArrayToTreeOptions;\n\n if (!Array.isArray(data)) {\n throw new ArrayToTreeError(\n \"Expected an array but got an invalid argument.\",\n );\n }\n\n const grouped = groupByParents(data, normalizeOptions);\n\n return createTree(\n grouped,\n grouped[normalizeOptions.rootId],\n normalizeOptions.customId,\n normalizeOptions.childrenId,\n );\n};\n","import type {\n ArrayToTreeOptions,\n NormalizedArrayToTreeOptions,\n} from \"../types\";\n\nexport const resolveOptions = (\n options?: ArrayToTreeOptions,\n): NormalizedArrayToTreeOptions => {\n const resolved = options ?? {};\n return {\n allowSelfAsParent: resolved.allowSelfAsParent ?? false,\n childrenId: resolved.childrenId ?? \"children\",\n customId: resolved.customId ?? \"id\",\n parentId: resolved.parentId ?? \"parentId\",\n rootId: Symbol(\"root\"),\n };\n};\n","import { ArrayToTreeError } from \"../errors\";\nimport type { NormalizedArrayToTreeOptions } from \"../types\";\nimport { get } from \"./get\";\n\nexport const groupByParents = (\n array: Record<string, any>[],\n options: NormalizedArrayToTreeOptions,\n) => {\n const arrayById: Record<string, any> = {};\n\n // 第一次遍历:构建索引并检测重复 id\n for (const item of array) {\n const key = get(item, options.customId);\n if (key != null && Object.hasOwn(arrayById, key)) {\n throw new ArrayToTreeError(`Duplicate node id \"${key}\" detected.`);\n }\n arrayById[key] = item;\n }\n\n const safe = new Set<any>();\n\n return array.reduce<Record<string, any[]>>((grouped, item) => {\n const id = get(item, options.customId);\n let parentId = get(item, options.parentId);\n\n // 1. 先处理自指节点\n if (parentId === id) {\n if (!options.allowSelfAsParent) {\n throw new ArrayToTreeError(\n `Node \"${id}\" cannot be its own parent (self reference found).`,\n );\n }\n parentId = options.rootId;\n }\n\n if (id != null && !safe.has(id)) {\n const path = new Set<any>([id]);\n let cursor = parentId;\n\n while (cursor != null && cursor !== options.rootId) {\n if (safe.has(cursor)) {\n break;\n }\n if (path.has(cursor)) {\n const cyclePath = [...path, cursor].join(\" -> \");\n throw new ArrayToTreeError(\n `Cycle detected in parent chain: ${cyclePath}`,\n );\n }\n path.add(cursor);\n\n const parentNode = arrayById[cursor];\n if (!parentNode) {\n break;\n }\n cursor = get(parentNode, options.parentId);\n }\n for (const n of path) safe.add(n);\n }\n\n if (parentId == null || !Object.hasOwn(arrayById, parentId)) {\n parentId = options.rootId;\n }\n\n if (Object.hasOwn(grouped, parentId)) {\n grouped[parentId].push(item);\n } else {\n grouped[parentId] = [item];\n }\n return grouped;\n }, {});\n};\n"],"names":["ArrayToTreeError","Error","constructor","message","super","this","name","get","value","path","segments","split","current","key","undefined","dequoted","replace","trim","createTree","grouped","rootNodes","customId","childrenProperty","Array","isArray","map","node","newNode","nodeId","children","arrayToTree","data","options","normalizeOptions","resolved","allowSelfAsParent","childrenId","parentId","rootId","Symbol","resolveOptions","array","arrayById","item","Object","hasOwn","safe","Set","reduce","id","has","cursor","cyclePath","join","add","parentNode","n","push","groupByParents"],"mappings":"AAAM,MAAOA,UAAyBC,MACpC,WAAAC,CAAYC,GACVC,MAAMD,GACNE,KAAKC,KAAO,kBACd,ECAK,MAAMC,EAAM,CAACC,EAAYC,KAC9B,MAAMC,EAAWD,EAAKE,MAAM,WAC5B,IAAIC,EAAeJ,EACnB,IAAK,MAAMK,KAAOH,EAAU,CAC1B,GAAgB,OAAZE,EAAkB,OAAO,KAC7B,QAAgBE,IAAZF,EAAuB,OAAO,KAClC,MAAMG,EAAWF,EAAIG,QAAQ,QAAS,IACd,KAApBD,EAASE,SACbL,EAAUA,EAAQG,GACpB,CACA,YAAgBD,IAAZF,EAA8B,KAC3BA,GCbIM,EAAa,CACxBC,EACAC,EACAC,EACAC,IAEKC,MAAMC,QAAQJ,GAIZA,EAAUK,IAAKC,IACpB,MAAMC,EAAU,IAAKD,GACfE,EAASrB,EAAImB,EAAML,GACnBQ,EAAqB,MAAVD,EAAiBT,EAAQS,QAAUd,EASpD,OARIe,IACFF,EAAQL,GAAoBJ,EAC1BC,EACAU,EACAR,EACAC,IAGGK,IAfA,GCFEG,EAAc,CACzBC,EACAC,KAEA,MAAMC,ECNsB,CAC5BD,IAEA,MAAME,EAAWF,GAAW,CAAA,EAC5B,MAAO,CACLG,kBAAmBD,EAASC,oBAAqB,EACjDC,WAAYF,EAASE,YAAc,WACnCf,SAAUa,EAASb,UAAY,KAC/BgB,SAAUH,EAASG,UAAY,WAC/BC,OAAQC,OAAO,UDHQC,CACvBR,GAGF,IAAKT,MAAMC,QAAQO,GACjB,MAAM,IAAI/B,EACR,kDAIJ,MAAMmB,EEjBsB,EAC5BsB,EACAT,KAEA,MAAMU,EAAiC,CAAA,EAGvC,IAAK,MAAMC,KAAQF,EAAO,CACxB,MAAM5B,EAAMN,EAAIoC,EAAMX,EAAQX,UAC9B,GAAW,MAAPR,GAAe+B,OAAOC,OAAOH,EAAW7B,GAC1C,MAAM,IAAIb,EAAiB,sBAAsBa,gBAEnD6B,EAAU7B,GAAO8B,CACnB,CAEA,MAAMG,EAAO,IAAIC,IAEjB,OAAON,EAAMO,OAA8B,CAAC7B,EAASwB,KACnD,MAAMM,EAAK1C,EAAIoC,EAAMX,EAAQX,UAC7B,IAAIgB,EAAW9B,EAAIoC,EAAMX,EAAQK,UAGjC,GAAIA,IAAaY,EAAI,CACnB,IAAKjB,EAAQG,kBACX,MAAM,IAAInC,EACR,SAASiD,uDAGbZ,EAAWL,EAAQM,MACrB,CAEA,GAAU,MAANW,IAAeH,EAAKI,IAAID,GAAK,CAC/B,MAAMxC,EAAO,IAAIsC,IAAS,CAACE,IAC3B,IAAIE,EAASd,EAEb,KAAiB,MAAVc,GAAkBA,IAAWnB,EAAQM,SACtCQ,EAAKI,IAAIC,IADqC,CAIlD,GAAI1C,EAAKyC,IAAIC,GAAS,CACpB,MAAMC,EAAY,IAAI3C,EAAM0C,GAAQE,KAAK,QACzC,MAAM,IAAIrD,EACR,mCAAmCoD,IAEvC,CACA3C,EAAK6C,IAAIH,GAET,MAAMI,EAAab,EAAUS,GAC7B,IAAKI,EACH,MAEFJ,EAAS5C,EAAIgD,EAAYvB,EAAQK,SACnC,CACA,IAAK,MAAMmB,KAAK/C,EAAMqC,EAAKQ,IAAIE,EACjC,CAWA,OATgB,MAAZnB,GAAqBO,OAAOC,OAAOH,EAAWL,KAChDA,EAAWL,EAAQM,QAGjBM,OAAOC,OAAO1B,EAASkB,GACzBlB,EAAQkB,GAAUoB,KAAKd,GAEvBxB,EAAQkB,GAAY,CAACM,GAEhBxB,GACN,CAAA,IFjDauC,CAAe3B,EAAME,GAErC,OAAOf,EACLC,EACAA,EAAQc,EAAiBK,QACzBL,EAAiBZ,SACjBY,EAAiBG"}
@@ -7,10 +7,11 @@ interface ArrayToTreeOptions {
7
7
  childrenId?: string;
8
8
  customId?: string;
9
9
  parentId?: string;
10
- rootId?: string;
11
10
  allowSelfAsParent?: boolean;
12
11
  }
13
- type NormalizedArrayToTreeOptions = Required<ArrayToTreeOptions>;
12
+ type NormalizedArrayToTreeOptions = Required<ArrayToTreeOptions> & {
13
+ rootId: symbol;
14
+ };
14
15
 
15
16
  declare const arrayToTree: (data: Record<string, any>[], options?: ArrayToTreeOptions) => any[];
16
17
 
package/package.json CHANGED
@@ -9,17 +9,17 @@
9
9
  },
10
10
  "description": "A TypeScript utility to convert a flat array into a hierarchical tree via parent-child relationships.",
11
11
  "devDependencies": {
12
- "@biomejs/biome": "2.2.5",
12
+ "@biomejs/biome": "2.3.14",
13
13
  "@jest/globals": "^30.2.0",
14
14
  "@rollup/plugin-terser": "^0.4.4",
15
- "@rollup/plugin-typescript": "^12.1.4",
16
- "@types/node": "^24.6.2",
15
+ "@rollup/plugin-typescript": "^12.3.0",
16
+ "@types/node": "^25.2.2",
17
17
  "jest": "^30.2.0",
18
- "rimraf": "^6.0.1",
19
- "rollup": "^4.52.4",
20
- "rollup-plugin-dts": "^6.2.3",
21
- "rollup-plugin-node-externals": "^8.1.1",
22
- "ts-jest": "^29.4.4",
18
+ "rimraf": "^6.1.2",
19
+ "rollup": "^4.57.1",
20
+ "rollup-plugin-dts": "^6.3.0",
21
+ "rollup-plugin-node-externals": "^8.1.2",
22
+ "ts-jest": "^29.4.6",
23
23
  "tslib": "^2.8.1",
24
24
  "typescript": "^5.9.3"
25
25
  },
@@ -42,6 +42,8 @@
42
42
  "utility"
43
43
  ],
44
44
  "license": "MIT",
45
+ "main": "./dist/cjs/index.cjs",
46
+ "module": "./dist/esm/index.mjs",
45
47
  "name": "@okutils/array-to-tree",
46
48
  "publishConfig": {
47
49
  "access": "public"
@@ -50,8 +52,6 @@
50
52
  "type": "git",
51
53
  "url": "git+https://github.com/okutils/array-to-tree.git"
52
54
  },
53
- "type": "module",
54
- "version": "0.0.3b",
55
55
  "scripts": {
56
56
  "build": "pnpm clean && rollup -c",
57
57
  "clean": "rimraf dist",
@@ -61,5 +61,8 @@
61
61
  "lint:fix": "biome check --write .",
62
62
  "test": "jest",
63
63
  "type-check": "tsc --noEmit"
64
- }
65
- }
64
+ },
65
+ "type": "module",
66
+ "types": "./dist/types/index.d.ts",
67
+ "version": "0.0.6"
68
+ }