mixcli 3.0.10 → 3.2.1

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/cli.ts","../src/command.ts","../src/option.ts","../src/utils.ts","../src/prompt.ts","../src/finder.ts"],"sourcesContent":["export * from \"./cli\"\r\nexport * from \"./utils\"\r\nexport * from \"./command\"\r\nexport * from \"./option\"","#!/usr/bin/env node\nimport \"flex-tools/string\"\nimport { LiteEvent, LiteEventSubscriber } from \"flex-tools/events/liteEvent\"\nimport { Command } from \"commander\"\nimport logsets from \"logsets\"\n\nimport { assignObject } from \"flex-tools/object/assignObject\"\nimport { MixCommand } from \"./command\"\nimport { addBuiltInOptions, fixIndent, isDebug } from './utils';\nimport { findCommands } from \"./finder\"\nimport { asyncSignal } from \"flex-tools/async/asyncSignal\"\n// @ts-ignore\nimport replaceAll from 'string.prototype.replaceall'\nimport { getPackageEntry, getPackageRootPath } from \"flex-tools\"\nimport { getPackageJson } from 'flex-tools/package/getPackageJson';\nreplaceAll.shim() \n\nexport interface MixCliOptions{\n name:string,\n title?:string | (string | boolean | number)[],\n description?:string,\n version?:string\n // 定义显示帮助信息\n logo?:string ,\n // 在根命令执行前执行==commander的preAction\n before?:(thisCommand:Command,actionCommand:Command)=>void,\n // 在根命令执行后执行==commander的postAction\n after?:(thisCommand:Command,actionCommand:Command)=>void, \n // flexcli运行时会在当前工程的package.json的依赖中查找以prefix/开头的包,然后自动加载其cli目录下的命令\n // 例如:prefix=myapp,则会自动加载flex-cli-xxx包中的cli目录下的命令\n // 如prefix=myapp, cliPath=\"cmds\",则会自动加载flex-cli-xxx包中的cmds目录下的命令\n include?:string | RegExp | string[] | RegExp[],\n // 忽略查找正则表达式\n exclude?:string | RegExp | string[] | RegExp[],\n // flexcli会在当前工程的以prefix/开头下查找命令声明\n // / pattern默认值是cli,即会在当前工程的以prefix/开头的包下查找cli目录下的命令\n // 指定cli所在的目录,默认值是cli,要遍历该目录下的所有js文件作为命令导出\n cliDir?:string \n context?:Record<string,any> // 传递给命令的共享上下文,所有命令均可要使用 \n // 默认是否启用交互提示, auto当没有值时,会根据当前是否在终端中运行来决定是否启用交互提示\n // 为false时,禁用所有交互提示,为true时,启用所有交互提示 \n prompt?:'auto' | boolean \n}\n\n \n \n\nexport type MixCliCommand = (cli:MixCli)=>MixCommand | MixCommand[] | void\n\n\nexport type MixCliEvents = \n \"register\" // 当命令注册时触发\n\nexport class MixCli extends LiteEvent<any,MixCliEvents>{\n options:Required<MixCliOptions> \n root!:Command \n private findSignals:any[]=[]\n constructor(options?:MixCliOptions){\n super()\n this.options= assignObject({\n name:\"mixcli\",\n package:null,\n cliDir:\"cli\",\n prompt:'auto'\n },options) \n this.createRootCommand() \n } \n get context(){return this.options.context}\n get name(){return this.options.name}\n /**\n * 是否禁用了所有的交互提示\n */\n get isDisabledPrompts(){\n return(this.root as any).rawArgs.includes(\"--no-prompts\") \n } \n /**\n * 扫描当前工程的依赖,加载匹配include的依赖下的命令\n */\n private async installCommands(){\n const cmders = await findCommands(this)\n for(let cmder of cmders){\n try{\n if(typeof(cmder)===\"function\"){\n let cmds = cmder(this)\n cmds =cmds ? (Array.isArray(cmds) ? cmds : [cmds]) : []\n this.register(()=>cmds) \n }\n }catch(e:any){\n }\n }\n } \n /**\n * 创建根命令\n * \n */\n private createRootCommand(){\n this.root = new MixCommand(this.name);\n this.root \n .helpOption('-h, --help')\n .action(()=>{ \n if(this.options.logo) logsets.log(fixIndent(this.options.logo,2))\n console.log()\n // 显示标题\n let title = this.options.title|| this.options.name\n if(Array.isArray(title)){\n logsets.log(String(title[0]).firstUpper(),[...title.slice(1)])\n }else{\n logsets.log(`${title.firstUpper()} Version: {}`,this.options.version)\n } \n // @ts-ignore\n if(this.options.description) logsets.log(logsets.colors.darkGray(this.options.description)) \n console.log()\n this.root.help() \n }) \n addBuiltInOptions(this.root)\n if(this.options.before) this.root.hook('preAction',this.options.before)\n if(this.options.after) this.root.hook('postAction',this.options.after) \n } \n /**\n * 添加帮助选项\n * \n * @param text 帮助文本\n * @param position 显示位置,可选值:before|after|beforeAll|afterAll\n * @param fixIndent 是否自动修正缩进,如果为true,则会自动修正缩进,当显示多行时文本时,会自动修正缩进\n * \n */\n public addHelp(text:string,{pos='beforeAll',alignIndent=true}:{pos:'before'|'after' | 'beforeAll' | 'afterAll',alignIndent?:boolean | number}){\n if(alignIndent) text = fixIndent(text,alignIndent)\n this.root.addHelpText(pos,text)\n }\n\n /**\n * 注册一个命令\n * @param cmd \n */\n register(cmd:MixCliCommand){\n if(typeof(cmd)==\"function\"){\n let result = cmd(this)\n let cmds = result instanceof Array ? result : (result==undefined ? [] : [result])\n for(let cmd of cmds){\n if(cmd instanceof MixCommand){\n if(this.hasCommand(cmd.name())){\n logsets.error(`Command <${cmd.name()}> has been registered!`)\n }else{\n this.root.addCommand(cmd) ;\n (cmd as any)._cli = this\n this.emit(\"register\",cmd.fullname,true)\n } \n }\n } \n }else{\n logsets.error(\"Invalid command\")\n } \n }\n\n hasCommand(name:string):boolean{\n return this.root.commands.some(c=>c.name()==name)\n }\n\n /**\n * 根据命令名称查找命令\n * \n * @remarks\n * \n * find(\"dev\")\n * find(\"dev.microservice\") 支持多级命令\n * find(\"abc\",DevCommand) 允许指定从DevCommand下开始查找abc命令\n * \n * @param name \n */\n get(name:string):MixCommand | undefined{\n const names=name.split(\".\")\n let curCmd:Command = this.root\n let resultCmd:MixCommand | undefined\n while(names.length>0){\n const topName = names.shift()\n const r = curCmd.commands.find(c=>c.name()==topName) as MixCommand\n if(r && names.length==0){\n resultCmd = r\n }\n curCmd = r\n } \n return resultCmd \n }\n /**\n * 查找一个命令\n * \n * 如果命令不存在,则等待命令注册后再返回\n * \n * 在多包场景下,如果命令在其他包中注册并且该包中的命令还没注册,则会等待命令注册后再返回\n * \n * @param name \n * @returns \n */\n find(name:string):Promise<MixCommand | undefined>{\n const cmd = this.get(name)\n if(cmd){\n return Promise.resolve(cmd) \n }else{\n const signal = asyncSignal()\n this.findSignals.push(signal)\n return new Promise<MixCommand | undefined>((resolve)=>{\n let listener:LiteEventSubscriber\n listener = this.on(\"register\",(fullname:string)=>{\n if(fullname==`${this.name}.${name}`){\n listener.off()\n signal.resolve()\n this.findSignals = this.findSignals.filter(s=>s!=signal)\n resolve(this.get(name))\n }\n },{objectify:true}) as LiteEventSubscriber\n })\n } \n }\n /**\n * 判断命令是否存在\n * \n * @param name \n * @returns \n */\n exists(name:string):boolean{\n if(name in this.root.commands){\n return true\n }else{\n return this.get(name) != undefined\n }\n } \n \n /**\n * 运行命令行程序\n */\n run(){ \n // 为什么有findSignal这玩意,解决什么问题?\n // 当我们要扩展command时,通过get(\"命令名称\")来获取已经注册的命令的方式有个缺陷\n // 就是如果对命令的注册顺序有严格的要求,比如调用get('dev')时要求dev命令必须已经存在\n // 这对动态包的命令注册扩展开发体验不好\n // 所以引入find(\"命令名称\")来获取命令,该方法可以获取到后注册的命令\n // 其副作用是,在run时,可能find还没有运行到,从而导致在帮助信息里面看不到扩展的信息(实际上是已经生效的)\n // 所以我们在find里面注入一个异步信号来解决此问题\n this.installCommands().then(()=>{\n return Promise.all(this.findSignals.map(signal=>signal(10000))).then(()=>{\n this.root.parseAsync(process.argv); \n })\n }) \n }\n /**\n * 创建一个命令\n * \n * \n */\n create(){\n } \n}\n ","import { Command, Option } from \"commander\";\r\nimport prompts, { PromptObject } from \"prompts\";\r\nimport { MixOption, type MixedOptionParams } from \"./option\";\r\nimport { addBuiltInOptions, isEnablePrompts, outputDebug } from \"./utils\";\r\nimport path from \"node:path\";\r\nimport fs from \"node:fs\";\r\nimport type { AsyncFunction } from \"flex-tools\";\r\n\r\nexport type ICommandHookListener = ({\r\n\targs,\r\n\toptions,\r\n\tcommand,\r\n}: {\r\n\targs: any[];\r\n\toptions: Record<string, any>;\r\n\tcommand: MixCommand;\r\n}) => void | Promise<void>;\r\n\r\nexport type BeforeCommandHookListener = ({\r\n\targs,\r\n\toptions,\r\n\tcommand,\r\n}: {\r\n\targs: any[];\r\n\toptions: Record<string, any>;\r\n\tcommand: MixCommand;\r\n}) => void | Promise<void>;\r\nexport type AfterCommandHookListener = ({\r\n\tvalue,\r\n\targs,\r\n\toptions,\r\n\tcommand,\r\n}: {\r\n\tvalue: any;\r\n\targs: any[];\r\n\toptions: Record<string, any>;\r\n\tcommand: MixCommand;\r\n}) => void | Promise<void>;\r\n\r\nexport interface ActionOptions {\r\n\tid: string;\r\n\tat: \"replace\" | \"before\" | \"after\" | \"preappend\" | \"append\" | number;\r\n\t// 函数签名类型,即采用原始的commander的action函数签名,还是mixcli的action函数签名\r\n\tenhance: boolean;\r\n}\r\n\r\nexport interface ActionRegistry extends Omit<ActionOptions, \"at\"> {\r\n\tfn: Function;\r\n}\r\n\r\n// 原始的Action动作函数\r\nexport type OriginalAction = (...args: any[]) => void | Promise<void>;\r\n// 增强的Action函数签名\r\nexport type EnhanceAction = ({\r\n\targs,\r\n\toptions,\r\n\tvalue,\r\n\tcommand,\r\n}: {\r\n\targs: any[];\r\n\toptions: Record<string, any>;\r\n\tvalue: any;\r\n\tcommand: MixCommand;\r\n}) => void | Promise<any>;\r\n\r\n// 执行action的返回结果\r\nexport const BREAK = Symbol(\"BREAK_ACTION\"); // 中止后续的action执行\r\n\r\nexport class MixCommand extends Command {\r\n\tprivate _beforeHooks: [BeforeCommandHookListener, boolean][] = [];\r\n\tprivate _afterHooks: [AfterCommandHookListener, boolean][] = [];\r\n\tprivate _customPrompts: PromptObject[] = [];\r\n\tprivate _optionValues: Record<string, any> = {}; // 命令行输入的选项值\r\n\tprivate _actions: ActionRegistry[] = []; // 允许多个action\r\n\tprivate _enable_prompts: boolean = true; // 是否启用交互提示\r\n\tconstructor(name?: string) {\r\n\t\tsuper(name);\r\n\t\tconst self = this;\r\n\t\tif (!this.isRoot) addBuiltInOptions(this);\r\n\t\tthis.hook(\"preAction\", async function (this: any) {\r\n\t\t\tself._optionValues = self.getOptionValues(this.hookedCommand);\r\n\t\t\ttry {\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tawait self.preActionHook.apply(self, arguments);\r\n\t\t\t} catch {}\r\n\t\t});\r\n\t}\r\n\t/**\r\n\t * 是否是根命令\r\n\t */\r\n\tget isRoot() {\r\n\t\treturn !!!this.parent;\r\n\t}\r\n\tget actions() {\r\n\t\treturn this._actions;\r\n\t}\r\n\tget beforeHooks() {\r\n\t\treturn this._beforeHooks;\r\n\t}\r\n\tget afterHooks() {\r\n\t\treturn this._afterHooks;\r\n\t}\r\n\tget fullname() {\r\n\t\tlet names = [this.name()];\r\n\t\tlet parent = this.parent;\r\n\t\twhile (parent) {\r\n\t\t\tif (parent.name() !== \"root\") {\r\n\t\t\t\tnames.unshift(parent.name());\r\n\t\t\t}\r\n\t\t\tparent = parent.parent;\r\n\t\t}\r\n\t\treturn names.join(\".\");\r\n\t}\r\n\r\n\t/**\r\n\t * 返回根命令\r\n\t */\r\n\troot() {\r\n\t\tlet root: MixCommand | null | undefined = this;\r\n\t\twhile (root && root.parent != null) {\r\n\t\t\troot = root.parent as unknown as MixCommand;\r\n\t\t}\r\n\t\treturn root;\r\n\t}\r\n\taction(fn: EnhanceAction, options: ActionOptions): this;\r\n\taction(fn: OriginalAction): this;\r\n\taction(fn: OriginalAction): this {\r\n\t\tconst actionFunc = arguments[0];\r\n\t\tif (arguments.length == 1 && typeof actionFunc == \"function\") {\r\n\t\t\t// 原始方式\r\n\t\t\tthis._actions.push({\r\n\t\t\t\tid: Math.random().toString(36).substring(2),\r\n\t\t\t\tenhance: false,\r\n\t\t\t\tfn: actionFunc,\r\n\t\t\t});\r\n\t\t} else if (\r\n\t\t\targuments.length == 2 &&\r\n\t\t\ttypeof actionFunc == \"function\" &&\r\n\t\t\ttypeof arguments[1] == \"object\"\r\n\t\t) {\r\n\t\t\t// 增强模式\r\n\t\t\tconst actionFn = arguments[0];\r\n\t\t\tconst actionOpts: ActionOptions = Object.assign({ at: \"append\" }, arguments[1]);\r\n\t\t\tif (actionOpts.at == \"replace\") this._actions = [];\r\n\t\t\tconst actionItem = {\r\n\t\t\t\tid: actionOpts.id || Math.random().toString(36).substring(2),\r\n\t\t\t\tenhance: actionOpts.enhance == undefined ? true : actionOpts.enhance,\r\n\t\t\t\tfn: actionFn,\r\n\t\t\t} as const;\r\n\t\t\tif (typeof actionOpts.at == \"number\") {\r\n\t\t\t\tthis._actions.splice(Number(actionOpts.at), 0, actionItem);\r\n\t\t\t} else if ([\"append\", \"before\"].includes(actionOpts.at)) {\r\n\t\t\t\tthis._actions.push(actionItem);\r\n\t\t\t} else if ([\"preappend\", \"after\"].includes(actionOpts.at)) {\r\n\t\t\t\tthis._actions.splice(0, 0, actionItem);\r\n\t\t\t} else {\r\n\t\t\t\tthis._actions.push(actionItem);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tconsole.log(\"[mixcli] action params error\");\r\n\t\t}\r\n\t\treturn super.action(this.getWrapperedAction());\r\n\t}\r\n\r\n\t/**\r\n\t * 读取命令配置值,包括父命令提供的配置选项\r\n\t * @param command\r\n\t */\r\n\tprivate getOptionValues(command: Command) {\r\n\t\tlet opts = {};\r\n\t\tlet parent: Command | null = command;\r\n\t\twhile (parent) {\r\n\t\t\tObject.assign(opts, (parent as MixCommand)._optionValues);\r\n\t\t\tparent = parent.parent;\r\n\t\t}\r\n\t\treturn opts;\r\n\t}\r\n\t/**\r\n\t * 本函数在运行时子类进行action生成该命令的action\r\n\t */\r\n\tprivate getWrapperedAction() {\r\n\t\treturn this.wrapperWorkDirsAction(this.wrapperChainActions());\r\n\t}\r\n\r\n\t/**\r\n\t * 向上查找所有祖先命令\r\n\t */\r\n\tprivate getAncestorCommands(): MixCommand[] {\r\n\t\tlet cmds: MixCommand[] = [];\r\n\t\tlet cmd: MixCommand | null = this;\r\n\t\twhile (cmd) {\r\n\t\t\tcmd = cmd.parent as MixCommand;\r\n\t\t\tif (cmd) {\r\n\t\t\t\tcmds.push(cmd);\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn cmds;\r\n\t}\r\n\t/***\r\n\t * 将所有actions包装成一个链式调用的函数\r\n\t */\r\n\tprivate wrapperChainActions() {\r\n\t\tconst self = this;\r\n\t\treturn async function (this: any) {\r\n\t\t\tconst args = Array.from(arguments); // 原始输入的参数\r\n\t\t\tlet preValue: any; // 保存上一个action的返回值\r\n\t\t\t//解析参数, 0-1个参数为options,最后一个参数为command\r\n\t\t\tlet actionOpts: Record<string, any> = {},\r\n\t\t\t\tactionArgs: any[] = [],\r\n\t\t\t\tcmd: any;\r\n\t\t\tif (args.length >= 2) {\r\n\t\t\t\tcmd = args[args.length - 1]; // 最后一个command\r\n\t\t\t\tactionOpts = args[args.length - 2];\r\n\t\t\t\tactionArgs = args.slice(0, args.length - 2);\r\n\t\t\t}\r\n\t\t\tawait self.executeBeforeHooks({ args: actionArgs, options: actionOpts, command: cmd });\r\n\t\t\ttry {\r\n\t\t\t\tfor (let action of self._actions) {\r\n\t\t\t\t\ttry {\r\n\t\t\t\t\t\tif (action.enhance) {\r\n\t\t\t\t\t\t\t// 增强模式\r\n\t\t\t\t\t\t\toutputDebug(\"执行<{}>: args={}, options={}\", () => [\r\n\t\t\t\t\t\t\t\tself.name(),\r\n\t\t\t\t\t\t\t\tactionArgs,\r\n\t\t\t\t\t\t\t\tactionOpts,\r\n\t\t\t\t\t\t\t]);\r\n\t\t\t\t\t\t\tpreValue = await action.fn.call(this, {\r\n\t\t\t\t\t\t\t\tcommand: cmd,\r\n\t\t\t\t\t\t\t\tvalue: preValue,\r\n\t\t\t\t\t\t\t\targs: actionArgs,\r\n\t\t\t\t\t\t\t\toptions: actionOpts,\r\n\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t// 原始模式\r\n\t\t\t\t\t\t\tpreValue = await action.fn.apply(this, args);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (preValue === BREAK) break;\r\n\t\t\t\t\t} catch (e) {\r\n\t\t\t\t\t\toutputDebug(\"命令{}的Action({})执行出错:{}\", [self.name, action.id, e]);\r\n\t\t\t\t\t\tthrow e;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t} finally {\r\n\t\t\t\tawait self.executeAfterHooks({\r\n\t\t\t\t\tvalue: preValue,\r\n\t\t\t\t\targs: actionArgs,\r\n\t\t\t\t\toptions: actionOpts,\r\n\t\t\t\t\tcommand: cmd,\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t};\r\n\t}\r\n\t/**\r\n\t * 当传入--work-dirs时用来处理工作目录\r\n\t */\r\n\tprivate wrapperWorkDirsAction(fn: AsyncFunction) {\r\n\t\tconst self = this;\r\n\t\treturn async function (this: any) {\r\n\t\t\tlet workDirs = self._optionValues.workDirs;\r\n\t\t\t// 未指定工作目录参数\r\n\t\t\tif (!workDirs) {\r\n\t\t\t\treturn await fn.apply(this, Array.from(arguments));\r\n\t\t\t}\r\n\t\t\tif (!Array.isArray(workDirs)) workDirs = workDirs.split(\",\");\r\n\t\t\tworkDirs = workDirs.reduce((dirs: any[], dir: string) => {\r\n\t\t\t\tif (typeof dir == \"string\") dirs.push(...dir.split(\",\"));\r\n\t\t\t\treturn dirs;\r\n\t\t\t}, []);\r\n\t\t\tfor (let workDir of workDirs) {\r\n\t\t\t\tconst cwd = process.cwd();\r\n\t\t\t\ttry {\r\n\t\t\t\t\tif (!path.isAbsolute(workDir)) workDir = path.join(cwd, workDir);\r\n\t\t\t\t\tif (fs.existsSync(workDir) && fs.statSync(workDir).isDirectory()) {\r\n\t\t\t\t\t\toutputDebug(\"切换到工作目录:{}\", workDir);\r\n\t\t\t\t\t\tprocess.chdir(workDir); // 切换\r\n\t\t\t\t\t\tawait fn.apply(this, Array.from(arguments));\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\toutputDebug(\"无效的工作目录:{}\", workDir);\r\n\t\t\t\t\t}\r\n\t\t\t\t} catch (e) {\r\n\t\t\t\t\tthrow e;\r\n\t\t\t\t} finally {\r\n\t\t\t\t\tprocess.chdir(cwd);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t};\r\n\t}\r\n\tgetOption(name: string): MixOption {\r\n\t\treturn this.options.find((option) => option.name() == name) as unknown as MixOption;\r\n\t}\r\n\t/**\r\n\t * 添加一个Before钩子\r\n\t * @param listener\r\n\t * @param scope =false时代表只在本命令执行,=true时代表在本命令及其子命令执行\r\n\t * @returns\r\n\t */\r\n\tbefore(listener: BeforeCommandHookListener, scope: boolean = true) {\r\n\t\tthis._beforeHooks.push([listener, scope]);\r\n\t\treturn this;\r\n\t}\r\n\tprivate async executeBeforeHooks(args: any) {\r\n\t\tconst hooks: [BeforeCommandHookListener, boolean, MixCommand][] = this.beforeHooks.map(\r\n\t\t\t([hook, scope]) => [hook, scope, this]\r\n\t\t);\r\n\t\tthis.getAncestorCommands().forEach((cmd: MixCommand) => {\r\n\t\t\thooks.unshift(\r\n\t\t\t\t...cmd.beforeHooks.map(([hook, scope]) => {\r\n\t\t\t\t\treturn [hook, scope, cmd] as [BeforeCommandHookListener, boolean, MixCommand];\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t});\r\n\t\tfor (let [hook, scope, cmd] of hooks) {\r\n\t\t\tif (!scope) continue;\r\n\t\t\tawait hook.call(cmd, args);\r\n\t\t}\r\n\t}\r\n\t/**\r\n\t * 添加一个After钩子\r\n\t * @param listener\r\n\t * @param scope =false时代表只在本命令执行,=true时代表在本命令及其子命令执行\r\n\t * @returns\r\n\t */\r\n\tafter(listener: AfterCommandHookListener, scope: boolean = true) {\r\n\t\tthis._afterHooks.push([listener, scope]);\r\n\t\treturn this;\r\n\t}\r\n\tprivate async executeAfterHooks(args: any) {\r\n\t\tconst hooks: [AfterCommandHookListener, boolean, MixCommand][] = this.afterHooks.map(\r\n\t\t\t([hook, scope]) => [hook, scope, this]\r\n\t\t);\r\n\t\tthis.getAncestorCommands().forEach((cmd: MixCommand) => {\r\n\t\t\thooks.push(\r\n\t\t\t\t...cmd.afterHooks.map(([hook, scope]) => {\r\n\t\t\t\t\treturn [hook, scope, cmd] as [BeforeCommandHookListener, boolean, MixCommand];\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t});\r\n\t\tfor (let [hook, scope, cmd] of hooks) {\r\n\t\t\tif (!scope) continue; //=false时不执行\r\n\t\t\tawait hook.call(cmd, args);\r\n\t\t}\r\n\t}\r\n\tprivate async preActionHook(thisCommand: Command, actionCommand: Command) {\r\n\t\tif (this.isEnablePrompts()) {\r\n\t\t\t// 自动生成提示\r\n\t\t\tconst questions: PromptObject[] = [\r\n\t\t\t\t...this.generateAutoPrompts(),\r\n\t\t\t\t...this._customPrompts,\r\n\t\t\t];\r\n\t\t\t// 用户提示\r\n\t\t\tif (questions.length > 0) {\r\n\t\t\t\tconst results = await prompts(questions);\r\n\t\t\t\tObject.entries(results).forEach(([key, value]) => {\r\n\t\t\t\t\tthisCommand.setOptionValue(key, value);\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tprivate isEnablePrompts() {\r\n\t\tif (isEnablePrompts() === false) {\r\n\t\t\t// 命令行参数禁用了提示,优先级最高\r\n\t\t\treturn false;\r\n\t\t} else {\r\n\t\t\treturn this._enable_prompts;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * 生成选项自动提示\r\n\t *\r\n\t * @remarks\r\n\t * FlexCli要求所有未提供默认值的Option自动生成提示\r\n\t *\r\n\t * - 未提供默认值,并且是必选的参数Option\r\n\t * - 指定了choices但未提供有效值的Option\r\n\t *\r\n\t */\r\n\tprivate generateAutoPrompts(): PromptObject[] {\r\n\t\tconst options = this.options as unknown as MixOption[];\r\n\t\tconst optionPromports = options\r\n\t\t\t.filter((option) => !option.hidden && option instanceof MixOption)\r\n\t\t\t.map((option) => option.getPrompt(this._optionValues[option.name()]))\r\n\t\t\t.filter((prompt) => prompt) as PromptObject[];\r\n\t\toutputDebug(\"命令<{}>自动生成{}个选项提示:{}\", [\r\n\t\t\tthis.name(),\r\n\t\t\toptionPromports.length,\r\n\t\t\toptionPromports.map((prompt) => `${prompt.name}(${prompt.type})`).join(\",\"),\r\n\t\t]);\r\n\t\treturn optionPromports;\r\n\t}\r\n\toption(flags: string, description?: string | undefined, defaultValue?: any): this;\r\n\toption(flags: string, description?: string | undefined, options?: MixedOptionParams): this {\r\n\t\t// @ts-ignore\r\n\t\tconst option = new MixOption(...arguments);\r\n\t\tif (option.required && !this.isEnablePrompts()) option.mandatory = true;\r\n\t\treturn this.addOption(option as unknown as Option);\r\n\t}\r\n\r\n\t/**\r\n\t * 添加提示\r\n\t *\r\n\t * @remarks\r\n\t *\r\n\t * 添加一些自定义提示\r\n\t *\r\n\t *\r\n\t * @param questions\r\n\t * @param show 是否显示提示信息,auto表示只有在用户没有提供option的值时才显示提示信息,always表示总是显示提示信息,never表示不显示提示信息\r\n\t * @returns\r\n\t */\r\n\tprompt(questions: PromptObject | PromptObject[]) {\r\n\t\tthis._customPrompts.push(...(Array.isArray(questions) ? questions : [questions]));\r\n\t\treturn this;\r\n\t}\r\n\t/**\r\n\t *\r\n\t * 选择命令并执行\r\n\t *\r\n\t * @remorks\r\n\t *\r\n\t * 当命令具有多个子命令时,并且没有提供默认子命令时,提示用户选择一个子命令\r\n\t *\r\n\t */\r\n\tasync selectCommands() {\r\n\t\tconst choices = this.commands.map((command) => ({\r\n\t\t\ttitle: `${command.description()}(${command.name()})`,\r\n\t\t\tvalue: command.name(),\r\n\t\t}));\r\n\t\tconst result = await prompts({\r\n\t\t\ttype: \"select\",\r\n\t\t\tname: \"command\",\r\n\t\t\tmessage: \"请选择命令:\",\r\n\t\t\tchoices,\r\n\t\t});\r\n\t\t// 重新解析命令行参数标志,\r\n\t\tconst command = this.commands.find((command) => command.name() === result.command);\r\n\t\tawait command?.parseAsync([result.command], { from: \"user\" });\r\n\t}\r\n\t/**\r\n\t * 禁用/启用所有提示\r\n\t */\r\n\tdisablePrompts() {\r\n\t\tthis._enable_prompts = false;\r\n\t\treturn this;\r\n\t}\r\n\tenablePrompts() {\r\n\t\tthis._enable_prompts = true;\r\n\t\treturn this;\r\n\t}\r\n}\r\n","import { Option } from 'commander'\nimport { PromptObject } from 'prompts'\nimport { IPromptable, IPromptableOptions, PromptChoice, PromptManager } from './prompt'\n\n\nexport interface MixedOptionParams extends IPromptableOptions{\n hidden?:boolean\n defaultDescription?:string // 默认值的描述 \n conflicts?:string | string[]\n env?:string\n argParser?:<T>(value: string, previous: T) => T \n hideHelp?:boolean\n mandatory?: boolean \n implies?:{[key:string]:any} \n}\n\n\nexport class MixOption extends Option implements IPromptable{\n // 是否提示用户输入\n prompt?: PromptManager \n promptChoices?:PromptChoice[]\n private _validate?: (value: any) => boolean \n constructor(flags: string, description?: string | undefined,optsOrDefault?:any) {\n super(flags, description)\n let params:MixedOptionParams = {}\n if(arguments.length==3 && typeof arguments[2] == \"object\"){\n params = Object.assign({ },arguments[2]) \n }else if(arguments.length==3){\n params.default = arguments[2]\n }\n if(params.prompt===undefined) params.prompt = 'auto'\n if(params.default) this.default(params.default,params.defaultDescription)\n if(params.choices) this.choices(params.choices)\n if(params.conflicts) this.conflicts(params.conflicts)\n if(params.env) this.env(params.env)\n if(params.argParser) this.argParser(params.argParser)\n if(params.hideHelp) this.hideHelp(params.hideHelp)\n if(params.hidden) this.hidden = params.hidden\n if(params.mandatory) this.makeOptionMandatory(params.mandatory)\n if(params.implies) this.implies(params.implies) \n if(params.optional) this.optional=params.optional\n if(typeof(params.validate)=='function') this._validate = params.validate.bind(this)\n if(params.required) {\n this.required = params.required\n if(!this._validate ) this._validate = (value:any)=>String(value).length>0\n }\n this.prompt = new PromptManager(this as IPromptable,params.prompt)\n } \n validate(value: any): boolean {\n if(typeof(this._validate)=='function'){\n return this._validate(value)\n }else{\n return true\n }\n }\n // @ts-ignore\n choices(values:(PromptChoice | string)[]){\n if(!this.promptChoices){\n this.promptChoices = values.map(choice=>{\n if(typeof(choice)=='object'){\n return choice\n }else{\n return {title:choice,value:choice} \n }\n })\n } \n super.choices(this.promptChoices.map((item:any)=>item.value)) \n } \n\n private resetChoices(){\n super.choices(this.promptChoices!.map((item:any)=>item.value)) \n }\n\n addChoice(value:PromptChoice | string){\n if(!this.promptChoices || !Array.isArray(this.promptChoices)) this.promptChoices = []\n this.promptChoices!.push(typeof(value)=='string' ? {title:value,value} : value)\n this.resetChoices()\n }\n removeChoice(value:any){\n this.promptChoices =this.promptChoices?.filter(choice=>choice.value!==value)\n this.resetChoices()\n }\n clearChoice(){\n this.promptChoices = []\n this.resetChoices()\n }\n\n \n /**\n * 返回选项的提示对象\n * \n * @remarks\n * \n *\n * \n * @param inputValue \n * @returns \n */\n getPrompt(inputValue?:any): PromptObject | undefined {\n return this.prompt?.get(inputValue)\n } \n}","import artTemplate from \"art-template\"\r\nimport fs from \"fs-extra\"\r\nimport path from \"node:path\"\r\nimport { promisify } from \"flex-tools/func/promisify\"\r\nimport logsets from \"logsets\" \r\n/**\r\n * \r\n * 在控制台输出一个字符串\r\n * 本方法会将字符串中的每一行空格去掉\r\n * \r\n * @remarks\r\n * \r\n * outputStr(String.raw`\r\n * a\r\n * b`)\r\n * \r\n * 会输出\r\n * a\r\n * b\r\n *\r\n * 此功能可以用于输出多行字符串时,保持代码的缩进格式,而不会影响输出结果\r\n * \r\n * @param str : 要输出的字符串\r\n * @param vars : 用于替换字符串中的变量\r\n * \r\n */\r\nexport function outputStr(str:string,vars?:Record<string,any> | any[]){ \r\n logsets.log(fixIndent(str),vars)\r\n}\r\n\r\n/**\r\n * 修正多行字符串的缩进\r\n * \r\n * @param text \r\n * @param indent \r\n * @returns \r\n */\r\nexport function fixIndent(text:string,indent?:boolean | number):string{\r\n let indentValue = (indent==undefined || indent===true) ? 0 : (typeof(indent)=='number' ? indent : -1)\r\n if(indentValue==-1) return text // 不修正缩进\r\n let lines:string[] = text.split(\"\\n\")\r\n let minSpaceCount = lines.reduce<number>((minCount,line,index)=>{\r\n if(index==0) return minCount\r\n const spaceCount = line.match(/^\\s*/)?.[0].length || 0\r\n return Math.min(minCount,spaceCount)\r\n },9999)\r\n lines = lines.map(line=>line.substring(minSpaceCount))\r\n return lines.join(\"\\n\")\r\n}\r\n\r\n/**\r\n * 增加内置选项\r\n * @param command \r\n */\r\nexport function addBuiltInOptions(command:any){ \r\n command.option(\"--work-dirs <values...>\",\"指定工作目录\",{hidden:true,optional:true,required:true,prompt:false})\r\n command.option(\"--disable-prompts\",\"禁用所有交互提示\",{hidden:true,prompt:false}) \r\n command.option(\"--debug-cli\",\"显示调试信息\",{hidden:true,prompt:false})\r\n}\r\n\r\n\r\n/**\r\n * 是否命令行中包含了--debug-cli选项\r\n */\r\nexport function isDebug(){\r\n return process.argv.includes(\"--debug-cli\")\r\n}\r\nexport function isEnablePrompts(){ \r\n return !process.argv.includes(\"--disable-prompts\")\r\n}\r\n\r\n/**\r\n * 打印调试信息\r\n * @param message \r\n * @param args \r\n */\r\nexport function outputDebug(message:string,...args:any[]){ \r\n let vars = (args.length == 1 && typeof(args[0])=='function') ? args[0]() : args\r\n if(isDebug()) logsets.log(`[MixCli] ${message}`,...vars)\r\n}\r\n\r\nexport const fileExists = promisify(fs.exists,{\r\n parseCallback:(results)=>{\r\n return results[0]\r\n }\r\n})\r\nexport const readFile = promisify(fs.readFile)\r\nexport const writeFile = promisify(fs.writeFile)\r\nexport const mkdir = promisify(fs.mkdir)\r\n\r\n/**\r\n * 基于artTemplate模板生成文件\r\n * \r\n * @param {*} tmplFile \r\n * @param {*} vars \r\n */\r\nexport async function createFileByTemplate(targetFile:string,tmplFile:string,vars:Record<string,any>={}){\r\n tmplFile=path.isAbsolute(tmplFile)? tmplFile : path.join(process.cwd(),tmplFile)\r\n if(!fs.existsSync(tmplFile)){\r\n throw new Error(\"模板文件不存在:\"+tmplFile)\r\n }\r\n targetFile=path.isAbsolute(targetFile)? targetFile : path.join(process.cwd(),targetFile)\r\n const outPath = path.dirname(targetFile)\r\n if(!await fileExists(outPath)){\r\n await mkdir(outPath,{recursive:true})\r\n } \r\n const template = artTemplate(tmplFile,await readFile(tmplFile,{encoding:\"utf-8\"})); \r\n await writeFile(targetFile,template(vars),{encoding:\"utf-8\"})\r\n return targetFile\r\n}\r\n\r\n/** \r\n * 创建目录 \r\n * \r\n * \r\n * \r\n * @param {String[]} dirs 要创建的目录列表,类型为字符串数组 \r\n * @param callback 创建目录过程中的回调函数,类型为异步函数,接收一个参数 dir,表示当前正在创建的目录 \r\n * @returns 该函数返回一个 Promise 对象,表示创建目录的操作是否完成 \r\n */\r\nexport async function mkDirs(dirs:string[],{callback,base}:{callback?:Function,base?:string}){\r\n if(!Array.isArray(dirs)) throw new Error(\"dirs参数必须为字符串数组\")\r\n for(let dir of dirs){\r\n if(!path.isAbsolute(dir)) dir = path.join(base || process.cwd(),dir)\r\n if(typeof(callback)=='function') callback(dir)\r\n await mkdir(dir,{recursive:true})\r\n }\r\n}\r\n\r\nexport function showError(e:any){\r\n if(isDebug()){\r\n outputDebug(\"导入命令<>出错:{}\",e.stack)\r\n }else{\r\n console.error(e)\r\n } \r\n\r\n}\r\n\r\n\r\nexport function getId(){\r\n return Math.random().toString(36).substr(2)\r\n}\r\n\r\n\r\nexport async function importModule(file:string){\r\n let module \r\n try{\r\n module = require(file)\r\n }catch(e:any){\r\n try{\r\n const cmd = await import(`file://${file}`)\r\n module = cmd.default\r\n }catch(e:any){\r\n throw e\r\n } \r\n }\r\n return module\r\n}\r\n","import { PromptObject } from \"prompts\" \nimport { outputDebug } from \"./utils\"\n \n\nexport type PromptType = \"text\" | \"password\" | \"invisible\" | \"number\"| \"confirm\"| \"list\"| \"toggle\"| \"select\" | \"multiselect\" | \"autocomplete\" | \"date\" | \"autocompleteMultiselect\"\n\nexport type PromptParam = 'auto' | boolean | PromptType | PromptObject\nexport type InputPromptParam = PromptParam | ((value:any)=>PromptParam) | boolean\nexport type PromptParamDefaultValue = string | boolean | string[] \n\nexport const promptTypeMap:Record<string,string> = {\n boolean:\"confirm\",\n string:\"text\",\n number:\"number\", \n array:\"list\", \n} \n\nexport const supportedPromptTypes = [\"text\",\"password\",\"invisible\", \"number\", \"confirm\" , \"list\", \"toggle\" , \"select\" , \"multiselect\" , \"autocomplete\" , \"date\" , \"autocompleteMultiselect\"]\nexport interface PromptChoice {\n title: string;\n value?: any;\n disabled?: boolean | undefined;\n selected?: boolean | undefined;\n description?: string | undefined;\n}\n\n\n\nexport interface IPromptableOptions{\n required?: boolean; // A value must be supplied when the option is specified.\n optional?: boolean; // A value is optional when the option is specified.\n default?:PromptParamDefaultValue\n choices?:(PromptChoice | any)[] // 选项值的可选值\n prompt?:InputPromptParam\n validate?:(value: any) => boolean\n}\n\n\nexport interface IPromptable{\n name():string \n description?:string\n flags:string\n promptChoices?:PromptChoice[]\n argChoices?:string[]\n variadic?:boolean\n defaultValue?:PromptParamDefaultValue\n input?:any \n required?:boolean\n validate?: (value: any) => boolean \n getPrompt(inputValue?:any):PromptObject | undefined \n}\n\n/**\n * 供command.option()使用的参数对象\n */\nexport interface PromptableObject{\n \n\n}\n\n\n/**\n * 负责生成prompt对象\n * \n */\nexport class PromptManager{\n args:InputPromptParam \n private _promptable:IPromptable // 对应的FlexOption或FlexArgument\n constructor(promptable:IPromptable,promptArgs?:InputPromptParam){ \n this._promptable = promptable\n this.args= promptArgs===undefined ? 'auto' : promptArgs\n }\n\n /**\n * 返回输入的是否是有效的prompt类型\n * @param type \n * @returns \n */\n isValid(type:any){\n return supportedPromptTypes.includes(String(type))\n }\n /**\n * 推断是否需要提示\n * \n */\n isNeed(input:any,defaultValue?:any){\n \n const promptArg = this.args\n const inputValue = input || defaultValue\n // 是否有输入值,即在命令行输入了值\n const hasInput = !(inputValue === undefined)\n // 1. 显式指定了_prompt为true,则需要提示,后续进行提示类型的推断,可能不会准确\n if(promptArg===true) return true\n if(promptArg===false) return false \n\n // 2. 提供了一个prompt对象,并且没有在命令行输入值,则需要提示\n if(typeof(promptArg)=='object'){\n return !hasInput\n }\n\n // 3. 指定了内置的prompt类型,如prompt='password',则使用password类型提示输入\n if(typeof(promptArg) == 'string' && supportedPromptTypes.includes(promptArg)){\n return !hasInput\n }\n \n // 4. 判断输入是否有效,则显示提示\n if(this._promptable.argChoices && this._promptable.argChoices.indexOf(inputValue) == -1){\n return true\n } \n return !hasInput\n }\n /**\n * 返回生成prompt对象\n * \n * @param inputValue 从命令行输入的值\n */\n get(inputValue?:any){\n const {description,promptChoices,validate,defaultValue} = this._promptable\n let input = inputValue || defaultValue\n // 判断是否需要输入提示\n if(!this.isNeed(input,defaultValue)) return\n // 推断prompt类型\n let promptType = this.infer(inputValue)\n const prompt = {\n type:promptType, \n name:this._promptable.name(),\n message:description,\n initial: input,\n ...typeof(this.args) == 'object' ? this.args : {}\n } as PromptObject\n // 指定了验证函数,用来验证输入值是否有效\n prompt.validate = validate?.bind(this._promptable)\n if(promptType=='multiselect') prompt.instructions=false\n if(['select','multiselect'].includes(promptType)){\n let index = promptChoices?.findIndex(item=>item.value==input)\n prompt.initial = index==-1 ? undefined : index\n } \n // 选项值的可选值\n if(Array.isArray(promptChoices)) {\n prompt.choices =promptChoices\n }\n return prompt\n }\n /**\n * 推断prompt类型\n * \n * @param inputValue 从命令行输入的值\n */\n infer(inputValue?:any){\n const {argChoices,variadic,defaultValue} = this._promptable\n let input = inputValue || defaultValue\n // 如果选择指定了\"-p [value]或[value...]\",则使用text类型,如果没有要求输入值,则使用confirm类型\n let promptType = /(\\<[\\w\\.]+\\>)|(\\[[\\w\\.]+\\])/.test(this._promptable.flags) ? 'text' : 'confirm'\n let promptArg = this.args\n if(this.isValid(promptArg)){ // 显式指定了prompt类型\n promptType = promptArg as string\n }else{ // 未显式指定prompt类型,需要按一定规则推断类型\n if(typeof(promptArg)=='object'){\n promptType = promptArg.type as string\n }else{\n if(argChoices){ // 提供多个可选值时\n promptType = variadic ? 'multiselect' : 'select'\n }else{\n const datatype:string = Array.isArray(defaultValue) ? 'array' : typeof(defaultValue) \n // 如果输入值班是数组,则使用list类型,允许使用逗号分隔的多个值\n if(Array.isArray(input) || variadic){\n promptType = \"list\"\n }else{\n if(datatype in promptTypeMap){\n promptType = promptTypeMap[datatype]\n }\n }\n }\n }\n }\n outputDebug(\"选项<{}> -> 提示类型<{}>\",[this._promptable.name(),promptType])\n return promptType\n }\n\n}","import { getPackageJson } from \"flex-tools/package/getPackageJson\"\r\nimport { getPackageRootPath } from 'flex-tools/package/getPackageRootPath';\r\nimport type { MixCli } from './cli';\r\nimport { globSync } from 'glob'\r\nimport { MixCliCommand } from './cli';\r\nimport { importModule, isDebug, outputDebug } from './utils';\r\nimport fs from \"node:fs\"\r\nimport path from \"node:path\"\r\n\r\n\r\n/**\r\n * \r\n * 在当前工程中查找符合FlexCli.prefix约定的命令 \r\n * \r\n * - 读取当前包的package.json\r\n * - 找出所有以cli.prefix开头的依赖\r\n * - 加载这些依赖的目录下的匹配cli.pattern的命令\r\n * - 加载加载这样命令\r\n * \r\n */\r\n \r\n\r\nexport function getMatchedDependencies(this:MixCli,entry:string):string[]{\r\n const pacakgeMacher = this.options.include\r\n if(!(pacakgeMacher instanceof RegExp)) return []\r\n \r\n // 找出当前包的所有依赖\r\n const { dependencies={},devDependencies={},peerDependencies={},optionalDependencies={},bundleDependencies={} } = getPackageJson(entry)\r\n const packageNames = [\r\n ...Object.keys(dependencies),\r\n ...Object.keys(devDependencies),\r\n ...Object.keys(peerDependencies),\r\n ...Object.keys(optionalDependencies),\r\n ...Object.keys(bundleDependencies)\r\n ]\r\n return packageNames.filter(name=>name!==\"@voerka/cli\" && pacakgeMacher.test(name))\r\n}\r\n\r\nfunction isMatched(str:string,reg?:string | RegExp | string[] | RegExp[]):boolean{\r\n // let regexps:RegExp[]=[]\r\n const regexps = reg ? (Array.isArray(reg) ? reg : [reg]) : []\r\n return regexps.some(regexp=>{\r\n if(typeof regexp === \"string\"){\r\n return (new RegExp(regexp)).test(str)\r\n }else if(regexp instanceof RegExp){\r\n return regexp.test(str)\r\n }else{\r\n return false\r\n }\r\n })\r\n}\r\n\r\nexport function findCliPaths(this:MixCli,packageName?:string ,entry?:string):string[]{\r\n const includeMacher = this.options.include\r\n const excludeMacher = this.options.exclude\r\n if(!includeMacher) return []\r\n const packageRoot = getPackageRootPath(entry || process.cwd())\r\n const packagePath = packageName ? path.dirname(require.resolve(packageName,{paths:[packageRoot as string]})) : packageRoot\r\n\r\n if(!packagePath) {\r\n outputDebug(\"MixCli只能运行在Nodejs环境\" )\r\n return []\r\n }\r\n\r\n // 找出当前包的所有依赖\r\n const packageNames = getMatchedDependencies.call(this,packagePath)\r\n\r\n const cliDirs:string[]=[]\r\n \r\n if(entry!==undefined) cliDirs.push(path.join(packagePath,this.options.cliDir))\r\n packageNames.filter(name=>{\r\n return isMatched(name,includeMacher) && !isMatched(name,excludeMacher) \r\n })\r\n .forEach(name=>{\r\n outputDebug(\"匹配包:{}\",`${packageName ? name+\" <- \"+packageName : name}`)\r\n try{\r\n const packageEntry = path.dirname(require.resolve(name,{paths:packagePath ? [packagePath] : [process.cwd()]}))\r\n const packageCliDir =path.join(packageEntry,this.options.cliDir!) \r\n // 查找当前包的所属工程的依赖\r\n let dependencies = getMatchedDependencies.call(this,packageEntry)\r\n cliDirs.push(...dependencies.reduce<string[]>((result,dependencie)=>{\r\n outputDebug(\"匹配包:{}\",`${dependencie} <- ${name}`)\r\n result.push(...findCliPaths.call(this,dependencie,packageEntry))\r\n return result\r\n },[])) \r\n if(fs.existsSync(packageCliDir)){\r\n cliDirs.push(packageCliDir)\r\n }\r\n }catch(e:any){\r\n outputDebug(\"解析包<{}>路径出错:{}\",[name,e.stack])\r\n } \r\n })\r\n // 由于一些包可能存在循环依赖,所以需要去重\r\n return [...new Set(cliDirs)]\r\n}\r\n\r\n\r\n/**\r\n * \r\n * 扫描当前工程中所有符合条件的命令\r\n * \r\n * @param cli \r\n * \r\n */\r\nexport async function findCommands(cli:MixCli){ \r\n const cliDirs = findCliPaths.call(cli)\r\n const commands:MixCliCommand[] = []\r\n const files = [] as string[]\r\n cliDirs.forEach(dir=>{\r\n globSync(\"*\",{\r\n cwd:dir,\r\n absolute :true \r\n }).forEach((file:string)=>{ \r\n const baseName = path.basename(file) \r\n if(baseName.startsWith(\"_\")) return\r\n const ext = path.extname(file).toLowerCase()\r\n if([\".js\",\".cjs\",\".mjs\"].includes(ext)){\r\n files.push(file)\r\n }else if(fs.statSync(file).isDirectory()){\r\n files.push(path.join(file,\"index.js\"))\r\n files.push(path.join(file,\"index.cjs\"))\r\n files.push(path.join(file,\"index.mjs\"))\r\n }\r\n })\r\n })\r\n for(let file of files){ \r\n if(!fs.existsSync(file)) continue\r\n try{\r\n outputDebug(\"导入命令:{}\",file)\r\n if(file.endsWith(\".cjs\") || file.endsWith(\".js\")){\r\n commands.push(await importModule(file))\r\n }else if(file.endsWith(\".mjs\")){\r\n const cmd = await import(`file://${file}`)\r\n commands.push(cmd.default)\r\n } \r\n }catch(e:any){\r\n outputDebug(e) \r\n }\r\n }\r\n return commands\r\n}\r\n\r\n"],"mappings":"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","names":["import_logsets","import_commander","logsets","fs","path","artTemplate","module","e","import_node_path","path","fs","prompts","command","import_node_fs","import_node_path","path","fs","replaceAll","logsets","cmd"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/command.ts","../src/option.ts","../src/prompt.ts","../src/utils.ts","../src/finder.ts"],"sourcesContent":["#!/usr/bin/env node\nimport \"flex-tools/string\"\nimport { LiteEvent, LiteEventSubscriber } from \"flex-tools/events/liteEvent\"\nimport { Command } from \"commander\"\nimport logsets from \"logsets\"\n\nimport { assignObject } from \"flex-tools/object/assignObject\"\nimport { MixCommand } from \"./command\"\nimport { addBuiltInOptions, fixIndent, outputDebug } from './utils';\nimport { findCommands } from \"./finder\"\nimport { asyncSignal } from \"flex-tools/async/asyncSignal\"\n// @ts-ignore\nimport replaceAll from 'string.prototype.replaceall' \nreplaceAll.shim() \n\nexport interface MixCliOptions{\n name:string,\n title?:string | (string | boolean | number)[],\n description?:string,\n version?:string\n // 定义显示帮助信息\n logo?:string ,\n // 在根命令执行前执行==commander的preAction\n before?:(thisCommand:Command,actionCommand:Command)=>void,\n // 在根命令执行后执行==commander的postAction\n after?:(thisCommand:Command,actionCommand:Command)=>void, \n // flexcli运行时会在当前工程的package.json的依赖中查找以prefix/开头的包,然后自动加载其cli目录下的命令\n // 例如:prefix=myapp,则会自动加载flex-cli-xxx包中的cli目录下的命令\n // 如prefix=myapp, cliPath=\"cmds\",则会自动加载flex-cli-xxx包中的cmds目录下的命令\n include?:string | RegExp | string[] | RegExp[],\n // 忽略查找正则表达式\n exclude?:string | RegExp | string[] | RegExp[],\n // flexcli会在当前工程的以prefix/开头下查找命令声明\n // / pattern默认值是cli,即会在当前工程的以prefix/开头的包下查找cli目录下的命令\n // 指定cli所在的目录,默认值是cli,要遍历该目录下的所有js文件作为命令导出\n cliDir?:string \n context?:Record<string,any> // 传递给命令的共享上下文,所有命令均可要使用 \n // 默认是否启用交互提示, auto当没有值时,会根据当前是否在终端中运行来决定是否启用交互提示\n // 为false时,禁用所有交互提示,为true时,启用所有交互提示 \n prompt?:'auto' | boolean \n ignoreError?:boolean\n}\n\n \n \n\nexport type MixCliCommand = (cli:MixCli)=>MixCommand | MixCommand[] | void\n\n\nexport type MixCliEvents = \n \"register\" // 当命令注册时触发\n\nexport class MixCli extends LiteEvent<any,MixCliEvents>{\n options:Required<MixCliOptions> \n root!:MixCommand \n private findSignals:any[]=[]\n constructor(options?:MixCliOptions){\n super()\n this.options= assignObject({\n name : \"mixcli\",\n package : null,\n cliDir : \"cli\",\n prompt : 'auto',\n ignoreError: false\n },options) as Required<MixCliOptions> \n this.createRootCommand() \n } \n get context(){return this.options.context}\n get name(){return this.options.name}\n /**\n * 是否禁用了所有的交互提示\n */\n get isDisabledPrompts(){\n return(this.root as any).rawArgs.includes(\"--no-prompts\") \n } \n /**\n * 扫描当前工程的依赖,加载匹配include的依赖下的命令\n */\n private async installCommands(){\n const cmders = await findCommands(this)\n for(let cmder of cmders){\n try{\n if(typeof(cmder)===\"function\"){\n let cmds = cmder(this)\n cmds = cmds ? (Array.isArray(cmds) ? cmds : [cmds]) : []\n this.register(()=>cmds) \n }\n }catch(e:any){\n outputDebug(\"注册命令失败:{}\",e.stack)\n }\n }\n } \n /**\n * 创建根命令\n * \n */\n private createRootCommand(){\n this.root = new MixCommand(this.name);\n this.root \n .helpOption('-h, --help')\n .action(()=>{ \n if(this.options.logo) logsets.log(fixIndent(this.options.logo,2))\n console.log()\n // 显示标题\n let title = this.options.title|| this.options.name\n if(Array.isArray(title)){\n logsets.log(String(title[0]).firstUpper(),[...title.slice(1)])\n }else{\n logsets.log(`${title.firstUpper()} Version: {}`,this.options.version)\n } \n // @ts-ignore\n if(this.options.description) logsets.log(logsets.colors.darkGray(this.options.description)) \n console.log()\n this.root.help() \n }) \n addBuiltInOptions(this.root)\n if(this.options.before) this.root.hook('preAction',this.options.before)\n if(this.options.after) this.root.hook('postAction',this.options.after) \n } \n /**\n * 添加帮助选项\n * \n * @param text 帮助文本\n * @param position 显示位置,可选值:before|after|beforeAll|afterAll\n * @param fixIndent 是否自动修正缩进,如果为true,则会自动修正缩进,当显示多行时文本时,会自动修正缩进\n * \n */\n public addHelp(text:string,{pos='beforeAll',alignIndent=true}:{pos:'before'|'after' | 'beforeAll' | 'afterAll',alignIndent?:boolean | number}){\n if(alignIndent) text = fixIndent(text,alignIndent)\n this.root.addHelpText(pos,text)\n }\n\n /**\n * 注册一个命令\n * @param cmd \n */\n register(cmd:MixCliCommand){\n if(typeof(cmd)==\"function\"){\n let result = cmd(this)\n let cmds = result instanceof Array ? result : (result==undefined ? [] : [result])\n for(let cmd of cmds){\n // 为什么不用cmd instanceof MixCommand来判断是否是一个有效的命令?\n // 因为当不同的包引用了与主包不一样版本的mixcli时,判断会失效,导致不能识别\n // 所以我们通过cmd.__MIX_COMMAND__来判断是否是一个有效的命令\n if(cmd.__MIX_COMMAND__){ \n if(this.hasCommand(cmd.name())){\n logsets.error(`Command <${cmd.name()}> has been registered!`)\n }else{\n outputDebug(\"注册命令:{}\",cmd.fullname)\n this.root.addCommand(cmd as Command) ;\n (cmd as any)._cli = this\n this.emit(\"register\",cmd.fullname,true)\n } \n }else{\n logsets.error(`Command <${cmd.toString()}> is not a valid command!`)\n }\n } \n }else{\n logsets.error(\"Invalid command\")\n } \n }\n\n hasCommand(name:string):boolean{\n return this.root.commands.some(c=>c.name()==name)\n }\n\n /**\n * 根据命令名称查找命令\n * \n * @remarks\n * \n * find(\"dev\")\n * find(\"dev.microservice\") 支持多级命令\n * find(\"abc\",DevCommand) 允许指定从DevCommand下开始查找abc命令\n * \n * @param name \n */\n get(name:string):MixCommand | undefined{\n const names=name.split(\".\")\n let curCmd:MixCommand = this.root\n let resultCmd:MixCommand | undefined\n while(names.length>0){\n const topName = names.shift()\n const r = curCmd.commands.find(c=>c.name()==topName) as MixCommand\n if(r && names.length==0){\n resultCmd = r\n }\n curCmd = r\n } \n return resultCmd \n }\n /**\n * 查找一个命令\n * \n * 如果命令不存在,则等待命令注册后再返回\n * \n * 在多包场景下,如果命令在其他包中注册并且该包中的命令还没注册,则会等待命令注册后再返回\n * \n * @param name \n * @returns \n */\n find(name:string):Promise<MixCommand | undefined>{\n const cmd = this.get(name)\n if(cmd){\n return Promise.resolve(cmd) \n }else{\n const signal = asyncSignal()\n this.findSignals.push(signal)\n return new Promise<MixCommand | undefined>((resolve)=>{\n let listener:LiteEventSubscriber\n listener = this.on(\"register\",(fullname:string)=>{\n if(fullname==`${this.name}.${name}`){\n listener.off()\n signal.resolve()\n this.findSignals = this.findSignals.filter(s=>s!=signal)\n resolve(this.get(name))\n }\n },{objectify:true}) as LiteEventSubscriber\n })\n } \n }\n /**\n * 判断命令是否存在\n * \n * @param name \n * @returns \n */\n exists(name:string):boolean{\n if(name in this.root.commands){\n return true\n }else{\n return this.get(name) != undefined\n }\n } \n \n /**\n * 运行命令行程序\n */\n run(){ \n // 为什么有findSignal这玩意,解决什么问题?\n // 当我们要扩展command时,通过get(\"命令名称\")来获取已经注册的命令的方式有个缺陷\n // 就是如果对命令的注册顺序有严格的要求,比如调用get('dev')时要求dev命令必须已经存在\n // 这对动态包的命令注册扩展开发体验不好\n // 所以引入find(\"命令名称\")来获取命令,该方法可以获取到后注册的命令\n // 其副作用是,在run时,可能find还没有运行到,从而导致在帮助信息里面看不到扩展的信息(实际上是已经生效的)\n // 所以我们在find里面注入一个异步信号来解决此问题\n this.installCommands().then(()=>{\n return Promise.all(this.findSignals.map(signal=>signal(10000))).then(()=>{\n this.root.parseAsync(process.argv); \n })\n }) \n }\n}\n ","import { Command, Option } from \"commander\";\nimport prompts, { PromptObject } from \"prompts\";\nimport { MixOption, type MixedOptionParams } from \"./option\";\nimport { addBuiltInOptions, hyphenToCamelCase, isDisablePrompts, outputDebug } from \"./utils\";\nimport type { AsyncFunction } from \"flex-tools/types\"; \nimport path from \"node:path\";\nimport fs from \"node:fs\";\n\n\n\nexport type IMixCommandHookListener = ({\n\targs,\n\toptions,\n\tcommand,\n}: {\n\targs: any[];\n\toptions: Record<string, any>;\n\tcommand: MixCommand;\n}) => void | Promise<void>;\n\nexport type BeforeMixCommandHookListener = ({\n\targs,\n\toptions,\n\tcommand,\n}: {\n\targs: any[];\n\toptions: Record<string, any>;\n\tcommand: MixCommand;\n}) => void | Promise<void>;\n\nexport type AfterMixCommandHookListener = ({\n\tvalue,\n\targs,\n\toptions,\n\tcommand,\n}: {\n\tvalue: any;\n\targs: any[];\n\toptions: Record<string, any>;\n\tcommand: MixCommand;\n}) => void | Promise<void>;\n\nexport interface MixActionOptions {\n\tid: string;\n\tat: \"replace\" | \"before\" | \"after\" | \"preappend\" | \"append\" | number;\t\n\tenhance: boolean;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 函数签名类型,即采用原始的commander的action函数签名,还是mixcli的action函数签名\n}\n\nexport interface MixActionRegistry extends Omit<MixActionOptions, \"at\"> {\n\tfn: Function;\n}\n\n// 原始的Action动作函数\nexport type MixOriginalAction = (...args: any[]) => any | Promise<void>;\n\n// 增强的Action函数签名\nexport type MixEnhanceAction = ({\n\targs,\n\toptions,\n\tvalue,\n\tcommand,\n}: {\n\targs: any[];\n\toptions: Record<string, any>;\n\tvalue: any;\n\tcommand: MixCommand;\n}) => any | Promise<any>;\n\n// 执行action的返回结果\nexport const BREAK = Symbol(\"BREAK_ACTION\"); // 中止后续的action执行\n\nexport class MixCommand extends Command {\n\t__MIX_COMMAND__ = true;\n\tprivate _beforeHooks : [ BeforeMixCommandHookListener, boolean ][] = [];\n\tprivate _afterHooks : [ AfterMixCommandHookListener, boolean ][] = [];\n\tprivate _customPrompts : PromptObject[] = [];\n\tprivate _optionValues : Record<string, any> = {}; \t\t\t\t\t\t\t// 命令行输入的选项值\n\tprivate _actions : MixActionRegistry[] = []; \t\t\t\t\t\t\t// 允许多个action\n\tprivate _enable_prompts: boolean = true; \t\t\t\t\t\t\t\t\t// 是否启用交互提示\n\tconstructor(name?: string) {\n\t\tsuper(name);\t\t\n\t\t// eslint-disable-next-line no-this-alias\n\t\tconst self = this\n\t\tif (!this.isRoot) addBuiltInOptions(this); \n\t\tthis.hook(\"preAction\", async function (this: any) {\n\t\t\tself._optionValues = self.getOptionValues(this.hookedCommand);\t\t\t\n\t\t\t// @ts-ignore\n\t\t\tawait self.preActionHook.apply(self, arguments);\n\t\t});\n\t} \n\tget isRoot() { return this.parent==undefined;\t}\n\tget optionValues(){ return this._optionValues }\n\tget actions() { return this._actions; }\n\tget beforeHooks() {\treturn this._beforeHooks; }\n\tget afterHooks() {return this._afterHooks;}\n\tget fullname() {\n\t\tlet names = [this.name()];\n\t\tlet parent = this.parent;\n\t\twhile (parent) {\n\t\t\tif (parent.name() !== \"root\") {\n\t\t\t\tnames.unshift(parent.name());\n\t\t\t}\n\t\t\tparent = parent.parent;\n\t\t}\n\t\treturn names.join(\".\");\n\t}\n\n\t/**\n\t * 返回根命令\n\t */\n\troot() { \n\t\t// eslint-disable-next-line no-this-alias\n\t\tlet root:any = this;\n\t\twhile (root && root.parent != null) {\n\t\t\troot = root.parent as unknown as MixCommand;\n\t\t}\n\t\treturn root;\n\t}\n\n\n\taction(fn: MixEnhanceAction, options: MixActionOptions): this;\n\taction(fn: MixOriginalAction): this;\n\taction(): this {\n\t\tconst actionFunc = arguments[0];\n\t\tif (arguments.length == 1 && typeof actionFunc == \"function\") {\n\t\t\t// 原始方式\n\t\t\tthis._actions.push({\n\t\t\t\tid: Math.random().toString(36).substring(2),\n\t\t\t\tenhance: false,\n\t\t\t\tfn: actionFunc,\n\t\t\t});\n\t\t} else if (arguments.length == 2 && typeof actionFunc == \"function\" && typeof arguments[1] == \"object\" ) {\n\t\t\t// 增强模式\n\t\t\tconst actionFn = arguments[0];\n\t\t\tconst actionOpts: MixActionOptions = Object.assign({ at: \"append\" }, arguments[1]);\n\t\t\tif (actionOpts.at == \"replace\") this._actions = [];\n\t\t\tconst actionItem = {\n\t\t\t\tid: actionOpts.id || Math.random().toString(36).substring(2),\n\t\t\t\tenhance: actionOpts.enhance == undefined ? true : actionOpts.enhance,\n\t\t\t\tfn: actionFn,\n\t\t\t} as const;\n\t\t\tif (typeof actionOpts.at == \"number\") {\n\t\t\t\tthis._actions.splice(Number(actionOpts.at), 0, actionItem);\n\t\t\t} else if ([\"append\", \"before\"].includes(actionOpts.at)) {\n\t\t\t\tthis._actions.push(actionItem);\n\t\t\t} else if ([\"preappend\", \"after\"].includes(actionOpts.at)) {\n\t\t\t\tthis._actions.splice(0, 0, actionItem);\n\t\t\t} else {\n\t\t\t\tthis._actions.push(actionItem);\n\t\t\t}\n\t\t} else {\n\t\t\tconsole.log(\"[mixcli] action params error\");\n\t\t}\n\t\treturn super.action(this.getWrapperedAction());\n\t}\n\n\t/**\n\t * 读取命令配置值,包括父命令提供的配置选项\n\t * @param command\n\t */\n\tprivate getOptionValues(command: MixCommand) {\n\t\tconst opts = {};\n\t\t// eslint-disable-next-line no-this-alias\n\t\tlet parent: any = command;\n\t\twhile (parent) {\n\t\t\tObject.assign(opts, (parent as MixCommand).optionValues);\n\t\t\tparent = parent.parent;\n\t\t}\n\t\treturn opts;\n\t}\n\t/**\n\t * 本函数在运行时子类进行action生成该命令的action\n\t */\n\tprivate getWrapperedAction() {\n\t\treturn this.wrapperWorkDirsAction(this.wrapperChainActions());\n\t}\n\n\t/**\n\t * 向上查找所有祖先命令\n\t */\n\tprivate getAncestorCommands(): MixCommand[] {\n\t\tlet cmds: MixCommand[] = [];\n\t\t// eslint-disable-next-line no-this-alias\n\t\tlet cmd: MixCommand | null = this;\n\t\twhile (cmd) {\n\t\t\tcmd = cmd.parent as unknown as MixCommand;\n\t\t\tif (cmd) {\n\t\t\t\tcmds.push(cmd);\n\t\t\t}\n\t\t}\n\t\treturn cmds;\n\t}\n\t/***\n\t * 将所有actions包装成一个链式调用的函数\n\t */\n\tprivate wrapperChainActions() {\n\t\t// eslint-disable-next-line no-this-alias\n\t\tconst self = this;\n\t\treturn async function (this: any) {\n\t\t\tconst args = Array.from(arguments); // 原始输入的参数\n\t\t\tlet preValue: any; // 保存上一个action的返回值\n\t\t\t//解析参数, 0-1个参数为options,最后一个参数为command\n\t\t\tlet actionOpts: Record<string, any> = {},\n\t\t\t\tactionArgs: any[] = [],\n\t\t\t\tcmd: any;\n\t\t\tif (args.length >= 2) {\n\t\t\t\tcmd = args[args.length - 1]; // 最后一个command\n\t\t\t\tactionOpts = args[args.length - 2];\n\t\t\t\tactionArgs = args.slice(0, args.length - 2);\n\t\t\t}\n\t\t\tawait self.executeBeforeHooks({ args: actionArgs, options: actionOpts, command: cmd });\n\t\t\ttry {\n\t\t\t\tfor (let action of self._actions) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (action.enhance) {\n\t\t\t\t\t\t\t// 增强模式\n\t\t\t\t\t\t\toutputDebug(\"执行<{}>: args={}, options={}\", () => [\n\t\t\t\t\t\t\t\tself.name(),\n\t\t\t\t\t\t\t\tactionArgs,\n\t\t\t\t\t\t\t\tactionOpts,\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\tpreValue = await action.fn.call(this, {\n\t\t\t\t\t\t\t\tcommand: cmd,\n\t\t\t\t\t\t\t\tvalue : preValue,\n\t\t\t\t\t\t\t\targs : actionArgs,\n\t\t\t\t\t\t\t\toptions: actionOpts,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// 原始模式\n\t\t\t\t\t\t\tpreValue = await action.fn.apply(this, args);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (preValue === BREAK) break;\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\toutputDebug(\"命令{}的Action({})执行出错:{}\", [self.name, action.id, e]);\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tawait self.executeAfterHooks({\n\t\t\t\t\tvalue: preValue,\n\t\t\t\t\targs: actionArgs,\n\t\t\t\t\toptions: actionOpts,\n\t\t\t\t\tcommand: cmd,\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t}\n\t/**\n\t * 当传入--work-dirs时用来处理工作目录\n\t */\n\tprivate wrapperWorkDirsAction(fn: AsyncFunction) {\n\t\t// eslint-disable-next-line no-this-alias\n\t\tconst self = this;\n\t\treturn async function (this: any) {\n\t\t\tlet workDirs = self._optionValues.workDirs;\n\t\t\t// 未指定工作目录参数\n\t\t\tif (!workDirs) {\n\t\t\t\treturn await fn.apply(this, Array.from(arguments));\n\t\t\t}\n\t\t\tif (!Array.isArray(workDirs)) workDirs = workDirs.split(\",\");\n\t\t\tworkDirs = workDirs.reduce((dirs: any[], dir: string) => {\n\t\t\t\tif (typeof dir == \"string\") dirs.push(...dir.split(\",\"));\n\t\t\t\treturn dirs;\n\t\t\t}, []);\n\t\t\tfor (let workDir of workDirs) {\n\t\t\t\tconst cwd = process.cwd();\n\t\t\t\ttry {\n\t\t\t\t\tif (!path.isAbsolute(workDir)) workDir = path.join(cwd, workDir);\n\t\t\t\t\tif (fs.existsSync(workDir) && fs.statSync(workDir).isDirectory()) {\n\t\t\t\t\t\toutputDebug(\"切换到工作目录:{}\", workDir);\n\t\t\t\t\t\tprocess.chdir(workDir); // 切换\n\t\t\t\t\t\tawait fn.apply(this, Array.from(arguments));\n\t\t\t\t\t} else {\n\t\t\t\t\t\toutputDebug(\"无效的工作目录:{}\", workDir);\n\t\t\t\t\t} \n\t\t\t\t} finally {\n\t\t\t\t\tprocess.chdir(cwd);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\tgetOption(name: string): MixOption {\n\t\treturn this.options.find((option) => option.name() == name) as unknown as MixOption;\n\t}\n\t/**\n\t * 添加一个Before钩子\n\t * @param listener\n\t * @param scope =false时代表只在本命令执行,=true时代表在本命令及其子命令执行\n\t * @returns\n\t */\n\tbefore(listener: BeforeMixCommandHookListener, scope: boolean = true) {\n\t\tthis._beforeHooks.push([listener, scope]);\n\t\treturn this;\n\t}\n\tprivate async executeBeforeHooks(args: any) {\n\t\tconst hooks: [BeforeMixCommandHookListener, boolean, MixCommand][] = this.beforeHooks.map(\n\t\t\t([hook, scope]) => [hook, scope, this]\n\t\t);\n\t\tthis.getAncestorCommands().forEach((cmd: MixCommand) => {\n\t\t\thooks.unshift(\n\t\t\t\t...cmd.beforeHooks.map(([hook, scope]) => {\n\t\t\t\t\treturn [hook, scope, cmd] as [BeforeMixCommandHookListener, boolean, MixCommand];\n\t\t\t\t})\n\t\t\t);\n\t\t});\n\t\tfor (let [hook, scope, cmd] of hooks) {\n\t\t\tif (!scope) continue;\n\t\t\tawait hook.call(cmd, args);\n\t\t}\n\t}\n\t/**\n\t * 添加一个After钩子\n\t * @param listener\n\t * @param scope =false时代表只在本命令执行,=true时代表在本命令及其子命令执行\n\t * @returns\n\t */\n\tafter(listener: AfterMixCommandHookListener, scope: boolean = true) {\n\t\tthis._afterHooks.push([listener, scope]);\n\t\treturn this;\n\t}\n\n\tprivate async executeAfterHooks(args: any) {\n\t\tconst hooks: [AfterMixCommandHookListener, boolean, MixCommand][] = this.afterHooks.map(\n\t\t\t([hook, scope]) => [hook, scope, this]\n\t\t);\n\t\tthis.getAncestorCommands().forEach((cmd: MixCommand) => {\n\t\t\thooks.push(\n\t\t\t\t...cmd.afterHooks.map(([hook, scope]) => {\n\t\t\t\t\treturn [hook, scope, cmd] as [BeforeMixCommandHookListener, boolean, MixCommand];\n\t\t\t\t})\n\t\t\t);\n\t\t});\n\t\tfor (let [hook, scope, cmd] of hooks) {\n\t\t\tif (!scope) continue; //=false时不执行\n\t\t\tawait hook.call(cmd, args);\n\t\t}\n\t}\n\tprivate async preActionHook(thisCommand: Command) {\n\t\tif (this.isEnablePrompts()) {\n\t\t\t// 自动生成提示\n\t\t\tconst questions: PromptObject[] = [\n\t\t\t\t...this.generateAutoPrompts(),\n\t\t\t\t...this._customPrompts,\n\t\t\t];\n\t\t\t// 用户提示\n\t\t\tif (questions.length > 0) {\n\t\t\t\tconst results = await prompts(questions);\n\t\t\t\tObject.entries(results).forEach(([key, value]) => {\n\t\t\t\t\tthisCommand.setOptionValue(key, value);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate isEnablePrompts() {\n\t\tif (isDisablePrompts()) {\t\t\t\n\t\t\treturn false;// 命令行参数禁用了提示,优先级最高\n\t\t} else {\n\t\t\treturn this._enable_prompts;\n\t\t}\n\t}\n\n\t/**\n\t * 生成选项自动提示\n\t *\n\t * @remarks\n\t * 要求所有未提供默认值的Option自动生成提示\n\t *\n\t * - 未提供默认值,并且是必选的参数Option\n\t * - 指定了choices但未提供有效值的Option\n\t *\n\t */\n\tprivate generateAutoPrompts(): PromptObject[] {\n\t\tconst options = this.options as unknown as MixOption[];\n\t\tconst optionPromports = options\n\t\t\t.filter((option) => !option.hidden && option.__MIX_OPTION__)\n\t\t\t.map((option) => option.getPrompt(this._optionValues[option.attributeName()]))\n\t\t\t.filter((prompt) => prompt) as PromptObject[];\n\t\t\t\n\t\toutputDebug(\"命令<{}>自动生成{}个选项提示:{}\", [\n\t\t\tthis.name(),\n\t\t\toptionPromports.length,\n\t\t\toptionPromports.map((prompt) => `${prompt.name}(${prompt.type})`).join(\",\"),\n\t\t]);\n\t\treturn optionPromports;\n\t} \n\n\t// @ts-ignore\n\toption( flags: string, description: string, options?: MixedOptionParams ):this{ \n \t\tconst option = new MixOption(flags, description, options);\n\t\tif (option.required && !this.isEnablePrompts()) option.mandatory = true;\t\t\n\t\treturn this.addOption(option as unknown as Option) \n\t}\n\n\t/**\n\t * 添加提示\n\t *\n\t * @remarks\n\t *\n\t * 添加一些自定义提示 \n\t *\n\t * @param questions\n\t * @returns\n\t */\n\tprompt(questions: PromptObject | PromptObject[]) {\n\t\tthis._customPrompts.push(...(Array.isArray(questions) ? questions : [questions]));\n\t\treturn this;\n\t}\n\n\t/**\n\t *\n\t * 选择命令并执行\n\t *\n\t * @remorks\n\t *\n\t * 当命令具有多个子命令时,并且没有提供默认子命令时,提示用户选择一个子命令\n\t *\n\t */\n\tasync selectCommands() {\n\t\tconst choices = this.commands.map((command) => ({\n\t\t\ttitle: `${command.description()}(${command.name()})`,\n\t\t\tvalue: command.name(),\n\t\t}));\n\t\tconst result = await prompts({\n\t\t\ttype : \"select\",\n\t\t\tname : \"command\",\n\t\t\tmessage: \"请选择命令:\",\n\t\t\tchoices,\n\t\t});\n\t\t// 重新解析命令行参数标志,\n\t\tconst command = this.commands.find((command) => command.name() === result.command);\n\t\tawait command?.parseAsync([result.command], { from: \"user\" });\n\t}\n\t/**\n\t * 禁用/启用所有提示\n\t */\n\tdisablePrompts() {\n\t\tthis._enable_prompts = false;\n\t\treturn this;\n\t}\n\t/**\n\t * 启用所有提示\n\t */\n\tenablePrompts() {\n\t\tthis._enable_prompts = true;\n\t\treturn this;\n\t}\n}\n\n\n\n// 编写一个类型号用来表示Commander的Option flags字面量类型","import { Option, OptionValues } from 'commander'\nimport { PromptObject } from 'prompts'\nimport { PromptChoice, MixOptionPrompt,PromptParams } from './prompt'\n \n\nexport interface MixedOptionParams {\n required? : boolean; // A value must be supplied when the option is specified.\n optional? : boolean; // A value is optional when the option is specified.\n variadic? : boolean; \n mandatory? : boolean; // The option must have a value after parsing, which usually means it must be specified on command line.\n negate? : boolean;\n default? : any;\n defaultDescription? : string;\n conflicts? : string | string[];\n argParser? : unknown;\n implies? : OptionValues\n envVar? : string;\n parseArg? : <T>(value: string, previous: T) => T;\n hidden? : boolean;\n choices? : (string | PromptChoice )[] | ((pre:any,answers:any)=>(string | PromptChoice)[]);\n validate? : (value: any) => boolean;\n preset? : unknown;\n prompt? : PromptParams\n}\n\n\nexport class MixOption extends Option{\n __MIX_OPTION__ = true\n prompt? : MixOptionPrompt \n constructor(flags: string, description: string,public params?: MixedOptionParams) {\n super(flags, description) \n this._setOption(params || {}) \n this.prompt = new MixOptionPrompt(this,params?.prompt) \n } \n private _setOption(params:MixedOptionParams){ \n if(params.default) this.default(params.default,params.defaultDescription)\n if(params.conflicts) this.conflicts(params.conflicts)\n if(params.envVar) this.env(params.envVar)\n if(params.parseArg) this.argParser(params.parseArg) \n if(params.hidden) this.hidden = params.hidden\n if(params.mandatory) this.makeOptionMandatory(params.mandatory)\n if(params.implies) this.implies(params.implies) \n if(params.optional) this.optional=params.optional\n if(params.variadic) this.variadic = params.variadic\n if(params.negate) this.negate = params.negate\n if(params.preset) this.preset(params.preset)\n if(params.required) this.required = params.required \n if(Array.isArray(params.choices)) this.choices(params.choices.map(choice=>typeof(choice)=='string' ? choice : choice.value))\n } \n \n /**\n * 返回选项的提示对象\n * \n * @remarks \n * @param inputValue \n * @returns \n */\n getPrompt(inputValue?:any): PromptObject | undefined {\n return this.prompt?.get(inputValue)\n } \n}","import { isPlainObject } from \"flex-tools/typecheck/isPlainObject\"\nimport { isNumber } from \"flex-tools/typecheck/isNumber\"\n\nimport { PromptObject } from \"prompts\" \nimport { outputDebug } from \"./utils\"\nimport { MixOption } from \"./option\" \n\nexport type PromptType = \"text\" | \"password\" | \"invisible\" | \"number\"| \"confirm\"| \"list\" \n | \"toggle\"| \"select\" | \"multiselect\" | \"autocomplete\" | \"date\" | \"autocompleteMultiselect\"\n\nexport type PromptParam = 'auto' | boolean | PromptType | PromptObject\nexport type InputPromptParam = PromptParam | ((value:any)=>PromptParam) | boolean\nexport type PromptParamDefaultValue = string | boolean | string[] \n\nexport const promptTypeMap:Record<string,string> = {\n boolean: \"confirm\",\n string : \"text\",\n number : \"number\", \n array : \"list\", \n date : \"date\"\n} \n\nexport const supportedPromptTypes = [\n \"text\",\n \"password\",\n \"invisible\", \n \"number\", \n \"confirm\" , \n \"list\", \n \"toggle\" , \n \"select\" , \n \"multiselect\" , \n \"autocomplete\" , \n \"date\" , \n \"autocompleteMultiselect\"\n]\n\nexport interface PromptChoice {\n title : string;\n value? : any;\n disabled? : boolean | undefined;\n selected? : boolean | undefined;\n description?: string | undefined;\n}\n\n \nexport type PromptParams = Omit<PromptObject,'name'> | PromptType | boolean | 'auto' | undefined \n\n/**\n * 负责生成prompt对象\n * \n */\nexport class MixOptionPrompt{\n params?: PromptParams\n constructor(public cliOption:MixOption,promptParams?:PromptParams){ \n this.params = promptParams\n }\n /**\n * 返回输入的是否是有效的prompt类型\n * @param type \n * @returns \n */\n isValidPromptType(type:any){\n return supportedPromptTypes.includes(String(type))\n }\n /**\n * 推断是否需要提示\n * \n * 1. 显式指定prompt=true或者提示类型,或者提示对象,则需要提示\n * \n * \n */\n isNeedPrompt(input:any,defaultValue?:any){\n \n const params = this.params\n\n const inputValue = input || defaultValue\n\n // 是否有输入值,即在命令行输入了值\n const hasInput = !(inputValue === undefined)\n \n // 1. 显式指定了_prompt为true,则需要提示,后续进行提示类型的推断,可能不会准确\n if(params === true) return true\n if(params === false) return false \n if(params === 'auto') return !hasInput\n\n // 2. 提供了一个prompt对象,并且没有在命令行输入值,则需要提示\n if(isPlainObject(params)){\n return !hasInput\n }\n\n // 3. 指定了内置的prompt类型,如prompt='password',则使用password类型提示输入\n if(typeof(params) == 'string' && this.isValidPromptType(params)){\n return true\n }\n\n // 4. 指定了可选值,但是没有输入值,则需要提示\n const isOptional = /(\\<s*\\w\\s*\\>)/.test(this.cliOption.flags) \n if(isOptional) return !hasInput\n \n // 4. 判断输入是否有效,则显示提示\n if(this.cliOption.argChoices && this.cliOption.argChoices.indexOf(inputValue) == -1){\n return true\n } \n return !hasInput\n\n }\n \n private _getChoices(){\n let choices:(string | PromptChoice)[] | ((pre:any,answers:any)=>(string | PromptChoice)[]) = []\n let choicesParam = this.cliOption.params?.choices\n if(this.cliOption.argChoices){\n choices = this.cliOption.argChoices.map(choice=>{\n if(typeof(choice)=='string'){\n return {title:choice,value:choice}\n }else{\n return choice\n }\n })\n }else if(choicesParam){\n choices = typeof(choicesParam)=='function' ? choicesParam : [] \n }else{\n return []\n } \n return choices\n } \n\n /**\n * 自动推断prompt类型\n * \n * \n * \n * @param inputValue 从命令行输入的值\n */\n infer(inputValue?:any){\n\n const { variadic, defaultValue } = this.cliOption\n\n const input = inputValue || defaultValue\n\n // 如果选择指定了\"-p [value]或[value...]\",则使用text类型,如果没有要求输入值,则使用confirm类型\n let promptType:PromptType = 'text'\n\n const params = this.params\n\n if(this.isValidPromptType(params)){ // 显式指定了prompt类型,m则以指定的类型为准 \n promptType = params as PromptType\n }else if(isPlainObject(params)){ // 显式指定了prompt对象\n promptType = (params as PromptObject).type as PromptType\n }else{ // 自动推断prompt类型\n \n const isListType = /(\\[\\s*\\w+\\.\\.\\.\\s*])|(\\<\\s*\\w+\\.\\.\\.\\s*>)/.test(this.cliOption.flags)\n const isTextType = /(\\<s*\\w+\\s*\\>)|(\\[\\w+\\])/.test(this.cliOption.flags) \n const isBooleanType = !/(\\[\\s*\\w+s*])|(\\<\\s*\\w+\\s*>)/.test(this.cliOption.flags)\n const isNumberType = isNumber(defaultValue)\n const isDate = defaultValue && defaultValue instanceof Date\n\n // 根据默认值的类型推断\n const datatype:string = Array.isArray(input) ? 'array' : \n input instanceof Date ? 'date' :\n typeof(input) \n\n const optionParams = this.cliOption.params\n\n if(optionParams && optionParams.choices){\n const choices = optionParams.choices\n if(isBooleanType && (Array.isArray(choices) && choices.length==2)){\n promptType = 'toggle'\n }else{\n promptType = variadic ? 'multiselect' : 'select'\n } \n }else if(isListType){ // 提供多个可选值时\n promptType = 'list'\n }else if(isDate){\n promptType = 'date'\n }else if(isNumberType){\n promptType = 'number'\n }else if(isTextType){ // 提供一个可选值时\n promptType = 'text' \n }else if(isBooleanType || typeof(defaultValue)==='boolean'){\n promptType = 'confirm'\n }else if(datatype in promptTypeMap){\n promptType = promptTypeMap[datatype] as PromptType\n }\n }\n outputDebug(\"选项<{}> -> 提示类型<{}>\",[this.cliOption.name(),promptType])\n return promptType\n }\n /**\n * 返回生成prompt对象\n * \n * @param inputValue 从命令行输入的值\n */\n get(inputValue?:any){\n\n const { description, defaultValue } = this.cliOption\n \n let input = inputValue || defaultValue\n\n // 1. 判断是否需要启用提示\n if(!this.isNeedPrompt(input,defaultValue)) return\n\n // 2. 推断prompt类型\n const promptType = this.infer(inputValue)\n\n const prompt = {\n type : promptType, \n name : this.cliOption.attributeName(),\n message: description,\n initial: input,\n ...typeof(this.params) == 'object' ? this.params : {}\n } as PromptObject\n\n\n // 指定了验证函数,用来验证输入值是否有效\n prompt.validate = this.cliOption.params?.validate\n\n if(promptType=='multiselect') prompt.instructions=false\n prompt.choices = prompt.choices || this._getChoices() as any \n\n if(['select','multiselect'].includes(promptType)){ \n\n }else if(promptType=='toggle'){ \n if(Array.isArray(prompt.choices)){\n if(!prompt.active) prompt.active = prompt.choices[0].value\n if(!prompt.inactive) prompt.inactive = prompt.choices[1].value \n }\n }\n\n if(input && typeof(prompt.initial)!='function'){\n if(prompt.choices && Array.isArray(prompt.choices)){\n if(promptType=='select'){\n const index = Array.isArray(prompt.choices) ? prompt.choices.findIndex(item=>item.value==input) : -1\n if(index!=-1){\n prompt.initial = index\n }\n }else if(promptType=='multiselect'){ \n prompt.choices.forEach((item)=>{\n if(Array.isArray(input) && input.includes(item.value)){\n item.selected = true\n }else if(item.value==input){\n item.selected = true\n }\n })\n }\n }\n }\n\n return prompt\n }\n\n\n}","import fs from \"fs-extra\"\nimport path from \"node:path\"\nimport { promisify } from \"flex-tools/func/promisify\"\nimport logsets from \"logsets\" \n\n\n/**\n * \n * 在控制台输出一个字符串\n * 本方法会将字符串中的每一行空格去掉\n * \n * @remarks\n * \n * outputStr(String.raw`\n * a\n * b`)\n * \n * 会输出\n * a\n * b\n *\n * 此功能可以用于输出多行字符串时,保持代码的缩进格式,而不会影响输出结果\n * \n * @param str : 要输出的字符串\n * @param vars : 用于替换字符串中的变量\n * \n */\nexport function outputStr(str:string,vars?:Record<string,any> | any[]){ \n logsets.log(fixIndent(str),vars)\n}\n\n/**\n * 修正多行字符串的缩进\n * \n * @param text \n * @param indent \n * @returns \n */\nexport function fixIndent(text:string,indent?:boolean | number):string{\n let indentValue = (indent==undefined || indent===true) ? 0 : (typeof(indent)=='number' ? indent : -1)\n if(indentValue==-1) return text // 不修正缩进\n let lines:string[] = text.split(\"\\n\")\n let minSpaceCount = lines.reduce<number>((minCount,line,index)=>{\n if(index==0) return minCount\n const spaceCount = line.match(/^\\s*/)?.[0].length || 0\n return Math.min(minCount,spaceCount)\n },9999)\n lines = lines.map(line=>line.substring(minSpaceCount))\n return lines.join(\"\\n\")\n}\n\n/**\n * 增加内置选项\n * @param command \n */\nexport function addBuiltInOptions(command:any){ \n command.option(\"--work-dirs <values...>\",\"指定工作目录\",{hidden:true,optional:true,required:true,prompt:false})\n command.option(\"--disable-prompts\",\"禁用所有交互提示\",{hidden:true,prompt:false}) \n command.option(\"--debug-cli\",\"显示调试信息\",{hidden:true,prompt:false})\n}\n\n\n/**\n * 是否命令行中包含了--debug-cli选项\n */\nexport function isDebug(){\n return process.argv.includes(\"--debug-cli\")\n}\n\n\nexport function isDisablePrompts(){ \n return process.argv.includes(\"--disable-prompts\")\n}\n\n/**\n * 打印调试信息\n * @param message \n * @param args \n */\nexport function outputDebug(message:string,...args:any[]){ \n let vars = (args.length == 1 && typeof(args[0])=='function') ? args[0]() : args\n if(isDebug()) logsets.log(`[MixCli] ${message}`,...vars)\n}\n\nexport const fileExists = promisify(fs.exists,{\n parseCallback:(results)=>{\n return results[0]\n }\n})\nexport const readFile = promisify(fs.readFile)\nexport const writeFile = promisify(fs.writeFile)\nexport const mkdir = promisify(fs.mkdir)\n \n/** \n * 创建目录 \n * \n * \n * \n * @param {String[]} dirs 要创建的目录列表,类型为字符串数组 \n * @param callback 创建目录过程中的回调函数,类型为异步函数,接收一个参数 dir,表示当前正在创建的目录 \n * @returns 该函数返回一个 Promise 对象,表示创建目录的操作是否完成 \n */\nexport async function mkDirs(dirs:string[],{callback,base}:{callback?:Function,base?:string}){\n if(!Array.isArray(dirs)) throw new Error(\"dirs参数必须为字符串数组\")\n for(let dir of dirs){\n if(!path.isAbsolute(dir)) dir = path.join(base || process.cwd(),dir)\n if(typeof(callback)=='function') callback(dir)\n await mkdir(dir,{recursive:true})\n }\n}\n\nexport function showError(e:any){\n if(isDebug()){\n outputDebug(\"导入命令<>出错:{}\",e.stack)\n }else{\n console.error(e)\n } \n\n}\n\n// 编写一个函数,用于将使用-分隔的字符串转换为驼峰式\nexport function hyphenToCamelCase(str:string){\n return str.replace(/-([a-z])/g,(_,letter)=>letter.toUpperCase())\n}\n\nexport function getId(){\n return Math.random().toString(36).substr(2)\n}\n\n\nexport async function importModule(file:string){\n let module \n try{\n module = require(file)\n }catch(e:any){\n try{\n const cmd = await import(`file://${file}`)\n module = cmd.default\n }catch(e:any){\n throw e\n } \n }\n return module\n}\n","import { getPackageJson } from \"flex-tools/package/getPackageJson\"\nimport { getPackageRootPath } from 'flex-tools/package/getPackageRootPath';\nimport type { MixCli } from './cli';\nimport { globSync } from 'glob'\nimport { MixCliCommand } from './cli';\nimport { importModule, outputDebug } from './utils';\nimport fs from \"node:fs\"\nimport path from \"node:path\"\n\n\n/**\n * \n * 在当前工程中查找符合FlexCli.prefix约定的命令 \n * \n * - 读取当前包的package.json\n * - 找出所有以cli.prefix开头的依赖\n * - 加载这些依赖的目录下的匹配cli.pattern的命令\n * - 加载加载这样命令\n * \n */\n \n\nexport function getMatchedDependencies(this:MixCli,entry:string):string[]{\n const pacakgeMacher = this.options.include\n if(!(pacakgeMacher instanceof RegExp)) return []\n \n // 找出当前包的所有依赖\n const { dependencies={},devDependencies={},peerDependencies={},optionalDependencies={},bundleDependencies={} } = getPackageJson(entry)\n const packageNames = [\n ...Object.keys(dependencies),\n ...Object.keys(devDependencies),\n ...Object.keys(peerDependencies),\n ...Object.keys(optionalDependencies),\n ...Object.keys(bundleDependencies)\n ]\n return packageNames.filter(name=>name!==\"@voerka/cli\" && pacakgeMacher.test(name))\n}\n\nfunction isMatched(str:string,reg?:string | RegExp | string[] | RegExp[]):boolean{\n // let regexps:RegExp[]=[]\n const regexps = reg ? (Array.isArray(reg) ? reg : [reg]) : []\n return regexps.some(regexp=>{\n if(typeof regexp === \"string\"){\n return (new RegExp(regexp)).test(str)\n }else if(regexp instanceof RegExp){\n return regexp.test(str)\n }else{\n return false\n }\n })\n}\n\nexport function findCliPaths(this:MixCli,packageName?:string ,entry?:string):string[]{\n const includeMacher = this.options.include\n const excludeMacher = this.options.exclude\n if(!includeMacher) return []\n const packageRoot = getPackageRootPath(entry || process.cwd())\n const packagePath = packageName ? path.dirname(require.resolve(packageName,{paths:[packageRoot as string]})) : packageRoot\n\n if(!packagePath) {\n outputDebug(\"MixCli只能运行在Nodejs环境\" )\n return []\n }\n\n // 找出当前包的所有依赖\n const packageNames = getMatchedDependencies.call(this,packagePath)\n\n const cliDirs:string[]=[]\n \n if(entry!==undefined) cliDirs.push(path.join(packagePath,this.options.cliDir))\n packageNames.filter(name=>{\n return isMatched(name,includeMacher) && !isMatched(name,excludeMacher) \n })\n .forEach(name=>{\n outputDebug(\"匹配包:{}\",`${packageName ? name+\" <- \"+packageName : name}`)\n try{\n const packageEntry = path.dirname(require.resolve(name,{paths:packagePath ? [packagePath] : [process.cwd()]}))\n const packageCliDir =path.join(packageEntry,this.options.cliDir!) \n // 查找当前包的所属工程的依赖\n let dependencies = getMatchedDependencies.call(this,packageEntry)\n cliDirs.push(...dependencies.reduce<string[]>((result,dependencie)=>{\n outputDebug(\"匹配包:{}\",`${dependencie} <- ${name}`)\n result.push(...findCliPaths.call(this,dependencie,packageEntry))\n return result\n },[])) \n if(fs.existsSync(packageCliDir)){\n cliDirs.push(packageCliDir)\n }\n }catch(e:any){\n outputDebug(\"解析包<{}>路径出错:{}\",[name,e.stack])\n } \n })\n // 由于一些包可能存在循环依赖,所以需要去重\n return [...new Set(cliDirs)]\n}\n\n\n/**\n * \n * 扫描当前工程中所有符合条件的命令\n * \n * @param cli \n * \n */\nexport async function findCommands(cli:MixCli){ \n const cliDirs = findCliPaths.call(cli)\n const commands:MixCliCommand[] = []\n const files = [] as string[]\n cliDirs.forEach(dir=>{\n globSync(\"*\",{\n cwd:dir,\n absolute :true \n }).forEach((file:string)=>{ \n const baseName = path.basename(file) \n if(baseName.startsWith(\"_\")) return\n const ext = path.extname(file).toLowerCase()\n if([\".js\",\".cjs\",\".mjs\"].includes(ext)){\n files.push(file)\n }else if(fs.statSync(file).isDirectory()){\n files.push(path.join(file,\"index.js\"))\n files.push(path.join(file,\"index.cjs\"))\n files.push(path.join(file,\"index.mjs\"))\n }\n })\n })\n for(let file of files){ \n if(!fs.existsSync(file)) continue\n try{\n outputDebug(\"导入命令:{}\",file)\n if(file.endsWith(\".cjs\") || file.endsWith(\".js\")){\n commands.push(await importModule(file))\n }else if(file.endsWith(\".mjs\")){\n const cmd = await import(`file://${file}`)\n commands.push(cmd.default)\n } \n }catch(e:any){\n outputDebug(e) \n }\n }\n return commands\n}\n\n"],"mappings":"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","names":["LiteEvent","logsets","assignObject","Command","prompts","Option","isPlainObject","isNumber","fs","path","promisify","logsets","outputStr","str","vars","logsets","fixIndent","text","indent","lines","minSpaceCount","minCount","line","index","_a","spaceCount","addBuiltInOptions","command","isDebug","isDisablePrompts","outputDebug","message","args","fileExists","promisify","fs","results","readFile","writeFile","mkdir","mkDirs","_0","_1","__async","dirs","callback","base","dir","path","showError","e","hyphenToCamelCase","_","letter","getId","importModule","file","module","__require","promptTypeMap","supportedPromptTypes","MixOptionPrompt","cliOption","promptParams","type","input","defaultValue","params","inputValue","hasInput","isPlainObject","_a","choices","choicesParam","choice","variadic","promptType","isListType","isTextType","isBooleanType","isNumberType","isNumber","isDate","datatype","optionParams","outputDebug","description","prompt","__spreadValues","index","item","MixOption","Option","flags","description","params","MixOptionPrompt","choice","inputValue","_a","path","fs","BREAK","MixCommand","Command","name","self","addBuiltInOptions","__async","names","parent","root","actionFunc","actionFn","actionOpts","actionItem","command","opts","cmds","cmd","args","preValue","actionArgs","action","outputDebug","e","fn","workDirs","dirs","dir","workDir","cwd","path","fs","option","listener","scope","hooks","hook","thisCommand","questions","results","prompts","key","value","isDisablePrompts","optionPromports","prompt","flags","description","options","MixOption","choices","result","getPackageJson","getPackageRootPath","globSync","fs","path","getMatchedDependencies","entry","pacakgeMacher","dependencies","devDependencies","peerDependencies","optionalDependencies","bundleDependencies","getPackageJson","name","isMatched","str","reg","regexp","findCliPaths","packageName","includeMacher","excludeMacher","packageRoot","getPackageRootPath","packagePath","path","__require","outputDebug","packageNames","cliDirs","packageEntry","packageCliDir","result","dependencie","fs","e","findCommands","cli","__async","commands","files","dir","globSync","file","ext","importModule","cmd","asyncSignal","replaceAll","replaceAll","MixCli","LiteEvent","options","assignObject","__async","cmders","findCommands","cmder","cmds","e","outputDebug","MixCommand","logsets","fixIndent","title","addBuiltInOptions","text","pos","alignIndent","cmd","result","name","c","names","curCmd","resultCmd","topName","r","signal","asyncSignal","resolve","listener","fullname","s"]}
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "mixcli",
3
- "version": "3.0.10",
3
+ "version": "3.2.1",
4
4
  "description": "Develop command line tool scaffolding for monorepo",
5
5
  "repository": "https://github.com/zhangfisher/mixcli.git",
6
6
  "homepage": "https://zhangfisher.github.io/mixcli/",
7
7
  "main": "./dist/index.js",
8
- "module": "./dist/index.mjs",
9
- "types": "./dist/index.d.ts",
8
+ "type": "module",
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
10
12
  "access": "public",
11
13
  "files": [
12
14
  "dist",
@@ -14,29 +16,44 @@
14
16
  "readme.md",
15
17
  "package.json"
16
18
  ],
17
- "keywords": [],
18
- "author": "",
19
+ "keywords": [
20
+ "commander",
21
+ "prompts",
22
+ "cli"
23
+ ],
24
+ "author": "zhangfisher",
19
25
  "license": "ISC",
20
26
  "dependencies": {
21
- "@types/prompts": "^2.4.4",
22
- "@voerkai18n/runtime": "^2.0.8",
27
+ "@types/prompts": "^2.4.9",
28
+ "@voerkai18n/runtime": "^2.1.13",
23
29
  "art-template": "^4.13.2",
24
- "commander": "^12.0.0",
25
- "flex-tools": "^1.3.71",
30
+ "commander": "^13.0.0",
31
+ "flex-tools": "^1.4.18",
26
32
  "fs-extra": "^11.1.1",
27
33
  "glob": "^10.3.12",
28
- "logsets": "^1.3.8",
34
+ "logsets": "^1.3.14",
29
35
  "prompts": "^2.4.2",
30
36
  "string.prototype.replaceall": "^1.0.7"
31
37
  },
32
38
  "devDependencies": {
39
+ "@changesets/cli": "^2.27.11",
33
40
  "@types/fs-extra": "^11.0.1",
34
41
  "@types/node": "^20.5.7",
35
- "typescript": "^5.2.2"
42
+ "tsup": "^8.3.5",
43
+ "type-fest": "^4.32.0",
44
+ "typescript": "^5.7.3",
45
+ "vitepress": "^1.5.0"
36
46
  },
37
47
  "scripts": {
38
48
  "build": "tsup",
39
49
  "build:watch": "tsup --watch",
40
- "release": "npm publish"
41
- }
50
+ "release": "changeset version && changeset publish && copy CHANGELOG.md docs\\CHANGELOG.md",
51
+ "docs:dev": "vitepress dev docs",
52
+ "docs:build": "vitepress build docs",
53
+ "docs:preview": "vitepress preview docs",
54
+ "sync": "cnpm sync mixcli",
55
+ "changeset": "changeset"
56
+ },
57
+ "module": "./dist/index.mjs",
58
+ "types": "./dist/index.d.ts"
42
59
  }
