()
| 92 | useEffect(() => { |
| 93 | let cancelled = false; |
| 94 | async function init() { |
| 95 | setChildrenMap(new Map()); |
| 96 | try { |
| 97 | const fetchedRoots = await dataProvider.fetchRoots(); |
| 98 | if (cancelled) return; |
| 99 | setRoots(fetchedRoots); |
| 100 | |
| 101 | // Auto-expand N levels (root → children → grandchildren → ...) |
| 102 | const newExpandedIds = new Set<string>(); |
| 103 | const newChildrenMap = new Map<string, TreeNodeData[]>(); |
| 104 | |
| 105 | async function expandLevel( |
| 106 | nodes: TreeNodeData[], |
| 107 | depth: number, |
| 108 | ): Promise<void> { |
| 109 | if (depth >= autoExpandDepth || cancelled) return; |
| 110 | const expandable = nodes.filter((n) => isExpandable(n)); |
| 111 | const childResults = await Promise.all( |
| 112 | expandable.map(async (n) => { |
| 113 | const children = await dataProvider.fetchChildren(n.id, n.type); |
| 114 | return { parentId: n.id, children }; |
| 115 | }), |
| 116 | ); |
| 117 | if (cancelled) return; |
| 118 | for (const { parentId, children } of childResults) { |
| 119 | newChildrenMap.set(parentId, children); |
| 120 | if (children.length > 0) newExpandedIds.add(parentId); |
| 121 | } |
| 122 | const allChildren = childResults.flatMap((r) => r.children); |
| 123 | await expandLevel(allChildren, depth + 1); |
| 124 | } |
| 125 | |
| 126 | await expandLevel(fetchedRoots, 0); |
| 127 | if (!cancelled) { |
| 128 | setChildrenMap((prev) => { |
| 129 | const next = new Map(prev); |
| 130 | for (const [k, v] of newChildrenMap) next.set(k, v); |
| 131 | return next; |
| 132 | }); |
| 133 | setExpanded((prev) => { |
| 134 | const next = new Set(prev); |
| 135 | for (const id of newExpandedIds) next.add(id); |
| 136 | return next; |
| 137 | }); |
| 138 | } |
| 139 | } finally { |
| 140 | if (!cancelled) setLoading(false); |
| 141 | } |
| 142 | } |
| 143 | init().catch((err: unknown) => { |
| 144 | // AbortError fires when clearGraph races with in-flight expansions |
| 145 | // (e.g. project switch). Expected — swallow silently. Preserve |
no test coverage detected