@backstage/cli
Version:
CLI for developing Backstage plugins and apps
72 lines (69 loc) • 2 kB
JavaScript
class CommandGraph {
graph = [];
/**
* Adds a command to the graph. The graph is sparse, so we use the path to determine the nodes
* to traverse. Only leaf nodes should have a command/action.
*/
add(command) {
const path = command.path;
let current = this.graph;
for (let i = 0; i < path.length - 1; i++) {
const name = path[i];
let next = current.find((n) => n.name === name);
if (!next) {
next = { $$type: "@tree/root", name, children: [] };
current.push(next);
} else if (next.$$type === "@tree/leaf") {
throw new Error(
`Command already exists at path: "${path.slice(0, i).join(" ")}"`
);
}
current = next.children;
}
const last = current.find((n) => n.name === path[path.length - 1]);
if (last && last.$$type === "@tree/leaf") {
throw new Error(
`Command already exists at path: "${path.slice(0, -1).join(" ")}"`
);
} else {
current.push({
$$type: "@tree/leaf",
name: path[path.length - 1],
command
});
}
}
/**
* Given a path, try to find a command that matches it.
*/
find(path) {
let current = this.graph;
for (let i = 0; i < path.length - 1; i++) {
const name = path[i];
const next = current.find((n) => n.name === name);
if (!next) {
return void 0;
} else if (next.$$type === "@tree/leaf") {
return void 0;
}
current = next.children;
}
const last = current.find((n) => n.name === path[path.length - 1]);
if (!last || last.$$type === "@tree/root") {
return void 0;
}
return last?.command;
}
atDepth(depth) {
let current = this.graph;
for (let i = 0; i < depth; i++) {
current = current.flatMap(
(n) => n.$$type === "@tree/root" ? n.children : []
);
}
return current;
}
}
exports.CommandGraph = CommandGraph;
//# sourceMappingURL=CommandGraph.cjs.js.map
;