@artus-cli/artus-cli
Advanced tools
Comparing version 0.2.6 to 0.2.7
@@ -32,9 +32,9 @@ import { Context } from '@artus/pipeline'; | ||
set raw(val: string[]); | ||
get commands(): Map<string, import("./parsed_commands").ParsedCommand>; | ||
get rootCommand(): import("./parsed_commands").ParsedCommand; | ||
get commands(): Map<string, import("./parsed_command").ParsedCommand>; | ||
get rootCommand(): import("./parsed_command").ParsedCommand; | ||
get args(): InputArgs; | ||
get fuzzyMatched(): import("./parsed_commands").ParsedCommand; | ||
get matched(): import("./parsed_commands").ParsedCommand | undefined; | ||
get fuzzyMatched(): import("./parsed_command").ParsedCommand; | ||
get matched(): import("./parsed_command").ParsedCommand | undefined; | ||
get error(): import("..").ArtusCliError | undefined; | ||
private parse; | ||
} |
/// <reference types="yargs-parser" /> | ||
import { Middlewares } from '@artus/pipeline'; | ||
import { CommandConfig, OptionConfig, MiddlewareConfig } from '../types'; | ||
import { ParsedCommandStruct, Positional } from './parser'; | ||
import { Command } from './command'; | ||
import { ArtusCliError } from '../errors'; | ||
import { ParsedCommand } from './parsed_command'; | ||
import { ParsedCommandTree } from './parsed_command_tree'; | ||
export interface MatchResult { | ||
@@ -25,66 +24,2 @@ /** | ||
} | ||
export interface ParsedCommandOption { | ||
location?: string; | ||
commandConfig: CommandConfig; | ||
parsedCommandInfo: ParsedCommandStruct; | ||
optionConfig?: { | ||
flagOptions: OptionConfig; | ||
argumentOptions: OptionConfig; | ||
}; | ||
} | ||
/** Wrapper of command */ | ||
export declare class ParsedCommand implements ParsedCommandStruct { | ||
clz: typeof Command; | ||
/** cmds.join(' ') */ | ||
uid: string; | ||
/** the last element of cmds, 'bin dev' is 'dev', 'bin module test [baseDir]' is 'test' */ | ||
cmd: string; | ||
/** convert command to array, like [ 'bin', 'dev' ] */ | ||
cmds: string[]; | ||
/** user defined in options but remove bin name */ | ||
command: string; | ||
alias: string[]; | ||
enable: boolean; | ||
demanded: Positional[]; | ||
optional: Positional[]; | ||
description: string; | ||
examples: string[]; | ||
globalOptions?: OptionConfig; | ||
flagOptions: OptionConfig; | ||
argumentOptions: OptionConfig; | ||
/** Command class location */ | ||
location?: string; | ||
/** child commands */ | ||
childs: ParsedCommand[]; | ||
/** parent command */ | ||
parent: ParsedCommand | null; | ||
/** inherit command */ | ||
inherit: ParsedCommand | null; | ||
commandConfig: CommandConfig; | ||
commandMiddlewares: Middlewares; | ||
executionMiddlewares: Middlewares; | ||
constructor(clz: typeof Command, option: ParsedCommandOption); | ||
get options(): OptionConfig; | ||
get isRoot(): boolean; | ||
get isRunable(): boolean; | ||
get depth(): number; | ||
addMiddlewares(type: 'command' | 'execution', config: MiddlewareConfig): void; | ||
updateGlobalOptions(opt: OptionConfig): void; | ||
} | ||
/** Parsed Command Tree */ | ||
export declare class ParsedCommandTree { | ||
private binName; | ||
private commandList; | ||
/** root of command tree */ | ||
root: ParsedCommand; | ||
/** command list, the key is command string used to match argv */ | ||
commands: Map<string, ParsedCommand>; | ||
/** cache the instance of parsedCommand */ | ||
parsedCommandMap: Map<typeof Command, ParsedCommand>; | ||
constructor(binName: string, commandList: (typeof Command)[]); | ||
/** convert Command class to ParsedCommand instance */ | ||
private initParsedCommand; | ||
private build; | ||
get(clz: typeof Command): ParsedCommand | undefined; | ||
} | ||
export declare class ParsedCommands { | ||
@@ -91,0 +26,0 @@ private readonly container; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ParsedCommands = exports.ParsedCommandTree = exports.ParsedCommand = void 0; | ||
exports.ParsedCommands = void 0; | ||
const tslib_1 = require("tslib"); | ||
const node_util_1 = require("node:util"); | ||
const node_console_1 = require("node:console"); | ||
const lodash_1 = require("lodash"); | ||
const core_1 = require("@artus/core"); | ||
const parser_1 = require("./parser"); | ||
const command_1 = require("./command"); | ||
const constant_1 = require("../constant"); | ||
const bin_info_1 = require("./bin_info"); | ||
const utils_1 = require("../utils"); | ||
const errors_1 = require("../errors"); | ||
const OPTION_SYMBOL = Symbol('ParsedCommand#Option'); | ||
const parsed_command_tree_1 = require("./parsed_command_tree"); | ||
const TREE_SYMBOL = Symbol('ParsedCommand#Tree'); | ||
const debug = (0, node_util_1.debuglog)('artus-cli#ParsedCommands'); | ||
/** Wrapper of command */ | ||
class ParsedCommand { | ||
constructor(clz, option) { | ||
this.clz = clz; | ||
const { location, commandConfig, parsedCommandInfo, optionConfig } = option; | ||
this.location = location; | ||
// read from parsed_command | ||
this.uid = parsedCommandInfo.uid; | ||
this.command = parsedCommandInfo.command; | ||
this.cmd = parsedCommandInfo.cmd; | ||
this.cmds = parsedCommandInfo.cmds; | ||
this.demanded = parsedCommandInfo.demanded; | ||
this.optional = parsedCommandInfo.optional; | ||
// read from option config | ||
this.flagOptions = (optionConfig === null || optionConfig === void 0 ? void 0 : optionConfig.flagOptions) || {}; | ||
this.argumentOptions = (optionConfig === null || optionConfig === void 0 ? void 0 : optionConfig.argumentOptions) || {}; | ||
this.childs = []; | ||
this.parent = null; | ||
this.inherit = null; | ||
// read from command config | ||
this.commandConfig = commandConfig; | ||
this.description = commandConfig.description || ''; | ||
this.examples = (0, utils_1.formatToArray)(commandConfig.examples); | ||
this.enable = typeof commandConfig.enable === 'boolean' ? commandConfig.enable : true; | ||
this.alias = (0, utils_1.formatToArray)(commandConfig.alias); | ||
// middleware config | ||
this.commandMiddlewares = []; | ||
this.executionMiddlewares = []; | ||
} | ||
get options() { | ||
if (!this[OPTION_SYMBOL]) { | ||
this[OPTION_SYMBOL] = Object.assign(Object.assign({}, this.globalOptions), this.flagOptions); | ||
} | ||
return this[OPTION_SYMBOL]; | ||
} | ||
get isRoot() { | ||
return !this.parent; | ||
} | ||
get isRunable() { | ||
return this.clz !== command_1.EmptyCommand && this.enable; | ||
} | ||
get depth() { | ||
return this.cmds.length; | ||
} | ||
addMiddlewares(type, config) { | ||
const { middleware, mergeType } = config; | ||
const middlewares = type === 'command' ? this.commandMiddlewares : this.executionMiddlewares; | ||
const extraMiddlewares = Array.isArray(middleware) ? middleware : [middleware]; | ||
// mergeType default is after | ||
if (!mergeType || mergeType === 'after') { | ||
middlewares.push(...extraMiddlewares); | ||
} | ||
else { | ||
middlewares.unshift(...extraMiddlewares); | ||
} | ||
} | ||
updateGlobalOptions(opt) { | ||
this.globalOptions = Object.assign(Object.assign({}, this.globalOptions), opt); | ||
this[OPTION_SYMBOL] = null; | ||
} | ||
} | ||
exports.ParsedCommand = ParsedCommand; | ||
/** Parsed Command Tree */ | ||
class ParsedCommandTree { | ||
constructor(binName, commandList) { | ||
this.binName = binName; | ||
this.commandList = commandList; | ||
this.build(); | ||
} | ||
/** convert Command class to ParsedCommand instance */ | ||
initParsedCommand(clz) { | ||
var _a; | ||
const metadata = Reflect.getOwnMetadata(constant_1.MetadataEnum.COMMAND, clz); | ||
if (!metadata) | ||
return null; | ||
const commandMeta = metadata; | ||
const inheritClass = Object.getPrototypeOf(clz); | ||
const inheritCommand = this.initParsedCommand(inheritClass); | ||
let commandConfig = Object.assign({}, commandMeta.config); | ||
// mege command config with inherit command | ||
if (inheritCommand && commandMeta.inheritMetadata !== false) { | ||
const inheritCommandConfig = inheritCommand.commandConfig; | ||
commandConfig = Object.assign({}, { | ||
alias: inheritCommandConfig.alias, | ||
command: inheritCommandConfig.command, | ||
description: inheritCommandConfig.description, | ||
parent: inheritCommandConfig.parent, | ||
}, commandConfig); | ||
} | ||
// default command is main command | ||
commandConfig.command = commandConfig.command || '$0'; | ||
// init parent | ||
let command = commandConfig.command; | ||
if (commandConfig.parent) { | ||
const parentParsedCommand = this.initParsedCommand(commandConfig.parent); | ||
(0, node_console_1.assert)(parentParsedCommand, `parent ${(_a = commandConfig.parent) === null || _a === void 0 ? void 0 : _a.name} is not a valid Command`); | ||
command = parentParsedCommand.cmds.concat(command).join(' '); | ||
} | ||
// avoid creating parsedCommand again. | ||
if (this.parsedCommandMap.has(clz)) { | ||
return this.parsedCommandMap.get(clz); | ||
} | ||
// parse command usage | ||
const parsedCommandInfo = (0, parser_1.parseCommand)(command, this.binName); | ||
// split options with argument key and merge option info with inherit command | ||
const optionMeta = Reflect.getOwnMetadata(constant_1.MetadataEnum.OPTION, clz); | ||
const argumentsKey = parsedCommandInfo.demanded.concat(parsedCommandInfo.optional).map(pos => pos.cmd); | ||
let flagOptions = (0, lodash_1.omit)((optionMeta === null || optionMeta === void 0 ? void 0 : optionMeta.config) || {}, argumentsKey); | ||
let argumentOptions = (0, lodash_1.pick)((optionMeta === null || optionMeta === void 0 ? void 0 : optionMeta.config) || {}, argumentsKey); | ||
if (inheritCommand && (optionMeta === null || optionMeta === void 0 ? void 0 : optionMeta.inheritMetadata) !== false) { | ||
flagOptions = Object.assign({}, inheritCommand.flagOptions, flagOptions); | ||
argumentOptions = Object.assign({}, inheritCommand.argumentOptions, argumentOptions); | ||
} | ||
const parsedCommand = new ParsedCommand(clz, { | ||
location: commandMeta.location, | ||
commandConfig, | ||
parsedCommandInfo, | ||
optionConfig: { flagOptions, argumentOptions }, | ||
}); | ||
if (inheritCommand) | ||
parsedCommand.inherit = inheritCommand; | ||
if (this.commands.has(parsedCommandInfo.uid)) { | ||
const existsParsedCommand = this.commands.get(parsedCommandInfo.uid); | ||
// override only allow in class inheritance or options.override=true | ||
const err = errors_1.errors.command_is_conflict(existsParsedCommand.command, existsParsedCommand.clz.name, existsParsedCommand.location, parsedCommand.clz.name, parsedCommand.location); | ||
if (!commandMeta.overrideCommand && !(0, utils_1.isInheritFrom)(parsedCommand.clz, existsParsedCommand.clz)) { | ||
throw err; | ||
} | ||
debug(err.message); | ||
} | ||
// handle middlewares | ||
// Default orders: | ||
// | ||
// In class inheritance: | ||
// command1 <-extend- command2 | ||
// trigger --> middleware1 --> middleware2 --> middleware3 --> run | ||
// | ||
// ------------ | ||
// | ||
// In run method: | ||
// command2 command1 | ||
// trigger --> middleware2 --> middleware3 --> run --> middleware1 --> super.run | ||
// merge command middlewares with inherit command | ||
const middlewareMeta = Reflect.getOwnMetadata(constant_1.MetadataEnum.MIDDLEWARE, clz); | ||
const commandMiddlewareConfigList = (middlewareMeta === null || middlewareMeta === void 0 ? void 0 : middlewareMeta.configList) || []; | ||
if (inheritCommand && (middlewareMeta === null || middlewareMeta === void 0 ? void 0 : middlewareMeta.inheritMetadata) !== false) { | ||
parsedCommand.addMiddlewares('command', { middleware: inheritCommand.commandMiddlewares }); | ||
} | ||
commandMiddlewareConfigList.forEach(config => parsedCommand.addMiddlewares('command', config)); | ||
// add run middlewares, no need to merge with inherit command | ||
const executionMiddlewareConfig = Reflect.getOwnMetadata(constant_1.MetadataEnum.RUN_MIDDLEWARE, clz); | ||
const executionMiddlewareConfigList = (executionMiddlewareConfig === null || executionMiddlewareConfig === void 0 ? void 0 : executionMiddlewareConfig.configList) || []; | ||
executionMiddlewareConfigList.forEach(config => parsedCommand.addMiddlewares('execution', config)); | ||
// cache the instance | ||
this.commands.set(parsedCommandInfo.uid, parsedCommand); | ||
this.parsedCommandMap.set(clz, parsedCommand); | ||
return parsedCommand; | ||
} | ||
build() { | ||
this.commands = new Map(); | ||
this.parsedCommandMap = new Map(); | ||
const parsedCommands = this.commandList | ||
.map(clz => this.initParsedCommand(clz)) | ||
.filter(c => !!c); | ||
// handle parent and childs | ||
parsedCommands | ||
.sort((a, b) => a.depth - b.depth) | ||
.forEach(parsedCommand => { | ||
let parent; | ||
parsedCommand.cmds.forEach(cmd => { | ||
// fullCmd is the key of this.commands | ||
const fullCmd = parent ? parent.cmds.concat(cmd).join(' ') : cmd; | ||
let cacheParsedCommand = this.commands.get(fullCmd); | ||
if (!cacheParsedCommand) { | ||
// create empty node | ||
debug('Create empty command for \'%s\'', fullCmd); | ||
cacheParsedCommand = new ParsedCommand(command_1.EmptyCommand, { | ||
commandConfig: {}, | ||
parsedCommandInfo: (0, parser_1.parseCommand)(fullCmd, this.binName), | ||
}); | ||
this.commands.set(fullCmd, cacheParsedCommand); | ||
} | ||
if (!parent) { | ||
this.root = parent = cacheParsedCommand; | ||
return; | ||
} | ||
cacheParsedCommand.parent = parent; | ||
parent.childs.push(cacheParsedCommand); | ||
parent = cacheParsedCommand; | ||
}); | ||
}); | ||
} | ||
get(clz) { | ||
return this.parsedCommandMap.get(clz); | ||
} | ||
} | ||
exports.ParsedCommandTree = ParsedCommandTree; | ||
let ParsedCommands = class ParsedCommands { | ||
@@ -220,3 +19,5 @@ // parse command tree lazily | ||
const commandList = this.container.getInjectableByTag(constant_1.MetadataEnum.COMMAND); | ||
this[TREE_SYMBOL] = new ParsedCommandTree(this.binInfo.binName, commandList); | ||
const tree = this.container.get(parsed_command_tree_1.ParsedCommandTree); | ||
tree.build(commandList); | ||
this[TREE_SYMBOL] = tree; | ||
} | ||
@@ -223,0 +24,0 @@ return this[TREE_SYMBOL]; |
@@ -134,6 +134,4 @@ "use strict"; | ||
throw new Error(`No command found in: ${cmd}`); | ||
// first cmd is binName or $0, remove it anyway | ||
if ([binName, '$0'].includes(splitCommand[0])) { | ||
if (splitCommand[0] === binName) | ||
splitCommand.shift(); | ||
} | ||
let command; | ||
@@ -140,0 +138,0 @@ if (!splitCommand[0] || splitCommand[0].match(bregex)) { |
@@ -7,3 +7,3 @@ /** | ||
import { BinInfo } from './bin_info'; | ||
import { ParsedCommand } from './parsed_commands'; | ||
import { ParsedCommand } from './parsed_command'; | ||
type MaybeParsedCommand = (typeof Command) | ParsedCommand; | ||
@@ -10,0 +10,0 @@ export declare class Program { |
@@ -12,2 +12,3 @@ "use strict"; | ||
const parsed_commands_1 = require("./parsed_commands"); | ||
const parsed_command_1 = require("./parsed_command"); | ||
let Program = class Program { | ||
@@ -39,3 +40,3 @@ /** all commands map */ | ||
getParsedCommand(clz) { | ||
return clz instanceof parsed_commands_1.ParsedCommand ? clz : this.parsedCommands.getCommand(clz); | ||
return clz instanceof parsed_command_1.ParsedCommand ? clz : this.parsedCommands.getCommand(clz); | ||
} | ||
@@ -42,0 +43,0 @@ /** add options, works in all command by default */ |
import { Trigger } from '@artus/core'; | ||
import { Output } from '@artus/pipeline'; | ||
import { CommandContext, CommandInput } from './context'; | ||
import { ParsedCommand } from './parsed_commands'; | ||
import { ParsedCommand } from './parsed_command'; | ||
export declare class CommandTrigger extends Trigger { | ||
@@ -6,0 +6,0 @@ start(): Promise<void>; |
@@ -1,2 +0,2 @@ | ||
import { ParsedCommand } from './parsed_commands'; | ||
import { ParsedCommand } from './parsed_command'; | ||
import { Command } from './command'; | ||
@@ -3,0 +3,0 @@ export declare class Utils { |
@@ -7,2 +7,3 @@ "use strict"; | ||
const parsed_commands_1 = require("./parsed_commands"); | ||
const parsed_command_1 = require("./parsed_command"); | ||
const constant_1 = require("../constant"); | ||
@@ -16,3 +17,3 @@ const context_1 = require("./context"); | ||
async forward(clz, args) { | ||
const cmd = clz instanceof parsed_commands_1.ParsedCommand ? clz : this.commands.getCommand(clz); | ||
const cmd = clz instanceof parsed_command_1.ParsedCommand ? clz : this.commands.getCommand(clz); | ||
(0, node_assert_1.default)(cmd, (0, node_util_1.format)('Can not forward to command %s', cmd === null || cmd === void 0 ? void 0 : cmd.clz.name)); | ||
@@ -19,0 +20,0 @@ const instance = this.ctx.container.get(cmd.clz); |
@@ -15,2 +15,4 @@ import 'reflect-metadata'; | ||
export * from './core/parsed_commands'; | ||
export * from './core/parsed_command'; | ||
export * from './core/parsed_command_tree'; | ||
export declare function start(options?: ArtusCliOptions): Promise<ArtusApplication | null>; |
@@ -23,2 +23,4 @@ "use strict"; | ||
tslib_1.__exportStar(require("./core/parsed_commands"), exports); | ||
tslib_1.__exportStar(require("./core/parsed_command"), exports); | ||
tslib_1.__exportStar(require("./core/parsed_command_tree"), exports); | ||
async function start(options = {}) { | ||
@@ -25,0 +27,0 @@ if (process.env.ARTUS_CLI_SCANNING) { |
@@ -11,3 +11,3 @@ import { Command } from './core/command'; | ||
/** command usage examples */ | ||
examples?: string | string[]; | ||
examples?: Array<string | [string] | [string, string]>; | ||
/** command alias */ | ||
@@ -84,1 +84,5 @@ alias?: string | string[]; | ||
} | ||
export interface ExampleItem { | ||
command: string; | ||
description?: string; | ||
} |
@@ -1,2 +0,2 @@ | ||
import { ParsedCommand } from './core/parsed_commands'; | ||
import { ParsedCommand } from './core/parsed_command'; | ||
export declare function isInheritFrom(clz: any, maybeParent: any): boolean; | ||
@@ -17,1 +17,5 @@ export declare function checkCommandCompatible(command: ParsedCommand, compareCommand: ParsedCommand): boolean; | ||
export declare function formatToArray<T>(input?: T | T[]): T[]; | ||
export declare function formatCmd(cmd: string, obj: Record<string, any> & { | ||
$0: string; | ||
}, prefix?: string): string; | ||
export declare function formatDesc(info: string, obj: Record<string, any>): string; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.formatToArray = exports.getCalleeDir = exports.getCalleeFile = exports.getCalleeList = exports.readPkg = exports.convertValue = exports.isNil = exports.checkCommandCompatible = exports.isInheritFrom = void 0; | ||
exports.formatDesc = exports.formatCmd = exports.formatToArray = exports.getCalleeDir = exports.getCalleeFile = exports.getCalleeList = exports.readPkg = exports.convertValue = exports.isNil = exports.checkCommandCompatible = exports.isInheritFrom = void 0; | ||
const tslib_1 = require("tslib"); | ||
@@ -102,1 +102,18 @@ const pkg_up_1 = tslib_1.__importDefault(require("pkg-up")); | ||
exports.formatToArray = formatToArray; | ||
function formatCmd(cmd, obj, prefix) { | ||
cmd = formatDesc(cmd.trim().replace(/^\$0( |$)/, `${obj.$0}$1`), obj); | ||
if (prefix) { | ||
if (cmd.startsWith(obj.$0)) { | ||
return `${prefix} ${cmd.substring(obj.$0.length).trim()}`; | ||
} | ||
else { | ||
return `${prefix} ${cmd}`; | ||
} | ||
} | ||
return cmd || obj.$0; | ||
} | ||
exports.formatCmd = formatCmd; | ||
function formatDesc(info, obj) { | ||
return info.replace(/\{\{\s*(\w+)\s*\}\}/g, (_, key) => obj[key]); | ||
} | ||
exports.formatDesc = formatDesc; |
{ | ||
"name": "@artus-cli/artus-cli", | ||
"version": "0.2.6", | ||
"version": "0.2.7", | ||
"description": "CLI framework with modern features", | ||
@@ -5,0 +5,0 @@ "homepage": "https://github.com/artus-cli/artus-cli", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
79058
41
1850