mixcli 3.0.3 → 3.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -271,6 +271,7 @@ declare class MixCli extends LiteEvent<any, MixCliEvents> {
271
271
  * 扫描当前工程的依赖,加载匹配include的依赖下的命令
272
272
  */
273
273
  private installCommands;
274
+ private getVersion;
274
275
  /**
275
276
  * 创建根命令
276
277
  *
@@ -406,5 +407,8 @@ declare function mkDirs(dirs: string[], { callback, base }: {
406
407
  callback?: Function;
407
408
  base?: string;
408
409
  }): Promise<void>;
410
+ declare function showError(e: any): void;
411
+ declare function getId(): string;
412
+ declare function importModule(file: string): Promise<any>;
409
413
 
410
- export { ActionOptions, ActionRegistry, AfterCommandHookListener, BREAK, BeforeCommandHookListener, EnhanceAction, ICommandHookListener, MixCli, MixCliCommand, MixCliEvents, MixCliOptions, MixCommand, MixOption, MixedOptionParams, OriginalAction, addBuiltInOptions, createFileByTemplate, fileExists, fixIndent, isDebug, isEnablePrompts, mkDirs, mkdir, outputDebug, outputStr, readFile, writeFile };
414
+ export { ActionOptions, ActionRegistry, AfterCommandHookListener, BREAK, BeforeCommandHookListener, EnhanceAction, ICommandHookListener, MixCli, MixCliCommand, MixCliEvents, MixCliOptions, MixCommand, MixOption, MixedOptionParams, OriginalAction, addBuiltInOptions, createFileByTemplate, fileExists, fixIndent, getId, importModule, isDebug, isEnablePrompts, mkDirs, mkdir, outputDebug, outputStr, readFile, showError, writeFile };
package/dist/index.d.ts CHANGED
@@ -271,6 +271,7 @@ declare class MixCli extends LiteEvent<any, MixCliEvents> {
271
271
  * 扫描当前工程的依赖,加载匹配include的依赖下的命令
272
272
  */
273
273
  private installCommands;
274
+ private getVersion;
274
275
  /**
275
276
  * 创建根命令
276
277
  *
@@ -406,5 +407,8 @@ declare function mkDirs(dirs: string[], { callback, base }: {
406
407
  callback?: Function;
407
408
  base?: string;
408
409
  }): Promise<void>;
410
+ declare function showError(e: any): void;
411
+ declare function getId(): string;
412
+ declare function importModule(file: string): Promise<any>;
409
413
 
410
- export { ActionOptions, ActionRegistry, AfterCommandHookListener, BREAK, BeforeCommandHookListener, EnhanceAction, ICommandHookListener, MixCli, MixCliCommand, MixCliEvents, MixCliOptions, MixCommand, MixOption, MixedOptionParams, OriginalAction, addBuiltInOptions, createFileByTemplate, fileExists, fixIndent, isDebug, isEnablePrompts, mkDirs, mkdir, outputDebug, outputStr, readFile, writeFile };
414
+ export { ActionOptions, ActionRegistry, AfterCommandHookListener, BREAK, BeforeCommandHookListener, EnhanceAction, ICommandHookListener, MixCli, MixCliCommand, MixCliEvents, MixCliOptions, MixCommand, MixOption, MixedOptionParams, OriginalAction, addBuiltInOptions, createFileByTemplate, fileExists, fixIndent, getId, importModule, isDebug, isEnablePrompts, mkDirs, mkdir, outputDebug, outputStr, readFile, showError, writeFile };
package/dist/index.js CHANGED
@@ -19,9 +19,6 @@ var __spreadValues = (a, b) => {
19
19
  }
20
20
  return a;
21
21
  };
22
- var __commonJS = (cb, mod) => function __require() {
23
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
24
- };
25
22
  var __export = (target, all) => {
26
23
  for (var name in all)
27
24
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -64,53 +61,6 @@ var __async = (__this, __arguments, generator) => {
64
61
  });
65
62
  };
66
63
 
67
- // package.json
68
- var require_package = __commonJS({
69
- "package.json"(exports, module2) {
70
- module2.exports = {
71
- name: "mixcli",
72
- version: "3.0.3",
73
- description: "Develop command line tool scaffolding for monorepo",
74
- repository: "https://github.com/zhangfisher/mixcli.git",
75
- homepage: "https://zhangfisher.github.io/mixcli/",
76
- main: "./dist/index.js",
77
- module: "./dist/index.mjs",
78
- types: "./dist/index.d.ts",
79
- scripts: {
80
- build: "tsup",
81
- "build:watch": "tsup --watch",
82
- release: "npm publish"
83
- },
84
- files: [
85
- "dist",
86
- "src",
87
- "readme.md",
88
- "package.json"
89
- ],
90
- keywords: [],
91
- author: "",
92
- license: "ISC",
93
- dependencies: {
94
- "@types/prompts": "^2.4.4",
95
- "@voerkai18n/runtime": "^2.0.8",
96
- "art-template": "^4.13.2",
97
- commander: "^12.0.0",
98
- "flex-tools": "^1.3.60",
99
- "fs-extra": "^11.1.1",
100
- glob: "^10.3.12",
101
- logsets: "^1.3.8",
102
- prompts: "^2.4.2",
103
- "string.prototype.replaceall": "^1.0.7"
104
- },
105
- devDependencies: {
106
- "@types/fs-extra": "^11.0.1",
107
- "@types/node": "^20.5.7",
108
- typescript: "^5.2.2"
109
- }
110
- };
111
- }
112
- });
113
-
114
64
  // src/index.ts
115
65
  var src_exports = {};
116
66
  __export(src_exports, {
@@ -122,6 +72,8 @@ __export(src_exports, {
122
72
  createFileByTemplate: () => createFileByTemplate,
123
73
  fileExists: () => fileExists,
124
74
  fixIndent: () => fixIndent,
75
+ getId: () => getId,
76
+ importModule: () => importModule,
125
77
  isDebug: () => isDebug,
126
78
  isEnablePrompts: () => isEnablePrompts,
127
79
  mkDirs: () => mkDirs,
@@ -129,6 +81,7 @@ __export(src_exports, {
129
81
  outputDebug: () => outputDebug,
130
82
  outputStr: () => outputStr,
131
83
  readFile: () => readFile,
84
+ showError: () => showError,
132
85
  writeFile: () => writeFile
133
86
  });
134
87
  module.exports = __toCommonJS(src_exports);
@@ -223,6 +176,32 @@ function mkDirs(_0, _1) {
223
176
  }
224
177
  });
225
178
  }
179
+ function showError(e) {
180
+ if (isDebug()) {
181
+ outputDebug("\u5BFC\u5165\u547D\u4EE4<>\u51FA\u9519:{}", e.stack);
182
+ } else {
183
+ console.error(e);
184
+ }
185
+ }
186
+ function getId() {
187
+ return Math.random().toString(36).substr(2);
188
+ }
189
+ function importModule(file) {
190
+ return __async(this, null, function* () {
191
+ let module2;
192
+ try {
193
+ module2 = require(file);
194
+ } catch (e) {
195
+ try {
196
+ const cmd = yield import(`file://${file}`);
197
+ module2 = cmd.default;
198
+ } catch (e2) {
199
+ throw e2;
200
+ }
201
+ }
202
+ return module2;
203
+ });
204
+ }
226
205
 
227
206
  // src/prompt.ts
228
207
  var promptTypeMap = {
@@ -814,11 +793,11 @@ var MixCommand = class extends import_commander2.Command {
814
793
  };
815
794
 
816
795
  // src/finder.ts
817
- var import_flex_tools = require("flex-tools");
796
+ var import_getPackageJson = require("flex-tools/package/getPackageJson");
797
+ var import_getPackageRootPath = require("flex-tools/package/getPackageRootPath");
818
798
  var import_glob = require("glob");
819
799
  var import_node_fs2 = __toESM(require("fs"));
820
800
  var import_node_path3 = __toESM(require("path"));
821
- var import_getPackageJson = require("flex-tools/package/getPackageJson");
822
801
  function getMatchedDependencies(entry) {
823
802
  const pacakgeMacher = this.options.include;
824
803
  if (!(pacakgeMacher instanceof RegExp))
@@ -850,8 +829,12 @@ function findCliPaths(packageName, entry) {
850
829
  const excludeMacher = this.options.exclude;
851
830
  if (!includeMacher)
852
831
  return [];
853
- const packageRoot = (0, import_flex_tools.getPackageRootPath)(entry || process.cwd());
832
+ const packageRoot = (0, import_getPackageRootPath.getPackageRootPath)(entry || process.cwd());
854
833
  const packagePath = packageName ? import_node_path3.default.dirname(require.resolve(packageName, { paths: [packageRoot] })) : packageName;
834
+ if (!packagePath) {
835
+ outputDebug("MixCli\u53EA\u80FD\u8FD0\u884C\u5728Nodejs\u73AF\u5883");
836
+ return [];
837
+ }
855
838
  const packageNames = getMatchedDependencies.call(this, packagePath);
856
839
  const cliDirs = [];
857
840
  if (entry !== void 0)
@@ -878,22 +861,6 @@ function findCliPaths(packageName, entry) {
878
861
  });
879
862
  return [...new Set(cliDirs)];
880
863
  }
881
- function importModule(file) {
882
- return __async(this, null, function* () {
883
- let module2;
884
- try {
885
- module2 = require(file);
886
- } catch (e) {
887
- try {
888
- const cmd = yield import(`file://${file}`);
889
- module2 = cmd.default;
890
- } catch (e2) {
891
- throw e2;
892
- }
893
- }
894
- return module2;
895
- });
896
- }
897
864
  function findCommands(cli) {
898
865
  return __async(this, null, function* () {
899
866
  const cliDirs = findCliPaths.call(cli);
@@ -936,6 +903,7 @@ function findCommands(cli) {
936
903
  // src/cli.ts
937
904
  var import_asyncSignal = require("flex-tools/async/asyncSignal");
938
905
  var import_string_prototype = __toESM(require("string.prototype.replaceall"));
906
+ var import_getPackageJson2 = require("flex-tools/package/getPackageJson");
939
907
  import_string_prototype.default.shim();
940
908
  var MixCli = class extends import_liteEvent.LiteEvent {
941
909
  constructor(options) {
@@ -979,13 +947,17 @@ var MixCli = class extends import_liteEvent.LiteEvent {
979
947
  }
980
948
  });
981
949
  }
950
+ getVersion() {
951
+ const packageInfo = (0, import_getPackageJson2.getPackageJson)();
952
+ return packageInfo.version;
953
+ }
982
954
  /**
983
955
  * 创建根命令
984
956
  *
985
957
  */
986
958
  createRootCommand() {
987
959
  this.root = new MixCommand(this.name);
988
- this.root.helpOption("-h, --help").version(require_package().version, "-v, --version").action(() => {
960
+ this.root.helpOption("-h, --help").version(this.getVersion(), "-v, --version").action(() => {
989
961
  if (this.options.logo)
990
962
  import_logsets2.default.log(fixIndent(this.options.logo, 2));
991
963
  console.log();
@@ -1141,6 +1113,8 @@ var MixCli = class extends import_liteEvent.LiteEvent {
1141
1113
  createFileByTemplate,
1142
1114
  fileExists,
1143
1115
  fixIndent,
1116
+ getId,
1117
+ importModule,
1144
1118
  isDebug,
1145
1119
  isEnablePrompts,
1146
1120
  mkDirs,
@@ -1148,6 +1122,7 @@ var MixCli = class extends import_liteEvent.LiteEvent {
1148
1122
  outputDebug,
1149
1123
  outputStr,
1150
1124
  readFile,
1125
+ showError,
1151
1126
  writeFile
1152
1127
  });
1153
1128
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../package.json","../src/index.ts","../src/cli.ts","../src/command.ts","../src/option.ts","../src/utils.ts","../src/prompt.ts","../src/finder.ts"],"sourcesContent":["{\n \"name\": \"mixcli\",\n \"version\": \"3.0.3\",\n \"description\": \"Develop command line tool scaffolding for monorepo\",\n \"repository\": \"https://github.com/zhangfisher/mixcli.git\",\n \"homepage\": \"https://zhangfisher.github.io/mixcli/\",\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"scripts\": {\n \"build\": \"tsup\",\n \"build:watch\": \"tsup --watch\",\n \"release\": \"npm publish\"\n },\n \"files\": [\n \"dist\",\n \"src\",\n \"readme.md\",\n \"package.json\"\n ],\n \"keywords\": [],\n \"author\": \"\",\n \"license\": \"ISC\",\n \"dependencies\": {\n \"@types/prompts\": \"^2.4.4\",\n \"@voerkai18n/runtime\": \"^2.0.8\",\n \"art-template\": \"^4.13.2\",\n \"commander\": \"^12.0.0\",\n \"flex-tools\": \"^1.3.60\",\n \"fs-extra\": \"^11.1.1\",\n \"glob\": \"^10.3.12\",\n \"logsets\": \"^1.3.8\",\n \"prompts\": \"^2.4.2\",\n \"string.prototype.replaceall\": \"^1.0.7\"\n },\n \"devDependencies\": {\n \"@types/fs-extra\": \"^11.0.1\",\n \"@types/node\": \"^20.5.7\",\n \"typescript\": \"^5.2.2\"\n }\n}\n","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 } 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}\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 .version(require(\"../package.json\").version,\"-v, --version\") \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}","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 { getPackageRootPath } from 'flex-tools';\r\nimport type { MixCli } from './cli';\r\nimport { globSync } from 'glob'\r\nimport { MixCliCommand } from './cli';\r\nimport { isDebug, outputDebug } from './utils';\r\nimport fs from \"node:fs\"\r\nimport path from \"node:path\"\r\nimport { getPackageJson } from \"flex-tools/package/getPackageJson\"\r\nimport { fileURLToPath } from 'node:url';\r\nimport { createRequire } from 'node:module';\r\n\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]})) : packageName!\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\nfunction 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\nasync 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\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 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":["module","import_logsets","import_commander","logsets","fs","path","artTemplate","import_node_path","path","fs","prompts","command","import_node_fs","import_node_path","path","fs","module","e","path","fs","replaceAll","logsets","cmd"]}
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 private getVersion(){\n const packageInfo = getPackageJson()\n return packageInfo.version\n }\n /**\n * 创建根命令\n * \n */\n private createRootCommand(){\n this.root = new MixCommand(this.name);\n this.root \n .helpOption('-h, --help') \n .version(this.getVersion(),\"-v, --version\") \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]})) : packageName!\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 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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCA,oBAAO;AACP,uBAA+C;AAE/C,IAAAA,kBAAqB;AAErB,0BAA6B;;;ACN7B,IAAAC,oBAAgC;AAChC,qBAAsC;;;ACDtC,uBAAuB;;;ACAvB,0BAAwB;AACxB,sBAAe;AACf,uBAAkB;AAClB,uBAA4B;AAC5B,qBAAoB;AAsBb,SAAS,UAAU,KAAW,MAAiC;AAClE,iBAAAC,QAAQ,IAAI,UAAU,GAAG,GAAE,IAAI;AACnC;AASO,SAAS,UAAU,MAAY,QAAgC;AAClE,MAAI,cAAe,UAAQ,UAAa,WAAS,OAAQ,IAAK,OAAO,UAAS,WAAW,SAAS;AAClG,MAAG,eAAa;AAAI,WAAO;AAC3B,MAAI,QAAiB,KAAK,MAAM,IAAI;AACpC,MAAI,gBAAgB,MAAM,OAAe,CAAC,UAAS,MAAK,UAAQ;AAzCpE;AA0CQ,QAAG,SAAO;AAAG,aAAO;AACpB,UAAM,eAAa,UAAK,MAAM,MAAM,MAAjB,mBAAqB,GAAG,WAAU;AACrD,WAAO,KAAK,IAAI,UAAS,UAAU;AAAA,EACvC,GAAE,IAAI;AACN,UAAQ,MAAM,IAAI,UAAM,KAAK,UAAU,aAAa,CAAC;AACrD,SAAO,MAAM,KAAK,IAAI;AAC1B;AAMO,SAAS,kBAAkB,SAAY;AAC1C,UAAQ,OAAO,2BAA0B,wCAAS,EAAC,QAAO,MAAK,UAAS,MAAK,UAAS,MAAK,QAAO,MAAK,CAAC;AACxG,UAAQ,OAAO,qBAAoB,oDAAW,EAAC,QAAO,MAAK,QAAO,MAAK,CAAC;AACxE,UAAQ,OAAO,eAAc,wCAAS,EAAC,QAAO,MAAK,QAAO,MAAK,CAAC;AACpE;AAMO,SAAS,UAAS;AACrB,SAAO,QAAQ,KAAK,SAAS,aAAa;AAC9C;AACO,SAAS,kBAAiB;AAC7B,SAAO,CAAC,QAAQ,KAAK,SAAS,mBAAmB;AACrD;AAOO,SAAS,YAAY,YAAkB,MAAW;AACrD,MAAI,OAAQ,KAAK,UAAU,KAAK,OAAO,KAAK,CAAC,KAAI,aAAc,KAAK,CAAC,EAAE,IAAI;AAC3E,MAAG,QAAQ;AAAG,mBAAAA,QAAQ,IAAI,YAAY,OAAO,IAAG,GAAG,IAAI;AAC3D;AAEO,IAAM,iBAAa,4BAAU,gBAAAC,QAAG,QAAO;AAAA,EAC1C,eAAc,CAAC,YAAU;AACrB,WAAO,QAAQ,CAAC;AAAA,EACpB;AACJ,CAAC;AACM,IAAM,eAAW,4BAAU,gBAAAA,QAAG,QAAQ;AACtC,IAAM,gBAAY,4BAAU,gBAAAA,QAAG,SAAS;AACxC,IAAM,YAAQ,4BAAU,gBAAAA,QAAG,KAAK;AAQvC,SAAsB,qBAAqB,IAAkB,IAA2C;AAAA,6CAA7D,YAAkB,UAAgB,OAAwB,CAAC,GAAE;AACpG,eAAS,iBAAAC,QAAK,WAAW,QAAQ,IAAG,WAAW,iBAAAA,QAAK,KAAK,QAAQ,IAAI,GAAE,QAAQ;AAC/E,QAAG,CAAC,gBAAAD,QAAG,WAAW,QAAQ,GAAE;AACxB,YAAM,IAAI,MAAM,gDAAW,QAAQ;AAAA,IACvC;AACA,iBAAW,iBAAAC,QAAK,WAAW,UAAU,IAAG,aAAa,iBAAAA,QAAK,KAAK,QAAQ,IAAI,GAAE,UAAU;AACvF,UAAM,UAAU,iBAAAA,QAAK,QAAQ,UAAU;AACvC,QAAG,EAAC,MAAM,WAAW,OAAO,IAAE;AAC1B,YAAM,MAAM,SAAQ,EAAC,WAAU,KAAI,CAAC;AAAA,IACxC;AACA,UAAM,eAAW,oBAAAC,SAAY,UAAS,MAAM,SAAS,UAAS,EAAC,UAAS,QAAO,CAAC,CAAC;AACjF,UAAM,UAAU,YAAW,SAAS,IAAI,GAAE,EAAC,UAAS,QAAO,CAAC;AAC5D,WAAO;AAAA,EACX;AAAA;AAWA,SAAsB,OAAO,IAAc,IAAkD;AAAA,6CAAhE,MAAc,EAAC,UAAS,KAAI,GAAoC;AACzF,QAAG,CAAC,MAAM,QAAQ,IAAI;AAAG,YAAM,IAAI,MAAM,kEAAgB;AACzD,aAAQ,OAAO,MAAK;AAChB,UAAG,CAAC,iBAAAD,QAAK,WAAW,GAAG;AAAG,cAAM,iBAAAA,QAAK,KAAK,QAAQ,QAAQ,IAAI,GAAE,GAAG;AACnE,UAAG,OAAO,YAAW;AAAY,iBAAS,GAAG;AAC7C,YAAM,MAAM,KAAI,EAAC,WAAU,KAAI,CAAC;AAAA,IACpC;AAAA,EACJ;AAAA;AAEO,SAAS,UAAU,GAAM;AAC5B,MAAG,QAAQ,GAAE;AACT,gBAAY,6CAAc,EAAE,KAAK;AAAA,EACrC,OAAK;AACD,YAAQ,MAAM,CAAC;AAAA,EACnB;AAEJ;AAGO,SAAS,QAAO;AACnB,SAAO,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,CAAC;AAC9C;AAGA,SAAsB,aAAa,MAAY;AAAA;AAC3C,QAAIE;AACJ,QAAG;AACC,MAAAA,UAAS,QAAQ,IAAI;AAAA,IACzB,SAAO,GAAM;AACT,UAAG;AACC,cAAM,MAAM,MAAM,OAAO,UAAU,IAAI;AACvC,QAAAA,UAAS,IAAI;AAAA,MACjB,SAAOC,IAAM;AACT,cAAMA;AAAA,MACV;AAAA,IACJ;AACA,WAAOD;AAAA,EACX;AAAA;;;ACnJO,IAAM,gBAAsC;AAAA,EAC/C,SAAQ;AAAA,EACR,QAAO;AAAA,EACP,QAAO;AAAA,EACP,OAAM;AACV;AAEO,IAAM,uBAAuB,CAAC,QAAO,YAAW,aAAa,UAAU,WAAY,QAAQ,UAAW,UAAW,eAAgB,gBAAiB,QAAS,yBAAyB;AAgDpL,IAAM,gBAAN,MAAmB;AAAA;AAAA,EAGtB,YAAY,YAAuB,YAA6B;AAC5D,SAAK,cAAc;AACnB,SAAK,OAAM,eAAa,SAAY,SAAS;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAQ,MAAS;AACb,WAAQ,qBAAqB,SAAS,OAAO,IAAI,CAAC;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,OAAU,cAAkB;AAE/B,UAAM,YAAY,KAAK;AACvB,UAAM,aAAa,SAAS;AAE5B,UAAM,WAAW,EAAE,eAAe;AAElC,QAAG,cAAY;AAAM,aAAO;AAC5B,QAAG,cAAY;AAAO,aAAO;AAG7B,QAAG,OAAO,aAAY,UAAS;AAC3B,aAAO,CAAC;AAAA,IACZ;AAGA,QAAG,OAAO,aAAc,YAAY,qBAAqB,SAAS,SAAS,GAAE;AACzE,aAAQ,CAAC;AAAA,IACb;AAGA,QAAG,KAAK,YAAY,cAAc,KAAK,YAAY,WAAW,QAAQ,UAAU,KAAK,IAAG;AACpF,aAAO;AAAA,IACX;AACA,WAAO,CAAC;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,YAAgB;AAChB,UAAM,EAAC,aAAY,eAAc,UAAS,aAAY,IAAI,KAAK;AAC/D,QAAI,QAAQ,cAAc;AAE1B,QAAG,CAAC,KAAK,OAAO,OAAM,YAAY;AAAG;AAErC,QAAI,aAAa,KAAK,MAAM,UAAU;AACtC,UAAM,SAAS;AAAA,MACX,MAAK;AAAA,MACL,MAAK,KAAK,YAAY,KAAK;AAAA,MAC3B,SAAQ;AAAA,MACR,SAAS;AAAA,OACN,OAAO,KAAK,QAAS,WAAW,KAAK,OAAO,CAAC;AAGpD,WAAO,WAAW,qCAAU,KAAK,KAAK;AACtC,QAAG,cAAY;AAAe,aAAO,eAAa;AAClD,QAAG,CAAC,UAAS,aAAa,EAAE,SAAS,UAAU,GAAE;AAC7C,UAAI,QAAQ,+CAAe,UAAU,UAAM,KAAK,SAAO;AACvD,aAAO,UAAU,SAAO,KAAK,SAAY;AAAA,IAC7C;AAEA,QAAG,MAAM,QAAQ,aAAa,GAAG;AAC7B,aAAO,UAAS;AAAA,IACpB;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,YAAgB;AAClB,UAAM,EAAC,YAAW,UAAS,aAAY,IAAI,KAAK;AAChD,QAAI,QAAQ,cAAc;AAE1B,QAAI,aAAa,8BAA8B,KAAK,KAAK,YAAY,KAAK,IAAI,SAAS;AACvF,QAAI,YAAY,KAAK;AACrB,QAAG,KAAK,QAAQ,SAAS,GAAE;AACvB,mBAAa;AAAA,IACjB,OAAK;AACD,UAAG,OAAO,aAAY,UAAS;AAC3B,qBAAa,UAAU;AAAA,MAC3B,OAAK;AACD,YAAG,YAAW;AACV,uBAAa,WAAW,gBAAgB;AAAA,QAC5C,OAAK;AACD,gBAAM,WAAkB,MAAM,QAAQ,YAAY,IAAI,UAAU,OAAO;AAEvE,cAAG,MAAM,QAAQ,KAAK,KAAK,UAAS;AAChC,yBAAa;AAAA,UACjB,OAAK;AACD,gBAAG,YAAY,eAAc;AACzB,2BAAa,cAAc,QAAQ;AAAA,YACvC;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AACA,gBAAY,oDAAqB,CAAC,KAAK,YAAY,KAAK,GAAE,UAAU,CAAC;AACrE,WAAO;AAAA,EACX;AAEJ;;;AFlKO,IAAM,YAAN,cAAwB,wBAA6B;AAAA,EAKxD,YAAY,OAAe,aAAiC,eAAoB;AAC5E,UAAM,OAAO,WAAW;AACxB,QAAI,SAA2B,CAAC;AAChC,QAAG,UAAU,UAAQ,KAAK,OAAO,UAAU,CAAC,KAAK,UAAS;AACtD,eAAS,OAAO,OAAO,CAAE,GAAE,UAAU,CAAC,CAAC;AAAA,IAC3C,WAAS,UAAU,UAAQ,GAAE;AACzB,aAAO,UAAU,UAAU,CAAC;AAAA,IAChC;AACA,QAAG,OAAO,WAAS;AAAW,aAAO,SAAS;AAC9C,QAAG,OAAO;AAAS,WAAK,QAAQ,OAAO,SAAQ,OAAO,kBAAkB;AACxE,QAAG,OAAO;AAAS,WAAK,QAAQ,OAAO,OAAO;AAC9C,QAAG,OAAO;AAAW,WAAK,UAAU,OAAO,SAAS;AACpD,QAAG,OAAO;AAAK,WAAK,IAAI,OAAO,GAAG;AAClC,QAAG,OAAO;AAAW,WAAK,UAAU,OAAO,SAAS;AACpD,QAAG,OAAO;AAAU,WAAK,SAAS,OAAO,QAAQ;AACjD,QAAG,OAAO;AAAQ,WAAK,SAAS,OAAO;AACvC,QAAG,OAAO;AAAW,WAAK,oBAAoB,OAAO,SAAS;AAC9D,QAAG,OAAO;AAAS,WAAK,QAAQ,OAAO,OAAO;AAC9C,QAAG,OAAO;AAAU,WAAK,WAAS,OAAO;AACzC,QAAG,OAAO,OAAO,YAAW;AAAY,WAAK,YAAY,OAAO,SAAS,KAAK,IAAI;AAClF,QAAG,OAAO,UAAU;AAChB,WAAK,WAAW,OAAO;AACvB,UAAG,CAAC,KAAK;AAAY,aAAK,YAAa,CAAC,UAAY,OAAO,KAAK,EAAE,SAAO;AAAA,IAC7E;AACA,SAAK,SAAS,IAAI,cAAc,MAAoB,OAAO,MAAM;AAAA,EACrE;AAAA,EACA,SAAS,OAAqB;AAC1B,QAAG,OAAO,KAAK,aAAY,YAAW;AAClC,aAAO,KAAK,UAAU,KAAK;AAAA,IAC/B,OAAK;AACD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA,EAEA,QAAQ,QAAiC;AACrC,QAAG,CAAC,KAAK,eAAc;AACnB,WAAK,gBAAgB,OAAO,IAAI,YAAQ;AACpC,YAAG,OAAO,UAAS,UAAS;AACxB,iBAAO;AAAA,QACX,OAAK;AACD,iBAAO,EAAC,OAAM,QAAO,OAAM,OAAM;AAAA,QACrC;AAAA,MACJ,CAAC;AAAA,IACL;AACA,UAAM,QAAQ,KAAK,cAAc,IAAI,CAAC,SAAW,KAAK,KAAK,CAAC;AAAA,EAChE;AAAA,EAEQ,eAAc;AAClB,UAAM,QAAQ,KAAK,cAAe,IAAI,CAAC,SAAW,KAAK,KAAK,CAAC;AAAA,EACjE;AAAA,EAEA,UAAU,OAA4B;AAClC,QAAG,CAAC,KAAK,iBAAiB,CAAC,MAAM,QAAQ,KAAK,aAAa;AAAG,WAAK,gBAAgB,CAAC;AACpF,SAAK,cAAe,KAAK,OAAO,SAAQ,WAAW,EAAC,OAAM,OAAM,MAAK,IAAI,KAAK;AAC9E,SAAK,aAAa;AAAA,EACtB;AAAA,EACA,aAAa,OAAU;AA9E3B;AA+EQ,SAAK,iBAAe,UAAK,kBAAL,mBAAoB,OAAO,YAAQ,OAAO,UAAQ;AACtE,SAAK,aAAa;AAAA,EACtB;AAAA,EACA,cAAa;AACT,SAAK,gBAAgB,CAAC;AACtB,SAAK,aAAa;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,UAAU,YAA2C;AAlGzD;AAmGQ,YAAO,UAAK,WAAL,mBAAa,IAAI;AAAA,EAC5B;AACJ;;;ADjGA,IAAAE,oBAAiB;AACjB,qBAAe;AA6DR,IAAM,QAAQ,OAAO,cAAc;AAEnC,IAAM,aAAN,cAAyB,0BAAQ;AAAA;AAAA,EAOvC,YAAY,MAAe;AAC1B,UAAM,IAAI;AAPX,SAAQ,eAAuD,CAAC;AAChE,SAAQ,cAAqD,CAAC;AAC9D,SAAQ,iBAAiC,CAAC;AAC1C,SAAQ,gBAAqC,CAAC;AAC9C;AAAA,SAAQ,WAA6B,CAAC;AACtC;AAAA,SAAQ,kBAA2B;AAGlC,UAAM,OAAO;AACb,QAAI,CAAC,KAAK;AAAQ,wBAAkB,IAAI;AACxC,SAAK,KAAK,aAAa,WAA2B;AAAA;AACjD,aAAK,gBAAgB,KAAK,gBAAgB,KAAK,aAAa;AAC5D,YAAI;AAEH,gBAAM,KAAK,cAAc,MAAM,MAAM,SAAS;AAAA,QAC/C,SAAQ;AAAA,QAAC;AAAA,MACV;AAAA,KAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAIA,IAAI,SAAS;AACZ,WAAO,CAAC,CAAC,CAAC,KAAK;AAAA,EAChB;AAAA,EACA,IAAI,UAAU;AACb,WAAO,KAAK;AAAA,EACb;AAAA,EACA,IAAI,cAAc;AACjB,WAAO,KAAK;AAAA,EACb;AAAA,EACA,IAAI,aAAa;AAChB,WAAO,KAAK;AAAA,EACb;AAAA,EACA,IAAI,WAAW;AACd,QAAI,QAAQ,CAAC,KAAK,KAAK,CAAC;AACxB,QAAI,SAAS,KAAK;AAClB,WAAO,QAAQ;AACd,UAAI,OAAO,KAAK,MAAM,QAAQ;AAC7B,cAAM,QAAQ,OAAO,KAAK,CAAC;AAAA,MAC5B;AACA,eAAS,OAAO;AAAA,IACjB;AACA,WAAO,MAAM,KAAK,GAAG;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO;AACN,QAAI,OAAsC;AAC1C,WAAO,QAAQ,KAAK,UAAU,MAAM;AACnC,aAAO,KAAK;AAAA,IACb;AACA,WAAO;AAAA,EACR;AAAA,EAGA,OAAO,IAA0B;AAChC,UAAM,aAAa,UAAU,CAAC;AAC9B,QAAI,UAAU,UAAU,KAAK,OAAO,cAAc,YAAY;AAE7D,WAAK,SAAS,KAAK;AAAA,QAClB,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,CAAC;AAAA,QAC1C,SAAS;AAAA,QACT,IAAI;AAAA,MACL,CAAC;AAAA,IACF,WACC,UAAU,UAAU,KACpB,OAAO,cAAc,cACrB,OAAO,UAAU,CAAC,KAAK,UACtB;AAED,YAAM,WAAW,UAAU,CAAC;AAC5B,YAAM,aAA4B,OAAO,OAAO,EAAE,IAAI,SAAS,GAAG,UAAU,CAAC,CAAC;AAC9E,UAAI,WAAW,MAAM;AAAW,aAAK,WAAW,CAAC;AACjD,YAAM,aAAa;AAAA,QAClB,IAAI,WAAW,MAAM,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,CAAC;AAAA,QAC3D,SAAS,WAAW,WAAW,SAAY,OAAO,WAAW;AAAA,QAC7D,IAAI;AAAA,MACL;AACA,UAAI,OAAO,WAAW,MAAM,UAAU;AACrC,aAAK,SAAS,OAAO,OAAO,WAAW,EAAE,GAAG,GAAG,UAAU;AAAA,MAC1D,WAAW,CAAC,UAAU,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG;AACxD,aAAK,SAAS,KAAK,UAAU;AAAA,MAC9B,WAAW,CAAC,aAAa,OAAO,EAAE,SAAS,WAAW,EAAE,GAAG;AAC1D,aAAK,SAAS,OAAO,GAAG,GAAG,UAAU;AAAA,MACtC,OAAO;AACN,aAAK,SAAS,KAAK,UAAU;AAAA,MAC9B;AAAA,IACD,OAAO;AACN,cAAQ,IAAI,8BAA8B;AAAA,IAC3C;AACA,WAAO,MAAM,OAAO,KAAK,mBAAmB,CAAC;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,gBAAgB,SAAkB;AACzC,QAAI,OAAO,CAAC;AACZ,QAAI,SAAyB;AAC7B,WAAO,QAAQ;AACd,aAAO,OAAO,MAAO,OAAsB,aAAa;AACxD,eAAS,OAAO;AAAA,IACjB;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAIQ,qBAAqB;AAC5B,WAAO,KAAK,sBAAsB,KAAK,oBAAoB,CAAC;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA,EAKQ,sBAAoC;AAC3C,QAAI,OAAqB,CAAC;AAC1B,QAAI,MAAyB;AAC7B,WAAO,KAAK;AACX,YAAM,IAAI;AACV,UAAI,KAAK;AACR,aAAK,KAAK,GAAG;AAAA,MACd;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAIQ,sBAAsB;AAC7B,UAAM,OAAO;AACb,WAAO,WAA2B;AAAA;AACjC,cAAM,OAAO,MAAM,KAAK,SAAS;AACjC,YAAI;AAEJ,YAAI,aAAkC,CAAC,GACtC,aAAoB,CAAC,GACrB;AACD,YAAI,KAAK,UAAU,GAAG;AACrB,gBAAM,KAAK,KAAK,SAAS,CAAC;AAC1B,uBAAa,KAAK,KAAK,SAAS,CAAC;AACjC,uBAAa,KAAK,MAAM,GAAG,KAAK,SAAS,CAAC;AAAA,QAC3C;AACA,cAAM,KAAK,mBAAmB,EAAE,MAAM,YAAY,SAAS,YAAY,SAAS,IAAI,CAAC;AACrF,YAAI;AACH,mBAAS,UAAU,KAAK,UAAU;AACjC,gBAAI;AACH,kBAAI,OAAO,SAAS;AAEnB,4BAAY,yCAA+B,MAAM;AAAA,kBAChD,KAAK,KAAK;AAAA,kBACV;AAAA,kBACA;AAAA,gBACD,CAAC;AACD,2BAAW,MAAM,OAAO,GAAG,KAAK,MAAM;AAAA,kBACrC,SAAS;AAAA,kBACT,OAAO;AAAA,kBACP,MAAM;AAAA,kBACN,SAAS;AAAA,gBACV,CAAC;AAAA,cACF,OAAO;AAEN,2BAAW,MAAM,OAAO,GAAG,MAAM,MAAM,IAAI;AAAA,cAC5C;AACA,kBAAI,aAAa;AAAO;AAAA,YACzB,SAAS,GAAG;AACX,0BAAY,6DAA0B,CAAC,KAAK,MAAM,OAAO,IAAI,CAAC,CAAC;AAC/D,oBAAM;AAAA,YACP;AAAA,UACD;AAAA,QACD,UAAE;AACD,gBAAM,KAAK,kBAAkB;AAAA,YAC5B,OAAO;AAAA,YACP,MAAM;AAAA,YACN,SAAS;AAAA,YACT,SAAS;AAAA,UACV,CAAC;AAAA,QACF;AAAA,MACD;AAAA;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAIQ,sBAAsB,IAAmB;AAChD,UAAM,OAAO;AACb,WAAO,WAA2B;AAAA;AACjC,YAAI,WAAW,KAAK,cAAc;AAElC,YAAI,CAAC,UAAU;AACd,iBAAO,MAAM,GAAG,MAAM,MAAM,MAAM,KAAK,SAAS,CAAC;AAAA,QAClD;AACA,YAAI,CAAC,MAAM,QAAQ,QAAQ;AAAG,qBAAW,SAAS,MAAM,GAAG;AAC3D,mBAAW,SAAS,OAAO,CAAC,MAAa,QAAgB;AACxD,cAAI,OAAO,OAAO;AAAU,iBAAK,KAAK,GAAG,IAAI,MAAM,GAAG,CAAC;AACvD,iBAAO;AAAA,QACR,GAAG,CAAC,CAAC;AACL,iBAAS,WAAW,UAAU;AAC7B,gBAAM,MAAM,QAAQ,IAAI;AACxB,cAAI;AACH,gBAAI,CAAC,kBAAAC,QAAK,WAAW,OAAO;AAAG,wBAAU,kBAAAA,QAAK,KAAK,KAAK,OAAO;AAC/D,gBAAI,eAAAC,QAAG,WAAW,OAAO,KAAK,eAAAA,QAAG,SAAS,OAAO,EAAE,YAAY,GAAG;AACjE,0BAAY,iDAAc,OAAO;AACjC,sBAAQ,MAAM,OAAO;AACrB,oBAAM,GAAG,MAAM,MAAM,MAAM,KAAK,SAAS,CAAC;AAAA,YAC3C,OAAO;AACN,0BAAY,iDAAc,OAAO;AAAA,YAClC;AAAA,UACD,SAAS,GAAG;AACX,kBAAM;AAAA,UACP,UAAE;AACD,oBAAQ,MAAM,GAAG;AAAA,UAClB;AAAA,QACD;AAAA,MACD;AAAA;AAAA,EACD;AAAA,EACA,UAAU,MAAyB;AAClC,WAAO,KAAK,QAAQ,KAAK,CAAC,WAAW,OAAO,KAAK,KAAK,IAAI;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,UAAqC,QAAiB,MAAM;AAClE,SAAK,aAAa,KAAK,CAAC,UAAU,KAAK,CAAC;AACxC,WAAO;AAAA,EACR;AAAA,EACc,mBAAmB,MAAW;AAAA;AAC3C,YAAM,QAA4D,KAAK,YAAY;AAAA,QAClF,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,OAAO,IAAI;AAAA,MACtC;AACA,WAAK,oBAAoB,EAAE,QAAQ,CAAC,QAAoB;AACvD,cAAM;AAAA,UACL,GAAG,IAAI,YAAY,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;AACzC,mBAAO,CAAC,MAAM,OAAO,GAAG;AAAA,UACzB,CAAC;AAAA,QACF;AAAA,MACD,CAAC;AACD,eAAS,CAAC,MAAM,OAAO,GAAG,KAAK,OAAO;AACrC,YAAI,CAAC;AAAO;AACZ,cAAM,KAAK,KAAK,KAAK,IAAI;AAAA,MAC1B;AAAA,IACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,UAAoC,QAAiB,MAAM;AAChE,SAAK,YAAY,KAAK,CAAC,UAAU,KAAK,CAAC;AACvC,WAAO;AAAA,EACR;AAAA,EACc,kBAAkB,MAAW;AAAA;AAC1C,YAAM,QAA2D,KAAK,WAAW;AAAA,QAChF,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,OAAO,IAAI;AAAA,MACtC;AACA,WAAK,oBAAoB,EAAE,QAAQ,CAAC,QAAoB;AACvD,cAAM;AAAA,UACL,GAAG,IAAI,WAAW,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;AACxC,mBAAO,CAAC,MAAM,OAAO,GAAG;AAAA,UACzB,CAAC;AAAA,QACF;AAAA,MACD,CAAC;AACD,eAAS,CAAC,MAAM,OAAO,GAAG,KAAK,OAAO;AACrC,YAAI,CAAC;AAAO;AACZ,cAAM,KAAK,KAAK,KAAK,IAAI;AAAA,MAC1B;AAAA,IACD;AAAA;AAAA,EACc,cAAc,aAAsB,eAAwB;AAAA;AACzE,UAAI,KAAK,gBAAgB,GAAG;AAE3B,cAAM,YAA4B;AAAA,UACjC,GAAG,KAAK,oBAAoB;AAAA,UAC5B,GAAG,KAAK;AAAA,QACT;AAEA,YAAI,UAAU,SAAS,GAAG;AACzB,gBAAM,UAAU,UAAM,eAAAC,SAAQ,SAAS;AACvC,iBAAO,QAAQ,OAAO,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AACjD,wBAAY,eAAe,KAAK,KAAK;AAAA,UACtC,CAAC;AAAA,QACF;AAAA,MACD;AAAA,IACD;AAAA;AAAA,EAEQ,kBAAkB;AACzB,QAAI,gBAAgB,MAAM,OAAO;AAEhC,aAAO;AAAA,IACR,OAAO;AACN,aAAO,KAAK;AAAA,IACb;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYQ,sBAAsC;AAC7C,UAAM,UAAU,KAAK;AACrB,UAAM,kBAAkB,QACtB,OAAO,CAAC,WAAW,CAAC,OAAO,UAAU,kBAAkB,SAAS,EAChE,IAAI,CAAC,WAAW,OAAO,UAAU,KAAK,cAAc,OAAO,KAAK,CAAC,CAAC,CAAC,EACnE,OAAO,CAAC,WAAW,MAAM;AAC3B,gBAAY,+EAAwB;AAAA,MACnC,KAAK,KAAK;AAAA,MACV,gBAAgB;AAAA,MAChB,gBAAgB,IAAI,CAAC,WAAW,GAAG,OAAO,IAAI,IAAI,OAAO,IAAI,GAAG,EAAE,KAAK,GAAG;AAAA,IAC3E,CAAC;AACD,WAAO;AAAA,EACR;AAAA,EAEA,OAAO,OAAe,aAAkC,SAAmC;AAE1F,UAAM,SAAS,IAAI,UAAU,GAAG,SAAS;AACzC,QAAI,OAAO,YAAY,CAAC,KAAK,gBAAgB;AAAG,aAAO,YAAY;AACnE,WAAO,KAAK,UAAU,MAA2B;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,OAAO,WAA0C;AAChD,SAAK,eAAe,KAAK,GAAI,MAAM,QAAQ,SAAS,IAAI,YAAY,CAAC,SAAS,CAAE;AAChF,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUM,iBAAiB;AAAA;AACtB,YAAM,UAAU,KAAK,SAAS,IAAI,CAACC,cAAa;AAAA,QAC/C,OAAO,GAAGA,SAAQ,YAAY,CAAC,IAAIA,SAAQ,KAAK,CAAC;AAAA,QACjD,OAAOA,SAAQ,KAAK;AAAA,MACrB,EAAE;AACF,YAAM,SAAS,UAAM,eAAAD,SAAQ;AAAA,QAC5B,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,QACT;AAAA,MACD,CAAC;AAED,YAAM,UAAU,KAAK,SAAS,KAAK,CAACC,aAAYA,SAAQ,KAAK,MAAM,OAAO,OAAO;AACjF,YAAM,mCAAS,WAAW,CAAC,OAAO,OAAO,GAAG,EAAE,MAAM,OAAO;AAAA,IAC5D;AAAA;AAAA;AAAA;AAAA;AAAA,EAIA,iBAAiB;AAChB,SAAK,kBAAkB;AACvB,WAAO;AAAA,EACR;AAAA,EACA,gBAAgB;AACf,SAAK,kBAAkB;AACvB,WAAO;AAAA,EACR;AACD;;;AIlcA,4BAAgC;AAChC,gCAAmC;AAEnC,kBAA0B;AAG1B,IAAAC,kBAAe;AACf,IAAAC,oBAAiB;AAeV,SAAS,uBAAmC,OAAsB;AACrE,QAAM,gBAAgB,KAAK,QAAQ;AACnC,MAAG,EAAE,yBAAyB;AAAS,WAAQ,CAAC;AAGhD,QAAM,EAAE,eAAa,CAAC,GAAE,kBAAgB,CAAC,GAAE,mBAAiB,CAAC,GAAE,uBAAqB,CAAC,GAAE,qBAAmB,CAAC,EAAE,QAAI,sCAAe,KAAK;AACrI,QAAM,eAAe;AAAA,IACjB,GAAG,OAAO,KAAK,YAAY;AAAA,IAC3B,GAAG,OAAO,KAAK,eAAe;AAAA,IAC9B,GAAG,OAAO,KAAK,gBAAgB;AAAA,IAC/B,GAAG,OAAO,KAAK,oBAAoB;AAAA,IACnC,GAAG,OAAO,KAAK,kBAAkB;AAAA,EACrC;AACA,SAAO,aAAa,OAAO,UAAM,SAAO,iBAAiB,cAAc,KAAK,IAAI,CAAC;AACrF;AAEA,SAAS,UAAU,KAAW,KAAmD;AAE7E,QAAM,UAAU,MAAO,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,GAAG,IAAK,CAAC;AAC5D,SAAO,QAAQ,KAAK,YAAQ;AACxB,QAAG,OAAO,WAAW,UAAS;AAC1B,aAAQ,IAAI,OAAO,MAAM,EAAG,KAAK,GAAG;AAAA,IACxC,WAAS,kBAAkB,QAAO;AAC9B,aAAO,OAAO,KAAK,GAAG;AAAA,IAC1B,OAAK;AACD,aAAO;AAAA,IACX;AAAA,EACJ,CAAC;AACL;AAEO,SAAS,aAAyB,aAAqB,OAAuB;AACjF,QAAM,gBAAgB,KAAK,QAAQ;AACnC,QAAM,gBAAgB,KAAK,QAAQ;AACnC,MAAG,CAAC;AAAe,WAAO,CAAC;AAC3B,QAAM,kBAAc,8CAAmB,SAAS,QAAQ,IAAI,CAAC;AAC7D,QAAM,cAAc,cAAc,kBAAAC,QAAK,QAAQ,QAAQ,QAAQ,aAAY,EAAC,OAAM,CAAC,WAAqB,EAAC,CAAC,CAAC,IAAI;AAE/G,MAAG,CAAC,aAAa;AACb,gBAAY,wDAAsB;AAClC,WAAO,CAAC;AAAA,EACZ;AAGA,QAAM,eAAe,uBAAuB,KAAK,MAAK,WAAW;AAEjE,QAAM,UAAiB,CAAC;AAExB,MAAG,UAAQ;AAAW,YAAQ,KAAK,kBAAAA,QAAK,KAAK,aAAY,KAAK,QAAQ,MAAM,CAAC;AAC7E,eAAa,OAAO,UAAM;AAClB,WAAQ,UAAU,MAAK,aAAa,KAAK,CAAC,UAAU,MAAK,aAAa;AAAA,EAC1E,CAAC,EACA,QAAQ,UAAM;AACX,gBAAY,yBAAS,GAAG,cAAc,OAAK,SAAO,cAAe,IAAI,EAAE;AACvE,QAAG;AACC,YAAM,eAAe,kBAAAA,QAAK,QAAQ,QAAQ,QAAQ,MAAK,EAAC,OAAM,cAAc,CAAC,WAAW,IAAI,CAAC,QAAQ,IAAI,CAAC,EAAC,CAAC,CAAC;AAC7G,YAAM,gBAAe,kBAAAA,QAAK,KAAK,cAAa,KAAK,QAAQ,MAAO;AAEhE,UAAI,eAAe,uBAAuB,KAAK,MAAK,YAAY;AAChE,cAAQ,KAAK,GAAG,aAAa,OAAiB,CAAC,QAAO,gBAAc;AAChE,oBAAY,yBAAS,GAAG,WAAW,OAAO,IAAI,EAAE;AAChD,eAAO,KAAK,GAAG,aAAa,KAAK,MAAK,aAAY,YAAY,CAAC;AAC/D,eAAO;AAAA,MACX,GAAE,CAAC,CAAC,CAAC;AACL,UAAG,gBAAAC,QAAG,WAAW,aAAa,GAAE;AAC5B,gBAAQ,KAAK,aAAa;AAAA,MAC9B;AAAA,IACJ,SAAO,GAAM;AACT,kBAAY,0DAAiB,CAAC,MAAK,EAAE,KAAK,CAAC;AAAA,IAC/C;AAAA,EACJ,CAAC;AAEL,SAAO,CAAC,GAAG,IAAI,IAAI,OAAO,CAAC;AAC/B;AAUA,SAAsB,aAAa,KAAW;AAAA;AAC1C,UAAM,UAAW,aAAa,KAAK,GAAG;AACtC,UAAM,WAA2B,CAAC;AAClC,UAAM,QAAQ,CAAC;AACf,YAAQ,QAAQ,SAAK;AACjB,gCAAS,KAAI;AAAA,QACT,KAAI;AAAA,QACJ,UAAU;AAAA,MACd,CAAC,EAAE,QAAQ,CAAC,SAAc;AACtB,cAAM,MAAM,kBAAAD,QAAK,QAAQ,IAAI,EAAE,YAAY;AAC3C,YAAG,CAAC,OAAM,QAAO,MAAM,EAAE,SAAS,GAAG,GAAE;AACnC,gBAAM,KAAK,IAAI;AAAA,QACnB,WAAS,gBAAAC,QAAG,SAAS,IAAI,EAAE,YAAY,GAAE;AACrC,gBAAM,KAAK,kBAAAD,QAAK,KAAK,MAAK,UAAU,CAAC;AACrC,gBAAM,KAAK,kBAAAA,QAAK,KAAK,MAAK,WAAW,CAAC;AACtC,gBAAM,KAAK,kBAAAA,QAAK,KAAK,MAAK,WAAW,CAAC;AAAA,QAC1C;AAAA,MACJ,CAAC;AAAA,IACL,CAAC;AACD,aAAQ,QAAQ,OAAM;AACnB,UAAG,CAAC,gBAAAC,QAAG,WAAW,IAAI;AAAG;AACxB,UAAG;AACC,oBAAY,+BAAU,IAAI;AAC1B,YAAG,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,KAAK,GAAE;AAC7C,mBAAS,KAAK,MAAM,aAAa,IAAI,CAAC;AAAA,QAC1C,WAAS,KAAK,SAAS,MAAM,GAAE;AAC3B,gBAAM,MAAM,MAAM,OAAO,UAAU,IAAI;AACvC,mBAAS,KAAK,IAAI,OAAO;AAAA,QAC7B;AAAA,MACJ,SAAO,GAAM;AACT,oBAAY,CAAC;AAAA,MACjB;AAAA,IACJ;AACA,WAAO;AAAA,EACX;AAAA;;;ALhIA,yBAA4B;AAE5B,8BAAwB;AAExB,IAAAC,yBAA+B;AAC/B,wBAAAC,QAAW,KAAK;AAsCT,IAAM,SAAN,cAAqB,2BAA2B;AAAA,EAInD,YAAY,SAAuB;AAC/B,UAAM;AAFV,SAAQ,cAAkB,CAAC;AAGvB,SAAK,cAAS,kCAAa;AAAA,MACvB,MAAK;AAAA,MACL,SAAQ;AAAA,MACR,QAAO;AAAA,MACP,QAAO;AAAA,IACX,GAAE,OAAO;AACT,SAAK,kBAAkB;AAAA,EAC3B;AAAA,EACA,IAAI,UAAS;AAAC,WAAO,KAAK,QAAQ;AAAA,EAAO;AAAA,EACzC,IAAI,OAAM;AAAC,WAAO,KAAK,QAAQ;AAAA,EAAI;AAAA;AAAA;AAAA;AAAA,EAInC,IAAI,oBAAmB;AACnB,WAAO,KAAK,KAAa,QAAQ,SAAS,cAAc;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAIc,kBAAiB;AAAA;AAC3B,YAAM,SAAS,MAAM,aAAa,IAAI;AACtC,eAAQ,SAAS,QAAO;AACpB,YAAG;AACC,cAAG,OAAO,UAAS,YAAW;AAC1B,gBAAI,OAAO,MAAM,IAAI;AACrB,mBAAM,OAAS,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI,IAAK,CAAC;AACvD,iBAAK,SAAS,MAAI,IAAI;AAAA,UAC1B;AAAA,QACJ,SAAO,GAAM;AAAA,QACb;AAAA,MACJ;AAAA,IACJ;AAAA;AAAA,EACQ,aAAY;AAChB,UAAM,kBAAc,uCAAe;AACnC,WAAO,YAAY;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAAmB;AACvB,SAAK,OAAO,IAAI,WAAW,KAAK,IAAI;AACpC,SAAK,KACA,WAAW,YAAY,EACvB,QAAQ,KAAK,WAAW,GAAE,eAAe,EACzC,OAAO,MAAI;AACR,UAAG,KAAK,QAAQ;AAAM,wBAAAC,QAAQ,IAAI,UAAU,KAAK,QAAQ,MAAK,CAAC,CAAC;AAChE,cAAQ,IAAI;AAEZ,UAAI,QAAQ,KAAK,QAAQ,SAAQ,KAAK,QAAQ;AAC9C,UAAG,MAAM,QAAQ,KAAK,GAAE;AACpB,wBAAAA,QAAQ,IAAI,OAAO,MAAM,CAAC,CAAC,EAAE,WAAW,GAAE,CAAC,GAAG,MAAM,MAAM,CAAC,CAAC,CAAC;AAAA,MACjE,OAAK;AACD,wBAAAA,QAAQ,IAAI,GAAG,MAAM,WAAW,CAAC,sBAAqB,KAAK,QAAQ,OAAO;AAAA,MAC9E;AAEA,UAAG,KAAK,QAAQ;AAAa,wBAAAA,QAAQ,IAAI,gBAAAA,QAAQ,OAAO,SAAS,KAAK,QAAQ,WAAW,CAAC;AAC1F,cAAQ,IAAI;AACZ,WAAK,KAAK,KAAK;AAAA,IACnB,CAAC;AACL,sBAAkB,KAAK,IAAI;AAC3B,QAAG,KAAK,QAAQ;AAAQ,WAAK,KAAK,KAAK,aAAY,KAAK,QAAQ,MAAM;AACtE,QAAG,KAAK,QAAQ;AAAO,WAAK,KAAK,KAAK,cAAa,KAAK,QAAQ,KAAK;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,QAAQ,MAAY,EAAC,MAAI,aAAY,cAAY,KAAI,GAAkF;AAC1I,QAAG;AAAa,aAAO,UAAU,MAAK,WAAW;AACjD,SAAK,KAAK,YAAY,KAAI,IAAI;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS,KAAkB;AACvB,QAAG,OAAO,OAAM,YAAW;AACvB,UAAI,SAAS,IAAI,IAAI;AACrB,UAAI,OAAO,kBAAkB,QAAQ,SAAU,UAAQ,SAAY,CAAC,IAAK,CAAC,MAAM;AAChF,eAAQC,QAAO,MAAK;AAChB,YAAGA,gBAAe,YAAW;AACzB,cAAG,KAAK,WAAWA,KAAI,KAAK,CAAC,GAAE;AAC3B,4BAAAD,QAAQ,MAAM,YAAYC,KAAI,KAAK,CAAC,wBAAwB;AAAA,UAChE,OAAK;AACD,iBAAK,KAAK,WAAWA,IAAG;AACxB,YAACA,KAAY,OAAO;AACpB,iBAAK,KAAK,YAAWA,KAAI,UAAS,IAAI;AAAA,UAC1C;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ,OAAK;AACD,sBAAAD,QAAQ,MAAM,iBAAiB;AAAA,IACnC;AAAA,EACJ;AAAA,EAEA,WAAW,MAAoB;AAC3B,WAAO,KAAK,KAAK,SAAS,KAAK,OAAG,EAAE,KAAK,KAAG,IAAI;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,IAAI,MAAmC;AACnC,UAAM,QAAM,KAAK,MAAM,GAAG;AAC1B,QAAI,SAAiB,KAAK;AAC1B,QAAI;AACJ,WAAM,MAAM,SAAO,GAAE;AACjB,YAAM,UAAU,MAAM,MAAM;AAC5B,YAAM,IAAI,OAAO,SAAS,KAAK,OAAG,EAAE,KAAK,KAAG,OAAO;AACnD,UAAG,KAAK,MAAM,UAAQ,GAAE;AACpB,oBAAY;AAAA,MAChB;AACA,eAAS;AAAA,IACb;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,KAAK,MAA4C;AAC7C,UAAM,MAAM,KAAK,IAAI,IAAI;AACzB,QAAG,KAAI;AACH,aAAO,QAAQ,QAAQ,GAAG;AAAA,IAC9B,OAAK;AACD,YAAM,aAAS,gCAAY;AAC3B,WAAK,YAAY,KAAK,MAAM;AAC5B,aAAO,IAAI,QAAgC,CAAC,YAAU;AAClD,YAAI;AACJ,mBAAW,KAAK,GAAG,YAAW,CAAC,aAAkB;AAC7C,cAAG,YAAU,GAAG,KAAK,IAAI,IAAI,IAAI,IAAG;AAChC,qBAAS,IAAI;AACb,mBAAO,QAAQ;AACf,iBAAK,cAAc,KAAK,YAAY,OAAO,OAAG,KAAG,MAAM;AACvD,oBAAQ,KAAK,IAAI,IAAI,CAAC;AAAA,UAC1B;AAAA,QACJ,GAAE,EAAC,WAAU,KAAI,CAAC;AAAA,MACtB,CAAC;AAAA,IACL;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,MAAoB;AACvB,QAAG,QAAQ,KAAK,KAAK,UAAS;AAC1B,aAAO;AAAA,IACX,OAAK;AACD,aAAO,KAAK,IAAI,IAAI,KAAK;AAAA,IAC7B;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAK;AAQD,SAAK,gBAAgB,EAAE,KAAK,MAAI;AAC5B,aAAO,QAAQ,IAAI,KAAK,YAAY,IAAI,YAAQ,OAAO,GAAK,CAAC,CAAC,EAAE,KAAK,MAAI;AACrE,aAAK,KAAK,WAAW,QAAQ,IAAI;AAAA,MACrC,CAAC;AAAA,IACL,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAQ;AAAA,EACR;AACJ;","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","import_getPackageJson","replaceAll","logsets","cmd"]}
package/dist/index.mjs CHANGED
@@ -1,5 +1,4 @@
1
1
  var __defProp = Object.defineProperty;
2
- var __getOwnPropNames = Object.getOwnPropertyNames;
3
2
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
4
3
  var __hasOwnProp = Object.prototype.hasOwnProperty;
5
4
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
@@ -22,9 +21,6 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
22
21
  return require.apply(this, arguments);
23
22
  throw Error('Dynamic require of "' + x + '" is not supported');
24
23
  });
25
- var __commonJS = (cb, mod) => function __require2() {
26
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
27
- };
28
24
  var __async = (__this, __arguments, generator) => {
29
25
  return new Promise((resolve, reject) => {
30
26
  var fulfilled = (value) => {
@@ -46,53 +42,6 @@ var __async = (__this, __arguments, generator) => {
46
42
  });
47
43
  };
48
44
 
49
- // package.json
50
- var require_package = __commonJS({
51
- "package.json"(exports, module) {
52
- module.exports = {
53
- name: "mixcli",
54
- version: "3.0.3",
55
- description: "Develop command line tool scaffolding for monorepo",
56
- repository: "https://github.com/zhangfisher/mixcli.git",
57
- homepage: "https://zhangfisher.github.io/mixcli/",
58
- main: "./dist/index.js",
59
- module: "./dist/index.mjs",
60
- types: "./dist/index.d.ts",
61
- scripts: {
62
- build: "tsup",
63
- "build:watch": "tsup --watch",
64
- release: "npm publish"
65
- },
66
- files: [
67
- "dist",
68
- "src",
69
- "readme.md",
70
- "package.json"
71
- ],
72
- keywords: [],
73
- author: "",
74
- license: "ISC",
75
- dependencies: {
76
- "@types/prompts": "^2.4.4",
77
- "@voerkai18n/runtime": "^2.0.8",
78
- "art-template": "^4.13.2",
79
- commander: "^12.0.0",
80
- "flex-tools": "^1.3.60",
81
- "fs-extra": "^11.1.1",
82
- glob: "^10.3.12",
83
- logsets: "^1.3.8",
84
- prompts: "^2.4.2",
85
- "string.prototype.replaceall": "^1.0.7"
86
- },
87
- devDependencies: {
88
- "@types/fs-extra": "^11.0.1",
89
- "@types/node": "^20.5.7",
90
- typescript: "^5.2.2"
91
- }
92
- };
93
- }
94
- });
95
-
96
45
  // src/cli.ts
97
46
  import "flex-tools/string";
98
47
  import { LiteEvent } from "flex-tools/events/liteEvent";
@@ -183,6 +132,32 @@ function mkDirs(_0, _1) {
183
132
  }
184
133
  });
185
134
  }
135
+ function showError(e) {
136
+ if (isDebug()) {
137
+ outputDebug("\u5BFC\u5165\u547D\u4EE4<>\u51FA\u9519:{}", e.stack);
138
+ } else {
139
+ console.error(e);
140
+ }
141
+ }
142
+ function getId() {
143
+ return Math.random().toString(36).substr(2);
144
+ }
145
+ function importModule(file) {
146
+ return __async(this, null, function* () {
147
+ let module;
148
+ try {
149
+ module = __require(file);
150
+ } catch (e) {
151
+ try {
152
+ const cmd = yield import(`file://${file}`);
153
+ module = cmd.default;
154
+ } catch (e2) {
155
+ throw e2;
156
+ }
157
+ }
158
+ return module;
159
+ });
160
+ }
186
161
 
187
162
  // src/prompt.ts
188
163
  var promptTypeMap = {
@@ -774,11 +749,11 @@ var MixCommand = class extends Command {
774
749
  };
775
750
 
776
751
  // src/finder.ts
777
- import { getPackageRootPath } from "flex-tools";
752
+ import { getPackageJson } from "flex-tools/package/getPackageJson";
753
+ import { getPackageRootPath } from "flex-tools/package/getPackageRootPath";
778
754
  import { globSync } from "glob";
779
755
  import fs3 from "fs";
780
756
  import path3 from "path";
781
- import { getPackageJson } from "flex-tools/package/getPackageJson";
782
757
  function getMatchedDependencies(entry) {
783
758
  const pacakgeMacher = this.options.include;
784
759
  if (!(pacakgeMacher instanceof RegExp))
@@ -812,6 +787,10 @@ function findCliPaths(packageName, entry) {
812
787
  return [];
813
788
  const packageRoot = getPackageRootPath(entry || process.cwd());
814
789
  const packagePath = packageName ? path3.dirname(__require.resolve(packageName, { paths: [packageRoot] })) : packageName;
790
+ if (!packagePath) {
791
+ outputDebug("MixCli\u53EA\u80FD\u8FD0\u884C\u5728Nodejs\u73AF\u5883");
792
+ return [];
793
+ }
815
794
  const packageNames = getMatchedDependencies.call(this, packagePath);
816
795
  const cliDirs = [];
817
796
  if (entry !== void 0)
@@ -838,22 +817,6 @@ function findCliPaths(packageName, entry) {
838
817
  });
839
818
  return [...new Set(cliDirs)];
840
819
  }
841
- function importModule(file) {
842
- return __async(this, null, function* () {
843
- let module;
844
- try {
845
- module = __require(file);
846
- } catch (e) {
847
- try {
848
- const cmd = yield import(`file://${file}`);
849
- module = cmd.default;
850
- } catch (e2) {
851
- throw e2;
852
- }
853
- }
854
- return module;
855
- });
856
- }
857
820
  function findCommands(cli) {
858
821
  return __async(this, null, function* () {
859
822
  const cliDirs = findCliPaths.call(cli);
@@ -896,6 +859,7 @@ function findCommands(cli) {
896
859
  // src/cli.ts
897
860
  import { asyncSignal } from "flex-tools/async/asyncSignal";
898
861
  import replaceAll from "string.prototype.replaceall";
862
+ import { getPackageJson as getPackageJson2 } from "flex-tools/package/getPackageJson";
899
863
  replaceAll.shim();
900
864
  var MixCli = class extends LiteEvent {
901
865
  constructor(options) {
@@ -939,13 +903,17 @@ var MixCli = class extends LiteEvent {
939
903
  }
940
904
  });
941
905
  }
906
+ getVersion() {
907
+ const packageInfo = getPackageJson2();
908
+ return packageInfo.version;
909
+ }
942
910
  /**
943
911
  * 创建根命令
944
912
  *
945
913
  */
946
914
  createRootCommand() {
947
915
  this.root = new MixCommand(this.name);
948
- this.root.helpOption("-h, --help").version(require_package().version, "-v, --version").action(() => {
916
+ this.root.helpOption("-h, --help").version(this.getVersion(), "-v, --version").action(() => {
949
917
  if (this.options.logo)
950
918
  logsets2.log(fixIndent(this.options.logo, 2));
951
919
  console.log();
@@ -1100,6 +1068,8 @@ export {
1100
1068
  createFileByTemplate,
1101
1069
  fileExists,
1102
1070
  fixIndent,
1071
+ getId,
1072
+ importModule,
1103
1073
  isDebug,
1104
1074
  isEnablePrompts,
1105
1075
  mkDirs,
@@ -1107,6 +1077,7 @@ export {
1107
1077
  outputDebug,
1108
1078
  outputStr,
1109
1079
  readFile,
1080
+ showError,
1110
1081
  writeFile
1111
1082
  };
1112
1083
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../package.json","../src/cli.ts","../src/command.ts","../src/option.ts","../src/utils.ts","../src/prompt.ts","../src/finder.ts"],"sourcesContent":["{\n \"name\": \"mixcli\",\n \"version\": \"3.0.3\",\n \"description\": \"Develop command line tool scaffolding for monorepo\",\n \"repository\": \"https://github.com/zhangfisher/mixcli.git\",\n \"homepage\": \"https://zhangfisher.github.io/mixcli/\",\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"scripts\": {\n \"build\": \"tsup\",\n \"build:watch\": \"tsup --watch\",\n \"release\": \"npm publish\"\n },\n \"files\": [\n \"dist\",\n \"src\",\n \"readme.md\",\n \"package.json\"\n ],\n \"keywords\": [],\n \"author\": \"\",\n \"license\": \"ISC\",\n \"dependencies\": {\n \"@types/prompts\": \"^2.4.4\",\n \"@voerkai18n/runtime\": \"^2.0.8\",\n \"art-template\": \"^4.13.2\",\n \"commander\": \"^12.0.0\",\n \"flex-tools\": \"^1.3.60\",\n \"fs-extra\": \"^11.1.1\",\n \"glob\": \"^10.3.12\",\n \"logsets\": \"^1.3.8\",\n \"prompts\": \"^2.4.2\",\n \"string.prototype.replaceall\": \"^1.0.7\"\n },\n \"devDependencies\": {\n \"@types/fs-extra\": \"^11.0.1\",\n \"@types/node\": \"^20.5.7\",\n \"typescript\": \"^5.2.2\"\n }\n}\n","#!/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 } 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}\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 .version(require(\"../package.json\").version,\"-v, --version\") \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}","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 { getPackageRootPath } from 'flex-tools';\r\nimport type { MixCli } from './cli';\r\nimport { globSync } from 'glob'\r\nimport { MixCliCommand } from './cli';\r\nimport { isDebug, outputDebug } from './utils';\r\nimport fs from \"node:fs\"\r\nimport path from \"node:path\"\r\nimport { getPackageJson } from \"flex-tools/package/getPackageJson\"\r\nimport { fileURLToPath } from 'node:url';\r\nimport { createRequire } from 'node:module';\r\n\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]})) : packageName!\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\nfunction 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\nasync 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\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 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":["logsets","path","fs","path","fs","command","fs","path","path","fs","e","path","fs","logsets","cmd"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/command.ts","../src/option.ts","../src/utils.ts","../src/prompt.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, 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 private getVersion(){\n const packageInfo = getPackageJson()\n return packageInfo.version\n }\n /**\n * 创建根命令\n * \n */\n private createRootCommand(){\n this.root = new MixCommand(this.name);\n this.root \n .helpOption('-h, --help') \n .version(this.getVersion(),\"-v, --version\") \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]})) : packageName!\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 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":["logsets","e","path","fs","path","fs","command","fs","path","path","fs","getPackageJson","getPackageJson","logsets","cmd"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mixcli",
3
- "version": "3.0.3",
3
+ "version": "3.0.5",
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/",
@@ -21,7 +21,7 @@
21
21
  "@voerkai18n/runtime": "^2.0.8",
22
22
  "art-template": "^4.13.2",
23
23
  "commander": "^12.0.0",
24
- "flex-tools": "^1.3.60",
24
+ "flex-tools": "^1.3.71",
25
25
  "fs-extra": "^11.1.1",
26
26
  "glob": "^10.3.12",
27
27
  "logsets": "^1.3.8",
package/src/cli.ts CHANGED
@@ -6,11 +6,13 @@ 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 } from './utils';
9
+ import { addBuiltInOptions, fixIndent, isDebug } from './utils';
10
10
  import { findCommands } from "./finder"
11
11
  import { asyncSignal } from "flex-tools/async/asyncSignal"
12
12
  // @ts-ignore
13
13
  import replaceAll from 'string.prototype.replaceall'
14
+ import { getPackageEntry, getPackageRootPath } from "flex-tools"
15
+ import { getPackageJson } from 'flex-tools/package/getPackageJson';
14
16
  replaceAll.shim()
15
17
 
16
18
  export interface MixCliOptions{
@@ -87,6 +89,10 @@ export class MixCli extends LiteEvent<any,MixCliEvents>{
87
89
  }
88
90
  }
89
91
  }
92
+ private getVersion(){
93
+ const packageInfo = getPackageJson()
94
+ return packageInfo.version
95
+ }
90
96
  /**
91
97
  * 创建根命令
92
98
  *
@@ -95,7 +101,7 @@ export class MixCli extends LiteEvent<any,MixCliEvents>{
95
101
  this.root = new MixCommand(this.name);
96
102
  this.root
97
103
  .helpOption('-h, --help')
98
- .version(require("../package.json").version,"-v, --version")
104
+ .version(this.getVersion(),"-v, --version")
99
105
  .action(()=>{
100
106
  if(this.options.logo) logsets.log(fixIndent(this.options.logo,2))
101
107
  console.log()
@@ -248,6 +254,6 @@ export class MixCli extends LiteEvent<any,MixCliEvents>{
248
254
  *
249
255
  */
250
256
  create(){
251
- }
257
+ }
252
258
  }
253
259
 
package/src/finder.ts CHANGED
@@ -1,14 +1,11 @@
1
- import { getPackageRootPath } from 'flex-tools';
1
+ import { getPackageJson } from "flex-tools/package/getPackageJson"
2
+ import { getPackageRootPath } from 'flex-tools/package/getPackageRootPath';
2
3
  import type { MixCli } from './cli';
3
4
  import { globSync } from 'glob'
4
5
  import { MixCliCommand } from './cli';
5
- import { isDebug, outputDebug } from './utils';
6
+ import { importModule, isDebug, outputDebug } from './utils';
6
7
  import fs from "node:fs"
7
8
  import path from "node:path"
8
- import { getPackageJson } from "flex-tools/package/getPackageJson"
9
- import { fileURLToPath } from 'node:url';
10
- import { createRequire } from 'node:module';
11
-
12
9
 
13
10
 
14
11
  /**
@@ -60,6 +57,11 @@ export function findCliPaths(this:MixCli,packageName?:string ,entry?:string):str
60
57
  const packageRoot = getPackageRootPath(entry || process.cwd())
61
58
  const packagePath = packageName ? path.dirname(require.resolve(packageName,{paths:[packageRoot as string]})) : packageName!
62
59
 
60
+ if(!packagePath) {
61
+ outputDebug("MixCli只能运行在Nodejs环境" )
62
+ return []
63
+ }
64
+
63
65
  // 找出当前包的所有依赖
64
66
  const packageNames = getMatchedDependencies.call(this,packagePath)
65
67
 
@@ -93,31 +95,6 @@ export function findCliPaths(this:MixCli,packageName?:string ,entry?:string):str
93
95
  }
94
96
 
95
97
 
96
- function showError(e:any){
97
- if(isDebug()){
98
- outputDebug("导入命令<>出错:{}",e.stack)
99
- }else{
100
- console.error(e)
101
- }
102
-
103
- }
104
-
105
-
106
- async function importModule(file:string){
107
- let module
108
- try{
109
- module = require(file)
110
- }catch(e:any){
111
- try{
112
- const cmd = await import(`file://${file}`)
113
- module = cmd.default
114
- }catch(e:any){
115
- throw e
116
- }
117
- }
118
- return module
119
- }
120
-
121
98
  /**
122
99
  *
123
100
  * 扫描当前工程中所有符合条件的命令
package/src/utils.ts CHANGED
@@ -125,4 +125,34 @@ export async function mkDirs(dirs:string[],{callback,base}:{callback?:Function,b
125
125
  if(typeof(callback)=='function') callback(dir)
126
126
  await mkdir(dir,{recursive:true})
127
127
  }
128
- }
128
+ }
129
+
130
+ export function showError(e:any){
131
+ if(isDebug()){
132
+ outputDebug("导入命令<>出错:{}",e.stack)
133
+ }else{
134
+ console.error(e)
135
+ }
136
+
137
+ }
138
+
139
+
140
+ export function getId(){
141
+ return Math.random().toString(36).substr(2)
142
+ }
143
+
144
+
145
+ export async function importModule(file:string){
146
+ let module
147
+ try{
148
+ module = require(file)
149
+ }catch(e:any){
150
+ try{
151
+ const cmd = await import(`file://${file}`)
152
+ module = cmd.default
153
+ }catch(e:any){
154
+ throw e
155
+ }
156
+ }
157
+ return module
158
+ }