UNPKG

@decaf-ts/utils

Version:

module management utils for decaf-ts

136 lines 5.24 kB
import { UserInput } from "./../input/input.js"; import { DefaultCommandOptions, DefaultCommandValues } from "./constants.js"; import { getDependencies, getPackageVersion } from "./../utils/fs.js"; import { printBanner } from "./../output/common.js"; import { LoggedClass, LoggedEnvironment, Logging, } from "@decaf-ts/logging"; /** * @class Command * @abstract * @template I - The type of input options for the command. * @template R - The return type of the command execution. * @memberOf module:utils * @description Abstract base class for command implementation. * @summary Provides a structure for creating command-line interface commands with input handling, logging, and execution flow. * * @param {string} name - The name of the command. * @param {CommandOptions<I>} [inputs] - The input options for the command. * @param {string[]} [requirements] - The list of required dependencies for the command. */ export class Command extends LoggedClass { constructor(name, inputs = {}, requirements = []) { super(); this.name = name; this.inputs = inputs; this.requirements = requirements; if (!Command.log) { Object.defineProperty(Command, "log", { writable: false, value: Logging.for(Command.name), }); } this.inputs = Object.assign({}, DefaultCommandOptions, inputs); } /** * @protected * @async * @description Checks if all required dependencies are present. * @summary Retrieves the list of dependencies and compares it against the required dependencies for the command. * @returns {Promise<void>} A promise that resolves when the check is complete. * * @mermaid * sequenceDiagram * participant Command * participant getDependencies * participant Set * Command->>getDependencies: Call * getDependencies-->>Command: Return {prod, dev, peer} * Command->>Set: Create Set from prod, dev, peer * Set-->>Command: Return unique dependencies * Command->>Command: Compare against requirements * alt Missing dependencies * Command->>Command: Add to missing list * end * Note over Command: If missing.length > 0, handle missing dependencies */ async checkRequirements() { const { prod, dev, peer } = await getDependencies(); const missing = []; const fullList = Array.from(new Set([...prod, ...dev, ...peer]).values()).map((d) => d.name); for (const dep of this.requirements) if (!fullList.includes(dep)) missing.push(dep); if (!missing.length) return; } /** * @protected * @description Provides help information for the command. * @summary This method should be overridden in derived classes to provide specific help information. * @param {ParseArgsResult} args - The parsed command-line arguments. * @returns {void} */ // eslint-disable-next-line @typescript-eslint/no-unused-vars help(args) { return this.log.info(`This is help. I'm no use because I should have been overridden.`); } /** * @async * @description Executes the command. * @summary This method handles the overall execution flow of the command, including parsing arguments, * setting up logging, checking for version or help requests, and running the command. * @returns {Promise<R | string | void>} A promise that resolves with the command's result. * * @mermaid * sequenceDiagram * participant Command * participant UserInput * participant Logging * participant getPackageVersion * participant printBanner * Command->>UserInput: parseArgs(inputs) * UserInput-->>Command: Return ParseArgsResult * Command->>Command: Process options * Command->>Logging: setConfig(options) * alt version requested * Command->>getPackageVersion: Call * getPackageVersion-->>Command: Return version * else help requested * Command->>Command: help(args) * else banner requested * Command->>printBanner: Call * end * Command->>Command: run(args) * alt error occurs * Command->>Command: Log error * end * Command-->>Command: Return result */ async execute() { const args = UserInput.parseArgs(this.inputs); const env = LoggedEnvironment.accumulate(DefaultCommandValues).accumulate(args.values); const { version, help, banner } = env; if (version) { return getPackageVersion(); } if (help) { return this.help(args); } if (banner) printBanner(this.log.for(printBanner, { timestamp: false, style: false, context: false, logLevel: false, })); let result; // eslint-disable-next-line no-useless-catch try { result = await this.run(env); } catch (e) { throw e; } return result; } } //# sourceMappingURL=command.js.map