UNPKG

@memlab/cli

Version:

command line interface for memlab

152 lines (151 loc) 5.85 kB
"use strict"; /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @format * @oncall memory_lab */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CommandCategory = void 0; var CommandCategory; (function (CommandCategory) { CommandCategory["COMMON"] = "COMMON"; CommandCategory["DEV"] = "DEV"; CommandCategory["MISC"] = "MISC"; })(CommandCategory || (exports.CommandCategory = CommandCategory = {})); class Command { constructor() { // If you are trying to add a new CLI command in MemLab, // DO NOT OVERRIDE any property or method in below in this class. // These methods are intended for internal orchestration // purposes. All commands should extend BaseCommand, // which contains the overridable hooks. this.parentCommand = null; } getCommandName() { const className = this.constructor.name; throw new Error(`${className}.getCommandName is not implemented`); } setParentCommand(parent) { this.parentCommand = parent; } getParentCommand() { return this.parentCommand; } getFullCommand() { const prefix = this.parentCommand ? this.parentCommand.getFullCommand() + ' ' : ''; return prefix + this.getCommandName(); } getFullOptionsFromPrerequisiteChain() { const self = this; const uniqueOptions = new Map(); const visitedCommands = new Set(); const queue = [self]; const excludedOptions = new Set(self.getExcludedOptions().map(option => option.getOptionName())); while (queue.length > 0) { const cur = queue.shift(); const options = cur.getOptions(); for (const option of options) { const optionName = option.getOptionName(); if (excludedOptions.has(optionName)) { continue; } if (!uniqueOptions.has(optionName)) { uniqueOptions.set(optionName, option); } } visitedCommands.add(cur.getCommandName()); for (const prereq of cur.getPrerequisites()) { if (!visitedCommands.has(prereq.getCommandName())) { queue.push(prereq); } } } return [...uniqueOptions.values()]; } } class BaseCommand extends Command { // The following terminal command will initiate with this command // `memlab <command-name>` getCommandName() { const className = this.constructor.name; throw new Error(`${className}.getCommandName is not implemented`); } // get a list of CLI option examples // examples will be displayed in helper text getExamples() { return []; } // get command's category, commands under the same category // are grouped together in helper text getCategory() { return CommandCategory.MISC; } // The description of this analysis will be printed by // `memlab` or `memlab help` getDescription() { const className = this.constructor.name; throw new Error(`${className}.getDescription is not implemented`); } // More detailed description or documentation about this command. // This will be printed as helper text in CLI for a specific command. // Documentation generator will also use the description returned here. getDocumentation() { return ''; } // get a sequence of commands that must be executed before // running this command getPrerequisites() { return []; } // internal command will not be listed in helper isInternalCommand() { return false; } // get options supported by this command getOptions() { return []; } // commands from getPrerequisites may propagate // options that does not make sense for the // current command, this returns the list of // options that should be excluded from helper text getExcludedOptions() { return []; } // get subcommands of this command // for example command 'A' has two sub-commands 'B' and 'C' // CLI supports running in terminal: `memlab A B` or `memlab A C` // The parent command will be executed before its subcommands // // If this callback returns null or undefined, it means // the command will handle the dispatcher won't try to match and process // the subcommands (the command will handle sub-commands by itself). getSubCommands() { return []; } // Callback for `memlab <command-name>` // Do the memory analysis and print results in this callback // eslint-disable-next-line @typescript-eslint/no-unused-vars run(_options) { return __awaiter(this, void 0, void 0, function* () { const className = this.constructor.name; throw new Error(`${className}.run is not implemented`); }); } } exports.default = BaseCommand;