Initial Commit
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Typed subtree builder. Given a root `Group` and a flat list of its
|
||||
* descendants (in arbitrary order), produces a nested `GroupTreeNode`
|
||||
* forest rooted at the supplied group. Replaces the upstream port's
|
||||
* `function buildTree(root: any, descendants: any[]): any`.
|
||||
*/
|
||||
|
||||
import type { Group, GroupTreeNode } from "@suaveplan/contacts";
|
||||
|
||||
/**
|
||||
* Build a typed tree rooted at `root` from a flat `descendants` list.
|
||||
* Children are derived by `parentId === root.id`; the result is
|
||||
* deterministic insofar as the input order is deterministic — the
|
||||
* caller is responsible for sorting descendants if a deterministic
|
||||
* traversal order is required.
|
||||
*/
|
||||
export function buildTree(
|
||||
root: Group,
|
||||
descendants: readonly Group[]
|
||||
): GroupTreeNode {
|
||||
const childrenByParent = new Map<string, Group[]>();
|
||||
for (const d of descendants) {
|
||||
const key =
|
||||
d.parentId !== null && d.parentId !== undefined ? d.parentId : "";
|
||||
const bucket = childrenByParent.get(key);
|
||||
if (bucket === undefined) {
|
||||
childrenByParent.set(key, [d]);
|
||||
} else {
|
||||
bucket.push(d);
|
||||
}
|
||||
}
|
||||
return walk(root, childrenByParent);
|
||||
}
|
||||
|
||||
function walk(node: Group, byParent: Map<string, Group[]>): GroupTreeNode {
|
||||
const children = byParent.get(node.id) ?? [];
|
||||
return {
|
||||
group: node,
|
||||
children: children.map((child) => walk(child, byParent)),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user