export interface TreeNode { name: string; children: TreeNode[]; } /* * Builds a nested tree like * [ * { * name: 'A', * children: [ * { name: 'AA', children: [] }, * { name: 'AB', children: [] }, * ] * } * ] */ function buildMetricTree(parent: string, depth: number): TreeNode[] { const chars = ['A', 'B', 'C']; const children: TreeNode[] = []; if (depth > 3) { return []; } for (const letter of chars) { const nodeName = `${parent}${letter}`; children.push({ name: nodeName, children: buildMetricTree(nodeName, depth + 1), }); } return children; } function queryTree(children: TreeNode[], query: string[], queryIndex: number): TreeNode[] { if (query[queryIndex] === '*') { return children; } const nodeQuery = query[queryIndex]; let result: TreeNode[] = []; let namesToMatch = [nodeQuery]; // handle glob queries if (nodeQuery.startsWith('{')) { namesToMatch = nodeQuery.replace(/\{|\}/g, '').split(','); } for (const node of children) { for (const nameToMatch of namesToMatch) { if (node.name === nameToMatch) { result = result.concat(queryTree(node.children, query, queryIndex + 1)); } } } return result; } export function queryMetricTree(query: string): TreeNode[] { const children = buildMetricTree('', 0); return queryTree(children, query.split('.'), 0); }