package/readme.md CHANGED
@@ -1,16 +1,12 @@
1
+ A toolkit for developing command line applications, based on `commander`, `prompts`, and `logsets`, providing functions such as command line parsing, automatic interactive prompts, and terminal interface enhancement.
1
2
 
2
- 开发命令行应用的工具包,基于`commander`、`prompts`和`logsets`,提供命令行解析、自动交互提示以及终端界面增强等功能。
3
3
 
4
- [文档]( https://zhangfisher.github.io/mixcli/)
4
+ [中文](https://zhangfisher.github.io/mixcli/)
5
5
 
6
- # 主要特性:
6
+ # Features:
7
7
 
8
- - [commander](https://github.com/tj/commander.js)提供命令行解析
9
- - [prompts](https://github.com/terkelg/prompts)提供交互提示
10
- - [logsets](https://github.com/terkelg/prompts)提供终端输出增强组件
11
- - 自动为命令行选项推断生成交互提示
12
- - 自动搜索当前依赖下符合条件的命令进行合并,适合于`monorepo`项目开发
13
-
14
-
15
-
16
-
8
+ - [commander](https://github.com/tj/commander.js) Provide command line parsing
9
+ - [prompts](https://github.com/terkelg/prompts) Provide interactive prompts
10
+ - [logsets](https://github.com/terkelg/prompts) Provide terminal output enhancement components
11
+ - Automatically generate interactive prompts for command line option inference
12
+ - Automatically search for commands that meet the conditions under the current dependency for merging, suitable for `monorepo` project development
package/src/cli.ts CHANGED
@@ -6,13 +6,11 @@ import logsets from "logsets"
6
6
 
7
7
  import { assignObject } from "flex-tools/object/assignObject"
8
8
  import { MixCommand } from "./command"
9
- import { addBuiltInOptions, fixIndent, isDebug } from './utils';
9
+ import { addBuiltInOptions, fixIndent, outputDebug } from './utils';
10
10
  import { findCommands } from "./finder"
11
11
  import { asyncSignal } from "flex-tools/async/asyncSignal"
12
12
  // @ts-ignore
13
- import replaceAll from 'string.prototype.replaceall'
14
- import { getPackageEntry, getPackageRootPath } from "flex-tools"
15
- import { getPackageJson } from 'flex-tools/package/getPackageJson';
13
+ import replaceAll from 'string.prototype.replaceall'
16
14
  replaceAll.shim()
17
15
 
18
16
  export interface MixCliOptions{
@@ -40,6 +38,7 @@ export interface MixCliOptions{
40
38
  // 默认是否启用交互提示, auto当没有值时,会根据当前是否在终端中运行来决定是否启用交互提示
41
39
  // 为false时,禁用所有交互提示,为true时,启用所有交互提示
42
40
  prompt?:'auto' | boolean
41
+ ignoreError?:boolean
43
42
  }
44
43
 
45
44
 
@@ -53,16 +52,17 @@ export type MixCliEvents =
53
52
 
54
53
  export class MixCli extends LiteEvent<any,MixCliEvents>{
55
54
  options:Required<MixCliOptions>
56
- root!:Command
55
+ root!:MixCommand
57
56
  private findSignals:any[]=[]
58
57
  constructor(options?:MixCliOptions){
59
58
  super()
60
59
  this.options= assignObject({
61
- name:"mixcli",
62
- package:null,
63
- cliDir:"cli",
64
- prompt:'auto'
65
- },options)
60
+ name : "mixcli",
61
+ package : null,
62
+ cliDir : "cli",
63
+ prompt : 'auto',
64
+ ignoreError: false
65
+ },options) as Required<MixCliOptions>
66
66
  this.createRootCommand()
67
67
  }
68
68
  get context(){return this.options.context}
@@ -82,10 +82,11 @@ export class MixCli extends LiteEvent<any,MixCliEvents>{
82
82
  try{
83
83
  if(typeof(cmder)==="function"){
84
84
  let cmds = cmder(this)
85
- cmds =cmds ? (Array.isArray(cmds) ? cmds : [cmds]) : []
85
+ cmds = cmds ? (Array.isArray(cmds) ? cmds : [cmds]) : []
86
86
  this.register(()=>cmds)
87
87
  }
88
88
  }catch(e:any){
89
+ outputDebug("注册命令失败:{}",e.stack)
89
90
  }
90
91
  }
91
92
  }
@@ -138,14 +139,20 @@ export class MixCli extends LiteEvent<any,MixCliEvents>{
138
139
  let result = cmd(this)
139
140
  let cmds = result instanceof Array ? result : (result==undefined ? [] : [result])
140
141
  for(let cmd of cmds){
141
- if(cmd instanceof MixCommand){
142
+ // 为什么不用cmd instanceof MixCommand来判断是否是一个有效的命令?
143
+ // 因为当不同的包引用了与主包不一样版本的mixcli时,判断会失效,导致不能识别
144
+ // 所以我们通过cmd.__MIX_COMMAND__来判断是否是一个有效的命令
145
+ if(cmd.__MIX_COMMAND__){
142
146
  if(this.hasCommand(cmd.name())){
143
147
  logsets.error(`Command <${cmd.name()}> has been registered!`)
144
148
  }else{
145
- this.root.addCommand(cmd) ;
149
+ outputDebug("注册命令:{}",cmd.fullname)
150
+ this.root.addCommand(cmd as Command) ;
146
151
  (cmd as any)._cli = this
147
152
  this.emit("register",cmd.fullname,true)
148
153
  }
154
+ }else{
155
+ logsets.error(`Command <${cmd.toString()}> is not a valid command!`)
149
156
  }
150
157
  }
151
158
  }else{
@@ -170,7 +177,7 @@ export class MixCli extends LiteEvent<any,MixCliEvents>{
170
177
  */
171
178
  get(name:string):MixCommand | undefined{
172
179
  const names=name.split(".")
173
- let curCmd:Command = this.root
180
+ let curCmd:MixCommand = this.root
174
181
  let resultCmd:MixCommand | undefined
175
182
  while(names.length>0){
176
183
  const topName = names.shift()
@@ -243,12 +250,5 @@ export class MixCli extends LiteEvent<any,MixCliEvents>{
243
250
  })
244
251
  })
245
252
  }
246
- /**
247
- * 创建一个命令
248
- *
249
- *
250
- */
251
- create(){
252
- }
253
253
  }
254
254