UNPKG

@backstage/cli

Version:

CLI for developing Backstage plugins and apps

168 lines (162 loc) • 6.2 kB
'use strict'; var CommandGraph = require('./CommandGraph.cjs.js'); 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'); var commander = require('commander'); var version = require('./version.cjs.js'); var chalk = require('chalk'); var errors = require('./errors.cjs.js'); var errors$1 = require('@backstage/errors'); var types = require('node:util/types'); function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; } var chalk__default = /*#__PURE__*/_interopDefaultCompat(chalk); class CliInitializer { graph = new CommandGraph.CommandGraph(); #uninitiazedFeatures = []; add(feature) { if (types.isPromise(feature)) { this.#uninitiazedFeatures.push( feature.then((f) => { const unwrapped = unwrapFeature(f.default); if (Array.isArray(unwrapped)) { return unwrapped.map((m) => ({ feature: m, fromArray: true })); } return [{ feature: unwrapped, fromArray: false }]; }) ); } else if (Array.isArray(feature)) { this.#uninitiazedFeatures.push( Promise.resolve(feature.map((m) => ({ feature: m, fromArray: true }))) ); } else { this.#uninitiazedFeatures.push( Promise.resolve([{ feature, fromArray: false }]) ); } } async #register(feature) { if (InternalCliModule.OpaqueCliModule.isType(feature)) { for (const command of await InternalCliModule.OpaqueCliModule.toInternal(feature).commands) { this.graph.add(command, feature); } } else { throw new Error(`Unsupported feature type: ${feature.$$type}`); } } async #doInit() { const resolvedGroups = await Promise.all(this.#uninitiazedFeatures); const allFeatures = resolvedGroups.flat(); const individualPaths = /* @__PURE__ */ new Set(); for (const { feature, fromArray } of allFeatures) { if (!fromArray && InternalCliModule.OpaqueCliModule.isType(feature)) { const cmds = await InternalCliModule.OpaqueCliModule.toInternal(feature).commands; for (const cmd of cmds) { individualPaths.add(cmd.path.join(" ")); } } } for (const { feature, fromArray } of allFeatures) { if (fromArray && InternalCliModule.OpaqueCliModule.isType(feature)) { const cmds = await InternalCliModule.OpaqueCliModule.toInternal(feature).commands; if (cmds.some((cmd) => individualPaths.has(cmd.path.join(" ")))) { continue; } } await this.#register(feature); } } /** * Actually parse argv and pass it to the command. */ async run() { await this.#doInit(); const programName = "backstage-cli"; const program = new commander.Command(); program.name(programName).version(version.version).allowUnknownOption(true).allowExcessArguments(true); const queue = this.graph.atDepth(0).map((node) => ({ node, argParser: program })); while (queue.length) { const { node, argParser } = queue.shift(); if (InternalCommandNode.OpaqueCommandTreeNode.isType(node)) { const internal = InternalCommandNode.OpaqueCommandTreeNode.toInternal(node); const treeParser = argParser.command(`${internal.name} [command]`, { hidden: InternalCommandNode.isCommandNodeHidden(node) }).description(internal.name); queue.push( ...internal.children.map((child) => ({ node: child, argParser: treeParser })) ); } else { const internal = InternalCommandNode.OpaqueCommandLeafNode.toInternal(node); argParser.command(internal.name, { hidden: !!internal.command.deprecated || !!internal.command.experimental }).description(internal.command.description).helpOption(false).allowUnknownOption(true).allowExcessArguments(true).action(async () => { try { const args = program.parseOptions(process.argv); const nonProcessArgs = args.operands.slice(2); const positionalArgs = []; let index = 0; for (let argIndex = 0; argIndex < nonProcessArgs.length; argIndex++) { if (argIndex === index && internal.command.path[argIndex] === nonProcessArgs[argIndex]) { index += 1; continue; } positionalArgs.push(nonProcessArgs[argIndex]); } const context = { args: [...positionalArgs, ...args.unknown], info: { usage: [programName, ...internal.command.path].join(" "), name: internal.command.path.join(" ") } }; if (typeof internal.command.execute === "function") { await internal.command.execute(context); } else { const mod = await internal.command.execute.loader(); const fn = typeof mod.default === "function" ? mod.default : mod.default.default; await fn(context); } process.exit(0); } catch (error) { errors.exitWithError(error); } }); } } program.on("command:*", () => { console.log(); console.log(chalk__default.default.red(`Invalid command: ${program.args.join(" ")}`)); console.log(); program.outputHelp(); process.exit(1); }); process.on("unhandledRejection", (rejection) => { errors.exitWithError(new errors$1.ForwardedError("Unhandled rejection", rejection)); }); await program.parseAsync(process.argv); } } function unwrapFeature(feature) { if (Array.isArray(feature)) { return feature; } if ("$$type" in feature) { return feature; } if ("default" in feature) { return feature.default; } return feature; } exports.CliInitializer = CliInitializer; exports.unwrapFeature = unwrapFeature; //# sourceMappingURL=CliInitializer.cjs.js.map