@backstage/cli
Version:
CLI for developing Backstage plugins and apps
130 lines (126 loc) • 4.74 kB
JavaScript
;
var InternalCliModule = require('../cli-internal/src/InternalCliModule.cjs.js');
var InternalCommandNode = require('../cli-internal/src/InternalCommandNode.cjs.js');
require('node:fs');
require('node:os');
require('node:path');
require('../cli-internal/src/knownPluginPackages.cjs.js');
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, module) {
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) => InternalCommandNode.OpaqueCommandTreeNode.isType(n) && InternalCommandNode.OpaqueCommandTreeNode.toInternal(n).name === name || InternalCommandNode.OpaqueCommandLeafNode.isType(n) && InternalCommandNode.OpaqueCommandLeafNode.toInternal(n).name === name
);
if (!next) {
next = InternalCommandNode.OpaqueCommandTreeNode.createInstance("v1", {
name,
children: []
});
current.push(next);
} else if (InternalCommandNode.OpaqueCommandLeafNode.isType(next)) {
throw new Error(
formatConflictError(
path,
module,
InternalCommandNode.OpaqueCommandLeafNode.toInternal(next).module
)
);
}
current = InternalCommandNode.OpaqueCommandTreeNode.toInternal(next).children;
}
const lastName = path[path.length - 1];
const last = current.find((n) => {
if (InternalCommandNode.OpaqueCommandTreeNode.isType(n)) {
return InternalCommandNode.OpaqueCommandTreeNode.toInternal(n).name === lastName;
}
return InternalCommandNode.OpaqueCommandLeafNode.toInternal(n).name === lastName;
});
if (last && InternalCommandNode.OpaqueCommandLeafNode.isType(last)) {
throw new Error(
formatConflictError(
path,
module,
InternalCommandNode.OpaqueCommandLeafNode.toInternal(last).module
)
);
} else {
current.push(
InternalCommandNode.OpaqueCommandLeafNode.createInstance("v1", {
name: lastName,
command,
module
})
);
}
}
/**
* 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) => {
if (InternalCommandNode.OpaqueCommandTreeNode.isType(n)) {
return InternalCommandNode.OpaqueCommandTreeNode.toInternal(n).name === name;
}
return InternalCommandNode.OpaqueCommandLeafNode.toInternal(n).name === name;
});
if (!next || InternalCommandNode.OpaqueCommandLeafNode.isType(next)) {
return void 0;
}
current = InternalCommandNode.OpaqueCommandTreeNode.toInternal(next).children;
}
const lastName = path[path.length - 1];
const last = current.find((n) => {
if (InternalCommandNode.OpaqueCommandTreeNode.isType(n)) {
return InternalCommandNode.OpaqueCommandTreeNode.toInternal(n).name === lastName;
}
return InternalCommandNode.OpaqueCommandLeafNode.toInternal(n).name === lastName;
});
if (!last || InternalCommandNode.OpaqueCommandTreeNode.isType(last)) {
return void 0;
}
return InternalCommandNode.OpaqueCommandLeafNode.toInternal(last).command;
}
atDepth(depth) {
let current = this.graph;
for (let i = 0; i < depth; i++) {
current = current.flatMap(
(n) => InternalCommandNode.OpaqueCommandTreeNode.isType(n) ? InternalCommandNode.OpaqueCommandTreeNode.toInternal(n).children : []
);
}
return current;
}
}
function getModuleName(module) {
if (module && InternalCliModule.OpaqueCliModule.isType(module)) {
return InternalCliModule.OpaqueCliModule.toInternal(module).packageName;
}
return void 0;
}
function formatConflictError(path, newModule, existingModule) {
const cmd = path.join(" ");
const newPkg = getModuleName(newModule);
const existingPkg = getModuleName(existingModule);
if (newPkg && existingPkg) {
return `Command "${cmd}" from "${newPkg}" conflicts with an existing command from "${existingPkg}"`;
}
if (newPkg) {
return `Command "${cmd}" from "${newPkg}" conflicts with an existing command`;
}
if (existingPkg) {
return `Command "${cmd}" conflicts with an existing command from "${existingPkg}"`;
}
return `Command "${cmd}" conflicts with an existing command`;
}
exports.CommandGraph = CommandGraph;
//# sourceMappingURL=CommandGraph.cjs.js.map