UNPKG

@decaf-ts/fabric-weaver

Version:
111 lines 13.5 kB
import { Command } from "commander"; import { VERSION } from "../../index"; import { Logging } from "@decaf-ts/logging"; import { addFabricToPath } from "../../utils-old/path"; import { EnvVars } from "../constants/env-vars"; import { printBanner, printBorder } from "../../utils-old/banner"; import fs from "fs"; import path from "path"; import { safeParseInt } from "../../utils/parsers"; /** * @class BaseCLI * @description Base class for creating command-line interfaces using Commander * @summary This class provides a foundation for building CLIs in the Fabric Weaver project. * It sets up a Commander program with basic configuration and logging. * * @example * class MyCLI extends BaseCLI { * constructor() { * super("my-cli", "My CLI description"); * this.setupCommands(); * } * * private setupCommands() { * this.program * .command("hello") * .description("Say hello") * .action(() => console.log("Hello, world!")); * } * } * * const cli = new MyCLI(); * cli.run(); */ export class BaseCLI { /** * @constructor * @param {string} name - The name of the CLI program * @param {string} description - A brief description of the CLI program */ constructor(name, description) { this.program = new Command(); this.log = Logging.for(this.constructor.name); this.program .name(name) .description(description) .version(VERSION) .option("-s, --skip-banner", "Suppress the Fabric Weaver banner") .option("-l, --limiter", "Supress the line after the command output") .hook("preAction", (cmd) => { const skipBanner = cmd.opts().skipBanner === true; const skipLimiter = cmd.opts().limiter === true; printBanner(skipBanner); this.log.debug(`Skip banner: ${skipBanner}`); this.log.debug(`Skip Limiter: ${skipLimiter}`); this.log.debug(`Starting ${this.program.name()} v${VERSION}`); addFabricToPath(process.env[EnvVars.FABRIC_BIN_FOLDER]); }) .hook("postAction", (cmd) => { const skipLimiter = cmd.opts().limiter === true; printBorder(skipLimiter); }); this.sleep(); this.copy(); } sleep() { this.program .command("sleep") .option("--time <number>", "sleep time in seconds", safeParseInt) .action(async () => { const time = this.program.opts().time || 120; const ms = time * 1000; await new Promise((resolve) => setTimeout(resolve, ms)); }); } copy() { this.program .command("copy") .description("Copy a file from origin to destination") .requiredOption("--origin <string>", "Origin file path") .requiredOption("--dest <string>", "Destination file path") .action(async (options) => { try { const { origin, dest } = options; // Check if the origin file exists if (!fs.existsSync(origin)) { this.log.error(`Origin file does not exist: ${origin}`); return; } // Ensure the destination directory exists const destDir = path.dirname(dest); if (!fs.existsSync(destDir)) { fs.mkdirSync(destDir, { recursive: true }); } // Copy the file fs.copyFileSync(origin, dest); this.log.info(`File copied successfully from ${origin} to ${dest}`); } catch (error) { this.log.error(`Error copying file: ${error.message}`); } }); } /** * @method run * @description Parses the command-line arguments and executes the appropriate command */ run() { this.program.parse(process.argv); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1jbGkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29yZS9jbGkvYmFzZS1jbGkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNwQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3RDLE9BQU8sRUFBVSxPQUFPLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDdkQsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ2hELE9BQU8sRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDbEUsT0FBTyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQ3BCLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUN4QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFbkQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBdUJHO0FBQ0gsTUFBTSxPQUFnQixPQUFPO0lBSTNCOzs7O09BSUc7SUFDSCxZQUFZLElBQVksRUFBRSxXQUFtQjtRQUMzQyxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksT0FBTyxFQUFFLENBQUM7UUFDN0IsSUFBSSxDQUFDLEdBQUcsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFOUMsSUFBSSxDQUFDLE9BQU87YUFDVCxJQUFJLENBQUMsSUFBSSxDQUFDO2FBQ1YsV0FBVyxDQUFDLFdBQVcsQ0FBQzthQUN4QixPQUFPLENBQUMsT0FBTyxDQUFDO2FBQ2hCLE1BQU0sQ0FBQyxtQkFBbUIsRUFBRSxtQ0FBbUMsQ0FBQzthQUNoRSxNQUFNLENBQUMsZUFBZSxFQUFFLDJDQUEyQyxDQUFDO2FBQ3BFLElBQUks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LElBQUksQ0FBQyxDQUFDO2dCQUU5QixJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxpQ0FBaUMsTUFBTSxPQUFPLElBQUksRUFBRSxDQUFDLENBQUM7WUFDdEUsQ0FBQztZQUFDLE9BQU8sS0FBYyxFQUFFLENBQUM7Z0JBQ3hCLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLHVCQUF3QixLQUFlLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUNwRSxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksR0FBRztRQUNSLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNuQyxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21tYW5kIH0gZnJvbSBcImNvbW1hbmRlclwiO1xuaW1wb3J0IHsgVkVSU0lPTiB9IGZyb20gXCIuLi8uLi9pbmRleFwiO1xuaW1wb3J0IHsgTG9nZ2VyLCBMb2dnaW5nIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5pbXBvcnQgeyBhZGRGYWJyaWNUb1BhdGggfSBmcm9tIFwiLi4vLi4vdXRpbHMtb2xkL3BhdGhcIjtcbmltcG9ydCB7IEVudlZhcnMgfSBmcm9tIFwiLi4vY29uc3RhbnRzL2Vudi12YXJzXCI7XG5pbXBvcnQgeyBwcmludEJhbm5lciwgcHJpbnRCb3JkZXIgfSBmcm9tIFwiLi4vLi4vdXRpbHMtb2xkL2Jhbm5lclwiO1xuaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IHNhZmVQYXJzZUludCB9IGZyb20gXCIuLi8uLi91dGlscy9wYXJzZXJzXCI7XG5cbi8qKlxuICogQGNsYXNzIEJhc2VDTElcbiAqIEBkZXNjcmlwdGlvbiBCYXNlIGNsYXNzIGZvciBjcmVhdGluZyBjb21tYW5kLWxpbmUgaW50ZXJmYWNlcyB1c2luZyBDb21tYW5kZXJcbiAqIEBzdW1tYXJ5IFRoaXMgY2xhc3MgcHJvdmlkZXMgYSBmb3VuZGF0aW9uIGZvciBidWlsZGluZyBDTElzIGluIHRoZSBGYWJyaWMgV2VhdmVyIHByb2plY3QuXG4gKiBJdCBzZXRzIHVwIGEgQ29tbWFuZGVyIHByb2dyYW0gd2l0aCBiYXNpYyBjb25maWd1cmF0aW9uIGFuZCBsb2dnaW5nLlxuICpcbiAqIEBleGFtcGxlXG4gKiBjbGFzcyBNeUNMSSBleHRlbmRzIEJhc2VDTEkge1xuICogICBjb25zdHJ1Y3RvcigpIHtcbiAqICAgICBzdXBlcihcIm15LWNsaVwiLCBcIk15IENMSSBkZXNjcmlwdGlvblwiKTtcbiAqICAgICB0aGlzLnNldHVwQ29tbWFuZHMoKTtcbiAqICAgfVxuICpcbiAqICAgcHJpdmF0ZSBzZXR1cENvbW1hbmRzKCkge1xuICogICAgIHRoaXMucHJvZ3JhbVxuICogICAgICAgLmNvbW1hbmQoXCJoZWxsb1wiKVxuICogICAgICAgLmRlc2NyaXB0aW9uKFwiU2F5IGhlbGxvXCIpXG4gKiAgICAgICAuYWN0aW9uKCgpID0+IGNvbnNvbGUubG9nKFwiSGVsbG8sIHdvcmxkIVwiKSk7XG4gKiAgIH1cbiAqIH1cbiAqXG4gKiBjb25zdCBjbGkgPSBuZXcgTXlDTEkoKTtcbiAqIGNsaS5ydW4oKTtcbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VDTEkge1xuICBwcm90ZWN0ZWQgcHJvZ3JhbTogQ29tbWFuZDtcbiAgcHJvdGVjdGVkIGxvZzogTG9nZ2VyO1xuXG4gIC8qKlxuICAgKiBAY29uc3RydWN0b3JcbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgQ0xJIHByb2dyYW1cbiAgICogQHBhcmFtIHtzdHJpbmd9IGRlc2NyaXB0aW9uIC0gQSBicmllZiBkZXNjcmlwdGlvbiBvZiB0aGUgQ0xJIHByb2dyYW1cbiAgICovXG4gIGNvbnN0cnVjdG9yKG5hbWU6IHN0cmluZywgZGVzY3JpcHRpb246IHN0cmluZykge1xuICAgIHRoaXMucHJvZ3JhbSA9IG5ldyBDb21tYW5kKCk7XG4gICAgdGhpcy5sb2cgPSBMb2dnaW5nLmZvcih0aGlzLmNvbnN0cnVjdG9yLm5hbWUpO1xuXG4gICAgdGhpcy5wcm9ncmFtXG4gICAgICAubmFtZShuYW1lKVxuICAgICAgLmRlc2NyaXB0aW9uKGRlc2NyaXB0aW9uKVxuICAgICAgLnZlcnNpb24oVkVSU0lPTilcbiAgICAgIC5vcHRpb24oXCItcywgLS1za2lwLWJhbm5lclwiLCBcIlN1cHByZXNzIHRoZSBGYWJyaWMgV2VhdmVyIGJhbm5lclwiKVxuICAgICAgLm9wdGlvbihcIi1sLCAtLWxpbWl0ZXJcIiwgXCJTdXByZXNzIHRoZSBsaW5lIGFmdGVyIHRoZSBjb21tYW5kIG91dHB1dFwiKVxuICAgICAgLmhvb2soXCJwcmVBY3Rpb25cIiwgKGNtZCkgPT4ge1xuICAgICAgICBjb25zdCBza2lwQmFubmVyID0gY21kLm9wdHMoKS5za2lwQmFubmVyID09PSB0cnVlO1xuICAgICAgICBjb25zdCBza2lwTGltaXRlciA9IGNtZC5vcHRzKCkubGltaXRlciA9PT0gdHJ1ZTtcbiAgICAgICAgcHJpbnRCYW5uZXIoc2tpcEJhbm5lcik7XG4gICAgICAgIHRoaXMubG9nLmRlYnVnKGBTa2lwIGJhbm5lcjogJHtza2lwQmFubmVyfWApO1xuICAgICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2tpcCBMaW1pdGVyOiAke3NraXBMaW1pdGVyfWApO1xuICAgICAgICB0aGlzLmxvZy5kZWJ1ZyhgU3RhcnRpbmcgJHt0aGlzLnByb2dyYW0ubmFtZSgpfSB2JHtWRVJTSU9OfWApO1xuICAgICAgICBhZGRGYWJyaWNUb1BhdGgocHJvY2Vzcy5lbnZbRW52VmFycy5GQUJSSUNfQklOX0ZPTERFUl0pO1xuICAgICAgfSlcbiAgICAgIC5ob29rKFwicG9zdEFjdGlvblwiLCAoY21kKSA9PiB7XG4gICAgICAgIGNvbnN0IHNraXBMaW1pdGVyID0gY21kLm9wdHMoKS5saW1pdGVyID09PSB0cnVlO1xuICAgICAgICBwcmludEJvcmRlcihza2lwTGltaXRlcik7XG4gICAgICB9KTtcblxuICAgIHRoaXMuc2xlZXAoKTtcbiAgICB0aGlzLmNvcHkoKTtcbiAgfVxuXG4gIHByaXZhdGUgc2xlZXAoKSB7XG4gICAgdGhpcy5wcm9ncmFtXG4gICAgICAuY29tbWFuZChcInNsZWVwXCIpXG4gICAgICAub3B0aW9uKFwiLS10aW1lIDxudW1iZXI+XCIsIFwic2xlZXAgdGltZSBpbiBzZWNvbmRzXCIsIHNhZmVQYXJzZUludClcbiAgICAgIC5hY3Rpb24oYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCB0aW1lID0gdGhpcy5wcm9ncmFtLm9wdHMoKS50aW1lIHx8IDEyMDtcbiAgICAgICAgY29uc3QgbXMgPSB0aW1lICogMTAwMDtcblxuICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCBtcykpO1xuICAgICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGNvcHkoKSB7XG4gICAgdGhpcy5wcm9ncmFtXG4gICAgICAuY29tbWFuZChcImNvcHlcIilcbiAgICAgIC5kZXNjcmlwdGlvbihcIkNvcHkgYSBmaWxlIGZyb20gb3JpZ2luIHRvIGRlc3RpbmF0aW9uXCIpXG4gICAgICAucmVxdWlyZWRPcHRpb24oXCItLW9yaWdpbiA8c3RyaW5nPlwiLCBcIk9yaWdpbiBmaWxlIHBhdGhcIilcbiAgICAgIC5yZXF1aXJlZE9wdGlvbihcIi0tZGVzdCA8c3RyaW5nPlwiLCBcIkRlc3RpbmF0aW9uIGZpbGUgcGF0aFwiKVxuICAgICAgLmFjdGlvbihhc3luYyAob3B0aW9ucykgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHsgb3JpZ2luLCBkZXN0IH0gPSBvcHRpb25zO1xuXG4gICAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIG9yaWdpbiBmaWxlIGV4aXN0c1xuICAgICAgICAgIGlmICghZnMuZXhpc3RzU3luYyhvcmlnaW4pKSB7XG4gICAgICAgICAgICB0aGlzLmxvZy5lcnJvcihgT3JpZ2luIGZpbGUgZG9lcyBub3QgZXhpc3Q6ICR7b3JpZ2lufWApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIEVuc3VyZSB0aGUgZGVzdGluYXRpb24gZGlyZWN0b3J5IGV4aXN0c1xuICAgICAgICAgIGNvbnN0IGRlc3REaXIgPSBwYXRoLmRpcm5hbWUoZGVzdCk7XG4gICAgICAgICAgaWYgKCFmcy5leGlzdHNTeW5jKGRlc3REaXIpKSB7XG4gICAgICAgICAgICBmcy5ta2RpclN5bmMoZGVzdERpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gQ29weSB0aGUgZmlsZVxuICAgICAgICAgIGZzLmNvcHlGaWxlU3luYyhvcmlnaW4sIGRlc3QpO1xuXG4gICAgICAgICAgdGhpcy5sb2cuaW5mbyhgRmlsZSBjb3BpZWQgc3VjY2Vzc2Z1bGx5IGZyb20gJHtvcmlnaW59IHRvICR7ZGVzdH1gKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgICAgICB0aGlzLmxvZy5lcnJvcihgRXJyb3IgY29weWluZyBmaWxlOiAkeyhlcnJvciBhcyBFcnJvcikubWVzc2FnZX1gKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBydW5cbiAgICogQGRlc2NyaXB0aW9uIFBhcnNlcyB0aGUgY29tbWFuZC1saW5lIGFyZ3VtZW50cyBhbmQgZXhlY3V0ZXMgdGhlIGFwcHJvcHJpYXRlIGNvbW1hbmRcbiAgICovXG4gIHB1YmxpYyBydW4oKTogdm9pZCB7XG4gICAgdGhpcy5wcm9ncmFtLnBhcnNlKHByb2Nlc3MuYXJndik7XG4gIH1cbn1cbiJdfQ==