mixcli 3.2.2 → 3.2.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,6 @@
1
1
  import { LiteEvent } from 'flex-tools/events/liteEvent';
2
2
  import { OptionValues, Option, Command } from 'commander';
3
3
  import { PromptObject } from 'prompts';
4
- import * as flex_tools__ from 'flex-tools/*';
5
4
 
6
5
  type PromptType = "text" | "password" | "invisible" | "number" | "confirm" | "list" | "toggle" | "select" | "multiselect" | "autocomplete" | "date" | "autocompleteMultiselect";
7
6
  type PromptParam = 'auto' | boolean | PromptType | PromptObject;
@@ -364,26 +363,9 @@ declare function isDisablePrompts(): boolean;
364
363
  * @param args
365
364
  */
366
365
  declare function outputDebug(message: string, ...args: any[]): void;
367
- declare const fileExists: flex_tools__.AsyncFunction;
368
- declare const readFile: flex_tools__.AsyncFunction;
369
- declare const writeFile: flex_tools__.AsyncFunction;
370
- declare const mkdir: flex_tools__.AsyncFunction;
371
- /**
372
- * 创建目录
373
- *
374
- *
375
- *
376
- * @param {String[]} dirs 要创建的目录列表,类型为字符串数组
377
- * @param callback 创建目录过程中的回调函数,类型为异步函数,接收一个参数 dir,表示当前正在创建的目录
378
- * @returns 该函数返回一个 Promise 对象,表示创建目录的操作是否完成
379
- */
380
- declare function mkDirs(dirs: string[], { callback, base }: {
381
- callback?: Function;
382
- base?: string;
383
- }): Promise<void>;
384
366
  declare function showError(e: any): void;
385
367
  declare function hyphenToCamelCase(str: string): string;
386
368
  declare function getId(): string;
387
369
  declare function importModule(file: string): Promise<any>;
388
370
 
389
- export { type AfterMixCommandHookListener, BREAK, type BeforeMixCommandHookListener, type IMixCommandHookListener, type InputPromptParam, type MixActionOptions, type MixActionRegistry, MixCli, type MixCliCommand, type MixCliEvents, type MixCliOptions, MixCommand, type MixEnhanceAction, MixOption, MixOptionPrompt, type MixOriginalAction, type MixedOptionParams, type PromptChoice, type PromptParam, type PromptParamDefaultValue, type PromptParams, type PromptType, addBuiltInOptions, fileExists, fixIndent, getId, hyphenToCamelCase, importModule, isDebug, isDisablePrompts, mkDirs, mkdir, outputDebug, outputStr, promptTypeMap, readFile, showError, supportedPromptTypes, writeFile };
371
+ export { type AfterMixCommandHookListener, BREAK, type BeforeMixCommandHookListener, type IMixCommandHookListener, type InputPromptParam, type MixActionOptions, type MixActionRegistry, MixCli, type MixCliCommand, type MixCliEvents, type MixCliOptions, MixCommand, type MixEnhanceAction, MixOption, MixOptionPrompt, type MixOriginalAction, type MixedOptionParams, type PromptChoice, type PromptParam, type PromptParamDefaultValue, type PromptParams, type PromptType, addBuiltInOptions, fixIndent, getId, hyphenToCamelCase, importModule, isDebug, isDisablePrompts, outputDebug, outputStr, promptTypeMap, showError, supportedPromptTypes };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { LiteEvent } from 'flex-tools/events/liteEvent';
2
2
  import { OptionValues, Option, Command } from 'commander';
3
3
  import { PromptObject } from 'prompts';
4
- import * as flex_tools__ from 'flex-tools/*';
5
4
 
6
5
  type PromptType = "text" | "password" | "invisible" | "number" | "confirm" | "list" | "toggle" | "select" | "multiselect" | "autocomplete" | "date" | "autocompleteMultiselect";
7
6
  type PromptParam = 'auto' | boolean | PromptType | PromptObject;
@@ -364,26 +363,9 @@ declare function isDisablePrompts(): boolean;
364
363
  * @param args
365
364
  */
366
365
  declare function outputDebug(message: string, ...args: any[]): void;
367
- declare const fileExists: flex_tools__.AsyncFunction;
368
- declare const readFile: flex_tools__.AsyncFunction;
369
- declare const writeFile: flex_tools__.AsyncFunction;
370
- declare const mkdir: flex_tools__.AsyncFunction;
371
- /**
372
- * 创建目录
373
- *
374
- *
375
- *
376
- * @param {String[]} dirs 要创建的目录列表,类型为字符串数组
377
- * @param callback 创建目录过程中的回调函数,类型为异步函数,接收一个参数 dir,表示当前正在创建的目录
378
- * @returns 该函数返回一个 Promise 对象,表示创建目录的操作是否完成
379
- */
380
- declare function mkDirs(dirs: string[], { callback, base }: {
381
- callback?: Function;
382
- base?: string;
383
- }): Promise<void>;
384
366
  declare function showError(e: any): void;
385
367
  declare function hyphenToCamelCase(str: string): string;
386
368
  declare function getId(): string;
387
369
  declare function importModule(file: string): Promise<any>;
388
370
 
389
- export { type AfterMixCommandHookListener, BREAK, type BeforeMixCommandHookListener, type IMixCommandHookListener, type InputPromptParam, type MixActionOptions, type MixActionRegistry, MixCli, type MixCliCommand, type MixCliEvents, type MixCliOptions, MixCommand, type MixEnhanceAction, MixOption, MixOptionPrompt, type MixOriginalAction, type MixedOptionParams, type PromptChoice, type PromptParam, type PromptParamDefaultValue, type PromptParams, type PromptType, addBuiltInOptions, fileExists, fixIndent, getId, hyphenToCamelCase, importModule, isDebug, isDisablePrompts, mkDirs, mkdir, outputDebug, outputStr, promptTypeMap, readFile, showError, supportedPromptTypes, writeFile };
371
+ export { type AfterMixCommandHookListener, BREAK, type BeforeMixCommandHookListener, type IMixCommandHookListener, type InputPromptParam, type MixActionOptions, type MixActionRegistry, MixCli, type MixCliCommand, type MixCliEvents, type MixCliOptions, MixCommand, type MixEnhanceAction, MixOption, MixOptionPrompt, type MixOriginalAction, type MixedOptionParams, type PromptChoice, type PromptParam, type PromptParamDefaultValue, type PromptParams, type PromptType, addBuiltInOptions, fixIndent, getId, hyphenToCamelCase, importModule, isDebug, isDisablePrompts, outputDebug, outputStr, promptTypeMap, showError, supportedPromptTypes };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- var U=Object.defineProperty;var _=Object.getOwnPropertySymbols;var K=Object.prototype.hasOwnProperty,z=Object.prototype.propertyIsEnumerable;var j=(s,n,t)=>n in s?U(s,n,{enumerable:!0,configurable:!0,writable:!0,value:t}):s[n]=t,D=(s,n)=>{for(var t in n||(n={}))K.call(n,t)&&j(s,t,n[t]);if(_)for(var t of _(n))z.call(n,t)&&j(s,t,n[t]);return s};var g=(s=>typeof require!="undefined"?require:typeof Proxy!="undefined"?new Proxy(s,{get:(n,t)=>(typeof require!="undefined"?require:n)[t]}):s)(function(s){if(typeof require!="undefined")return require.apply(this,arguments);throw Error('Dynamic require of "'+s+'" is not supported')});var l=(s,n,t)=>new Promise((e,i)=>{var o=a=>{try{p(t.next(a))}catch(c){i(c)}},r=a=>{try{p(t.throw(a))}catch(c){i(c)}},p=a=>a.done?e(a.value):Promise.resolve(a.value).then(o,r);p((t=t.apply(s,n)).next())});import"flex-tools/string";import{LiteEvent as nt}from"flex-tools/events/liteEvent";import f from"logsets";import{assignObject as rt}from"flex-tools/object/assignObject";import{Command as Z}from"commander";import L from"prompts";import{Option as Y}from"commander";import{isPlainObject as V}from"flex-tools/typecheck/isPlainObject";import{isNumber as J}from"flex-tools/typecheck/isNumber";import x from"fs-extra";import E from"node:path";import{promisify as b}from"flex-tools/func/promisify";import H from"logsets";function ft(s,n){H.log(C(s),n)}function C(s,n){if((n==null||n===!0?0:typeof n=="number"?n:-1)==-1)return s;let e=s.split(`
2
- `),i=e.reduce((o,r,p)=>{var c;if(p==0)return o;let a=((c=r.match(/^\s*/))==null?void 0:c[0].length)||0;return Math.min(o,a)},9999);return e=e.map(o=>o.substring(i)),e.join(`
3
- `)}function M(s){s.option("--work-dirs <values...>","\u6307\u5B9A\u5DE5\u4F5C\u76EE\u5F55",{hidden:!0,optional:!0,required:!0,prompt:!1}),s.option("--disable-prompts","\u7981\u7528\u6240\u6709\u4EA4\u4E92\u63D0\u793A",{hidden:!0,prompt:!1}),s.option("--debug-cli","\u663E\u793A\u8C03\u8BD5\u4FE1\u606F",{hidden:!0,prompt:!1})}function R(){return process.argv.includes("--debug-cli")}function T(){return process.argv.includes("--disable-prompts")}function m(s,...n){let t=n.length==1&&typeof n[0]=="function"?n[0]():n;R()&&H.log(`[MixCli] ${s}`,...t)}var dt=b(x.exists,{parseCallback:s=>s[0]}),ht=b(x.readFile),gt=b(x.writeFile),G=b(x.mkdir);function yt(e,i){return l(this,arguments,function*(s,{callback:n,base:t}){if(!Array.isArray(s))throw new Error("dirs\u53C2\u6570\u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32\u6570\u7EC4");for(let o of s)E.isAbsolute(o)||(o=E.join(t||process.cwd(),o)),typeof n=="function"&&n(o),yield G(o,{recursive:!0})})}function xt(s){R()?m("\u5BFC\u5165\u547D\u4EE4<>\u51FA\u9519:{}",s.stack):console.error(s)}function bt(s){return s.replace(/-([a-z])/g,(n,t)=>t.toUpperCase())}function Ct(){return Math.random().toString(36).substr(2)}function S(s){return l(this,null,function*(){let n;try{n=g(s)}catch(t){try{n=(yield import(`file://${s}`)).default}catch(e){throw e}}return n})}var I={boolean:"confirm",string:"text",number:"number",array:"list",date:"date"},Q=["text","password","invisible","number","confirm","list","toggle","select","multiselect","autocomplete","date","autocompleteMultiselect"],P=class{constructor(n,t){this.cliOption=n;this.params=t}isValidPromptType(n){return Q.includes(String(n))}isNeedPrompt(n,t){let e=this.params,i=n||t,o=i!==void 0;return e===!0?!0:e===!1?!1:e==="auto"||V(e)?!o:typeof e=="string"&&this.isValidPromptType(e)?!0:/(\<s*\w\s*\>)/.test(this.cliOption.flags)?!o:this.cliOption.argChoices&&this.cliOption.argChoices.indexOf(i)==-1?!0:!o}_getChoices(){var e;let n=[],t=(e=this.cliOption.params)==null?void 0:e.choices;if(this.cliOption.argChoices)n=this.cliOption.argChoices.map(i=>typeof i=="string"?{title:i,value:i}:i);else if(t)n=typeof t=="function"?t:[];else return[];return n}infer(n){let{variadic:t,defaultValue:e}=this.cliOption,i=n||e,o="text",r=this.params;if(this.isValidPromptType(r))o=r;else if(V(r))o=r.type;else{let p=/(\[\s*\w+\.\.\.\s*])|(\<\s*\w+\.\.\.\s*>)/.test(this.cliOption.flags),a=/(\<s*\w+\s*\>)|(\[\w+\])/.test(this.cliOption.flags),c=!/(\[\s*\w+s*])|(\<\s*\w+\s*>)/.test(this.cliOption.flags),y=J(e),A=e&&e instanceof Date,h=Array.isArray(i)?"array":i instanceof Date?"date":typeof i,d=this.cliOption.params;if(d&&d.choices){let w=d.choices;c&&Array.isArray(w)&&w.length==2?o="toggle":o=t?"multiselect":"select"}else p?o="list":A?o="date":y?o="number":a?o="text":c||typeof e=="boolean"?o="confirm":h in I&&(o=I[h])}return m("\u9009\u9879<{}> -> \u63D0\u793A\u7C7B\u578B<{}>",[this.cliOption.name(),o]),o}get(n){var p;let{description:t,defaultValue:e}=this.cliOption,i=n||e;if(!this.isNeedPrompt(i,e))return;let o=this.infer(n),r=D({type:o,name:this.cliOption.attributeName(),message:t,initial:i},typeof this.params=="object"?this.params:{});if(r.validate=(p=this.cliOption.params)==null?void 0:p.validate,o=="multiselect"&&(r.instructions=!1),r.choices=r.choices||this._getChoices(),["select","multiselect"].includes(o)||o=="toggle"&&Array.isArray(r.choices)&&(r.active||(r.active=r.choices[0].value),r.inactive||(r.inactive=r.choices[1].value)),i&&typeof r.initial!="function"&&r.choices&&Array.isArray(r.choices))if(o=="select"){let a=Array.isArray(r.choices)?r.choices.findIndex(c=>c.value==i):-1;a!=-1&&(r.initial=a)}else o=="multiselect"&&r.choices.forEach(a=>{(Array.isArray(i)&&i.includes(a.value)||a.value==i)&&(a.selected=!0)});return r}};var O=class extends Y{constructor(t,e,i){super(t,e);this.params=i;this.__MIX_OPTION__=!0;this._setOption(i||{}),this.prompt=new P(this,i==null?void 0:i.prompt)}_setOption(t){t.default&&this.default(t.default,t.defaultDescription),t.conflicts&&this.conflicts(t.conflicts),t.envVar&&this.env(t.envVar),t.parseArg&&this.argParser(t.parseArg),t.hidden&&(this.hidden=t.hidden),t.mandatory&&this.makeOptionMandatory(t.mandatory),t.implies&&this.implies(t.implies),t.optional&&(this.optional=t.optional),t.variadic&&(this.variadic=t.variadic),t.negate&&(this.negate=t.negate),t.preset&&this.preset(t.preset),t.required&&(this.required=t.required),Array.isArray(t.choices)&&this.choices(t.choices.map(e=>typeof e=="string"?e:e.value))}getPrompt(t){var e;return(e=this.prompt)==null?void 0:e.get(t)}};import N from"node:path";import $ from"node:fs";var tt=Symbol("BREAK_ACTION"),v=class extends Z{constructor(t){super(t);this.__MIX_COMMAND__=!0;this._beforeHooks=[];this._afterHooks=[];this._customPrompts=[];this._optionValues={};this._actions=[];this._enable_prompts=!0;let e=this;this.isRoot||M(this),this.hook("preAction",function(){return l(this,arguments,function*(){e._optionValues=e.getOptionValues(this.hookedCommand),yield e.preActionHook.apply(e,arguments)})})}get isRoot(){return this.parent==null}get optionValues(){return this._optionValues}get actions(){return this._actions}get beforeHooks(){return this._beforeHooks}get afterHooks(){return this._afterHooks}get fullname(){let t=[this.name()],e=this.parent;for(;e;)e.name()!=="root"&&t.unshift(e.name()),e=e.parent;return t.join(".")}root(){let t=this;for(;t&&t.parent!=null;)t=t.parent;return t}action(){let t=arguments[0];if(arguments.length==1&&typeof t=="function")this._actions.push({id:Math.random().toString(36).substring(2),enhance:!1,fn:t});else if(arguments.length==2&&typeof t=="function"&&typeof arguments[1]=="object"){let e=arguments[0],i=Object.assign({at:"append"},arguments[1]);i.at=="replace"&&(this._actions=[]);let o={id:i.id||Math.random().toString(36).substring(2),enhance:i.enhance==null?!0:i.enhance,fn:e};typeof i.at=="number"?this._actions.splice(Number(i.at),0,o):["append","before"].includes(i.at)?this._actions.push(o):["preappend","after"].includes(i.at)?this._actions.splice(0,0,o):this._actions.push(o)}else console.log("[mixcli] action params error");return super.action(this.getWrapperedAction())}getOptionValues(t){let e={},i=t;for(;i;)Object.assign(e,i.optionValues),i=i.parent;return e}getWrapperedAction(){return this.wrapperWorkDirsAction(this.wrapperChainActions())}getAncestorCommands(){let t=[],e=this;for(;e;)e=e.parent,e&&t.push(e);return t}wrapperChainActions(){let t=this;return function(){return l(this,arguments,function*(){let e=Array.from(arguments),i,o={},r=[],p;e.length>=2&&(p=e[e.length-1],o=e[e.length-2],r=e.slice(0,e.length-2)),yield t.executeBeforeHooks({args:r,options:o,command:p});try{for(let a of t._actions)try{if(a.enhance?(m("\u6267\u884C<{}>: args={}, options={}",()=>[t.name(),r,o]),i=yield a.fn.call(this,{command:p,value:i,args:r,options:o})):i=yield a.fn.apply(this,e),i===tt)break}catch(c){throw m("\u547D\u4EE4{}\u7684Action({})\u6267\u884C\u51FA\u9519:{}",[t.name,a.id,c]),c}}finally{yield t.executeAfterHooks({value:i,args:r,options:o,command:p})}})}}wrapperWorkDirsAction(t){let e=this;return function(){return l(this,arguments,function*(){let i=e._optionValues.workDirs;if(!i)return yield t.apply(this,Array.from(arguments));Array.isArray(i)||(i=i.split(",")),i=i.reduce((o,r)=>(typeof r=="string"&&o.push(...r.split(",")),o),[]);for(let o of i){let r=process.cwd();try{N.isAbsolute(o)||(o=N.join(r,o)),$.existsSync(o)&&$.statSync(o).isDirectory()?(m("\u5207\u6362\u5230\u5DE5\u4F5C\u76EE\u5F55:{}",o),process.chdir(o),yield t.apply(this,Array.from(arguments))):m("\u65E0\u6548\u7684\u5DE5\u4F5C\u76EE\u5F55:{}",o)}finally{process.chdir(r)}}})}}getOption(t){return this.options.find(e=>e.name()==t)}before(t,e=!0){return this._beforeHooks.push([t,e]),this}executeBeforeHooks(t){return l(this,null,function*(){let e=this.beforeHooks.map(([i,o])=>[i,o,this]);this.getAncestorCommands().forEach(i=>{e.unshift(...i.beforeHooks.map(([o,r])=>[o,r,i]))});for(let[i,o,r]of e)o&&(yield i.call(r,t))})}after(t,e=!0){return this._afterHooks.push([t,e]),this}executeAfterHooks(t){return l(this,null,function*(){let e=this.afterHooks.map(([i,o])=>[i,o,this]);this.getAncestorCommands().forEach(i=>{e.push(...i.afterHooks.map(([o,r])=>[o,r,i]))});for(let[i,o,r]of e)o&&(yield i.call(r,t))})}preActionHook(t){return l(this,null,function*(){if(this.isEnablePrompts()){let e=[...this.generateAutoPrompts(),...this._customPrompts];if(e.length>0){let i=yield L(e);Object.entries(i).forEach(([o,r])=>{t.setOptionValue(o,r)})}}})}isEnablePrompts(){return T()?!1:this._enable_prompts}generateAutoPrompts(){let e=this.options.filter(i=>!i.hidden&&i.__MIX_OPTION__).map(i=>i.getPrompt(this._optionValues[i.attributeName()])).filter(i=>i);return m("\u547D\u4EE4<{}>\u81EA\u52A8\u751F\u6210{}\u4E2A\u9009\u9879\u63D0\u793A:{}",[this.name(),e.length,e.map(i=>`${i.name}(${i.type})`).join(",")]),e}option(t,e,i){let o=new O(t,e,i);return o.required&&!this.isEnablePrompts()&&(o.mandatory=!0),this.addOption(o)}prompt(t){return this._customPrompts.push(...Array.isArray(t)?t:[t]),this}selectCommands(){return l(this,null,function*(){let t=this.commands.map(o=>({title:`${o.description()}(${o.name()})`,value:o.name()})),e=yield L({type:"select",name:"command",message:"\u8BF7\u9009\u62E9\u547D\u4EE4:",choices:t}),i=this.commands.find(o=>o.name()===e.command);yield i==null?void 0:i.parseAsync([e.command],{from:"user"})})}disablePrompts(){return this._enable_prompts=!1,this}enablePrompts(){return this._enable_prompts=!0,this}};import{getPackageJson as et}from"flex-tools/package/getPackageJson";import{getPackageRootPath as it}from"flex-tools/package/getPackageRootPath";import{globSync as ot}from"glob";import k from"node:fs";import u from"node:path";function B(s){let n=this.options.include;if(!(n instanceof RegExp))return[];let{dependencies:t={},devDependencies:e={},peerDependencies:i={},optionalDependencies:o={},bundleDependencies:r={}}=et(s);return[...Object.keys(t),...Object.keys(e),...Object.keys(i),...Object.keys(o),...Object.keys(r)].filter(a=>a!=="@voerka/cli"&&n.test(a))}function q(s,n){return(n?Array.isArray(n)?n:[n]:[]).some(e=>typeof e=="string"?new RegExp(e).test(s):e instanceof RegExp?e.test(s):!1)}function F(s,n){let t=this.options.include,e=this.options.exclude;if(!t)return[];let i=it(n||process.cwd()),o=s?u.dirname(g.resolve(s,{paths:[i]})):i;if(!o)return m("MixCli\u53EA\u80FD\u8FD0\u884C\u5728Nodejs\u73AF\u5883"),[];let r=B.call(this,o),p=[];return n!==void 0&&p.push(u.join(o,this.options.cliDir)),r.filter(a=>q(a,t)&&!q(a,e)).forEach(a=>{m("\u5339\u914D\u5305:{}",`${s?a+" <- "+s:a}`);try{let c=u.dirname(g.resolve(a,{paths:o?[o]:[process.cwd()]})),y=u.join(c,this.options.cliDir),A=B.call(this,c);p.push(...A.reduce((h,d)=>(m("\u5339\u914D\u5305:{}",`${d} <- ${a}`),h.push(...F.call(this,d,c)),h),[])),k.existsSync(y)&&p.push(y)}catch(c){m("\u89E3\u6790\u5305<{}>\u8DEF\u5F84\u51FA\u9519\uFF1A{}",[a,c.stack])}}),[...new Set(p)]}function W(s){return l(this,null,function*(){let n=F.call(s),t=[],e=[];n.forEach(i=>{ot("*",{cwd:i,absolute:!0}).forEach(o=>{if(u.basename(o).startsWith("_"))return;let p=u.extname(o).toLowerCase();[".js",".cjs",".mjs"].includes(p)?e.push(o):k.statSync(o).isDirectory()&&(e.push(u.join(o,"index.js")),e.push(u.join(o,"index.cjs")),e.push(u.join(o,"index.mjs")))})});for(let i of e)if(k.existsSync(i))try{if(m("\u5BFC\u5165\u547D\u4EE4:{}",i),i.endsWith(".cjs")||i.endsWith(".js"))t.push(yield S(i));else if(i.endsWith(".mjs")){let o=yield import(`file://${i}`);t.push(o.default)}}catch(o){m(o)}return t})}import{asyncSignal as st}from"flex-tools/async/asyncSignal";import at from"string.prototype.replaceall";at.shim();var X=class extends nt{constructor(t){super();this.findSignals=[];this.options=rt({name:"mixcli",package:null,cliDir:"cli",prompt:"auto",ignoreError:!1},t),this.createRootCommand()}get context(){return this.options.context}get name(){return this.options.name}get isDisabledPrompts(){return this.root.rawArgs.includes("--no-prompts")}installCommands(){return l(this,null,function*(){let t=yield W(this);for(let e of t)try{if(typeof e=="function"){let i=e(this);i=i?Array.isArray(i)?i:[i]:[],this.register(()=>i)}}catch(i){m("\u6CE8\u518C\u547D\u4EE4\u5931\u8D25:{}",i.stack)}})}createRootCommand(){this.root=new v(this.name),this.root.helpOption("-h, --help").action(()=>{this.options.logo&&f.log(C(this.options.logo,2)),console.log();let t=this.options.title||this.options.name;Array.isArray(t)?f.log(String(t[0]).firstUpper(),[...t.slice(1)]):f.log(`${t.firstUpper()} Version: {}`,this.options.version),this.options.description&&f.log(f.colors.darkGray(this.options.description)),console.log(),this.root.help()}),M(this.root),this.options.before&&this.root.hook("preAction",this.options.before),this.options.after&&this.root.hook("postAction",this.options.after)}addHelp(t,{pos:e="beforeAll",alignIndent:i=!0}){i&&(t=C(t,i)),this.root.addHelpText(e,t)}register(t){if(typeof t=="function"){let e=t(this),i=e instanceof Array?e:e==null?[]:[e];for(let o of i)o.__MIX_COMMAND__?this.hasCommand(o.name())?f.error(`Command <${o.name()}> has been registered!`):(m("\u6CE8\u518C\u547D\u4EE4:{}",o.fullname),this.root.addCommand(o),o._cli=this,this.emit("register",o.fullname,!0)):f.error(`Command <${o.toString()}> is not a valid command!`)}else f.error("Invalid command")}hasCommand(t){return this.root.commands.some(e=>e.name()==t)}get(t){let e=t.split("."),i=this.root,o;for(;e.length>0;){let r=e.shift(),p=i.commands.find(a=>a.name()==r);p&&e.length==0&&(o=p),i=p}return o}find(t){let e=this.get(t);if(e)return Promise.resolve(e);{let i=st();return this.findSignals.push(i),new Promise(o=>{let r;r=this.on("register",p=>{p==`${this.name}.${t}`&&(r.off(),i.resolve(),this.findSignals=this.findSignals.filter(a=>a!=i),o(this.get(t)))},{objectify:!0})})}}exists(t){return t in this.root.commands?!0:this.get(t)!=null}run(){this.installCommands().then(()=>Promise.all(this.findSignals.map(t=>t(1e4))).then(()=>{this.root.parseAsync(process.argv)}))}};export{tt as BREAK,X as MixCli,v as MixCommand,O as MixOption,P as MixOptionPrompt,M as addBuiltInOptions,dt as fileExists,C as fixIndent,Ct as getId,bt as hyphenToCamelCase,S as importModule,R as isDebug,T as isDisablePrompts,yt as mkDirs,G as mkdir,m as outputDebug,ft as outputStr,I as promptTypeMap,ht as readFile,xt as showError,Q as supportedPromptTypes,gt as writeFile};
1
+ "use strict";var nt=Object.create;var y=Object.defineProperty;var st=Object.getOwnPropertyDescriptor;var rt=Object.getOwnPropertyNames,I=Object.getOwnPropertySymbols,at=Object.getPrototypeOf,N=Object.prototype.hasOwnProperty,pt=Object.prototype.propertyIsEnumerable;var L=(r,n,t)=>n in r?y(r,n,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[n]=t,$=(r,n)=>{for(var t in n||(n={}))N.call(n,t)&&L(r,t,n[t]);if(I)for(var t of I(n))pt.call(n,t)&&L(r,t,n[t]);return r};var ct=(r,n)=>{for(var t in n)y(r,t,{get:n[t],enumerable:!0})},B=(r,n,t,i)=>{if(n&&typeof n=="object"||typeof n=="function")for(let e of rt(n))!N.call(r,e)&&e!==t&&y(r,e,{get:()=>n[e],enumerable:!(i=st(n,e))||i.enumerable});return r};var d=(r,n,t)=>(t=r!=null?nt(at(r)):{},B(n||!r||!r.__esModule?y(t,"default",{value:r,enumerable:!0}):t,r)),mt=r=>B(y({},"__esModule",{value:!0}),r);var l=(r,n,t)=>new Promise((i,e)=>{var o=a=>{try{p(t.next(a))}catch(c){e(c)}},s=a=>{try{p(t.throw(a))}catch(c){e(c)}},p=a=>a.done?i(a.value):Promise.resolve(a.value).then(o,s);p((t=t.apply(r,n)).next())});var ht={};ct(ht,{BREAK:()=>U,MixCli:()=>S,MixCommand:()=>P,MixOption:()=>M,MixOptionPrompt:()=>C,addBuiltInOptions:()=>b,fixIndent:()=>x,getId:()=>dt,hyphenToCamelCase:()=>ft,importModule:()=>j,isDebug:()=>w,isDisablePrompts:()=>_,outputDebug:()=>m,outputStr:()=>lt,promptTypeMap:()=>E,showError:()=>ut,supportedPromptTypes:()=>W});module.exports=mt(ht);var Vt=require("flex-tools/string"),tt=require("flex-tools/events/liteEvent"),f=d(require("logsets")),et=require("flex-tools/object/assignObject");var X=require("commander"),H=d(require("prompts"));var F=require("commander");var D=require("flex-tools/typecheck/isPlainObject"),q=require("flex-tools/typecheck/isNumber");var k=d(require("logsets"));function lt(r,n){k.default.log(x(r),n)}function x(r,n){if((n==null||n===!0?0:typeof n=="number"?n:-1)==-1)return r;let i=r.split(`
2
+ `),e=i.reduce((o,s,p)=>{var c;if(p==0)return o;let a=((c=s.match(/^\s*/))==null?void 0:c[0].length)||0;return Math.min(o,a)},9999);return i=i.map(o=>o.substring(e)),i.join(`
3
+ `)}function b(r){r.option("--work-dirs <values...>","\u6307\u5B9A\u5DE5\u4F5C\u76EE\u5F55",{hidden:!0,optional:!0,required:!0,prompt:!1}),r.option("--disable-prompts","\u7981\u7528\u6240\u6709\u4EA4\u4E92\u63D0\u793A",{hidden:!0,prompt:!1}),r.option("--debug-cli","\u663E\u793A\u8C03\u8BD5\u4FE1\u606F",{hidden:!0,prompt:!1})}function w(){return process.argv.includes("--debug-cli")}function _(){return process.argv.includes("--disable-prompts")}function m(r,...n){let t=n.length==1&&typeof n[0]=="function"?n[0]():n;w()&&k.default.log(`[MixCli] ${r}`,...t)}function ut(r){w()?m("\u5BFC\u5165\u547D\u4EE4<>\u51FA\u9519:{}",r.stack):console.error(r)}function ft(r){return r.replace(/-([a-z])/g,(n,t)=>t.toUpperCase())}function dt(){return Math.random().toString(36).substr(2)}function j(r){return l(this,null,function*(){let n;try{n=require(r)}catch(t){throw n=(yield import(`file://${r}`)).default,t}return n})}var E={boolean:"confirm",string:"text",number:"number",array:"list",date:"date"},W=["text","password","invisible","number","confirm","list","toggle","select","multiselect","autocomplete","date","autocompleteMultiselect"],C=class{constructor(n,t){this.cliOption=n;this.params=t}isValidPromptType(n){return W.includes(String(n))}isNeedPrompt(n,t){let i=this.params,e=n||t,o=e!==void 0;return i===!0?!0:i===!1?!1:i==="auto"||(0,D.isPlainObject)(i)?!o:typeof i=="string"&&this.isValidPromptType(i)?!0:/(\<s*\w\s*\>)/.test(this.cliOption.flags)?!o:this.cliOption.argChoices&&this.cliOption.argChoices.indexOf(e)==-1?!0:!o}_getChoices(){var i;let n=[],t=(i=this.cliOption.params)==null?void 0:i.choices;if(this.cliOption.argChoices)n=this.cliOption.argChoices.map(e=>typeof e=="string"?{title:e,value:e}:e);else if(t)n=typeof t=="function"?t:[];else return[];return n}infer(n){let{variadic:t,defaultValue:i}=this.cliOption,e=n||i,o="text",s=this.params;if(this.isValidPromptType(s))o=s;else if((0,D.isPlainObject)(s))o=s.type;else{let p=/(\[\s*\w+\.\.\.\s*])|(\<\s*\w+\.\.\.\s*>)/.test(this.cliOption.flags),a=/(\<s*\w+\s*\>)|(\[\w+\])/.test(this.cliOption.flags),c=!/(\[\s*\w+s*])|(\<\s*\w+\s*>)/.test(this.cliOption.flags),O=(0,q.isNumber)(i),A=i&&i instanceof Date,g=Array.isArray(e)?"array":e instanceof Date?"date":typeof e,h=this.cliOption.params;if(h&&h.choices){let V=h.choices;c&&Array.isArray(V)&&V.length==2?o="toggle":o=t?"multiselect":"select"}else p?o="list":A?o="date":O?o="number":a?o="text":c||typeof i=="boolean"?o="confirm":g in E&&(o=E[g])}return m("\u9009\u9879<{}> -> \u63D0\u793A\u7C7B\u578B<{}>",[this.cliOption.name(),o]),o}get(n){var p;let{description:t,defaultValue:i}=this.cliOption,e=n||i;if(!this.isNeedPrompt(e,i))return;let o=this.infer(n),s=$({type:o,name:this.cliOption.attributeName(),message:t,initial:e},typeof this.params=="object"?this.params:{});if(s.validate=(p=this.cliOption.params)==null?void 0:p.validate,o=="multiselect"&&(s.instructions=!1),s.choices=s.choices||this._getChoices(),["select","multiselect"].includes(o)||o=="toggle"&&Array.isArray(s.choices)&&(s.active||(s.active=s.choices[0].value),s.inactive||(s.inactive=s.choices[1].value)),e&&typeof s.initial!="function"&&s.choices&&Array.isArray(s.choices))if(o=="select"){let a=Array.isArray(s.choices)?s.choices.findIndex(c=>c.value==e):-1;a!=-1&&(s.initial=a)}else o=="multiselect"&&s.choices.forEach(a=>{(Array.isArray(e)&&e.includes(a.value)||a.value==e)&&(a.selected=!0)});return s}};var M=class extends F.Option{constructor(t,i,e){super(t,i);this.params=e;this.__MIX_OPTION__=!0;this._setOption(e||{}),this.prompt=new C(this,e==null?void 0:e.prompt)}_setOption(t){t.default&&this.default(t.default,t.defaultDescription),t.conflicts&&this.conflicts(t.conflicts),t.envVar&&this.env(t.envVar),t.parseArg&&this.argParser(t.parseArg),t.hidden&&(this.hidden=t.hidden),t.mandatory&&this.makeOptionMandatory(t.mandatory),t.implies&&this.implies(t.implies),t.optional&&(this.optional=t.optional),t.variadic&&(this.variadic=t.variadic),t.negate&&(this.negate=t.negate),t.preset&&this.preset(t.preset),t.required&&(this.required=t.required),Array.isArray(t.choices)&&this.choices(t.choices.map(i=>typeof i=="string"?i:i.value))}getPrompt(t){var i;return(i=this.prompt)==null?void 0:i.get(t)}};var R=d(require("path")),T=d(require("fs"));var U=Symbol("BREAK_ACTION"),P=class extends X.Command{constructor(t){super(t);this.__MIX_COMMAND__=!0;this._beforeHooks=[];this._afterHooks=[];this._customPrompts=[];this._optionValues={};this._actions=[];this._enable_prompts=!0;let i=this;this.isRoot||b(this),this.hook("preAction",function(){return l(this,arguments,function*(){i._optionValues=i.getOptionValues(this.hookedCommand),yield i.preActionHook.apply(i,arguments)})})}get isRoot(){return this.parent==null}get optionValues(){return this._optionValues}get actions(){return this._actions}get beforeHooks(){return this._beforeHooks}get afterHooks(){return this._afterHooks}get fullname(){let t=[this.name()],i=this.parent;for(;i;)i.name()!=="root"&&t.unshift(i.name()),i=i.parent;return t.join(".")}root(){let t=this;for(;t&&t.parent!=null;)t=t.parent;return t}action(){let t=arguments[0];if(arguments.length==1&&typeof t=="function")this._actions.push({id:Math.random().toString(36).substring(2),enhance:!1,fn:t});else if(arguments.length==2&&typeof t=="function"&&typeof arguments[1]=="object"){let i=arguments[0],e=Object.assign({at:"append"},arguments[1]);e.at=="replace"&&(this._actions=[]);let o={id:e.id||Math.random().toString(36).substring(2),enhance:e.enhance==null?!0:e.enhance,fn:i};typeof e.at=="number"?this._actions.splice(Number(e.at),0,o):["append","before"].includes(e.at)?this._actions.push(o):["preappend","after"].includes(e.at)?this._actions.splice(0,0,o):this._actions.push(o)}else console.log("[mixcli] action params error");return super.action(this.getWrapperedAction())}getOptionValues(t){let i={},e=t;for(;e;)Object.assign(i,e.optionValues),e=e.parent;return i}getWrapperedAction(){return this.wrapperWorkDirsAction(this.wrapperChainActions())}getAncestorCommands(){let t=[],i=this;for(;i;)i=i.parent,i&&t.push(i);return t}wrapperChainActions(){let t=this;return function(){return l(this,arguments,function*(){let i=Array.from(arguments),e,o={},s=[],p;i.length>=2&&(p=i[i.length-1],o=i[i.length-2],s=i.slice(0,i.length-2)),yield t.executeBeforeHooks({args:s,options:o,command:p});try{for(let a of t._actions)try{if(a.enhance?(m("\u6267\u884C<{}>: args={}, options={}",()=>[t.name(),s,o]),e=yield a.fn.call(this,{command:p,value:e,args:s,options:o})):e=yield a.fn.apply(this,i),e===U)break}catch(c){throw m("\u547D\u4EE4{}\u7684Action({})\u6267\u884C\u51FA\u9519:{}",[t.name,a.id,c]),c}}finally{yield t.executeAfterHooks({value:e,args:s,options:o,command:p})}})}}wrapperWorkDirsAction(t){let i=this;return function(){return l(this,arguments,function*(){let e=i._optionValues.workDirs;if(!e)return yield t.apply(this,Array.from(arguments));Array.isArray(e)||(e=e.split(",")),e=e.reduce((o,s)=>(typeof s=="string"&&o.push(...s.split(",")),o),[]);for(let o of e){let s=process.cwd();try{R.default.isAbsolute(o)||(o=R.default.join(s,o)),T.default.existsSync(o)&&T.default.statSync(o).isDirectory()?(m("\u5207\u6362\u5230\u5DE5\u4F5C\u76EE\u5F55:{}",o),process.chdir(o),yield t.apply(this,Array.from(arguments))):m("\u65E0\u6548\u7684\u5DE5\u4F5C\u76EE\u5F55:{}",o)}finally{process.chdir(s)}}})}}getOption(t){return this.options.find(i=>i.name()==t)}before(t,i=!0){return this._beforeHooks.push([t,i]),this}executeBeforeHooks(t){return l(this,null,function*(){let i=this.beforeHooks.map(([e,o])=>[e,o,this]);this.getAncestorCommands().forEach(e=>{i.unshift(...e.beforeHooks.map(([o,s])=>[o,s,e]))});for(let[e,o,s]of i)o&&(yield e.call(s,t))})}after(t,i=!0){return this._afterHooks.push([t,i]),this}executeAfterHooks(t){return l(this,null,function*(){let i=this.afterHooks.map(([e,o])=>[e,o,this]);this.getAncestorCommands().forEach(e=>{i.push(...e.afterHooks.map(([o,s])=>[o,s,e]))});for(let[e,o,s]of i)o&&(yield e.call(s,t))})}preActionHook(t){return l(this,null,function*(){if(this.isEnablePrompts()){let i=[...this.generateAutoPrompts(),...this._customPrompts];if(i.length>0){let e=yield(0,H.default)(i);Object.entries(e).forEach(([o,s])=>{t.setOptionValue(o,s)})}}})}isEnablePrompts(){return _()?!1:this._enable_prompts}generateAutoPrompts(){let i=this.options.filter(e=>!e.hidden&&e.__MIX_OPTION__).map(e=>e.getPrompt(this._optionValues[e.attributeName()])).filter(e=>e);return m("\u547D\u4EE4<{}>\u81EA\u52A8\u751F\u6210{}\u4E2A\u9009\u9879\u63D0\u793A:{}",[this.name(),i.length,i.map(e=>`${e.name}(${e.type})`).join(",")]),i}option(t,i,e){let o=new M(t,i,e);return o.required&&!this.isEnablePrompts()&&(o.mandatory=!0),this.addOption(o)}prompt(t){return this._customPrompts.push(...Array.isArray(t)?t:[t]),this}selectCommands(){return l(this,null,function*(){let t=this.commands.map(o=>({title:`${o.description()}(${o.name()})`,value:o.name()})),i=yield(0,H.default)({type:"select",name:"command",message:"\u8BF7\u9009\u62E9\u547D\u4EE4:",choices:t}),e=this.commands.find(o=>o.name()===i.command);yield e==null?void 0:e.parseAsync([i.command],{from:"user"})})}disablePrompts(){return this._enable_prompts=!1,this}enablePrompts(){return this._enable_prompts=!0,this}};var G=require("flex-tools/package/getPackageJson"),J=require("flex-tools/package/getPackageRootPath"),Q=require("glob");var v=d(require("fs")),u=d(require("path"));function K(r){let n=this.options.include;if(!(n instanceof RegExp))return[];let{dependencies:t={},devDependencies:i={},peerDependencies:e={},optionalDependencies:o={},bundleDependencies:s={}}=(0,G.getPackageJson)(r);return[...Object.keys(t),...Object.keys(i),...Object.keys(e),...Object.keys(o),...Object.keys(s)].filter(a=>a!=="@voerka/cli"&&n.test(a))}function z(r,n){return(n?Array.isArray(n)?n:[n]:[]).some(i=>typeof i=="string"?new RegExp(i).test(r):i instanceof RegExp?i.test(r):!1)}function Y(r,n){let t=this.options.include,i=this.options.exclude;if(!t)return[];let e=(0,J.getPackageRootPath)(n||process.cwd()),o=r?u.default.dirname(require.resolve(r,{paths:[e]})):e;if(!o)return m("MixCli\u53EA\u80FD\u8FD0\u884C\u5728Nodejs\u73AF\u5883"),[];let s=K.call(this,o),p=[];return n!==void 0&&p.push(u.default.join(o,this.options.cliDir)),s.filter(a=>z(a,t)&&!z(a,i)).forEach(a=>{m("\u5339\u914D\u5305:{}",`${r?a+" <- "+r:a}`);try{let c=u.default.dirname(require.resolve(a,{paths:o?[o]:[process.cwd()]})),O=u.default.join(c,this.options.cliDir),A=K.call(this,c);p.push(...A.reduce((g,h)=>(m("\u5339\u914D\u5305:{}",`${h} <- ${a}`),g.push(...Y.call(this,h,c)),g),[])),v.default.existsSync(O)&&p.push(O)}catch(c){m("\u89E3\u6790\u5305<{}>\u8DEF\u5F84\u51FA\u9519\uFF1A{}",[a,c.stack])}}),[...new Set(p)]}function Z(r){return l(this,null,function*(){let n=Y.call(r),t=[],i=[];n.forEach(e=>{(0,Q.globSync)("*",{cwd:e,absolute:!0}).forEach(o=>{if(u.default.basename(o).startsWith("_"))return;let p=u.default.extname(o).toLowerCase();[".js",".cjs",".mjs"].includes(p)?i.push(o):v.default.statSync(o).isDirectory()&&(i.push(u.default.join(o,"index.js")),i.push(u.default.join(o,"index.cjs")),i.push(u.default.join(o,"index.mjs")))})});for(let e of i)if(v.default.existsSync(e))try{if(m("\u5BFC\u5165\u547D\u4EE4:{}",e),e.endsWith(".cjs")||e.endsWith(".js"))t.push(yield j(e));else if(e.endsWith(".mjs")){let o=yield import(`file://${e}`);t.push(o.default)}}catch(o){m(o)}return t})}var it=require("flex-tools/async/asyncSignal"),ot=d(require("string.prototype.replaceall"));ot.default.shim();var S=class extends tt.LiteEvent{constructor(t){super();this.findSignals=[];this.options=(0,et.assignObject)({name:"mixcli",package:null,cliDir:"cli",prompt:"auto",ignoreError:!1},t),this.createRootCommand()}get context(){return this.options.context}get name(){return this.options.name}get isDisabledPrompts(){return this.root.rawArgs.includes("--no-prompts")}installCommands(){return l(this,null,function*(){let t=yield Z(this);for(let i of t)try{if(typeof i=="function"){let e=i(this);e=e?Array.isArray(e)?e:[e]:[],this.register(()=>e)}}catch(e){m("\u6CE8\u518C\u547D\u4EE4\u5931\u8D25:{}",e.stack)}})}createRootCommand(){this.root=new P(this.name),this.root.helpOption("-h, --help").action(()=>{this.options.logo&&f.default.log(x(this.options.logo,2)),console.log();let t=this.options.title||this.options.name;Array.isArray(t)?f.default.log(String(t[0]).firstUpper(),[...t.slice(1)]):f.default.log(`${t.firstUpper()} Version: {}`,this.options.version),this.options.description&&f.default.log(f.default.colors.darkGray(this.options.description)),console.log(),this.root.help()}),b(this.root),this.options.before&&this.root.hook("preAction",this.options.before),this.options.after&&this.root.hook("postAction",this.options.after)}addHelp(t,{pos:i="beforeAll",alignIndent:e=!0}){e&&(t=x(t,e)),this.root.addHelpText(i,t)}register(t){if(typeof t=="function"){let i=t(this),e=i instanceof Array?i:i==null?[]:[i];for(let o of e)o.__MIX_COMMAND__?this.hasCommand(o.name())?f.default.error(`Command <${o.name()}> has been registered!`):(m("\u6CE8\u518C\u547D\u4EE4:{}",o.fullname),this.root.addCommand(o),o._cli=this,this.emit("register",o.fullname,!0)):f.default.error(`Command <${o.toString()}> is not a valid command!`)}else f.default.error("Invalid command")}hasCommand(t){return this.root.commands.some(i=>i.name()==t)}get(t){let i=t.split("."),e=this.root,o;for(;i.length>0;){let s=i.shift(),p=e.commands.find(a=>a.name()==s);p&&i.length==0&&(o=p),e=p}return o}find(t){let i=this.get(t);if(i)return Promise.resolve(i);{let e=(0,it.asyncSignal)();return this.findSignals.push(e),new Promise(o=>{let s;s=this.on("register",p=>{p==`${this.name}.${t}`&&(s.off(),e.resolve(),this.findSignals=this.findSignals.filter(a=>a!=e),o(this.get(t)))},{objectify:!0})})}}exists(t){return t in this.root.commands?!0:this.get(t)!=null}run(){this.installCommands().then(()=>Promise.all(this.findSignals.map(t=>t(1e4))).then(()=>{this.root.parseAsync(process.argv)}))}};0&&(module.exports={BREAK,MixCli,MixCommand,MixOption,MixOptionPrompt,addBuiltInOptions,fixIndent,getId,hyphenToCamelCase,importModule,isDebug,isDisablePrompts,outputDebug,outputStr,promptTypeMap,showError,supportedPromptTypes});
4
4
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/command.ts","../src/option.ts","../src/prompt.ts","../src/utils.ts","../src/finder.ts"],"sourcesContent":["#!/usr/bin/env node\nimport \"flex-tools/string\"\nimport { LiteEvent, LiteEventSubscriber } from \"flex-tools/events/liteEvent\"\nimport { Command } from \"commander\"\nimport logsets from \"logsets\"\n\nimport { assignObject } from \"flex-tools/object/assignObject\"\nimport { MixCommand } from \"./command\"\nimport { addBuiltInOptions, fixIndent, outputDebug } from './utils';\nimport { findCommands } from \"./finder\"\nimport { asyncSignal } from \"flex-tools/async/asyncSignal\"\n// @ts-ignore\nimport replaceAll from 'string.prototype.replaceall' \nreplaceAll.shim() \n\nexport interface MixCliOptions{\n name:string,\n title?:string | (string | boolean | number)[],\n description?:string,\n version?:string\n // 定义显示帮助信息\n logo?:string ,\n // 在根命令执行前执行==commander的preAction\n before?:(thisCommand:Command,actionCommand:Command)=>void,\n // 在根命令执行后执行==commander的postAction\n after?:(thisCommand:Command,actionCommand:Command)=>void, \n // flexcli运行时会在当前工程的package.json的依赖中查找以prefix/开头的包,然后自动加载其cli目录下的命令\n // 例如:prefix=myapp,则会自动加载flex-cli-xxx包中的cli目录下的命令\n // 如prefix=myapp, cliPath=\"cmds\",则会自动加载flex-cli-xxx包中的cmds目录下的命令\n include?:string | RegExp | string[] | RegExp[],\n // 忽略查找正则表达式\n exclude?:string | RegExp | string[] | RegExp[],\n // flexcli会在当前工程的以prefix/开头下查找命令声明\n // / pattern默认值是cli,即会在当前工程的以prefix/开头的包下查找cli目录下的命令\n // 指定cli所在的目录,默认值是cli,要遍历该目录下的所有js文件作为命令导出\n cliDir?:string \n context?:Record<string,any> // 传递给命令的共享上下文,所有命令均可要使用 \n // 默认是否启用交互提示, auto当没有值时,会根据当前是否在终端中运行来决定是否启用交互提示\n // 为false时,禁用所有交互提示,为true时,启用所有交互提示 \n prompt?:'auto' | boolean \n ignoreError?:boolean\n}\n\n \n \n\nexport type MixCliCommand = (cli:MixCli)=>MixCommand | MixCommand[] | void\n\n\nexport type MixCliEvents = \n \"register\" // 当命令注册时触发\n\nexport class MixCli extends LiteEvent<any,MixCliEvents>{\n options:Required<MixCliOptions> \n root!:MixCommand \n private findSignals:any[]=[]\n constructor(options?:MixCliOptions){\n super()\n this.options= assignObject({\n name : \"mixcli\",\n package : null,\n cliDir : \"cli\",\n prompt : 'auto',\n ignoreError: false\n },options) as Required<MixCliOptions> \n this.createRootCommand() \n } \n get context(){return this.options.context}\n get name(){return this.options.name}\n /**\n * 是否禁用了所有的交互提示\n */\n get isDisabledPrompts(){\n return(this.root as any).rawArgs.includes(\"--no-prompts\") \n } \n /**\n * 扫描当前工程的依赖,加载匹配include的依赖下的命令\n */\n private async installCommands(){\n const cmders = await findCommands(this)\n for(let cmder of cmders){\n try{\n if(typeof(cmder)===\"function\"){\n let cmds = cmder(this)\n cmds = cmds ? (Array.isArray(cmds) ? cmds : [cmds]) : []\n this.register(()=>cmds) \n }\n }catch(e:any){\n outputDebug(\"注册命令失败:{}\",e.stack)\n }\n }\n } \n /**\n * 创建根命令\n * \n */\n private createRootCommand(){\n this.root = new MixCommand(this.name);\n this.root \n .helpOption('-h, --help')\n .action(()=>{ \n if(this.options.logo) logsets.log(fixIndent(this.options.logo,2))\n console.log()\n // 显示标题\n let title = this.options.title|| this.options.name\n if(Array.isArray(title)){\n logsets.log(String(title[0]).firstUpper(),[...title.slice(1)])\n }else{\n logsets.log(`${title.firstUpper()} Version: {}`,this.options.version)\n } \n // @ts-ignore\n if(this.options.description) logsets.log(logsets.colors.darkGray(this.options.description)) \n console.log()\n this.root.help() \n }) \n addBuiltInOptions(this.root)\n if(this.options.before) this.root.hook('preAction',this.options.before)\n if(this.options.after) this.root.hook('postAction',this.options.after) \n } \n /**\n * 添加帮助选项\n * \n * @param text 帮助文本\n * @param position 显示位置,可选值:before|after|beforeAll|afterAll\n * @param fixIndent 是否自动修正缩进,如果为true,则会自动修正缩进,当显示多行时文本时,会自动修正缩进\n * \n */\n public addHelp(text:string,{pos='beforeAll',alignIndent=true}:{pos:'before'|'after' | 'beforeAll' | 'afterAll',alignIndent?:boolean | number}){\n if(alignIndent) text = fixIndent(text,alignIndent)\n this.root.addHelpText(pos,text)\n }\n\n /**\n * 注册一个命令\n * @param cmd \n */\n register(cmd:MixCliCommand){\n if(typeof(cmd)==\"function\"){\n let result = cmd(this)\n let cmds = result instanceof Array ? result : (result==undefined ? [] : [result])\n for(let cmd of cmds){\n // 为什么不用cmd instanceof MixCommand来判断是否是一个有效的命令?\n // 因为当不同的包引用了与主包不一样版本的mixcli时,判断会失效,导致不能识别\n // 所以我们通过cmd.__MIX_COMMAND__来判断是否是一个有效的命令\n if(cmd.__MIX_COMMAND__){ \n if(this.hasCommand(cmd.name())){\n logsets.error(`Command <${cmd.name()}> has been registered!`)\n }else{\n outputDebug(\"注册命令:{}\",cmd.fullname)\n this.root.addCommand(cmd as Command) ;\n (cmd as any)._cli = this\n this.emit(\"register\",cmd.fullname,true)\n } \n }else{\n logsets.error(`Command <${cmd.toString()}> is not a valid command!`)\n }\n } \n }else{\n logsets.error(\"Invalid command\")\n } \n }\n\n hasCommand(name:string):boolean{\n return this.root.commands.some(c=>c.name()==name)\n }\n\n /**\n * 根据命令名称查找命令\n * \n * @remarks\n * \n * find(\"dev\")\n * find(\"dev.microservice\") 支持多级命令\n * find(\"abc\",DevCommand) 允许指定从DevCommand下开始查找abc命令\n * \n * @param name \n */\n get(name:string):MixCommand | undefined{\n const names=name.split(\".\")\n let curCmd:MixCommand = this.root\n let resultCmd:MixCommand | undefined\n while(names.length>0){\n const topName = names.shift()\n const r = curCmd.commands.find(c=>c.name()==topName) as MixCommand\n if(r && names.length==0){\n resultCmd = r\n }\n curCmd = r\n } \n return resultCmd \n }\n /**\n * 查找一个命令\n * \n * 如果命令不存在,则等待命令注册后再返回\n * \n * 在多包场景下,如果命令在其他包中注册并且该包中的命令还没注册,则会等待命令注册后再返回\n * \n * @param name \n * @returns \n */\n find(name:string):Promise<MixCommand | undefined>{\n const cmd = this.get(name)\n if(cmd){\n return Promise.resolve(cmd) \n }else{\n const signal = asyncSignal()\n this.findSignals.push(signal)\n return new Promise<MixCommand | undefined>((resolve)=>{\n let listener:LiteEventSubscriber\n listener = this.on(\"register\",(fullname:string)=>{\n if(fullname==`${this.name}.${name}`){\n listener.off()\n signal.resolve()\n this.findSignals = this.findSignals.filter(s=>s!=signal)\n resolve(this.get(name))\n }\n },{objectify:true}) as LiteEventSubscriber\n })\n } \n }\n /**\n * 判断命令是否存在\n * \n * @param name \n * @returns \n */\n exists(name:string):boolean{\n if(name in this.root.commands){\n return true\n }else{\n return this.get(name) != undefined\n }\n } \n \n /**\n * 运行命令行程序\n */\n run(){ \n // 为什么有findSignal这玩意,解决什么问题?\n // 当我们要扩展command时,通过get(\"命令名称\")来获取已经注册的命令的方式有个缺陷\n // 就是如果对命令的注册顺序有严格的要求,比如调用get('dev')时要求dev命令必须已经存在\n // 这对动态包的命令注册扩展开发体验不好\n // 所以引入find(\"命令名称\")来获取命令,该方法可以获取到后注册的命令\n // 其副作用是,在run时,可能find还没有运行到,从而导致在帮助信息里面看不到扩展的信息(实际上是已经生效的)\n // 所以我们在find里面注入一个异步信号来解决此问题\n this.installCommands().then(()=>{\n return Promise.all(this.findSignals.map(signal=>signal(10000))).then(()=>{\n this.root.parseAsync(process.argv); \n })\n }) \n }\n}\n ","import { Command, Option } from \"commander\";\nimport prompts, { PromptObject } from \"prompts\";\nimport { MixOption, type MixedOptionParams } from \"./option\";\nimport { addBuiltInOptions, hyphenToCamelCase, isDisablePrompts, outputDebug } from \"./utils\";\nimport type { AsyncFunction } from \"flex-tools/types\"; \nimport path from \"node:path\";\nimport fs from \"node:fs\";\n\n\n\nexport type IMixCommandHookListener = ({\n\targs,\n\toptions,\n\tcommand,\n}: {\n\targs: any[];\n\toptions: Record<string, any>;\n\tcommand: MixCommand;\n}) => void | Promise<void>;\n\nexport type BeforeMixCommandHookListener = ({\n\targs,\n\toptions,\n\tcommand,\n}: {\n\targs: any[];\n\toptions: Record<string, any>;\n\tcommand: MixCommand;\n}) => void | Promise<void>;\n\nexport type AfterMixCommandHookListener = ({\n\tvalue,\n\targs,\n\toptions,\n\tcommand,\n}: {\n\tvalue: any;\n\targs: any[];\n\toptions: Record<string, any>;\n\tcommand: MixCommand;\n}) => void | Promise<void>;\n\nexport interface MixActionOptions {\n\tid: string;\n\tat: \"replace\" | \"before\" | \"after\" | \"preappend\" | \"append\" | number;\t\n\tenhance: boolean;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 函数签名类型,即采用原始的commander的action函数签名,还是mixcli的action函数签名\n}\n\nexport interface MixActionRegistry extends Omit<MixActionOptions, \"at\"> {\n\tfn: Function;\n}\n\n// 原始的Action动作函数\nexport type MixOriginalAction = (...args: any[]) => any | Promise<void>;\n\n// 增强的Action函数签名\nexport type MixEnhanceAction = ({\n\targs,\n\toptions,\n\tvalue,\n\tcommand,\n}: {\n\targs: any[];\n\toptions: Record<string, any>;\n\tvalue: any;\n\tcommand: MixCommand;\n}) => any | Promise<any>;\n\n// 执行action的返回结果\nexport const BREAK = Symbol(\"BREAK_ACTION\"); // 中止后续的action执行\n\nexport class MixCommand extends Command {\n\t__MIX_COMMAND__ = true;\n\tprivate _beforeHooks : [ BeforeMixCommandHookListener, boolean ][] = [];\n\tprivate _afterHooks : [ AfterMixCommandHookListener, boolean ][] = [];\n\tprivate _customPrompts : PromptObject[] = [];\n\tprivate _optionValues : Record<string, any> = {}; \t\t\t\t\t\t\t// 命令行输入的选项值\n\tprivate _actions : MixActionRegistry[] = []; \t\t\t\t\t\t\t// 允许多个action\n\tprivate _enable_prompts: boolean = true; \t\t\t\t\t\t\t\t\t// 是否启用交互提示\n\tconstructor(name?: string) {\n\t\tsuper(name);\t\t\n\t\t// eslint-disable-next-line no-this-alias\n\t\tconst self = this\n\t\tif (!this.isRoot) addBuiltInOptions(this); \n\t\tthis.hook(\"preAction\", async function (this: any) {\n\t\t\tself._optionValues = self.getOptionValues(this.hookedCommand);\t\t\t\n\t\t\t// @ts-ignore\n\t\t\tawait self.preActionHook.apply(self, arguments);\n\t\t});\n\t} \n\tget isRoot() { return this.parent==undefined;\t}\n\tget optionValues(){ return this._optionValues }\n\tget actions() { return this._actions; }\n\tget beforeHooks() {\treturn this._beforeHooks; }\n\tget afterHooks() {return this._afterHooks;}\n\tget fullname() {\n\t\tlet names = [this.name()];\n\t\tlet parent = this.parent;\n\t\twhile (parent) {\n\t\t\tif (parent.name() !== \"root\") {\n\t\t\t\tnames.unshift(parent.name());\n\t\t\t}\n\t\t\tparent = parent.parent;\n\t\t}\n\t\treturn names.join(\".\");\n\t}\n\n\t/**\n\t * 返回根命令\n\t */\n\troot() { \n\t\t// eslint-disable-next-line no-this-alias\n\t\tlet root:any = this;\n\t\twhile (root && root.parent != null) {\n\t\t\troot = root.parent as unknown as MixCommand;\n\t\t}\n\t\treturn root;\n\t}\n\n\n\taction(fn: MixEnhanceAction, options: MixActionOptions): this;\n\taction(fn: MixOriginalAction): this;\n\taction(): this {\n\t\tconst actionFunc = arguments[0];\n\t\tif (arguments.length == 1 && typeof actionFunc == \"function\") {\n\t\t\t// 原始方式\n\t\t\tthis._actions.push({\n\t\t\t\tid: Math.random().toString(36).substring(2),\n\t\t\t\tenhance: false,\n\t\t\t\tfn: actionFunc,\n\t\t\t});\n\t\t} else if (arguments.length == 2 && typeof actionFunc == \"function\" && typeof arguments[1] == \"object\" ) {\n\t\t\t// 增强模式\n\t\t\tconst actionFn = arguments[0];\n\t\t\tconst actionOpts: MixActionOptions = Object.assign({ at: \"append\" }, arguments[1]);\n\t\t\tif (actionOpts.at == \"replace\") this._actions = [];\n\t\t\tconst actionItem = {\n\t\t\t\tid: actionOpts.id || Math.random().toString(36).substring(2),\n\t\t\t\tenhance: actionOpts.enhance == undefined ? true : actionOpts.enhance,\n\t\t\t\tfn: actionFn,\n\t\t\t} as const;\n\t\t\tif (typeof actionOpts.at == \"number\") {\n\t\t\t\tthis._actions.splice(Number(actionOpts.at), 0, actionItem);\n\t\t\t} else if ([\"append\", \"before\"].includes(actionOpts.at)) {\n\t\t\t\tthis._actions.push(actionItem);\n\t\t\t} else if ([\"preappend\", \"after\"].includes(actionOpts.at)) {\n\t\t\t\tthis._actions.splice(0, 0, actionItem);\n\t\t\t} else {\n\t\t\t\tthis._actions.push(actionItem);\n\t\t\t}\n\t\t} else {\n\t\t\tconsole.log(\"[mixcli] action params error\");\n\t\t}\n\t\treturn super.action(this.getWrapperedAction());\n\t}\n\n\t/**\n\t * 读取命令配置值,包括父命令提供的配置选项\n\t * @param command\n\t */\n\tprivate getOptionValues(command: MixCommand) {\n\t\tconst opts = {};\n\t\t// eslint-disable-next-line no-this-alias\n\t\tlet parent: any = command;\n\t\twhile (parent) {\n\t\t\tObject.assign(opts, (parent as MixCommand).optionValues);\n\t\t\tparent = parent.parent;\n\t\t}\n\t\treturn opts;\n\t}\n\t/**\n\t * 本函数在运行时子类进行action生成该命令的action\n\t */\n\tprivate getWrapperedAction() {\n\t\treturn this.wrapperWorkDirsAction(this.wrapperChainActions());\n\t}\n\n\t/**\n\t * 向上查找所有祖先命令\n\t */\n\tprivate getAncestorCommands(): MixCommand[] {\n\t\tlet cmds: MixCommand[] = [];\n\t\t// eslint-disable-next-line no-this-alias\n\t\tlet cmd: MixCommand | null = this;\n\t\twhile (cmd) {\n\t\t\tcmd = cmd.parent as unknown as MixCommand;\n\t\t\tif (cmd) {\n\t\t\t\tcmds.push(cmd);\n\t\t\t}\n\t\t}\n\t\treturn cmds;\n\t}\n\t/***\n\t * 将所有actions包装成一个链式调用的函数\n\t */\n\tprivate wrapperChainActions() {\n\t\t// eslint-disable-next-line no-this-alias\n\t\tconst self = this;\n\t\treturn async function (this: any) {\n\t\t\tconst args = Array.from(arguments); // 原始输入的参数\n\t\t\tlet preValue: any; // 保存上一个action的返回值\n\t\t\t//解析参数, 0-1个参数为options,最后一个参数为command\n\t\t\tlet actionOpts: Record<string, any> = {},\n\t\t\t\tactionArgs: any[] = [],\n\t\t\t\tcmd: any;\n\t\t\tif (args.length >= 2) {\n\t\t\t\tcmd = args[args.length - 1]; // 最后一个command\n\t\t\t\tactionOpts = args[args.length - 2];\n\t\t\t\tactionArgs = args.slice(0, args.length - 2);\n\t\t\t}\n\t\t\tawait self.executeBeforeHooks({ args: actionArgs, options: actionOpts, command: cmd });\n\t\t\ttry {\n\t\t\t\tfor (let action of self._actions) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (action.enhance) {\n\t\t\t\t\t\t\t// 增强模式\n\t\t\t\t\t\t\toutputDebug(\"执行<{}>: args={}, options={}\", () => [\n\t\t\t\t\t\t\t\tself.name(),\n\t\t\t\t\t\t\t\tactionArgs,\n\t\t\t\t\t\t\t\tactionOpts,\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\tpreValue = await action.fn.call(this, {\n\t\t\t\t\t\t\t\tcommand: cmd,\n\t\t\t\t\t\t\t\tvalue : preValue,\n\t\t\t\t\t\t\t\targs : actionArgs,\n\t\t\t\t\t\t\t\toptions: actionOpts,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// 原始模式\n\t\t\t\t\t\t\tpreValue = await action.fn.apply(this, args);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (preValue === BREAK) break;\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\toutputDebug(\"命令{}的Action({})执行出错:{}\", [self.name, action.id, e]);\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tawait self.executeAfterHooks({\n\t\t\t\t\tvalue: preValue,\n\t\t\t\t\targs: actionArgs,\n\t\t\t\t\toptions: actionOpts,\n\t\t\t\t\tcommand: cmd,\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t}\n\t/**\n\t * 当传入--work-dirs时用来处理工作目录\n\t */\n\tprivate wrapperWorkDirsAction(fn: AsyncFunction) {\n\t\t// eslint-disable-next-line no-this-alias\n\t\tconst self = this;\n\t\treturn async function (this: any) {\n\t\t\tlet workDirs = self._optionValues.workDirs;\n\t\t\t// 未指定工作目录参数\n\t\t\tif (!workDirs) {\n\t\t\t\treturn await fn.apply(this, Array.from(arguments));\n\t\t\t}\n\t\t\tif (!Array.isArray(workDirs)) workDirs = workDirs.split(\",\");\n\t\t\tworkDirs = workDirs.reduce((dirs: any[], dir: string) => {\n\t\t\t\tif (typeof dir == \"string\") dirs.push(...dir.split(\",\"));\n\t\t\t\treturn dirs;\n\t\t\t}, []);\n\t\t\tfor (let workDir of workDirs) {\n\t\t\t\tconst cwd = process.cwd();\n\t\t\t\ttry {\n\t\t\t\t\tif (!path.isAbsolute(workDir)) workDir = path.join(cwd, workDir);\n\t\t\t\t\tif (fs.existsSync(workDir) && fs.statSync(workDir).isDirectory()) {\n\t\t\t\t\t\toutputDebug(\"切换到工作目录:{}\", workDir);\n\t\t\t\t\t\tprocess.chdir(workDir); // 切换\n\t\t\t\t\t\tawait fn.apply(this, Array.from(arguments));\n\t\t\t\t\t} else {\n\t\t\t\t\t\toutputDebug(\"无效的工作目录:{}\", workDir);\n\t\t\t\t\t} \n\t\t\t\t} finally {\n\t\t\t\t\tprocess.chdir(cwd);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\tgetOption(name: string): MixOption {\n\t\treturn this.options.find((option) => option.name() == name) as unknown as MixOption;\n\t}\n\t/**\n\t * 添加一个Before钩子\n\t * @param listener\n\t * @param scope =false时代表只在本命令执行,=true时代表在本命令及其子命令执行\n\t * @returns\n\t */\n\tbefore(listener: BeforeMixCommandHookListener, scope: boolean = true) {\n\t\tthis._beforeHooks.push([listener, scope]);\n\t\treturn this;\n\t}\n\tprivate async executeBeforeHooks(args: any) {\n\t\tconst hooks: [BeforeMixCommandHookListener, boolean, MixCommand][] = this.beforeHooks.map(\n\t\t\t([hook, scope]) => [hook, scope, this]\n\t\t);\n\t\tthis.getAncestorCommands().forEach((cmd: MixCommand) => {\n\t\t\thooks.unshift(\n\t\t\t\t...cmd.beforeHooks.map(([hook, scope]) => {\n\t\t\t\t\treturn [hook, scope, cmd] as [BeforeMixCommandHookListener, boolean, MixCommand];\n\t\t\t\t})\n\t\t\t);\n\t\t});\n\t\tfor (let [hook, scope, cmd] of hooks) {\n\t\t\tif (!scope) continue;\n\t\t\tawait hook.call(cmd, args);\n\t\t}\n\t}\n\t/**\n\t * 添加一个After钩子\n\t * @param listener\n\t * @param scope =false时代表只在本命令执行,=true时代表在本命令及其子命令执行\n\t * @returns\n\t */\n\tafter(listener: AfterMixCommandHookListener, scope: boolean = true) {\n\t\tthis._afterHooks.push([listener, scope]);\n\t\treturn this;\n\t}\n\n\tprivate async executeAfterHooks(args: any) {\n\t\tconst hooks: [AfterMixCommandHookListener, boolean, MixCommand][] = this.afterHooks.map(\n\t\t\t([hook, scope]) => [hook, scope, this]\n\t\t);\n\t\tthis.getAncestorCommands().forEach((cmd: MixCommand) => {\n\t\t\thooks.push(\n\t\t\t\t...cmd.afterHooks.map(([hook, scope]) => {\n\t\t\t\t\treturn [hook, scope, cmd] as [BeforeMixCommandHookListener, boolean, MixCommand];\n\t\t\t\t})\n\t\t\t);\n\t\t});\n\t\tfor (let [hook, scope, cmd] of hooks) {\n\t\t\tif (!scope) continue; //=false时不执行\n\t\t\tawait hook.call(cmd, args);\n\t\t}\n\t}\n\tprivate async preActionHook(thisCommand: Command) {\n\t\tif (this.isEnablePrompts()) {\n\t\t\t// 自动生成提示\n\t\t\tconst questions: PromptObject[] = [\n\t\t\t\t...this.generateAutoPrompts(),\n\t\t\t\t...this._customPrompts,\n\t\t\t];\n\t\t\t// 用户提示\n\t\t\tif (questions.length > 0) {\n\t\t\t\tconst results = await prompts(questions);\n\t\t\t\tObject.entries(results).forEach(([key, value]) => {\n\t\t\t\t\tthisCommand.setOptionValue(key, value);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate isEnablePrompts() {\n\t\tif (isDisablePrompts()) {\t\t\t\n\t\t\treturn false;// 命令行参数禁用了提示,优先级最高\n\t\t} else {\n\t\t\treturn this._enable_prompts;\n\t\t}\n\t}\n\n\t/**\n\t * 生成选项自动提示\n\t *\n\t * @remarks\n\t * 要求所有未提供默认值的Option自动生成提示\n\t *\n\t * - 未提供默认值,并且是必选的参数Option\n\t * - 指定了choices但未提供有效值的Option\n\t *\n\t */\n\tprivate generateAutoPrompts(): PromptObject[] {\n\t\tconst options = this.options as unknown as MixOption[];\n\t\tconst optionPromports = options\n\t\t\t.filter((option) => !option.hidden && option.__MIX_OPTION__)\n\t\t\t.map((option) => option.getPrompt(this._optionValues[option.attributeName()]))\n\t\t\t.filter((prompt) => prompt) as PromptObject[];\n\t\t\t\n\t\toutputDebug(\"命令<{}>自动生成{}个选项提示:{}\", [\n\t\t\tthis.name(),\n\t\t\toptionPromports.length,\n\t\t\toptionPromports.map((prompt) => `${prompt.name}(${prompt.type})`).join(\",\"),\n\t\t]);\n\t\treturn optionPromports;\n\t} \n\n\t// @ts-ignore\n\toption( flags: string, description: string, options?: MixedOptionParams ):this{ \n \t\tconst option = new MixOption(flags, description, options);\n\t\tif (option.required && !this.isEnablePrompts()) option.mandatory = true;\t\t\n\t\treturn this.addOption(option as unknown as Option) \n\t}\n\n\t/**\n\t * 添加提示\n\t *\n\t * @remarks\n\t *\n\t * 添加一些自定义提示 \n\t *\n\t * @param questions\n\t * @returns\n\t */\n\tprompt(questions: PromptObject | PromptObject[]) {\n\t\tthis._customPrompts.push(...(Array.isArray(questions) ? questions : [questions]));\n\t\treturn this;\n\t}\n\n\t/**\n\t *\n\t * 选择命令并执行\n\t *\n\t * @remorks\n\t *\n\t * 当命令具有多个子命令时,并且没有提供默认子命令时,提示用户选择一个子命令\n\t *\n\t */\n\tasync selectCommands() {\n\t\tconst choices = this.commands.map((command) => ({\n\t\t\ttitle: `${command.description()}(${command.name()})`,\n\t\t\tvalue: command.name(),\n\t\t}));\n\t\tconst result = await prompts({\n\t\t\ttype : \"select\",\n\t\t\tname : \"command\",\n\t\t\tmessage: \"请选择命令:\",\n\t\t\tchoices,\n\t\t});\n\t\t// 重新解析命令行参数标志,\n\t\tconst command = this.commands.find((command) => command.name() === result.command);\n\t\tawait command?.parseAsync([result.command], { from: \"user\" });\n\t}\n\t/**\n\t * 禁用/启用所有提示\n\t */\n\tdisablePrompts() {\n\t\tthis._enable_prompts = false;\n\t\treturn this;\n\t}\n\t/**\n\t * 启用所有提示\n\t */\n\tenablePrompts() {\n\t\tthis._enable_prompts = true;\n\t\treturn this;\n\t}\n}\n\n\n\n// 编写一个类型号用来表示Commander的Option flags字面量类型","import { Option, OptionValues } from 'commander'\nimport { PromptObject } from 'prompts'\nimport { PromptChoice, MixOptionPrompt,PromptParams } from './prompt'\n \n\nexport interface MixedOptionParams {\n required? : boolean; // A value must be supplied when the option is specified.\n optional? : boolean; // A value is optional when the option is specified.\n variadic? : boolean; \n mandatory? : boolean; // The option must have a value after parsing, which usually means it must be specified on command line.\n negate? : boolean;\n default? : any;\n defaultDescription? : string;\n conflicts? : string | string[];\n argParser? : unknown;\n implies? : OptionValues\n envVar? : string;\n parseArg? : <T>(value: string, previous: T) => T;\n hidden? : boolean;\n choices? : (string | PromptChoice )[] | ((pre:any,answers:any)=>(string | PromptChoice)[]);\n validate? : (value: any) => boolean;\n preset? : unknown;\n prompt? : PromptParams\n}\n\n\nexport class MixOption extends Option{\n __MIX_OPTION__ = true\n prompt? : MixOptionPrompt \n constructor(flags: string, description: string,public params?: MixedOptionParams) {\n super(flags, description) \n this._setOption(params || {}) \n this.prompt = new MixOptionPrompt(this,params?.prompt) \n } \n private _setOption(params:MixedOptionParams){ \n if(params.default) this.default(params.default,params.defaultDescription)\n if(params.conflicts) this.conflicts(params.conflicts)\n if(params.envVar) this.env(params.envVar)\n if(params.parseArg) this.argParser(params.parseArg) \n if(params.hidden) this.hidden = params.hidden\n if(params.mandatory) this.makeOptionMandatory(params.mandatory)\n if(params.implies) this.implies(params.implies) \n if(params.optional) this.optional=params.optional\n if(params.variadic) this.variadic = params.variadic\n if(params.negate) this.negate = params.negate\n if(params.preset) this.preset(params.preset)\n if(params.required) this.required = params.required \n if(Array.isArray(params.choices)) this.choices(params.choices.map(choice=>typeof(choice)=='string' ? choice : choice.value))\n } \n \n /**\n * 返回选项的提示对象\n * \n * @remarks \n * @param inputValue \n * @returns \n */\n getPrompt(inputValue?:any): PromptObject | undefined {\n return this.prompt?.get(inputValue)\n } \n}","import { isPlainObject } from \"flex-tools/typecheck/isPlainObject\"\nimport { isNumber } from \"flex-tools/typecheck/isNumber\"\n\nimport { PromptObject } from \"prompts\" \nimport { outputDebug } from \"./utils\"\nimport { MixOption } from \"./option\" \n\nexport type PromptType = \"text\" | \"password\" | \"invisible\" | \"number\"| \"confirm\"| \"list\" \n | \"toggle\"| \"select\" | \"multiselect\" | \"autocomplete\" | \"date\" | \"autocompleteMultiselect\"\n\nexport type PromptParam = 'auto' | boolean | PromptType | PromptObject\nexport type InputPromptParam = PromptParam | ((value:any)=>PromptParam) | boolean\nexport type PromptParamDefaultValue = string | boolean | string[] \n\nexport const promptTypeMap:Record<string,string> = {\n boolean: \"confirm\",\n string : \"text\",\n number : \"number\", \n array : \"list\", \n date : \"date\"\n} \n\nexport const supportedPromptTypes = [\n \"text\",\n \"password\",\n \"invisible\", \n \"number\", \n \"confirm\" , \n \"list\", \n \"toggle\" , \n \"select\" , \n \"multiselect\" , \n \"autocomplete\" , \n \"date\" , \n \"autocompleteMultiselect\"\n]\n\nexport interface PromptChoice {\n title : string;\n value? : any;\n disabled? : boolean | undefined;\n selected? : boolean | undefined;\n description?: string | undefined;\n}\n\n \nexport type PromptParams = Omit<PromptObject,'name'> | PromptType | boolean | 'auto' | undefined \n\n/**\n * 负责生成prompt对象\n * \n */\nexport class MixOptionPrompt{\n params?: PromptParams\n constructor(public cliOption:MixOption,promptParams?:PromptParams){ \n this.params = promptParams\n }\n /**\n * 返回输入的是否是有效的prompt类型\n * @param type \n * @returns \n */\n isValidPromptType(type:any){\n return supportedPromptTypes.includes(String(type))\n }\n /**\n * 推断是否需要提示\n * \n * 1. 显式指定prompt=true或者提示类型,或者提示对象,则需要提示\n * \n * \n */\n isNeedPrompt(input:any,defaultValue?:any){\n \n const params = this.params\n\n const inputValue = input || defaultValue\n\n // 是否有输入值,即在命令行输入了值\n const hasInput = !(inputValue === undefined)\n \n // 1. 显式指定了_prompt为true,则需要提示,后续进行提示类型的推断,可能不会准确\n if(params === true) return true\n if(params === false) return false \n if(params === 'auto') return !hasInput\n\n // 2. 提供了一个prompt对象,并且没有在命令行输入值,则需要提示\n if(isPlainObject(params)){\n return !hasInput\n }\n\n // 3. 指定了内置的prompt类型,如prompt='password',则使用password类型提示输入\n if(typeof(params) == 'string' && this.isValidPromptType(params)){\n return true\n }\n\n // 4. 指定了可选值,但是没有输入值,则需要提示\n const isOptional = /(\\<s*\\w\\s*\\>)/.test(this.cliOption.flags) \n if(isOptional) return !hasInput\n \n // 4. 判断输入是否有效,则显示提示\n if(this.cliOption.argChoices && this.cliOption.argChoices.indexOf(inputValue) == -1){\n return true\n } \n return !hasInput\n\n }\n \n private _getChoices(){\n let choices:(string | PromptChoice)[] | ((pre:any,answers:any)=>(string | PromptChoice)[]) = []\n let choicesParam = this.cliOption.params?.choices\n if(this.cliOption.argChoices){\n choices = this.cliOption.argChoices.map(choice=>{\n if(typeof(choice)=='string'){\n return {title:choice,value:choice}\n }else{\n return choice\n }\n })\n }else if(choicesParam){\n choices = typeof(choicesParam)=='function' ? choicesParam : [] \n }else{\n return []\n } \n return choices\n } \n\n /**\n * 自动推断prompt类型\n * \n * \n * \n * @param inputValue 从命令行输入的值\n */\n infer(inputValue?:any){\n\n const { variadic, defaultValue } = this.cliOption\n\n const input = inputValue || defaultValue\n\n // 如果选择指定了\"-p [value]或[value...]\",则使用text类型,如果没有要求输入值,则使用confirm类型\n let promptType:PromptType = 'text'\n\n const params = this.params\n\n if(this.isValidPromptType(params)){ // 显式指定了prompt类型,m则以指定的类型为准 \n promptType = params as PromptType\n }else if(isPlainObject(params)){ // 显式指定了prompt对象\n promptType = (params as PromptObject).type as PromptType\n }else{ // 自动推断prompt类型\n \n const isListType = /(\\[\\s*\\w+\\.\\.\\.\\s*])|(\\<\\s*\\w+\\.\\.\\.\\s*>)/.test(this.cliOption.flags)\n const isTextType = /(\\<s*\\w+\\s*\\>)|(\\[\\w+\\])/.test(this.cliOption.flags) \n const isBooleanType = !/(\\[\\s*\\w+s*])|(\\<\\s*\\w+\\s*>)/.test(this.cliOption.flags)\n const isNumberType = isNumber(defaultValue)\n const isDate = defaultValue && defaultValue instanceof Date\n\n // 根据默认值的类型推断\n const datatype:string = Array.isArray(input) ? 'array' : \n input instanceof Date ? 'date' :\n typeof(input) \n\n const optionParams = this.cliOption.params\n\n if(optionParams && optionParams.choices){\n const choices = optionParams.choices\n if(isBooleanType && (Array.isArray(choices) && choices.length==2)){\n promptType = 'toggle'\n }else{\n promptType = variadic ? 'multiselect' : 'select'\n } \n }else if(isListType){ // 提供多个可选值时\n promptType = 'list'\n }else if(isDate){\n promptType = 'date'\n }else if(isNumberType){\n promptType = 'number'\n }else if(isTextType){ // 提供一个可选值时\n promptType = 'text' \n }else if(isBooleanType || typeof(defaultValue)==='boolean'){\n promptType = 'confirm'\n }else if(datatype in promptTypeMap){\n promptType = promptTypeMap[datatype] as PromptType\n }\n }\n outputDebug(\"选项<{}> -> 提示类型<{}>\",[this.cliOption.name(),promptType])\n return promptType\n }\n /**\n * 返回生成prompt对象\n * \n * @param inputValue 从命令行输入的值\n */\n get(inputValue?:any){\n\n const { description, defaultValue } = this.cliOption\n \n let input = inputValue || defaultValue\n\n // 1. 判断是否需要启用提示\n if(!this.isNeedPrompt(input,defaultValue)) return\n\n // 2. 推断prompt类型\n const promptType = this.infer(inputValue)\n\n const prompt = {\n type : promptType, \n name : this.cliOption.attributeName(),\n message: description,\n initial: input,\n ...typeof(this.params) == 'object' ? this.params : {}\n } as PromptObject\n\n\n // 指定了验证函数,用来验证输入值是否有效\n prompt.validate = this.cliOption.params?.validate\n\n if(promptType=='multiselect') prompt.instructions=false\n prompt.choices = prompt.choices || this._getChoices() as any \n\n if(['select','multiselect'].includes(promptType)){ \n\n }else if(promptType=='toggle'){ \n if(Array.isArray(prompt.choices)){\n if(!prompt.active) prompt.active = prompt.choices[0].value\n if(!prompt.inactive) prompt.inactive = prompt.choices[1].value \n }\n }\n\n if(input && typeof(prompt.initial)!='function'){\n if(prompt.choices && Array.isArray(prompt.choices)){\n if(promptType=='select'){\n const index = Array.isArray(prompt.choices) ? prompt.choices.findIndex(item=>item.value==input) : -1\n if(index!=-1){\n prompt.initial = index\n }\n }else if(promptType=='multiselect'){ \n prompt.choices.forEach((item)=>{\n if(Array.isArray(input) && input.includes(item.value)){\n item.selected = true\n }else if(item.value==input){\n item.selected = true\n }\n })\n }\n }\n }\n\n return prompt\n }\n\n\n}","import fs from \"fs-extra\"\nimport path from \"node:path\"\nimport { promisify } from \"flex-tools/func/promisify\"\nimport logsets from \"logsets\" \n\n\n/**\n * \n * 在控制台输出一个字符串\n * 本方法会将字符串中的每一行空格去掉\n * \n * @remarks\n * \n * outputStr(String.raw`\n * a\n * b`)\n * \n * 会输出\n * a\n * b\n *\n * 此功能可以用于输出多行字符串时,保持代码的缩进格式,而不会影响输出结果\n * \n * @param str : 要输出的字符串\n * @param vars : 用于替换字符串中的变量\n * \n */\nexport function outputStr(str:string,vars?:Record<string,any> | any[]){ \n logsets.log(fixIndent(str),vars)\n}\n\n/**\n * 修正多行字符串的缩进\n * \n * @param text \n * @param indent \n * @returns \n */\nexport function fixIndent(text:string,indent?:boolean | number):string{\n let indentValue = (indent==undefined || indent===true) ? 0 : (typeof(indent)=='number' ? indent : -1)\n if(indentValue==-1) return text // 不修正缩进\n let lines:string[] = text.split(\"\\n\")\n let minSpaceCount = lines.reduce<number>((minCount,line,index)=>{\n if(index==0) return minCount\n const spaceCount = line.match(/^\\s*/)?.[0].length || 0\n return Math.min(minCount,spaceCount)\n },9999)\n lines = lines.map(line=>line.substring(minSpaceCount))\n return lines.join(\"\\n\")\n}\n\n/**\n * 增加内置选项\n * @param command \n */\nexport function addBuiltInOptions(command:any){ \n command.option(\"--work-dirs <values...>\",\"指定工作目录\",{hidden:true,optional:true,required:true,prompt:false})\n command.option(\"--disable-prompts\",\"禁用所有交互提示\",{hidden:true,prompt:false}) \n command.option(\"--debug-cli\",\"显示调试信息\",{hidden:true,prompt:false})\n}\n\n\n/**\n * 是否命令行中包含了--debug-cli选项\n */\nexport function isDebug(){\n return process.argv.includes(\"--debug-cli\")\n}\n\n\nexport function isDisablePrompts(){ \n return process.argv.includes(\"--disable-prompts\")\n}\n\n/**\n * 打印调试信息\n * @param message \n * @param args \n */\nexport function outputDebug(message:string,...args:any[]){ \n let vars = (args.length == 1 && typeof(args[0])=='function') ? args[0]() : args\n if(isDebug()) logsets.log(`[MixCli] ${message}`,...vars)\n}\n\nexport const fileExists = promisify(fs.exists,{\n parseCallback:(results)=>{\n return results[0]\n }\n})\nexport const readFile = promisify(fs.readFile)\nexport const writeFile = promisify(fs.writeFile)\nexport const mkdir = promisify(fs.mkdir)\n \n/** \n * 创建目录 \n * \n * \n * \n * @param {String[]} dirs 要创建的目录列表,类型为字符串数组 \n * @param callback 创建目录过程中的回调函数,类型为异步函数,接收一个参数 dir,表示当前正在创建的目录 \n * @returns 该函数返回一个 Promise 对象,表示创建目录的操作是否完成 \n */\nexport async function mkDirs(dirs:string[],{callback,base}:{callback?:Function,base?:string}){\n if(!Array.isArray(dirs)) throw new Error(\"dirs参数必须为字符串数组\")\n for(let dir of dirs){\n if(!path.isAbsolute(dir)) dir = path.join(base || process.cwd(),dir)\n if(typeof(callback)=='function') callback(dir)\n await mkdir(dir,{recursive:true})\n }\n}\n\nexport function showError(e:any){\n if(isDebug()){\n outputDebug(\"导入命令<>出错:{}\",e.stack)\n }else{\n console.error(e)\n } \n\n}\n\n// 编写一个函数,用于将使用-分隔的字符串转换为驼峰式\nexport function hyphenToCamelCase(str:string){\n return str.replace(/-([a-z])/g,(_,letter)=>letter.toUpperCase())\n}\n\nexport function getId(){\n return Math.random().toString(36).substr(2)\n}\n\n\nexport async function importModule(file:string){\n let module \n try{\n module = require(file)\n }catch(e:any){\n try{\n const cmd = await import(`file://${file}`)\n module = cmd.default\n }catch(e:any){\n throw e\n } \n }\n return module\n}\n","import { getPackageJson } from \"flex-tools/package/getPackageJson\"\nimport { getPackageRootPath } from 'flex-tools/package/getPackageRootPath';\nimport type { MixCli } from './cli';\nimport { globSync } from 'glob'\nimport { MixCliCommand } from './cli';\nimport { importModule, outputDebug } from './utils';\nimport fs from \"node:fs\"\nimport path from \"node:path\"\n\n\n/**\n * \n * 在当前工程中查找符合FlexCli.prefix约定的命令 \n * \n * - 读取当前包的package.json\n * - 找出所有以cli.prefix开头的依赖\n * - 加载这些依赖的目录下的匹配cli.pattern的命令\n * - 加载加载这样命令\n * \n */\n \n\nexport function getMatchedDependencies(this:MixCli,entry:string):string[]{\n const pacakgeMacher = this.options.include\n if(!(pacakgeMacher instanceof RegExp)) return []\n \n // 找出当前包的所有依赖\n const { dependencies={},devDependencies={},peerDependencies={},optionalDependencies={},bundleDependencies={} } = getPackageJson(entry)\n const packageNames = [\n ...Object.keys(dependencies),\n ...Object.keys(devDependencies),\n ...Object.keys(peerDependencies),\n ...Object.keys(optionalDependencies),\n ...Object.keys(bundleDependencies)\n ]\n return packageNames.filter(name=>name!==\"@voerka/cli\" && pacakgeMacher.test(name))\n}\n\nfunction isMatched(str:string,reg?:string | RegExp | string[] | RegExp[]):boolean{\n // let regexps:RegExp[]=[]\n const regexps = reg ? (Array.isArray(reg) ? reg : [reg]) : []\n return regexps.some(regexp=>{\n if(typeof regexp === \"string\"){\n return (new RegExp(regexp)).test(str)\n }else if(regexp instanceof RegExp){\n return regexp.test(str)\n }else{\n return false\n }\n })\n}\n\nexport function findCliPaths(this:MixCli,packageName?:string ,entry?:string):string[]{\n const includeMacher = this.options.include\n const excludeMacher = this.options.exclude\n if(!includeMacher) return []\n const packageRoot = getPackageRootPath(entry || process.cwd())\n const packagePath = packageName ? path.dirname(require.resolve(packageName,{paths:[packageRoot as string]})) : packageRoot\n\n if(!packagePath) {\n outputDebug(\"MixCli只能运行在Nodejs环境\" )\n return []\n }\n\n // 找出当前包的所有依赖\n const packageNames = getMatchedDependencies.call(this,packagePath)\n\n const cliDirs:string[]=[]\n \n if(entry!==undefined) cliDirs.push(path.join(packagePath,this.options.cliDir))\n packageNames.filter(name=>{\n return isMatched(name,includeMacher) && !isMatched(name,excludeMacher) \n })\n .forEach(name=>{\n outputDebug(\"匹配包:{}\",`${packageName ? name+\" <- \"+packageName : name}`)\n try{\n const packageEntry = path.dirname(require.resolve(name,{paths:packagePath ? [packagePath] : [process.cwd()]}))\n const packageCliDir =path.join(packageEntry,this.options.cliDir!) \n // 查找当前包的所属工程的依赖\n let dependencies = getMatchedDependencies.call(this,packageEntry)\n cliDirs.push(...dependencies.reduce<string[]>((result,dependencie)=>{\n outputDebug(\"匹配包:{}\",`${dependencie} <- ${name}`)\n result.push(...findCliPaths.call(this,dependencie,packageEntry))\n return result\n },[])) \n if(fs.existsSync(packageCliDir)){\n cliDirs.push(packageCliDir)\n }\n }catch(e:any){\n outputDebug(\"解析包<{}>路径出错:{}\",[name,e.stack])\n } \n })\n // 由于一些包可能存在循环依赖,所以需要去重\n return [...new Set(cliDirs)]\n}\n\n\n/**\n * \n * 扫描当前工程中所有符合条件的命令\n * \n * @param cli \n * \n */\nexport async function findCommands(cli:MixCli){ \n const cliDirs = findCliPaths.call(cli)\n const commands:MixCliCommand[] = []\n const files = [] as string[]\n cliDirs.forEach(dir=>{\n globSync(\"*\",{\n cwd:dir,\n absolute :true \n }).forEach((file:string)=>{ \n const baseName = path.basename(file) \n if(baseName.startsWith(\"_\")) return\n const ext = path.extname(file).toLowerCase()\n if([\".js\",\".cjs\",\".mjs\"].includes(ext)){\n files.push(file)\n }else if(fs.statSync(file).isDirectory()){\n files.push(path.join(file,\"index.js\"))\n files.push(path.join(file,\"index.cjs\"))\n files.push(path.join(file,\"index.mjs\"))\n }\n })\n })\n for(let file of files){ \n if(!fs.existsSync(file)) continue\n try{\n outputDebug(\"导入命令:{}\",file)\n if(file.endsWith(\".cjs\") || file.endsWith(\".js\")){\n commands.push(await importModule(file))\n }else if(file.endsWith(\".mjs\")){\n const cmd = await import(`file://${file}`)\n commands.push(cmd.default)\n } \n }catch(e:any){\n outputDebug(e) \n }\n }\n return commands\n}\n\n"],"mappings":"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","names":["LiteEvent","logsets","assignObject","Command","prompts","Option","isPlainObject","isNumber","fs","path","promisify","logsets","outputStr","str","vars","logsets","fixIndent","text","indent","lines","minSpaceCount","minCount","line","index","_a","spaceCount","addBuiltInOptions","command","isDebug","isDisablePrompts","outputDebug","message","args","fileExists","promisify","fs","results","readFile","writeFile","mkdir","mkDirs","_0","_1","__async","dirs","callback","base","dir","path","showError","e","hyphenToCamelCase","_","letter","getId","importModule","file","module","__require","promptTypeMap","supportedPromptTypes","MixOptionPrompt","cliOption","promptParams","type","input","defaultValue","params","inputValue","hasInput","isPlainObject","_a","choices","choicesParam","choice","variadic","promptType","isListType","isTextType","isBooleanType","isNumberType","isNumber","isDate","datatype","optionParams","outputDebug","description","prompt","__spreadValues","index","item","MixOption","Option","flags","description","params","MixOptionPrompt","choice","inputValue","_a","path","fs","BREAK","MixCommand","Command","name","self","addBuiltInOptions","__async","names","parent","root","actionFunc","actionFn","actionOpts","actionItem","command","opts","cmds","cmd","args","preValue","actionArgs","action","outputDebug","e","fn","workDirs","dirs","dir","workDir","cwd","path","fs","option","listener","scope","hooks","hook","thisCommand","questions","results","prompts","key","value","isDisablePrompts","optionPromports","prompt","flags","description","options","MixOption","choices","result","getPackageJson","getPackageRootPath","globSync","fs","path","getMatchedDependencies","entry","pacakgeMacher","dependencies","devDependencies","peerDependencies","optionalDependencies","bundleDependencies","getPackageJson","name","isMatched","str","reg","regexp","findCliPaths","packageName","includeMacher","excludeMacher","packageRoot","getPackageRootPath","packagePath","path","__require","outputDebug","packageNames","cliDirs","packageEntry","packageCliDir","result","dependencie","fs","e","findCommands","cli","__async","commands","files","dir","globSync","file","ext","importModule","cmd","asyncSignal","replaceAll","replaceAll","MixCli","LiteEvent","options","assignObject","__async","cmders","findCommands","cmder","cmds","e","outputDebug","MixCommand","logsets","fixIndent","title","addBuiltInOptions","text","pos","alignIndent","cmd","result","name","c","names","curCmd","resultCmd","topName","r","signal","asyncSignal","resolve","listener","fullname","s"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/cli.ts","../src/command.ts","../src/option.ts","../src/prompt.ts","../src/utils.ts","../src/finder.ts"],"sourcesContent":["export * from \"./cli\"\nexport * from \"./utils\"\nexport * from \"./command\"\nexport * from \"./option\"\nexport * from \"./prompt\"","#!/usr/bin/env node\nimport \"flex-tools/string\"\nimport { LiteEvent, LiteEventSubscriber } from \"flex-tools/events/liteEvent\"\nimport { Command } from \"commander\"\nimport logsets from \"logsets\"\n\nimport { assignObject } from \"flex-tools/object/assignObject\"\nimport { MixCommand } from \"./command\"\nimport { addBuiltInOptions, fixIndent, outputDebug } from './utils';\nimport { findCommands } from \"./finder\"\nimport { asyncSignal } from \"flex-tools/async/asyncSignal\"\n// @ts-ignore\nimport replaceAll from 'string.prototype.replaceall' \nreplaceAll.shim() \n\nexport interface MixCliOptions{\n name:string,\n title?:string | (string | boolean | number)[],\n description?:string,\n version?:string\n // 定义显示帮助信息\n logo?:string ,\n // 在根命令执行前执行==commander的preAction\n before?:(thisCommand:Command,actionCommand:Command)=>void,\n // 在根命令执行后执行==commander的postAction\n after?:(thisCommand:Command,actionCommand:Command)=>void, \n // flexcli运行时会在当前工程的package.json的依赖中查找以prefix/开头的包,然后自动加载其cli目录下的命令\n // 例如:prefix=myapp,则会自动加载flex-cli-xxx包中的cli目录下的命令\n // 如prefix=myapp, cliPath=\"cmds\",则会自动加载flex-cli-xxx包中的cmds目录下的命令\n include?:string | RegExp | string[] | RegExp[],\n // 忽略查找正则表达式\n exclude?:string | RegExp | string[] | RegExp[],\n // flexcli会在当前工程的以prefix/开头下查找命令声明\n // / pattern默认值是cli,即会在当前工程的以prefix/开头的包下查找cli目录下的命令\n // 指定cli所在的目录,默认值是cli,要遍历该目录下的所有js文件作为命令导出\n cliDir?:string \n context?:Record<string,any> // 传递给命令的共享上下文,所有命令均可要使用 \n // 默认是否启用交互提示, auto当没有值时,会根据当前是否在终端中运行来决定是否启用交互提示\n // 为false时,禁用所有交互提示,为true时,启用所有交互提示 \n prompt?:'auto' | boolean \n ignoreError?:boolean\n}\n\n \n \n\nexport type MixCliCommand = (cli:MixCli)=>MixCommand | MixCommand[] | void\n\n\nexport type MixCliEvents = \n \"register\" // 当命令注册时触发\n\nexport class MixCli extends LiteEvent<any,MixCliEvents>{\n options:Required<MixCliOptions> \n root!:MixCommand \n private findSignals:any[]=[]\n constructor(options?:MixCliOptions){\n super()\n this.options= assignObject({\n name : \"mixcli\",\n package : null,\n cliDir : \"cli\",\n prompt : 'auto',\n ignoreError: false\n },options) as Required<MixCliOptions> \n this.createRootCommand() \n } \n get context(){return this.options.context}\n get name(){return this.options.name}\n /**\n * 是否禁用了所有的交互提示\n */\n get isDisabledPrompts(){\n return(this.root as any).rawArgs.includes(\"--no-prompts\") \n } \n /**\n * 扫描当前工程的依赖,加载匹配include的依赖下的命令\n */\n private async installCommands(){\n const cmders = await findCommands(this)\n for(let cmder of cmders){\n try{\n if(typeof(cmder)===\"function\"){\n let cmds = cmder(this)\n cmds = cmds ? (Array.isArray(cmds) ? cmds : [cmds]) : []\n this.register(()=>cmds) \n }\n }catch(e:any){\n outputDebug(\"注册命令失败:{}\",e.stack)\n }\n }\n } \n /**\n * 创建根命令\n * \n */\n private createRootCommand(){\n this.root = new MixCommand(this.name);\n this.root \n .helpOption('-h, --help')\n .action(()=>{ \n if(this.options.logo) logsets.log(fixIndent(this.options.logo,2))\n console.log()\n // 显示标题\n let title = this.options.title|| this.options.name\n if(Array.isArray(title)){\n logsets.log(String(title[0]).firstUpper(),[...title.slice(1)])\n }else{\n logsets.log(`${title.firstUpper()} Version: {}`,this.options.version)\n } \n // @ts-ignore\n if(this.options.description) logsets.log(logsets.colors.darkGray(this.options.description)) \n console.log()\n this.root.help() \n }) \n addBuiltInOptions(this.root)\n if(this.options.before) this.root.hook('preAction',this.options.before)\n if(this.options.after) this.root.hook('postAction',this.options.after) \n } \n /**\n * 添加帮助选项\n * \n * @param text 帮助文本\n * @param position 显示位置,可选值:before|after|beforeAll|afterAll\n * @param fixIndent 是否自动修正缩进,如果为true,则会自动修正缩进,当显示多行时文本时,会自动修正缩进\n * \n */\n public addHelp(text:string,{pos='beforeAll',alignIndent=true}:{pos:'before'|'after' | 'beforeAll' | 'afterAll',alignIndent?:boolean | number}){\n if(alignIndent) text = fixIndent(text,alignIndent)\n this.root.addHelpText(pos,text)\n }\n\n /**\n * 注册一个命令\n * @param cmd \n */\n register(cmd:MixCliCommand){\n if(typeof(cmd)==\"function\"){\n let result = cmd(this)\n let cmds = result instanceof Array ? result : (result==undefined ? [] : [result])\n for(let cmd of cmds){\n // 为什么不用cmd instanceof MixCommand来判断是否是一个有效的命令?\n // 因为当不同的包引用了与主包不一样版本的mixcli时,判断会失效,导致不能识别\n // 所以我们通过cmd.__MIX_COMMAND__来判断是否是一个有效的命令\n if(cmd.__MIX_COMMAND__){ \n if(this.hasCommand(cmd.name())){\n logsets.error(`Command <${cmd.name()}> has been registered!`)\n }else{\n outputDebug(\"注册命令:{}\",cmd.fullname)\n this.root.addCommand(cmd as Command) ;\n (cmd as any)._cli = this\n this.emit(\"register\",cmd.fullname,true)\n } \n }else{\n logsets.error(`Command <${cmd.toString()}> is not a valid command!`)\n }\n } \n }else{\n logsets.error(\"Invalid command\")\n } \n }\n\n hasCommand(name:string):boolean{\n return this.root.commands.some(c=>c.name()==name)\n }\n\n /**\n * 根据命令名称查找命令\n * \n * @remarks\n * \n * find(\"dev\")\n * find(\"dev.microservice\") 支持多级命令\n * find(\"abc\",DevCommand) 允许指定从DevCommand下开始查找abc命令\n * \n * @param name \n */\n get(name:string):MixCommand | undefined{\n const names=name.split(\".\")\n let curCmd:MixCommand = this.root\n let resultCmd:MixCommand | undefined\n while(names.length>0){\n const topName = names.shift()\n const r = curCmd.commands.find(c=>c.name()==topName) as MixCommand\n if(r && names.length==0){\n resultCmd = r\n }\n curCmd = r\n } \n return resultCmd \n }\n /**\n * 查找一个命令\n * \n * 如果命令不存在,则等待命令注册后再返回\n * \n * 在多包场景下,如果命令在其他包中注册并且该包中的命令还没注册,则会等待命令注册后再返回\n * \n * @param name \n * @returns \n */\n find(name:string):Promise<MixCommand | undefined>{\n const cmd = this.get(name)\n if(cmd){\n return Promise.resolve(cmd) \n }else{\n const signal = asyncSignal()\n this.findSignals.push(signal)\n return new Promise<MixCommand | undefined>((resolve)=>{\n let listener:LiteEventSubscriber\n listener = this.on(\"register\",(fullname:string)=>{\n if(fullname==`${this.name}.${name}`){\n listener.off()\n signal.resolve()\n this.findSignals = this.findSignals.filter(s=>s!=signal)\n resolve(this.get(name))\n }\n },{objectify:true}) as LiteEventSubscriber\n })\n } \n }\n /**\n * 判断命令是否存在\n * \n * @param name \n * @returns \n */\n exists(name:string):boolean{\n if(name in this.root.commands){\n return true\n }else{\n return this.get(name) != undefined\n }\n } \n \n /**\n * 运行命令行程序\n */\n run(){ \n // 为什么有findSignal这玩意,解决什么问题?\n // 当我们要扩展command时,通过get(\"命令名称\")来获取已经注册的命令的方式有个缺陷\n // 就是如果对命令的注册顺序有严格的要求,比如调用get('dev')时要求dev命令必须已经存在\n // 这对动态包的命令注册扩展开发体验不好\n // 所以引入find(\"命令名称\")来获取命令,该方法可以获取到后注册的命令\n // 其副作用是,在run时,可能find还没有运行到,从而导致在帮助信息里面看不到扩展的信息(实际上是已经生效的)\n // 所以我们在find里面注入一个异步信号来解决此问题\n this.installCommands().then(()=>{\n return Promise.all(this.findSignals.map(signal=>signal(10000))).then(()=>{\n this.root.parseAsync(process.argv); \n })\n }) \n }\n}\n ","import { Command, Option } from \"commander\";\nimport prompts, { PromptObject } from \"prompts\";\nimport { MixOption, type MixedOptionParams } from \"./option\";\nimport { addBuiltInOptions, isDisablePrompts, outputDebug } from \"./utils\";\nimport type { AsyncFunction } from \"flex-tools/types\"; \nimport path from \"node:path\";\nimport fs from \"node:fs\";\n\n\n\nexport type IMixCommandHookListener = ({\n\targs,\n\toptions,\n\tcommand,\n}: {\n\targs: any[];\n\toptions: Record<string, any>;\n\tcommand: MixCommand;\n}) => void | Promise<void>;\n\nexport type BeforeMixCommandHookListener = ({\n\targs,\n\toptions,\n\tcommand,\n}: {\n\targs: any[];\n\toptions: Record<string, any>;\n\tcommand: MixCommand;\n}) => void | Promise<void>;\n\nexport type AfterMixCommandHookListener = ({\n\tvalue,\n\targs,\n\toptions,\n\tcommand,\n}: {\n\tvalue: any;\n\targs: any[];\n\toptions: Record<string, any>;\n\tcommand: MixCommand;\n}) => void | Promise<void>;\n\nexport interface MixActionOptions {\n\tid: string;\n\tat: \"replace\" | \"before\" | \"after\" | \"preappend\" | \"append\" | number;\t\n\tenhance: boolean;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 函数签名类型,即采用原始的commander的action函数签名,还是mixcli的action函数签名\n}\n\nexport interface MixActionRegistry extends Omit<MixActionOptions, \"at\"> {\n\tfn: Function;\n}\n\n// 原始的Action动作函数\nexport type MixOriginalAction = (...args: any[]) => any | Promise<void>;\n\n// 增强的Action函数签名\nexport type MixEnhanceAction = ({\n\targs,\n\toptions,\n\tvalue,\n\tcommand,\n}: {\n\targs: any[];\n\toptions: Record<string, any>;\n\tvalue: any;\n\tcommand: MixCommand;\n}) => any | Promise<any>;\n\n// 执行action的返回结果\nexport const BREAK = Symbol(\"BREAK_ACTION\"); // 中止后续的action执行\n\nexport class MixCommand extends Command {\n\t__MIX_COMMAND__ = true;\n\tprivate _beforeHooks : [ BeforeMixCommandHookListener, boolean ][] = [];\n\tprivate _afterHooks : [ AfterMixCommandHookListener, boolean ][] = [];\n\tprivate _customPrompts : PromptObject[] = [];\n\tprivate _optionValues : Record<string, any> = {}; \t\t\t\t\t\t\t// 命令行输入的选项值\n\tprivate _actions : MixActionRegistry[] = []; \t\t\t\t\t\t\t// 允许多个action\n\tprivate _enable_prompts: boolean = true; \t\t\t\t\t\t\t\t\t// 是否启用交互提示\n\tconstructor(name?: string) {\n\t\tsuper(name);\t\t\n\t\t// eslint-disable-next-line no-this-alias\n\t\tconst self = this\n\t\tif (!this.isRoot) addBuiltInOptions(this); \n\t\tthis.hook(\"preAction\", async function (this: any) {\n\t\t\tself._optionValues = self.getOptionValues(this.hookedCommand);\t\t\t\n\t\t\t// @ts-ignore\n\t\t\tawait self.preActionHook.apply(self, arguments);\n\t\t});\n\t} \n\tget isRoot() { return this.parent==undefined;\t}\n\tget optionValues(){ return this._optionValues }\n\tget actions() { return this._actions; }\n\tget beforeHooks() {\treturn this._beforeHooks; }\n\tget afterHooks() {return this._afterHooks;}\n\tget fullname() {\n\t\tlet names = [this.name()];\n\t\tlet parent = this.parent;\n\t\twhile (parent) {\n\t\t\tif (parent.name() !== \"root\") {\n\t\t\t\tnames.unshift(parent.name());\n\t\t\t}\n\t\t\tparent = parent.parent;\n\t\t}\n\t\treturn names.join(\".\");\n\t}\n\n\t/**\n\t * 返回根命令\n\t */\n\troot() { \n\t\t// eslint-disable-next-line no-this-alias\n\t\tlet root:any = this;\n\t\twhile (root && root.parent != null) {\n\t\t\troot = root.parent as unknown as MixCommand;\n\t\t}\n\t\treturn root;\n\t}\n\n\n\taction(fn: MixEnhanceAction, options: MixActionOptions): this;\n\taction(fn: MixOriginalAction): this;\n\taction(): this {\n\t\tconst actionFunc = arguments[0];\n\t\tif (arguments.length == 1 && typeof actionFunc == \"function\") {\n\t\t\t// 原始方式\n\t\t\tthis._actions.push({\n\t\t\t\tid: Math.random().toString(36).substring(2),\n\t\t\t\tenhance: false,\n\t\t\t\tfn: actionFunc,\n\t\t\t});\n\t\t} else if (arguments.length == 2 && typeof actionFunc == \"function\" && typeof arguments[1] == \"object\" ) {\n\t\t\t// 增强模式\n\t\t\tconst actionFn = arguments[0];\n\t\t\tconst actionOpts: MixActionOptions = Object.assign({ at: \"append\" }, arguments[1]);\n\t\t\tif (actionOpts.at == \"replace\") this._actions = [];\n\t\t\tconst actionItem = {\n\t\t\t\tid: actionOpts.id || Math.random().toString(36).substring(2),\n\t\t\t\tenhance: actionOpts.enhance == undefined ? true : actionOpts.enhance,\n\t\t\t\tfn: actionFn,\n\t\t\t} as const;\n\t\t\tif (typeof actionOpts.at == \"number\") {\n\t\t\t\tthis._actions.splice(Number(actionOpts.at), 0, actionItem);\n\t\t\t} else if ([\"append\", \"before\"].includes(actionOpts.at)) {\n\t\t\t\tthis._actions.push(actionItem);\n\t\t\t} else if ([\"preappend\", \"after\"].includes(actionOpts.at)) {\n\t\t\t\tthis._actions.splice(0, 0, actionItem);\n\t\t\t} else {\n\t\t\t\tthis._actions.push(actionItem);\n\t\t\t}\n\t\t} else {\n\t\t\tconsole.log(\"[mixcli] action params error\");\n\t\t}\n\t\treturn super.action(this.getWrapperedAction());\n\t}\n\n\t/**\n\t * 读取命令配置值,包括父命令提供的配置选项\n\t * @param command\n\t */\n\tprivate getOptionValues(command: MixCommand) {\n\t\tconst opts = {};\n\t\t// eslint-disable-next-line no-this-alias\n\t\tlet parent: any = command;\n\t\twhile (parent) {\n\t\t\tObject.assign(opts, (parent as MixCommand).optionValues);\n\t\t\tparent = parent.parent;\n\t\t}\n\t\treturn opts;\n\t}\n\t/**\n\t * 本函数在运行时子类进行action生成该命令的action\n\t */\n\tprivate getWrapperedAction() {\n\t\treturn this.wrapperWorkDirsAction(this.wrapperChainActions());\n\t}\n\n\t/**\n\t * 向上查找所有祖先命令\n\t */\n\tprivate getAncestorCommands(): MixCommand[] {\n\t\tlet cmds: MixCommand[] = [];\n\t\t// eslint-disable-next-line no-this-alias\n\t\tlet cmd: MixCommand | null = this;\n\t\twhile (cmd) {\n\t\t\tcmd = cmd.parent as unknown as MixCommand;\n\t\t\tif (cmd) {\n\t\t\t\tcmds.push(cmd);\n\t\t\t}\n\t\t}\n\t\treturn cmds;\n\t}\n\t/***\n\t * 将所有actions包装成一个链式调用的函数\n\t */\n\tprivate wrapperChainActions() {\n\t\t// eslint-disable-next-line no-this-alias\n\t\tconst self = this;\n\t\treturn async function (this: any) {\n\t\t\tconst args = Array.from(arguments); // 原始输入的参数\n\t\t\tlet preValue: any; // 保存上一个action的返回值\n\t\t\t//解析参数, 0-1个参数为options,最后一个参数为command\n\t\t\tlet actionOpts: Record<string, any> = {},\n\t\t\t\tactionArgs: any[] = [],\n\t\t\t\tcmd: any;\n\t\t\tif (args.length >= 2) {\n\t\t\t\tcmd = args[args.length - 1]; // 最后一个command\n\t\t\t\tactionOpts = args[args.length - 2];\n\t\t\t\tactionArgs = args.slice(0, args.length - 2);\n\t\t\t}\n\t\t\tawait self.executeBeforeHooks({ args: actionArgs, options: actionOpts, command: cmd });\n\t\t\ttry {\n\t\t\t\tfor (let action of self._actions) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (action.enhance) {\n\t\t\t\t\t\t\t// 增强模式\n\t\t\t\t\t\t\toutputDebug(\"执行<{}>: args={}, options={}\", () => [\n\t\t\t\t\t\t\t\tself.name(),\n\t\t\t\t\t\t\t\tactionArgs,\n\t\t\t\t\t\t\t\tactionOpts,\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\tpreValue = await action.fn.call(this, {\n\t\t\t\t\t\t\t\tcommand: cmd,\n\t\t\t\t\t\t\t\tvalue : preValue,\n\t\t\t\t\t\t\t\targs : actionArgs,\n\t\t\t\t\t\t\t\toptions: actionOpts,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// 原始模式\n\t\t\t\t\t\t\tpreValue = await action.fn.apply(this, args);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (preValue === BREAK) break;\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\toutputDebug(\"命令{}的Action({})执行出错:{}\", [self.name, action.id, e]);\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tawait self.executeAfterHooks({\n\t\t\t\t\tvalue: preValue,\n\t\t\t\t\targs: actionArgs,\n\t\t\t\t\toptions: actionOpts,\n\t\t\t\t\tcommand: cmd,\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t}\n\t/**\n\t * 当传入--work-dirs时用来处理工作目录\n\t */\n\tprivate wrapperWorkDirsAction(fn: AsyncFunction) {\n\t\t// eslint-disable-next-line no-this-alias\n\t\tconst self = this;\n\t\treturn async function (this: any) {\n\t\t\tlet workDirs = self._optionValues.workDirs;\n\t\t\t// 未指定工作目录参数\n\t\t\tif (!workDirs) {\n\t\t\t\treturn await fn.apply(this, Array.from(arguments));\n\t\t\t}\n\t\t\tif (!Array.isArray(workDirs)) workDirs = workDirs.split(\",\");\n\t\t\tworkDirs = workDirs.reduce((dirs: any[], dir: string) => {\n\t\t\t\tif (typeof dir == \"string\") dirs.push(...dir.split(\",\"));\n\t\t\t\treturn dirs;\n\t\t\t}, []);\n\t\t\tfor (let workDir of workDirs) {\n\t\t\t\tconst cwd = process.cwd();\n\t\t\t\ttry {\n\t\t\t\t\tif (!path.isAbsolute(workDir)) workDir = path.join(cwd, workDir);\n\t\t\t\t\tif (fs.existsSync(workDir) && fs.statSync(workDir).isDirectory()) {\n\t\t\t\t\t\toutputDebug(\"切换到工作目录:{}\", workDir);\n\t\t\t\t\t\tprocess.chdir(workDir); // 切换\n\t\t\t\t\t\tawait fn.apply(this, Array.from(arguments));\n\t\t\t\t\t} else {\n\t\t\t\t\t\toutputDebug(\"无效的工作目录:{}\", workDir);\n\t\t\t\t\t} \n\t\t\t\t} finally {\n\t\t\t\t\tprocess.chdir(cwd);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\tgetOption(name: string): MixOption {\n\t\treturn this.options.find((option) => option.name() == name) as unknown as MixOption;\n\t}\n\t/**\n\t * 添加一个Before钩子\n\t * @param listener\n\t * @param scope =false时代表只在本命令执行,=true时代表在本命令及其子命令执行\n\t * @returns\n\t */\n\tbefore(listener: BeforeMixCommandHookListener, scope: boolean = true) {\n\t\tthis._beforeHooks.push([listener, scope]);\n\t\treturn this;\n\t}\n\tprivate async executeBeforeHooks(args: any) {\n\t\tconst hooks: [BeforeMixCommandHookListener, boolean, MixCommand][] = this.beforeHooks.map(\n\t\t\t([hook, scope]) => [hook, scope, this]\n\t\t);\n\t\tthis.getAncestorCommands().forEach((cmd: MixCommand) => {\n\t\t\thooks.unshift(\n\t\t\t\t...cmd.beforeHooks.map(([hook, scope]) => {\n\t\t\t\t\treturn [hook, scope, cmd] as [BeforeMixCommandHookListener, boolean, MixCommand];\n\t\t\t\t})\n\t\t\t);\n\t\t});\n\t\tfor (let [hook, scope, cmd] of hooks) {\n\t\t\tif (!scope) continue;\n\t\t\tawait hook.call(cmd, args);\n\t\t}\n\t}\n\t/**\n\t * 添加一个After钩子\n\t * @param listener\n\t * @param scope =false时代表只在本命令执行,=true时代表在本命令及其子命令执行\n\t * @returns\n\t */\n\tafter(listener: AfterMixCommandHookListener, scope: boolean = true) {\n\t\tthis._afterHooks.push([listener, scope]);\n\t\treturn this;\n\t}\n\n\tprivate async executeAfterHooks(args: any) {\n\t\tconst hooks: [AfterMixCommandHookListener, boolean, MixCommand][] = this.afterHooks.map(\n\t\t\t([hook, scope]) => [hook, scope, this]\n\t\t);\n\t\tthis.getAncestorCommands().forEach((cmd: MixCommand) => {\n\t\t\thooks.push(\n\t\t\t\t...cmd.afterHooks.map(([hook, scope]) => {\n\t\t\t\t\treturn [hook, scope, cmd] as [BeforeMixCommandHookListener, boolean, MixCommand];\n\t\t\t\t})\n\t\t\t);\n\t\t});\n\t\tfor (let [hook, scope, cmd] of hooks) {\n\t\t\tif (!scope) continue; //=false时不执行\n\t\t\tawait hook.call(cmd, args);\n\t\t}\n\t}\n\tprivate async preActionHook(thisCommand: Command) {\n\t\tif (this.isEnablePrompts()) {\n\t\t\t// 自动生成提示\n\t\t\tconst questions: PromptObject[] = [\n\t\t\t\t...this.generateAutoPrompts(),\n\t\t\t\t...this._customPrompts,\n\t\t\t];\n\t\t\t// 用户提示\n\t\t\tif (questions.length > 0) {\n\t\t\t\tconst results = await prompts(questions);\n\t\t\t\tObject.entries(results).forEach(([key, value]) => {\n\t\t\t\t\tthisCommand.setOptionValue(key, value);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate isEnablePrompts() {\n\t\tif (isDisablePrompts()) {\t\t\t\n\t\t\treturn false;// 命令行参数禁用了提示,优先级最高\n\t\t} else {\n\t\t\treturn this._enable_prompts;\n\t\t}\n\t}\n\n\t/**\n\t * 生成选项自动提示\n\t *\n\t * @remarks\n\t * 要求所有未提供默认值的Option自动生成提示\n\t *\n\t * - 未提供默认值,并且是必选的参数Option\n\t * - 指定了choices但未提供有效值的Option\n\t *\n\t */\n\tprivate generateAutoPrompts(): PromptObject[] {\n\t\tconst options = this.options as unknown as MixOption[];\n\t\tconst optionPromports = options\n\t\t\t.filter((option) => !option.hidden && option.__MIX_OPTION__)\n\t\t\t.map((option) => option.getPrompt(this._optionValues[option.attributeName()]))\n\t\t\t.filter((prompt) => prompt) as PromptObject[];\n\t\t\t\n\t\toutputDebug(\"命令<{}>自动生成{}个选项提示:{}\", [\n\t\t\tthis.name(),\n\t\t\toptionPromports.length,\n\t\t\toptionPromports.map((prompt) => `${prompt.name}(${prompt.type})`).join(\",\"),\n\t\t]);\n\t\treturn optionPromports;\n\t} \n\n\t// @ts-ignore\n\toption( flags: string, description: string, options?: MixedOptionParams ):this{ \n \t\tconst option = new MixOption(flags, description, options);\n\t\tif (option.required && !this.isEnablePrompts()) option.mandatory = true;\t\t\n\t\treturn this.addOption(option as unknown as Option) \n\t}\n\n\t/**\n\t * 添加提示\n\t *\n\t * @remarks\n\t *\n\t * 添加一些自定义提示 \n\t *\n\t * @param questions\n\t * @returns\n\t */\n\tprompt(questions: PromptObject | PromptObject[]) {\n\t\tthis._customPrompts.push(...(Array.isArray(questions) ? questions : [questions]));\n\t\treturn this;\n\t}\n\n\t/**\n\t *\n\t * 选择命令并执行\n\t *\n\t * @remorks\n\t *\n\t * 当命令具有多个子命令时,并且没有提供默认子命令时,提示用户选择一个子命令\n\t *\n\t */\n\tasync selectCommands() {\n\t\tconst choices = this.commands.map((command) => ({\n\t\t\ttitle: `${command.description()}(${command.name()})`,\n\t\t\tvalue: command.name(),\n\t\t}));\n\t\tconst result = await prompts({\n\t\t\ttype : \"select\",\n\t\t\tname : \"command\",\n\t\t\tmessage: \"请选择命令:\",\n\t\t\tchoices,\n\t\t});\n\t\t// 重新解析命令行参数标志,\n\t\tconst command = this.commands.find((command) => command.name() === result.command);\n\t\tawait command?.parseAsync([result.command], { from: \"user\" });\n\t}\n\t/**\n\t * 禁用/启用所有提示\n\t */\n\tdisablePrompts() {\n\t\tthis._enable_prompts = false;\n\t\treturn this;\n\t}\n\t/**\n\t * 启用所有提示\n\t */\n\tenablePrompts() {\n\t\tthis._enable_prompts = true;\n\t\treturn this;\n\t}\n}\n\n\n\n// 编写一个类型号用来表示Commander的Option flags字面量类型","import { Option, OptionValues } from 'commander'\nimport { PromptObject } from 'prompts'\nimport { PromptChoice, MixOptionPrompt,PromptParams } from './prompt'\n \n\nexport interface MixedOptionParams {\n required? : boolean; // A value must be supplied when the option is specified.\n optional? : boolean; // A value is optional when the option is specified.\n variadic? : boolean; \n mandatory? : boolean; // The option must have a value after parsing, which usually means it must be specified on command line.\n negate? : boolean;\n default? : any;\n defaultDescription? : string;\n conflicts? : string | string[];\n argParser? : unknown;\n implies? : OptionValues\n envVar? : string;\n parseArg? : <T>(value: string, previous: T) => T;\n hidden? : boolean;\n choices? : (string | PromptChoice )[] | ((pre:any,answers:any)=>(string | PromptChoice)[]);\n validate? : (value: any) => boolean;\n preset? : unknown;\n prompt? : PromptParams\n}\n\n\nexport class MixOption extends Option{\n __MIX_OPTION__ = true\n prompt? : MixOptionPrompt \n constructor(flags: string, description: string,public params?: MixedOptionParams) {\n super(flags, description) \n this._setOption(params || {}) \n this.prompt = new MixOptionPrompt(this,params?.prompt) \n } \n private _setOption(params:MixedOptionParams){ \n if(params.default) this.default(params.default,params.defaultDescription)\n if(params.conflicts) this.conflicts(params.conflicts)\n if(params.envVar) this.env(params.envVar)\n if(params.parseArg) this.argParser(params.parseArg) \n if(params.hidden) this.hidden = params.hidden\n if(params.mandatory) this.makeOptionMandatory(params.mandatory)\n if(params.implies) this.implies(params.implies) \n if(params.optional) this.optional=params.optional\n if(params.variadic) this.variadic = params.variadic\n if(params.negate) this.negate = params.negate\n if(params.preset) this.preset(params.preset)\n if(params.required) this.required = params.required \n if(Array.isArray(params.choices)) this.choices(params.choices.map(choice=>typeof(choice)=='string' ? choice : choice.value))\n } \n \n /**\n * 返回选项的提示对象\n * \n * @remarks \n * @param inputValue \n * @returns \n */\n getPrompt(inputValue?:any): PromptObject | undefined {\n return this.prompt?.get(inputValue)\n } \n}","import { isPlainObject } from \"flex-tools/typecheck/isPlainObject\"\nimport { isNumber } from \"flex-tools/typecheck/isNumber\"\n\nimport { PromptObject } from \"prompts\" \nimport { outputDebug } from \"./utils\"\nimport { MixOption } from \"./option\" \n\nexport type PromptType = \"text\" | \"password\" | \"invisible\" | \"number\"| \"confirm\"| \"list\" \n | \"toggle\"| \"select\" | \"multiselect\" | \"autocomplete\" | \"date\" | \"autocompleteMultiselect\"\n\nexport type PromptParam = 'auto' | boolean | PromptType | PromptObject\nexport type InputPromptParam = PromptParam | ((value:any)=>PromptParam) | boolean\nexport type PromptParamDefaultValue = string | boolean | string[] \n\nexport const promptTypeMap:Record<string,string> = {\n boolean: \"confirm\",\n string : \"text\",\n number : \"number\", \n array : \"list\", \n date : \"date\"\n} \n\nexport const supportedPromptTypes = [\n \"text\",\n \"password\",\n \"invisible\", \n \"number\", \n \"confirm\" , \n \"list\", \n \"toggle\" , \n \"select\" , \n \"multiselect\" , \n \"autocomplete\" , \n \"date\" , \n \"autocompleteMultiselect\"\n]\n\nexport interface PromptChoice {\n title : string;\n value? : any;\n disabled? : boolean | undefined;\n selected? : boolean | undefined;\n description?: string | undefined;\n}\n\n \nexport type PromptParams = Omit<PromptObject,'name'> | PromptType | boolean | 'auto' | undefined \n\n/**\n * 负责生成prompt对象\n * \n */\nexport class MixOptionPrompt{\n params?: PromptParams\n constructor(public cliOption:MixOption,promptParams?:PromptParams){ \n this.params = promptParams\n }\n /**\n * 返回输入的是否是有效的prompt类型\n * @param type \n * @returns \n */\n isValidPromptType(type:any){\n return supportedPromptTypes.includes(String(type))\n }\n /**\n * 推断是否需要提示\n * \n * 1. 显式指定prompt=true或者提示类型,或者提示对象,则需要提示\n * \n * \n */\n isNeedPrompt(input:any,defaultValue?:any){\n \n const params = this.params\n\n const inputValue = input || defaultValue\n\n // 是否有输入值,即在命令行输入了值\n const hasInput = !(inputValue === undefined)\n \n // 1. 显式指定了_prompt为true,则需要提示,后续进行提示类型的推断,可能不会准确\n if(params === true) return true\n if(params === false) return false \n if(params === 'auto') return !hasInput\n\n // 2. 提供了一个prompt对象,并且没有在命令行输入值,则需要提示\n if(isPlainObject(params)){\n return !hasInput\n }\n\n // 3. 指定了内置的prompt类型,如prompt='password',则使用password类型提示输入\n if(typeof(params) == 'string' && this.isValidPromptType(params)){\n return true\n }\n\n // 4. 指定了可选值,但是没有输入值,则需要提示\n const isOptional = /(\\<s*\\w\\s*\\>)/.test(this.cliOption.flags) \n if(isOptional) return !hasInput\n \n // 4. 判断输入是否有效,则显示提示\n if(this.cliOption.argChoices && this.cliOption.argChoices.indexOf(inputValue) == -1){\n return true\n } \n return !hasInput\n\n }\n \n private _getChoices(){\n let choices:(string | PromptChoice)[] | ((pre:any,answers:any)=>(string | PromptChoice)[]) = []\n let choicesParam = this.cliOption.params?.choices\n if(this.cliOption.argChoices){\n choices = this.cliOption.argChoices.map(choice=>{\n if(typeof(choice)=='string'){\n return {title:choice,value:choice}\n }else{\n return choice\n }\n })\n }else if(choicesParam){\n choices = typeof(choicesParam)=='function' ? choicesParam : [] \n }else{\n return []\n } \n return choices\n } \n\n /**\n * 自动推断prompt类型\n * \n * \n * \n * @param inputValue 从命令行输入的值\n */\n infer(inputValue?:any){\n\n const { variadic, defaultValue } = this.cliOption\n\n const input = inputValue || defaultValue\n\n // 如果选择指定了\"-p [value]或[value...]\",则使用text类型,如果没有要求输入值,则使用confirm类型\n let promptType:PromptType = 'text'\n\n const params = this.params\n\n if(this.isValidPromptType(params)){ // 显式指定了prompt类型,m则以指定的类型为准 \n promptType = params as PromptType\n }else if(isPlainObject(params)){ // 显式指定了prompt对象\n promptType = (params as PromptObject).type as PromptType\n }else{ // 自动推断prompt类型\n \n const isListType = /(\\[\\s*\\w+\\.\\.\\.\\s*])|(\\<\\s*\\w+\\.\\.\\.\\s*>)/.test(this.cliOption.flags)\n const isTextType = /(\\<s*\\w+\\s*\\>)|(\\[\\w+\\])/.test(this.cliOption.flags) \n const isBooleanType = !/(\\[\\s*\\w+s*])|(\\<\\s*\\w+\\s*>)/.test(this.cliOption.flags)\n const isNumberType = isNumber(defaultValue)\n const isDate = defaultValue && defaultValue instanceof Date\n\n // 根据默认值的类型推断\n const datatype:string = Array.isArray(input) ? 'array' : \n input instanceof Date ? 'date' :\n typeof(input) \n\n const optionParams = this.cliOption.params\n\n if(optionParams && optionParams.choices){\n const choices = optionParams.choices\n if(isBooleanType && (Array.isArray(choices) && choices.length==2)){\n promptType = 'toggle'\n }else{\n promptType = variadic ? 'multiselect' : 'select'\n } \n }else if(isListType){ // 提供多个可选值时\n promptType = 'list'\n }else if(isDate){\n promptType = 'date'\n }else if(isNumberType){\n promptType = 'number'\n }else if(isTextType){ // 提供一个可选值时\n promptType = 'text' \n }else if(isBooleanType || typeof(defaultValue)==='boolean'){\n promptType = 'confirm'\n }else if(datatype in promptTypeMap){\n promptType = promptTypeMap[datatype] as PromptType\n }\n }\n outputDebug(\"选项<{}> -> 提示类型<{}>\",[this.cliOption.name(),promptType])\n return promptType\n }\n /**\n * 返回生成prompt对象\n * \n * @param inputValue 从命令行输入的值\n */\n get(inputValue?:any){\n\n const { description, defaultValue } = this.cliOption\n \n let input = inputValue || defaultValue\n\n // 1. 判断是否需要启用提示\n if(!this.isNeedPrompt(input,defaultValue)) return\n\n // 2. 推断prompt类型\n const promptType = this.infer(inputValue)\n\n const prompt = {\n type : promptType, \n name : this.cliOption.attributeName(),\n message: description,\n initial: input,\n ...typeof(this.params) == 'object' ? this.params : {}\n } as PromptObject\n\n\n // 指定了验证函数,用来验证输入值是否有效\n prompt.validate = this.cliOption.params?.validate\n\n if(promptType=='multiselect') prompt.instructions=false\n prompt.choices = prompt.choices || this._getChoices() as any \n\n if(['select','multiselect'].includes(promptType)){ \n\n }else if(promptType=='toggle'){ \n if(Array.isArray(prompt.choices)){\n if(!prompt.active) prompt.active = prompt.choices[0].value\n if(!prompt.inactive) prompt.inactive = prompt.choices[1].value \n }\n }\n\n if(input && typeof(prompt.initial)!='function'){\n if(prompt.choices && Array.isArray(prompt.choices)){\n if(promptType=='select'){\n const index = Array.isArray(prompt.choices) ? prompt.choices.findIndex(item=>item.value==input) : -1\n if(index!=-1){\n prompt.initial = index\n }\n }else if(promptType=='multiselect'){ \n prompt.choices.forEach((item)=>{\n if(Array.isArray(input) && input.includes(item.value)){\n item.selected = true\n }else if(item.value==input){\n item.selected = true\n }\n })\n }\n }\n }\n\n return prompt\n }\n\n\n}"," import logsets from \"logsets\" \n\n\n/**\n * \n * 在控制台输出一个字符串\n * 本方法会将字符串中的每一行空格去掉\n * \n * @remarks\n * \n * outputStr(String.raw`\n * a\n * b`)\n * \n * 会输出\n * a\n * b\n *\n * 此功能可以用于输出多行字符串时,保持代码的缩进格式,而不会影响输出结果\n * \n * @param str : 要输出的字符串\n * @param vars : 用于替换字符串中的变量\n * \n */\nexport function outputStr(str:string,vars?:Record<string,any> | any[]){ \n logsets.log(fixIndent(str),vars)\n}\n\n/**\n * 修正多行字符串的缩进\n * \n * @param text \n * @param indent \n * @returns \n */\nexport function fixIndent(text:string,indent?:boolean | number):string{\n let indentValue = (indent==undefined || indent===true) ? 0 : (typeof(indent)=='number' ? indent : -1)\n if(indentValue==-1) return text // 不修正缩进\n let lines:string[] = text.split(\"\\n\")\n let minSpaceCount = lines.reduce<number>((minCount,line,index)=>{\n if(index==0) return minCount\n const spaceCount = line.match(/^\\s*/)?.[0].length || 0\n return Math.min(minCount,spaceCount)\n },9999)\n lines = lines.map(line=>line.substring(minSpaceCount))\n return lines.join(\"\\n\")\n}\n\n/**\n * 增加内置选项\n * @param command \n */\nexport function addBuiltInOptions(command:any){ \n command.option(\"--work-dirs <values...>\",\"指定工作目录\",{hidden:true,optional:true,required:true,prompt:false})\n command.option(\"--disable-prompts\",\"禁用所有交互提示\",{hidden:true,prompt:false}) \n command.option(\"--debug-cli\",\"显示调试信息\",{hidden:true,prompt:false})\n}\n\n\n/**\n * 是否命令行中包含了--debug-cli选项\n */\nexport function isDebug(){\n return process.argv.includes(\"--debug-cli\")\n}\n\n\nexport function isDisablePrompts(){ \n return process.argv.includes(\"--disable-prompts\")\n}\n\n/**\n * 打印调试信息\n * @param message \n * @param args \n */\nexport function outputDebug(message:string,...args:any[]){ \n let vars = (args.length == 1 && typeof(args[0])=='function') ? args[0]() : args\n if(isDebug()) logsets.log(`[MixCli] ${message}`,...vars)\n}\n \n\nexport function showError(e:any){\n if(isDebug()){\n outputDebug(\"导入命令<>出错:{}\",e.stack)\n }else{\n console.error(e)\n } \n\n}\n\n// 编写一个函数,用于将使用-分隔的字符串转换为驼峰式\nexport function hyphenToCamelCase(str:string){\n return str.replace(/-([a-z])/g,(_,letter)=>letter.toUpperCase())\n}\n\nexport function getId(){\n return Math.random().toString(36).substr(2)\n}\n\n\nexport async function importModule(file:string){\n let module \n try{\n module = require(file)\n }catch(e:any){ \n const cmd = await import(`file://${file}`)\n module = cmd.default \n throw e\n }\n return module\n}\n","import { getPackageJson } from \"flex-tools/package/getPackageJson\"\nimport { getPackageRootPath } from 'flex-tools/package/getPackageRootPath';\nimport type { MixCli } from './cli';\nimport { globSync } from 'glob'\nimport { MixCliCommand } from './cli';\nimport { importModule, outputDebug } from './utils';\nimport fs from \"node:fs\"\nimport path from \"node:path\"\n\n\n/**\n * \n * 在当前工程中查找符合FlexCli.prefix约定的命令 \n * \n * - 读取当前包的package.json\n * - 找出所有以cli.prefix开头的依赖\n * - 加载这些依赖的目录下的匹配cli.pattern的命令\n * - 加载加载这样命令\n * \n */\n \n\nexport function getMatchedDependencies(this:MixCli,entry:string):string[]{\n const pacakgeMacher = this.options.include\n if(!(pacakgeMacher instanceof RegExp)) return []\n \n // 找出当前包的所有依赖\n const { dependencies={},devDependencies={},peerDependencies={},optionalDependencies={},bundleDependencies={} } = getPackageJson(entry)\n const packageNames = [\n ...Object.keys(dependencies),\n ...Object.keys(devDependencies),\n ...Object.keys(peerDependencies),\n ...Object.keys(optionalDependencies),\n ...Object.keys(bundleDependencies)\n ]\n return packageNames.filter(name=>name!==\"@voerka/cli\" && pacakgeMacher.test(name))\n}\n\nfunction isMatched(str:string,reg?:string | RegExp | string[] | RegExp[]):boolean{\n // let regexps:RegExp[]=[]\n const regexps = reg ? (Array.isArray(reg) ? reg : [reg]) : []\n return regexps.some(regexp=>{\n if(typeof regexp === \"string\"){\n return (new RegExp(regexp)).test(str)\n }else if(regexp instanceof RegExp){\n return regexp.test(str)\n }else{\n return false\n }\n })\n}\n\nexport function findCliPaths(this:MixCli,packageName?:string ,entry?:string):string[]{\n const includeMacher = this.options.include\n const excludeMacher = this.options.exclude\n if(!includeMacher) return []\n const packageRoot = getPackageRootPath(entry || process.cwd())\n const packagePath = packageName ? path.dirname(require.resolve(packageName,{paths:[packageRoot as string]})) : packageRoot\n\n if(!packagePath) {\n outputDebug(\"MixCli只能运行在Nodejs环境\" )\n return []\n }\n\n // 找出当前包的所有依赖\n const packageNames = getMatchedDependencies.call(this,packagePath)\n\n const cliDirs:string[]=[]\n \n if(entry!==undefined) cliDirs.push(path.join(packagePath,this.options.cliDir))\n packageNames.filter(name=>{\n return isMatched(name,includeMacher) && !isMatched(name,excludeMacher) \n })\n .forEach(name=>{\n outputDebug(\"匹配包:{}\",`${packageName ? name+\" <- \"+packageName : name}`)\n try{\n const packageEntry = path.dirname(require.resolve(name,{paths:packagePath ? [packagePath] : [process.cwd()]}))\n const packageCliDir =path.join(packageEntry,this.options.cliDir!) \n // 查找当前包的所属工程的依赖\n let dependencies = getMatchedDependencies.call(this,packageEntry)\n cliDirs.push(...dependencies.reduce<string[]>((result,dependencie)=>{\n outputDebug(\"匹配包:{}\",`${dependencie} <- ${name}`)\n result.push(...findCliPaths.call(this,dependencie,packageEntry))\n return result\n },[])) \n if(fs.existsSync(packageCliDir)){\n cliDirs.push(packageCliDir)\n }\n }catch(e:any){\n outputDebug(\"解析包<{}>路径出错:{}\",[name,e.stack])\n } \n })\n // 由于一些包可能存在循环依赖,所以需要去重\n return [...new Set(cliDirs)]\n}\n\n\n/**\n * \n * 扫描当前工程中所有符合条件的命令\n * \n * @param cli \n * \n */\nexport async function findCommands(cli:MixCli){ \n const cliDirs = findCliPaths.call(cli)\n const commands:MixCliCommand[] = []\n const files = [] as string[]\n cliDirs.forEach(dir=>{\n globSync(\"*\",{\n cwd:dir,\n absolute :true \n }).forEach((file:string)=>{ \n const baseName = path.basename(file) \n if(baseName.startsWith(\"_\")) return\n const ext = path.extname(file).toLowerCase()\n if([\".js\",\".cjs\",\".mjs\"].includes(ext)){\n files.push(file)\n }else if(fs.statSync(file).isDirectory()){\n files.push(path.join(file,\"index.js\"))\n files.push(path.join(file,\"index.cjs\"))\n files.push(path.join(file,\"index.mjs\"))\n }\n })\n })\n for(let file of files){ \n if(!fs.existsSync(file)) continue\n try{\n outputDebug(\"导入命令:{}\",file)\n if(file.endsWith(\".cjs\") || file.endsWith(\".js\")){\n commands.push(await importModule(file))\n }else if(file.endsWith(\".mjs\")){\n const cmd = await import(`file://${file}`)\n commands.push(cmd.default)\n } \n }catch(e:any){\n outputDebug(e) \n }\n }\n return commands\n}\n\n"],"mappings":"kiCAAA,IAAAA,GAAA,GAAAC,GAAAD,GAAA,WAAAE,EAAA,WAAAC,EAAA,eAAAC,EAAA,cAAAC,EAAA,oBAAAC,EAAA,sBAAAC,EAAA,cAAAC,EAAA,UAAAC,GAAA,sBAAAC,GAAA,iBAAAC,EAAA,YAAAC,EAAA,qBAAAC,EAAA,gBAAAC,EAAA,cAAAC,GAAA,kBAAAC,EAAA,cAAAC,GAAA,yBAAAC,IAAA,eAAAC,GAAAnB,ICCA,IAAAoB,GAAO,6BACPC,GAA+C,uCAE/CC,EAAqB,sBAErBC,GAA6B,0CCN7B,IAAAC,EAAgC,qBAChCC,EAAsC,sBCDtC,IAAAC,EAAqC,qBCArC,IAAAC,EAA8B,8CAC9BC,EAA0B,yCCDzB,IAAAC,EAAoB,sBAwBd,SAASC,GAAUC,EAAWC,EAAiC,CAClE,EAAAC,QAAQ,IAAIC,EAAUH,CAAG,EAAEC,CAAI,CACnC,CASO,SAASE,EAAUC,EAAYC,EAAgC,CAElE,IADmBA,GAAQ,MAAaA,IAAS,GAAQ,EAAK,OAAOA,GAAS,SAAWA,EAAS,KAClF,GAAI,OAAOD,EAC3B,IAAIE,EAAiBF,EAAK,MAAM;AAAA,CAAI,EAChCG,EAAgBD,EAAM,OAAe,CAACE,EAASC,EAAKC,IAAQ,CAvCpE,IAAAC,EAwCQ,GAAGD,GAAO,EAAG,OAAOF,EACpB,IAAMI,IAAaD,EAAAF,EAAK,MAAM,MAAM,IAAjB,YAAAE,EAAqB,GAAG,SAAU,EACrD,OAAO,KAAK,IAAIH,EAASI,CAAU,CACvC,EAAE,IAAI,EACN,OAAAN,EAAQA,EAAM,IAAIG,GAAMA,EAAK,UAAUF,CAAa,CAAC,EAC9CD,EAAM,KAAK;AAAA,CAAI,CAC1B,CAMO,SAASO,EAAkBC,EAAY,CAC1CA,EAAQ,OAAO,0BAA0B,uCAAS,CAAC,OAAO,GAAK,SAAS,GAAK,SAAS,GAAK,OAAO,EAAK,CAAC,EACxGA,EAAQ,OAAO,oBAAoB,mDAAW,CAAC,OAAO,GAAK,OAAO,EAAK,CAAC,EACxEA,EAAQ,OAAO,cAAc,uCAAS,CAAC,OAAO,GAAK,OAAO,EAAK,CAAC,CACpE,CAMO,SAASC,GAAS,CACrB,OAAO,QAAQ,KAAK,SAAS,aAAa,CAC9C,CAGO,SAASC,GAAkB,CAC9B,OAAO,QAAQ,KAAK,SAAS,mBAAmB,CACpD,CAOO,SAASC,EAAYC,KAAkBC,EAAW,CACrD,IAAIlB,EAAQkB,EAAK,QAAU,GAAK,OAAOA,EAAK,CAAC,GAAI,WAAcA,EAAK,CAAC,EAAE,EAAIA,EACxEJ,EAAQ,GAAG,EAAAb,QAAQ,IAAI,YAAYgB,CAAO,GAAG,GAAGjB,CAAI,CAC3D,CAGO,SAASmB,GAAUC,EAAM,CACzBN,EAAQ,EACPE,EAAY,4CAAcI,EAAE,KAAK,EAEjC,QAAQ,MAAMA,CAAC,CAGvB,CAGO,SAASC,GAAkBtB,EAAW,CACzC,OAAOA,EAAI,QAAQ,YAAY,CAACuB,EAAEC,IAASA,EAAO,YAAY,CAAC,CACnE,CAEO,SAASC,IAAO,CACnB,OAAO,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,CAAC,CAC9C,CAGA,SAAsBC,EAAaC,EAAY,QAAAC,EAAA,sBAC3C,IAAIC,EACJ,GAAG,CACCA,EAAS,QAAQF,CAAI,CACzB,OAAON,EAAM,CAET,MAAAQ,GADY,MAAM,OAAO,UAAUF,CAAI,KAC1B,QACPN,CACV,CACA,OAAOQ,CACX,GDjGO,IAAMC,EAAsC,CAC/C,QAAS,UACT,OAAS,OACT,OAAS,SACT,MAAS,OACT,KAAS,MACb,EAEaC,EAAuB,CAChC,OACA,WACA,YACA,SACA,UACA,OACA,SACA,SACA,cACA,eACA,OACA,yBACJ,EAiBaC,EAAN,KAAqB,CAExB,YAAmBC,EAAoBC,EAA2B,CAA/C,eAAAD,EACf,KAAK,OAASC,CAClB,CAMA,kBAAkBC,EAAS,CACvB,OAAQJ,EAAqB,SAAS,OAAOI,CAAI,CAAC,CACtD,CAQA,aAAaC,EAAUC,EAAkB,CAErC,IAAMC,EAAS,KAAK,OAEdC,EAAaH,GAASC,EAGtBG,EAAaD,IAAe,OAGlC,OAAGD,IAAW,GAAa,GACxBA,IAAW,GAAc,GACzBA,IAAW,WAGX,iBAAcA,CAAM,EACZ,CAACE,EAIT,OAAOF,GAAW,UAAY,KAAK,kBAAkBA,CAAM,EAClD,GAIO,gBAAgB,KAAK,KAAK,UAAU,KAAK,EACtC,CAACE,EAGpB,KAAK,UAAU,YAAc,KAAK,UAAU,WAAW,QAAQD,CAAU,GAAK,GACtE,GAEJ,CAACC,CAEZ,CAEQ,aAAa,CA5GzB,IAAAC,EA6GQ,IAAIC,EAAyF,CAAC,EAC1FC,GAAeF,EAAA,KAAK,UAAU,SAAf,YAAAA,EAAuB,QAC1C,GAAG,KAAK,UAAU,WACdC,EAAW,KAAK,UAAU,WAAW,IAAIE,GAClC,OAAOA,GAAS,SACR,CAAC,MAAMA,EAAO,MAAMA,CAAM,EAE1BA,CAEd,UACID,EACLD,EAAU,OAAOC,GAAe,WAAaA,EAAe,CAAC,MAE7D,OAAO,CAAC,EAEZ,OAAOD,CACX,CASA,MAAMH,EAAgB,CAElB,GAAM,CAAE,SAAAM,EAAU,aAAAR,CAAa,EAAI,KAAK,UAElCD,EAAQG,GAAcF,EAGxBS,EAAwB,OAEtBR,EAAS,KAAK,OAEpB,GAAG,KAAK,kBAAkBA,CAAM,EAC5BQ,EAAaR,aACR,iBAAcA,CAAM,EACzBQ,EAAcR,EAAwB,SACrC,CAED,IAAMS,EAAa,4CAA4C,KAAK,KAAK,UAAU,KAAK,EAClFC,EAAa,2BAA2B,KAAK,KAAK,UAAU,KAAK,EACjEC,EAAgB,CAAC,+BAA+B,KAAK,KAAK,UAAU,KAAK,EACzEC,KAAe,YAASb,CAAY,EACpCc,EAASd,GAAgBA,aAAwB,KAGjDe,EAAkB,MAAM,QAAQhB,CAAK,EAAI,QAC3CA,aAAiB,KAAO,OACxB,OAAOA,EAELiB,EAAe,KAAK,UAAU,OAEpC,GAAGA,GAAgBA,EAAa,QAAQ,CACpC,IAAMX,EAAUW,EAAa,QAC1BJ,GAAkB,MAAM,QAAQP,CAAO,GAAKA,EAAQ,QAAQ,EAC3DI,EAAa,SAEbA,EAAaD,EAAW,cAAgB,QAEhD,MAASE,EACLD,EAAa,OACRK,EACLL,EAAa,OACRI,EACLJ,EAAa,SACRE,EACLF,EAAa,OACRG,GAAiB,OAAOZ,GAAgB,UAC7CS,EAAa,UACRM,KAAYtB,IACjBgB,EAAahB,EAAcsB,CAAQ,EAE3C,CACA,OAAAE,EAAY,mDAAqB,CAAC,KAAK,UAAU,KAAK,EAAER,CAAU,CAAC,EAC5DA,CACX,CAMA,IAAIP,EAAgB,CAjMxB,IAAAE,EAmMQ,GAAM,CAAE,YAAAc,EAAa,aAAAlB,CAAa,EAAI,KAAK,UAEvCD,EAAQG,GAAcF,EAG1B,GAAG,CAAC,KAAK,aAAaD,EAAMC,CAAY,EAAG,OAG3C,IAAMS,EAAa,KAAK,MAAMP,CAAU,EAElCiB,EAASC,EAAA,CACX,KAASX,EACT,KAAS,KAAK,UAAU,cAAc,EACtC,QAASS,EACT,QAASnB,GACN,OAAO,KAAK,QAAW,SAAW,KAAK,OAAS,CAAC,GAmBxD,GAdAoB,EAAO,UAAWf,EAAA,KAAK,UAAU,SAAf,YAAAA,EAAuB,SAEtCK,GAAY,gBAAeU,EAAO,aAAa,IAClDA,EAAO,QAAUA,EAAO,SAAW,KAAK,YAAY,EAEjD,CAAC,SAAS,aAAa,EAAE,SAASV,CAAU,GAEtCA,GAAY,UACd,MAAM,QAAQU,EAAO,OAAO,IACvBA,EAAO,SAAQA,EAAO,OAASA,EAAO,QAAQ,CAAC,EAAE,OACjDA,EAAO,WAAUA,EAAO,SAAWA,EAAO,QAAQ,CAAC,EAAE,QAI9DpB,GAAS,OAAOoB,EAAO,SAAU,YAC7BA,EAAO,SAAW,MAAM,QAAQA,EAAO,OAAO,EAC7C,GAAGV,GAAY,SAAS,CACpB,IAAMY,EAAQ,MAAM,QAAQF,EAAO,OAAO,EAAIA,EAAO,QAAQ,UAAUG,GAAMA,EAAK,OAAOvB,CAAK,EAAI,GAC/FsB,GAAO,KACNF,EAAO,QAAUE,EAEzB,MAASZ,GAAY,eACjBU,EAAO,QAAQ,QAASG,GAAO,EACxB,MAAM,QAAQvB,CAAK,GAAKA,EAAM,SAASuB,EAAK,KAAK,GAE3CA,EAAK,OAAOvB,KACjBuB,EAAK,SAAW,GAExB,CAAC,EAKb,OAAOH,CACX,CAGJ,EDlOO,IAAMI,EAAN,cAAwB,QAAM,CAGjC,YAAYC,EAAeC,EAA2BC,EAA4B,CAC9E,MAAMF,EAAOC,CAAW,EAD0B,YAAAC,EAFtD,oBAAiB,GAIb,KAAK,WAAWA,GAAU,CAAC,CAAC,EAC5B,KAAK,OAAS,IAAIC,EAAgB,KAAKD,GAAA,YAAAA,EAAQ,MAAM,CACzD,CACQ,WAAWA,EAAyB,CACrCA,EAAO,SAAS,KAAK,QAAQA,EAAO,QAAQA,EAAO,kBAAkB,EACrEA,EAAO,WAAW,KAAK,UAAUA,EAAO,SAAS,EACjDA,EAAO,QAAQ,KAAK,IAAIA,EAAO,MAAM,EACrCA,EAAO,UAAU,KAAK,UAAUA,EAAO,QAAQ,EAC/CA,EAAO,SAAQ,KAAK,OAASA,EAAO,QACpCA,EAAO,WAAW,KAAK,oBAAoBA,EAAO,SAAS,EAC3DA,EAAO,SAAS,KAAK,QAAQA,EAAO,OAAO,EAC3CA,EAAO,WAAU,KAAK,SAASA,EAAO,UACtCA,EAAO,WAAU,KAAK,SAAWA,EAAO,UACxCA,EAAO,SAAQ,KAAK,OAASA,EAAO,QACpCA,EAAO,QAAQ,KAAK,OAAOA,EAAO,MAAM,EACxCA,EAAO,WAAU,KAAK,SAAWA,EAAO,UACxC,MAAM,QAAQA,EAAO,OAAO,GAAG,KAAK,QAAQA,EAAO,QAAQ,IAAIE,GAAQ,OAAOA,GAAS,SAAWA,EAASA,EAAO,KAAK,CAAC,CAC/H,CASA,UAAUC,EAA2C,CAzDzD,IAAAC,EA0DQ,OAAOA,EAAA,KAAK,SAAL,YAAAA,EAAa,IAAID,EAC5B,CACJ,EDvDA,IAAAE,EAAiB,mBACjBC,EAAe,iBA+DR,IAAMC,EAAQ,OAAO,cAAc,EAE7BC,EAAN,cAAyB,SAAQ,CAQvC,YAAYC,EAAe,CAC1B,MAAMA,CAAI,EARX,qBAAkB,GAClB,KAAQ,aAA+D,CAAC,EACxE,KAAQ,YAA8D,CAAC,EACvE,KAAQ,eAAkC,CAAC,EAC3C,KAAQ,cAAuC,CAAC,EAChD,KAAQ,SAAuC,CAAC,EAChD,KAAQ,gBAA2B,GAIlC,IAAMC,EAAO,KACR,KAAK,QAAQC,EAAkB,IAAI,EACxC,KAAK,KAAK,YAAa,UAA2B,QAAAC,EAAA,2BACjDF,EAAK,cAAgBA,EAAK,gBAAgB,KAAK,aAAa,EAE5D,MAAMA,EAAK,cAAc,MAAMA,EAAM,SAAS,CAC/C,GAAC,CACF,CACA,IAAI,QAAS,CAAE,OAAO,KAAK,QAAQ,IAAW,CAC9C,IAAI,cAAc,CAAE,OAAO,KAAK,aAAc,CAC9C,IAAI,SAAU,CAAE,OAAO,KAAK,QAAU,CACtC,IAAI,aAAc,CAAE,OAAO,KAAK,YAAc,CAC9C,IAAI,YAAa,CAAC,OAAO,KAAK,WAAY,CAC1C,IAAI,UAAW,CACd,IAAIG,EAAQ,CAAC,KAAK,KAAK,CAAC,EACpBC,EAAS,KAAK,OAClB,KAAOA,GACFA,EAAO,KAAK,IAAM,QACrBD,EAAM,QAAQC,EAAO,KAAK,CAAC,EAE5BA,EAASA,EAAO,OAEjB,OAAOD,EAAM,KAAK,GAAG,CACtB,CAKA,MAAO,CAEN,IAAIE,EAAW,KACf,KAAOA,GAAQA,EAAK,QAAU,MAC7BA,EAAOA,EAAK,OAEb,OAAOA,CACR,CAKA,QAAe,CACd,IAAMC,EAAa,UAAU,CAAC,EAC9B,GAAI,UAAU,QAAU,GAAK,OAAOA,GAAc,WAEjD,KAAK,SAAS,KAAK,CAClB,GAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,CAAC,EAC1C,QAAS,GACT,GAAIA,CACL,CAAC,UACS,UAAU,QAAU,GAAM,OAAOA,GAAc,YAAc,OAAO,UAAU,CAAC,GAAK,SAAW,CAEzG,IAAMC,EAAW,UAAU,CAAC,EACtBC,EAA+B,OAAO,OAAO,CAAE,GAAI,QAAS,EAAG,UAAU,CAAC,CAAC,EAC7EA,EAAW,IAAM,YAAW,KAAK,SAAW,CAAC,GACjD,IAAMC,EAAa,CAClB,GAAID,EAAW,IAAM,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,CAAC,EAC3D,QAASA,EAAW,SAAW,KAAY,GAAOA,EAAW,QAC7D,GAAID,CACL,EACI,OAAOC,EAAW,IAAM,SAC3B,KAAK,SAAS,OAAO,OAAOA,EAAW,EAAE,EAAG,EAAGC,CAAU,EAC/C,CAAC,SAAU,QAAQ,EAAE,SAASD,EAAW,EAAE,EACrD,KAAK,SAAS,KAAKC,CAAU,EACnB,CAAC,YAAa,OAAO,EAAE,SAASD,EAAW,EAAE,EACvD,KAAK,SAAS,OAAO,EAAG,EAAGC,CAAU,EAErC,KAAK,SAAS,KAAKA,CAAU,CAE/B,MACC,QAAQ,IAAI,8BAA8B,EAE3C,OAAO,MAAM,OAAO,KAAK,mBAAmB,CAAC,CAC9C,CAMQ,gBAAgBC,EAAqB,CAC5C,IAAMC,EAAO,CAAC,EAEVP,EAAcM,EAClB,KAAON,GACN,OAAO,OAAOO,EAAOP,EAAsB,YAAY,EACvDA,EAASA,EAAO,OAEjB,OAAOO,CACR,CAIQ,oBAAqB,CAC5B,OAAO,KAAK,sBAAsB,KAAK,oBAAoB,CAAC,CAC7D,CAKQ,qBAAoC,CAC3C,IAAIC,EAAqB,CAAC,EAEtBC,EAAyB,KAC7B,KAAOA,GACNA,EAAMA,EAAI,OACNA,GACHD,EAAK,KAAKC,CAAG,EAGf,OAAOD,CACR,CAIQ,qBAAsB,CAE7B,IAAMZ,EAAO,KACb,OAAO,UAA2B,QAAAE,EAAA,2BACjC,IAAMY,EAAO,MAAM,KAAK,SAAS,EAC7BC,EAEAP,EAAkC,CAAC,EACtCQ,EAAoB,CAAC,EACrBH,EACGC,EAAK,QAAU,IAClBD,EAAMC,EAAKA,EAAK,OAAS,CAAC,EAC1BN,EAAaM,EAAKA,EAAK,OAAS,CAAC,EACjCE,EAAaF,EAAK,MAAM,EAAGA,EAAK,OAAS,CAAC,GAE3C,MAAMd,EAAK,mBAAmB,CAAE,KAAMgB,EAAY,QAASR,EAAY,QAASK,CAAI,CAAC,EACrF,GAAI,CACH,QAASI,KAAUjB,EAAK,SACvB,GAAI,CAkBH,GAjBIiB,EAAO,SAEVC,EAAY,wCAA+B,IAAM,CAChDlB,EAAK,KAAK,EACVgB,EACAR,CACD,CAAC,EACDO,EAAW,MAAME,EAAO,GAAG,KAAK,KAAM,CACrC,QAASJ,EACT,MAASE,EACT,KAASC,EACT,QAASR,CACV,CAAC,GAGDO,EAAW,MAAME,EAAO,GAAG,MAAM,KAAMH,CAAI,EAExCC,IAAalB,EAAO,KACzB,OAASsB,EAAG,CACX,MAAAD,EAAY,4DAA0B,CAAClB,EAAK,KAAMiB,EAAO,GAAIE,CAAC,CAAC,EACzDA,CACP,CAEF,QAAE,CACD,MAAMnB,EAAK,kBAAkB,CAC5B,MAAOe,EACP,KAAMC,EACN,QAASR,EACT,QAASK,CACV,CAAC,CACF,CACD,GACD,CAIQ,sBAAsBO,EAAmB,CAEhD,IAAMpB,EAAO,KACb,OAAO,UAA2B,QAAAE,EAAA,2BACjC,IAAImB,EAAWrB,EAAK,cAAc,SAElC,GAAI,CAACqB,EACJ,OAAO,MAAMD,EAAG,MAAM,KAAM,MAAM,KAAK,SAAS,CAAC,EAE7C,MAAM,QAAQC,CAAQ,IAAGA,EAAWA,EAAS,MAAM,GAAG,GAC3DA,EAAWA,EAAS,OAAO,CAACC,EAAaC,KACpC,OAAOA,GAAO,UAAUD,EAAK,KAAK,GAAGC,EAAI,MAAM,GAAG,CAAC,EAChDD,GACL,CAAC,CAAC,EACL,QAASE,KAAWH,EAAU,CAC7B,IAAMI,EAAM,QAAQ,IAAI,EACxB,GAAI,CACE,EAAAC,QAAK,WAAWF,CAAO,IAAGA,EAAU,EAAAE,QAAK,KAAKD,EAAKD,CAAO,GAC3D,EAAAG,QAAG,WAAWH,CAAO,GAAK,EAAAG,QAAG,SAASH,CAAO,EAAE,YAAY,GAC9DN,EAAY,gDAAcM,CAAO,EACjC,QAAQ,MAAMA,CAAO,EACrB,MAAMJ,EAAG,MAAM,KAAM,MAAM,KAAK,SAAS,CAAC,GAE1CF,EAAY,gDAAcM,CAAO,CAEnC,QAAE,CACD,QAAQ,MAAMC,CAAG,CAClB,CACD,CACD,GACD,CACA,UAAU1B,EAAyB,CAClC,OAAO,KAAK,QAAQ,KAAM6B,GAAWA,EAAO,KAAK,GAAK7B,CAAI,CAC3D,CAOA,OAAO8B,EAAwCC,EAAiB,GAAM,CACrE,YAAK,aAAa,KAAK,CAACD,EAAUC,CAAK,CAAC,EACjC,IACR,CACc,mBAAmBhB,EAAW,QAAAZ,EAAA,sBAC3C,IAAM6B,EAA+D,KAAK,YAAY,IACrF,CAAC,CAACC,EAAMF,CAAK,IAAM,CAACE,EAAMF,EAAO,IAAI,CACtC,EACA,KAAK,oBAAoB,EAAE,QAASjB,GAAoB,CACvDkB,EAAM,QACL,GAAGlB,EAAI,YAAY,IAAI,CAAC,CAACmB,EAAMF,CAAK,IAC5B,CAACE,EAAMF,EAAOjB,CAAG,CACxB,CACF,CACD,CAAC,EACD,OAAS,CAACmB,EAAMF,EAAOjB,CAAG,IAAKkB,EACzBD,IACL,MAAME,EAAK,KAAKnB,EAAKC,CAAI,EAE3B,GAOA,MAAMe,EAAuCC,EAAiB,GAAM,CACnE,YAAK,YAAY,KAAK,CAACD,EAAUC,CAAK,CAAC,EAChC,IACR,CAEc,kBAAkBhB,EAAW,QAAAZ,EAAA,sBAC1C,IAAM6B,EAA8D,KAAK,WAAW,IACnF,CAAC,CAACC,EAAMF,CAAK,IAAM,CAACE,EAAMF,EAAO,IAAI,CACtC,EACA,KAAK,oBAAoB,EAAE,QAASjB,GAAoB,CACvDkB,EAAM,KACL,GAAGlB,EAAI,WAAW,IAAI,CAAC,CAACmB,EAAMF,CAAK,IAC3B,CAACE,EAAMF,EAAOjB,CAAG,CACxB,CACF,CACD,CAAC,EACD,OAAS,CAACmB,EAAMF,EAAOjB,CAAG,IAAKkB,EACzBD,IACL,MAAME,EAAK,KAAKnB,EAAKC,CAAI,EAE3B,GACc,cAAcmB,EAAsB,QAAA/B,EAAA,sBACjD,GAAI,KAAK,gBAAgB,EAAG,CAE3B,IAAMgC,EAA4B,CACjC,GAAG,KAAK,oBAAoB,EAC5B,GAAG,KAAK,cACT,EAEA,GAAIA,EAAU,OAAS,EAAG,CACzB,IAAMC,EAAU,QAAM,EAAAC,SAAQF,CAAS,EACvC,OAAO,QAAQC,CAAO,EAAE,QAAQ,CAAC,CAACE,EAAKC,CAAK,IAAM,CACjDL,EAAY,eAAeI,EAAKC,CAAK,CACtC,CAAC,CACF,CACD,CACD,GAEQ,iBAAkB,CACzB,OAAIC,EAAiB,EACb,GAEA,KAAK,eAEd,CAYQ,qBAAsC,CAE7C,IAAMC,EADU,KAAK,QAEnB,OAAQZ,GAAW,CAACA,EAAO,QAAUA,EAAO,cAAc,EAC1D,IAAKA,GAAWA,EAAO,UAAU,KAAK,cAAcA,EAAO,cAAc,CAAC,CAAC,CAAC,EAC5E,OAAQa,GAAWA,CAAM,EAE3B,OAAAvB,EAAY,8EAAwB,CACnC,KAAK,KAAK,EACVsB,EAAgB,OAChBA,EAAgB,IAAKC,GAAW,GAAGA,EAAO,IAAI,IAAIA,EAAO,IAAI,GAAG,EAAE,KAAK,GAAG,CAC3E,CAAC,EACMD,CACR,CAGA,OAAQE,EAAeC,EAAqBC,EAAkC,CAC5E,IAAMhB,EAAS,IAAIiB,EAAUH,EAAOC,EAAaC,CAAO,EACzD,OAAIhB,EAAO,UAAY,CAAC,KAAK,gBAAgB,IAAGA,EAAO,UAAY,IAC5D,KAAK,UAAUA,CAA2B,CAClD,CAYA,OAAOM,EAA0C,CAChD,YAAK,eAAe,KAAK,GAAI,MAAM,QAAQA,CAAS,EAAIA,EAAY,CAACA,CAAS,CAAE,EACzE,IACR,CAWM,gBAAiB,QAAAhC,EAAA,sBACtB,IAAM4C,EAAU,KAAK,SAAS,IAAKpC,IAAa,CAC/C,MAAO,GAAGA,EAAQ,YAAY,CAAC,IAAIA,EAAQ,KAAK,CAAC,IACjD,MAAOA,EAAQ,KAAK,CACrB,EAAE,EACIqC,EAAS,QAAM,EAAAX,SAAQ,CAC5B,KAAS,SACT,KAAS,UACT,QAAS,kCACT,QAAAU,CACD,CAAC,EAEKpC,EAAU,KAAK,SAAS,KAAMA,GAAYA,EAAQ,KAAK,IAAMqC,EAAO,OAAO,EACjF,MAAMrC,GAAA,YAAAA,EAAS,WAAW,CAACqC,EAAO,OAAO,EAAG,CAAE,KAAM,MAAO,EAC5D,GAIA,gBAAiB,CAChB,YAAK,gBAAkB,GAChB,IACR,CAIA,eAAgB,CACf,YAAK,gBAAkB,GAChB,IACR,CACD,EI/bA,IAAAC,EAAgC,6CAChCC,EAAmC,iDAEnCC,EAA0B,gBAG1B,IAAAC,EAAe,iBACfC,EAAiB,mBAeV,SAASC,EAAmCC,EAAsB,CACrE,IAAMC,EAAgB,KAAK,QAAQ,QACnC,GAAG,EAAEA,aAAyB,QAAS,MAAQ,CAAC,EAGhD,GAAM,CAAE,aAAAC,EAAa,CAAC,EAAE,gBAAAC,EAAgB,CAAC,EAAE,iBAAAC,EAAiB,CAAC,EAAE,qBAAAC,EAAqB,CAAC,EAAE,mBAAAC,EAAmB,CAAC,CAAE,KAAI,kBAAeN,CAAK,EAQrI,MAPqB,CACjB,GAAG,OAAO,KAAKE,CAAY,EAC3B,GAAG,OAAO,KAAKC,CAAe,EAC9B,GAAG,OAAO,KAAKC,CAAgB,EAC/B,GAAG,OAAO,KAAKC,CAAoB,EACnC,GAAG,OAAO,KAAKC,CAAkB,CACrC,EACoB,OAAOC,GAAMA,IAAO,eAAiBN,EAAc,KAAKM,CAAI,CAAC,CACrF,CAEA,SAASC,EAAUC,EAAWC,EAAmD,CAG7E,OADgBA,EAAO,MAAM,QAAQA,CAAG,EAAIA,EAAM,CAACA,CAAG,EAAK,CAAC,GAC7C,KAAKC,GACb,OAAOA,GAAW,SACT,IAAI,OAAOA,CAAM,EAAG,KAAKF,CAAG,EAC/BE,aAAkB,OAChBA,EAAO,KAAKF,CAAG,EAEf,EAEd,CACL,CAEO,SAASG,EAAyBC,EAAqBb,EAAuB,CACjF,IAAMc,EAAgB,KAAK,QAAQ,QAC7BC,EAAgB,KAAK,QAAQ,QACnC,GAAG,CAACD,EAAe,MAAO,CAAC,EAC3B,IAAME,KAAc,sBAAmBhB,GAAS,QAAQ,IAAI,CAAC,EACvDiB,EAAcJ,EAAc,EAAAK,QAAK,QAAQ,QAAQ,QAAQL,EAAY,CAAC,MAAM,CAACG,CAAqB,CAAC,CAAC,CAAC,EAAIA,EAE/G,GAAG,CAACC,EACA,OAAAE,EAAY,wDAAsB,EAC3B,CAAC,EAIZ,IAAMC,EAAerB,EAAuB,KAAK,KAAKkB,CAAW,EAE3DI,EAAiB,CAAC,EAExB,OAAGrB,IAAQ,QAAWqB,EAAQ,KAAK,EAAAH,QAAK,KAAKD,EAAY,KAAK,QAAQ,MAAM,CAAC,EAC7EG,EAAa,OAAOb,GACJC,EAAUD,EAAKO,CAAa,GAAK,CAACN,EAAUD,EAAKQ,CAAa,CACzE,EACA,QAAQR,GAAM,CACXY,EAAY,wBAAS,GAAGN,EAAcN,EAAK,OAAOM,EAAeN,CAAI,EAAE,EACvE,GAAG,CACC,IAAMe,EAAe,EAAAJ,QAAK,QAAQ,QAAQ,QAAQX,EAAK,CAAC,MAAMU,EAAc,CAACA,CAAW,EAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,EACvGM,EAAe,EAAAL,QAAK,KAAKI,EAAa,KAAK,QAAQ,MAAO,EAE5DpB,EAAeH,EAAuB,KAAK,KAAKuB,CAAY,EAChED,EAAQ,KAAK,GAAGnB,EAAa,OAAiB,CAACsB,EAAOC,KAClDN,EAAY,wBAAS,GAAGM,CAAW,OAAOlB,CAAI,EAAE,EAChDiB,EAAO,KAAK,GAAGZ,EAAa,KAAK,KAAKa,EAAYH,CAAY,CAAC,EACxDE,GACT,CAAC,CAAC,CAAC,EACF,EAAAE,QAAG,WAAWH,CAAa,GAC1BF,EAAQ,KAAKE,CAAa,CAElC,OAAOI,EAAM,CACTR,EAAY,yDAAiB,CAACZ,EAAKoB,EAAE,KAAK,CAAC,CAC/C,CACJ,CAAC,EAEE,CAAC,GAAG,IAAI,IAAIN,CAAO,CAAC,CAC/B,CAUA,SAAsBO,EAAaC,EAAW,QAAAC,EAAA,sBAC1C,IAAMT,EAAWT,EAAa,KAAKiB,CAAG,EAChCE,EAA2B,CAAC,EAC5BC,EAAQ,CAAC,EACfX,EAAQ,QAAQY,GAAK,IACjB,YAAS,IAAI,CACT,IAAIA,EACJ,SAAU,EACd,CAAC,EAAE,QAASC,GAAc,CAEtB,GADiB,EAAAhB,QAAK,SAASgB,CAAI,EACvB,WAAW,GAAG,EAAG,OAC7B,IAAMC,EAAM,EAAAjB,QAAK,QAAQgB,CAAI,EAAE,YAAY,EACxC,CAAC,MAAM,OAAO,MAAM,EAAE,SAASC,CAAG,EACjCH,EAAM,KAAKE,CAAI,EACV,EAAAR,QAAG,SAASQ,CAAI,EAAE,YAAY,IACnCF,EAAM,KAAK,EAAAd,QAAK,KAAKgB,EAAK,UAAU,CAAC,EACrCF,EAAM,KAAK,EAAAd,QAAK,KAAKgB,EAAK,WAAW,CAAC,EACtCF,EAAM,KAAK,EAAAd,QAAK,KAAKgB,EAAK,WAAW,CAAC,EAE9C,CAAC,CACL,CAAC,EACD,QAAQA,KAAQF,EACb,GAAI,EAAAN,QAAG,WAAWQ,CAAI,EACrB,GAAG,CAEC,GADAf,EAAY,8BAAUe,CAAI,EACvBA,EAAK,SAAS,MAAM,GAAKA,EAAK,SAAS,KAAK,EAC3CH,EAAS,KAAK,MAAMK,EAAaF,CAAI,CAAC,UACjCA,EAAK,SAAS,MAAM,EAAE,CAC3B,IAAMG,EAAM,MAAM,OAAO,UAAUH,CAAI,IACvCH,EAAS,KAAKM,EAAI,OAAO,CAC7B,CACJ,OAAOV,EAAM,CACTR,EAAYQ,CAAC,CACjB,CAEJ,OAAOI,CACX,GLlIA,IAAAO,GAA4B,wCAE5BC,GAAwB,0CACxB,GAAAC,QAAW,KAAK,EAuCT,IAAMC,EAAN,cAAqB,YAA2B,CAInD,YAAYC,EAAuB,CAC/B,MAAM,EAFV,KAAQ,YAAkB,CAAC,EAGvB,KAAK,WAAS,iBAAa,CACvB,KAAa,SACb,QAAa,KACb,OAAa,MACb,OAAa,OACb,YAAa,EACjB,EAAEA,CAAO,EACT,KAAK,kBAAkB,CAC3B,CACA,IAAI,SAAS,CAAC,OAAO,KAAK,QAAQ,OAAO,CACzC,IAAI,MAAM,CAAC,OAAO,KAAK,QAAQ,IAAI,CAInC,IAAI,mBAAmB,CACnB,OAAO,KAAK,KAAa,QAAQ,SAAS,cAAc,CAC5D,CAIc,iBAAiB,QAAAC,EAAA,sBAC3B,IAAMC,EAAS,MAAMC,EAAa,IAAI,EACtC,QAAQC,KAASF,EACb,GAAG,CACC,GAAG,OAAOE,GAAS,WAAW,CAC1B,IAAIC,EAAOD,EAAM,IAAI,EACrBC,EAAOA,EAAS,MAAM,QAAQA,CAAI,EAAIA,EAAO,CAACA,CAAI,EAAK,CAAC,EACxD,KAAK,SAAS,IAAIA,CAAI,CAC1B,CACJ,OAAO,EAAM,CACTC,EAAY,0CAAY,EAAE,KAAK,CACnC,CAER,GAKQ,mBAAmB,CACvB,KAAK,KAAO,IAAIC,EAAW,KAAK,IAAI,EACpC,KAAK,KACA,WAAW,YAAY,EACvB,OAAO,IAAI,CACL,KAAK,QAAQ,MAAM,EAAAC,QAAQ,IAAIC,EAAU,KAAK,QAAQ,KAAK,CAAC,CAAC,EAChE,QAAQ,IAAI,EAEZ,IAAIC,EAAQ,KAAK,QAAQ,OAAQ,KAAK,QAAQ,KAC3C,MAAM,QAAQA,CAAK,EAClB,EAAAF,QAAQ,IAAI,OAAOE,EAAM,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,GAAGA,EAAM,MAAM,CAAC,CAAC,CAAC,EAE7D,EAAAF,QAAQ,IAAI,GAAGE,EAAM,WAAW,CAAC,qBAAqB,KAAK,QAAQ,OAAO,EAG3E,KAAK,QAAQ,aAAa,EAAAF,QAAQ,IAAI,EAAAA,QAAQ,OAAO,SAAS,KAAK,QAAQ,WAAW,CAAC,EAC1F,QAAQ,IAAI,EACZ,KAAK,KAAK,KAAK,CACnB,CAAC,EACLG,EAAkB,KAAK,IAAI,EACxB,KAAK,QAAQ,QAAQ,KAAK,KAAK,KAAK,YAAY,KAAK,QAAQ,MAAM,EACnE,KAAK,QAAQ,OAAO,KAAK,KAAK,KAAK,aAAa,KAAK,QAAQ,KAAK,CACzE,CASO,QAAQC,EAAY,CAAC,IAAAC,EAAI,YAAY,YAAAC,EAAY,EAAI,EAAkF,CACvIA,IAAaF,EAAOH,EAAUG,EAAKE,CAAW,GACjD,KAAK,KAAK,YAAYD,EAAID,CAAI,CAClC,CAMA,SAASG,EAAkB,CACvB,GAAG,OAAOA,GAAM,WAAW,CACvB,IAAIC,EAASD,EAAI,IAAI,EACjBV,EAAOW,aAAkB,MAAQA,EAAUA,GAAQ,KAAY,CAAC,EAAK,CAACA,CAAM,EAChF,QAAQD,KAAOV,EAIRU,EAAI,gBACA,KAAK,WAAWA,EAAI,KAAK,CAAC,EACzB,EAAAP,QAAQ,MAAM,YAAYO,EAAI,KAAK,CAAC,wBAAwB,GAE5DT,EAAY,8BAAUS,EAAI,QAAQ,EAClC,KAAK,KAAK,WAAWA,CAAc,EAClCA,EAAY,KAAO,KACpB,KAAK,KAAK,WAAWA,EAAI,SAAS,EAAI,GAG1C,EAAAP,QAAQ,MAAM,YAAYO,EAAI,SAAS,CAAC,2BAA2B,CAG/E,MACI,EAAAP,QAAQ,MAAM,iBAAiB,CAEvC,CAEA,WAAWS,EAAoB,CAC3B,OAAO,KAAK,KAAK,SAAS,KAAKC,GAAGA,EAAE,KAAK,GAAGD,CAAI,CACpD,CAaA,IAAIA,EAAmC,CACnC,IAAME,EAAMF,EAAK,MAAM,GAAG,EACtBG,EAAoB,KAAK,KACzBC,EACJ,KAAMF,EAAM,OAAO,GAAE,CACjB,IAAMG,EAAUH,EAAM,MAAM,EACtBI,EAAIH,EAAO,SAAS,KAAKF,GAAGA,EAAE,KAAK,GAAGI,CAAO,EAChDC,GAAKJ,EAAM,QAAQ,IAClBE,EAAYE,GAEhBH,EAASG,CACb,CACA,OAAOF,CACX,CAWA,KAAKJ,EAA4C,CAC7C,IAAMF,EAAM,KAAK,IAAIE,CAAI,EACzB,GAAGF,EACC,OAAO,QAAQ,QAAQA,CAAG,EACzB,CACD,IAAMS,KAAS,gBAAY,EAC3B,YAAK,YAAY,KAAKA,CAAM,EACrB,IAAI,QAAiCC,GAAU,CAClD,IAAIC,EACJA,EAAW,KAAK,GAAG,WAAYC,GAAkB,CAC1CA,GAAU,GAAG,KAAK,IAAI,IAAIV,CAAI,KAC7BS,EAAS,IAAI,EACbF,EAAO,QAAQ,EACf,KAAK,YAAc,KAAK,YAAY,OAAOI,GAAGA,GAAGJ,CAAM,EACvDC,EAAQ,KAAK,IAAIR,CAAI,CAAC,EAE9B,EAAE,CAAC,UAAU,EAAI,CAAC,CACtB,CAAC,CACL,CACJ,CAOA,OAAOA,EAAoB,CACvB,OAAGA,KAAQ,KAAK,KAAK,SACV,GAEA,KAAK,IAAIA,CAAI,GAAK,IAEjC,CAKA,KAAK,CAQD,KAAK,gBAAgB,EAAE,KAAK,IACjB,QAAQ,IAAI,KAAK,YAAY,IAAIO,GAAQA,EAAO,GAAK,CAAC,CAAC,EAAE,KAAK,IAAI,CACrE,KAAK,KAAK,WAAW,QAAQ,IAAI,CACrC,CAAC,CACJ,CACL,CACJ","names":["index_exports","__export","BREAK","MixCli","MixCommand","MixOption","MixOptionPrompt","addBuiltInOptions","fixIndent","getId","hyphenToCamelCase","importModule","isDebug","isDisablePrompts","outputDebug","outputStr","promptTypeMap","showError","supportedPromptTypes","__toCommonJS","import_string","import_liteEvent","import_logsets","import_assignObject","import_commander","import_prompts","import_commander","import_isPlainObject","import_isNumber","import_logsets","outputStr","str","vars","logsets","fixIndent","text","indent","lines","minSpaceCount","minCount","line","index","_a","spaceCount","addBuiltInOptions","command","isDebug","isDisablePrompts","outputDebug","message","args","showError","e","hyphenToCamelCase","_","letter","getId","importModule","file","__async","module","promptTypeMap","supportedPromptTypes","MixOptionPrompt","cliOption","promptParams","type","input","defaultValue","params","inputValue","hasInput","_a","choices","choicesParam","choice","variadic","promptType","isListType","isTextType","isBooleanType","isNumberType","isDate","datatype","optionParams","outputDebug","description","prompt","__spreadValues","index","item","MixOption","flags","description","params","MixOptionPrompt","choice","inputValue","_a","import_node_path","import_node_fs","BREAK","MixCommand","name","self","addBuiltInOptions","__async","names","parent","root","actionFunc","actionFn","actionOpts","actionItem","command","opts","cmds","cmd","args","preValue","actionArgs","action","outputDebug","e","fn","workDirs","dirs","dir","workDir","cwd","path","fs","option","listener","scope","hooks","hook","thisCommand","questions","results","prompts","key","value","isDisablePrompts","optionPromports","prompt","flags","description","options","MixOption","choices","result","import_getPackageJson","import_getPackageRootPath","import_glob","import_node_fs","import_node_path","getMatchedDependencies","entry","pacakgeMacher","dependencies","devDependencies","peerDependencies","optionalDependencies","bundleDependencies","name","isMatched","str","reg","regexp","findCliPaths","packageName","includeMacher","excludeMacher","packageRoot","packagePath","path","outputDebug","packageNames","cliDirs","packageEntry","packageCliDir","result","dependencie","fs","e","findCommands","cli","__async","commands","files","dir","file","ext","importModule","cmd","import_asyncSignal","import_string_prototype","replaceAll","MixCli","options","__async","cmders","findCommands","cmder","cmds","outputDebug","MixCommand","logsets","fixIndent","title","addBuiltInOptions","text","pos","alignIndent","cmd","result","name","c","names","curCmd","resultCmd","topName","r","signal","resolve","listener","fullname","s"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,4 @@
1
+ var W=Object.defineProperty;var k=Object.getOwnPropertySymbols;var F=Object.prototype.hasOwnProperty,X=Object.prototype.propertyIsEnumerable;var w=(r,n,t)=>n in r?W(r,n,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[n]=t,_=(r,n)=>{for(var t in n||(n={}))F.call(n,t)&&w(r,t,n[t]);if(k)for(var t of k(n))X.call(n,t)&&w(r,t,n[t]);return r};var g=(r=>typeof require!="undefined"?require:typeof Proxy!="undefined"?new Proxy(r,{get:(n,t)=>(typeof require!="undefined"?require:n)[t]}):r)(function(r){if(typeof require!="undefined")return require.apply(this,arguments);throw Error('Dynamic require of "'+r+'" is not supported')});var l=(r,n,t)=>new Promise((e,i)=>{var o=a=>{try{p(t.next(a))}catch(c){i(c)}},s=a=>{try{p(t.throw(a))}catch(c){i(c)}},p=a=>a.done?e(a.value):Promise.resolve(a.value).then(o,s);p((t=t.apply(r,n)).next())});import"flex-tools/string";import{LiteEvent as tt}from"flex-tools/events/liteEvent";import f from"logsets";import{assignObject as et}from"flex-tools/object/assignObject";import{Command as G}from"commander";import S from"prompts";import{Option as z}from"commander";import{isPlainObject as R}from"flex-tools/typecheck/isPlainObject";import{isNumber as U}from"flex-tools/typecheck/isNumber";import j from"logsets";function rt(r,n){j.log(x(r),n)}function x(r,n){if((n==null||n===!0?0:typeof n=="number"?n:-1)==-1)return r;let e=r.split(`
2
+ `),i=e.reduce((o,s,p)=>{var c;if(p==0)return o;let a=((c=s.match(/^\s*/))==null?void 0:c[0].length)||0;return Math.min(o,a)},9999);return e=e.map(o=>o.substring(i)),e.join(`
3
+ `)}function b(r){r.option("--work-dirs <values...>","\u6307\u5B9A\u5DE5\u4F5C\u76EE\u5F55",{hidden:!0,optional:!0,required:!0,prompt:!1}),r.option("--disable-prompts","\u7981\u7528\u6240\u6709\u4EA4\u4E92\u63D0\u793A",{hidden:!0,prompt:!1}),r.option("--debug-cli","\u663E\u793A\u8C03\u8BD5\u4FE1\u606F",{hidden:!0,prompt:!1})}function D(){return process.argv.includes("--debug-cli")}function E(){return process.argv.includes("--disable-prompts")}function m(r,...n){let t=n.length==1&&typeof n[0]=="function"?n[0]():n;D()&&j.log(`[MixCli] ${r}`,...t)}function at(r){D()?m("\u5BFC\u5165\u547D\u4EE4<>\u51FA\u9519:{}",r.stack):console.error(r)}function pt(r){return r.replace(/-([a-z])/g,(n,t)=>t.toUpperCase())}function ct(){return Math.random().toString(36).substr(2)}function H(r){return l(this,null,function*(){let n;try{n=g(r)}catch(t){throw n=(yield import(`file://${r}`)).default,t}return n})}var T={boolean:"confirm",string:"text",number:"number",array:"list",date:"date"},K=["text","password","invisible","number","confirm","list","toggle","select","multiselect","autocomplete","date","autocompleteMultiselect"],C=class{constructor(n,t){this.cliOption=n;this.params=t}isValidPromptType(n){return K.includes(String(n))}isNeedPrompt(n,t){let e=this.params,i=n||t,o=i!==void 0;return e===!0?!0:e===!1?!1:e==="auto"||R(e)?!o:typeof e=="string"&&this.isValidPromptType(e)?!0:/(\<s*\w\s*\>)/.test(this.cliOption.flags)?!o:this.cliOption.argChoices&&this.cliOption.argChoices.indexOf(i)==-1?!0:!o}_getChoices(){var e;let n=[],t=(e=this.cliOption.params)==null?void 0:e.choices;if(this.cliOption.argChoices)n=this.cliOption.argChoices.map(i=>typeof i=="string"?{title:i,value:i}:i);else if(t)n=typeof t=="function"?t:[];else return[];return n}infer(n){let{variadic:t,defaultValue:e}=this.cliOption,i=n||e,o="text",s=this.params;if(this.isValidPromptType(s))o=s;else if(R(s))o=s.type;else{let p=/(\[\s*\w+\.\.\.\s*])|(\<\s*\w+\.\.\.\s*>)/.test(this.cliOption.flags),a=/(\<s*\w+\s*\>)|(\[\w+\])/.test(this.cliOption.flags),c=!/(\[\s*\w+s*])|(\<\s*\w+\s*>)/.test(this.cliOption.flags),y=U(e),O=e&&e instanceof Date,h=Array.isArray(i)?"array":i instanceof Date?"date":typeof i,d=this.cliOption.params;if(d&&d.choices){let A=d.choices;c&&Array.isArray(A)&&A.length==2?o="toggle":o=t?"multiselect":"select"}else p?o="list":O?o="date":y?o="number":a?o="text":c||typeof e=="boolean"?o="confirm":h in T&&(o=T[h])}return m("\u9009\u9879<{}> -> \u63D0\u793A\u7C7B\u578B<{}>",[this.cliOption.name(),o]),o}get(n){var p;let{description:t,defaultValue:e}=this.cliOption,i=n||e;if(!this.isNeedPrompt(i,e))return;let o=this.infer(n),s=_({type:o,name:this.cliOption.attributeName(),message:t,initial:i},typeof this.params=="object"?this.params:{});if(s.validate=(p=this.cliOption.params)==null?void 0:p.validate,o=="multiselect"&&(s.instructions=!1),s.choices=s.choices||this._getChoices(),["select","multiselect"].includes(o)||o=="toggle"&&Array.isArray(s.choices)&&(s.active||(s.active=s.choices[0].value),s.inactive||(s.inactive=s.choices[1].value)),i&&typeof s.initial!="function"&&s.choices&&Array.isArray(s.choices))if(o=="select"){let a=Array.isArray(s.choices)?s.choices.findIndex(c=>c.value==i):-1;a!=-1&&(s.initial=a)}else o=="multiselect"&&s.choices.forEach(a=>{(Array.isArray(i)&&i.includes(a.value)||a.value==i)&&(a.selected=!0)});return s}};var M=class extends z{constructor(t,e,i){super(t,e);this.params=i;this.__MIX_OPTION__=!0;this._setOption(i||{}),this.prompt=new C(this,i==null?void 0:i.prompt)}_setOption(t){t.default&&this.default(t.default,t.defaultDescription),t.conflicts&&this.conflicts(t.conflicts),t.envVar&&this.env(t.envVar),t.parseArg&&this.argParser(t.parseArg),t.hidden&&(this.hidden=t.hidden),t.mandatory&&this.makeOptionMandatory(t.mandatory),t.implies&&this.implies(t.implies),t.optional&&(this.optional=t.optional),t.variadic&&(this.variadic=t.variadic),t.negate&&(this.negate=t.negate),t.preset&&this.preset(t.preset),t.required&&(this.required=t.required),Array.isArray(t.choices)&&this.choices(t.choices.map(e=>typeof e=="string"?e:e.value))}getPrompt(t){var e;return(e=this.prompt)==null?void 0:e.get(t)}};import V from"node:path";import I from"node:fs";var J=Symbol("BREAK_ACTION"),P=class extends G{constructor(t){super(t);this.__MIX_COMMAND__=!0;this._beforeHooks=[];this._afterHooks=[];this._customPrompts=[];this._optionValues={};this._actions=[];this._enable_prompts=!0;let e=this;this.isRoot||b(this),this.hook("preAction",function(){return l(this,arguments,function*(){e._optionValues=e.getOptionValues(this.hookedCommand),yield e.preActionHook.apply(e,arguments)})})}get isRoot(){return this.parent==null}get optionValues(){return this._optionValues}get actions(){return this._actions}get beforeHooks(){return this._beforeHooks}get afterHooks(){return this._afterHooks}get fullname(){let t=[this.name()],e=this.parent;for(;e;)e.name()!=="root"&&t.unshift(e.name()),e=e.parent;return t.join(".")}root(){let t=this;for(;t&&t.parent!=null;)t=t.parent;return t}action(){let t=arguments[0];if(arguments.length==1&&typeof t=="function")this._actions.push({id:Math.random().toString(36).substring(2),enhance:!1,fn:t});else if(arguments.length==2&&typeof t=="function"&&typeof arguments[1]=="object"){let e=arguments[0],i=Object.assign({at:"append"},arguments[1]);i.at=="replace"&&(this._actions=[]);let o={id:i.id||Math.random().toString(36).substring(2),enhance:i.enhance==null?!0:i.enhance,fn:e};typeof i.at=="number"?this._actions.splice(Number(i.at),0,o):["append","before"].includes(i.at)?this._actions.push(o):["preappend","after"].includes(i.at)?this._actions.splice(0,0,o):this._actions.push(o)}else console.log("[mixcli] action params error");return super.action(this.getWrapperedAction())}getOptionValues(t){let e={},i=t;for(;i;)Object.assign(e,i.optionValues),i=i.parent;return e}getWrapperedAction(){return this.wrapperWorkDirsAction(this.wrapperChainActions())}getAncestorCommands(){let t=[],e=this;for(;e;)e=e.parent,e&&t.push(e);return t}wrapperChainActions(){let t=this;return function(){return l(this,arguments,function*(){let e=Array.from(arguments),i,o={},s=[],p;e.length>=2&&(p=e[e.length-1],o=e[e.length-2],s=e.slice(0,e.length-2)),yield t.executeBeforeHooks({args:s,options:o,command:p});try{for(let a of t._actions)try{if(a.enhance?(m("\u6267\u884C<{}>: args={}, options={}",()=>[t.name(),s,o]),i=yield a.fn.call(this,{command:p,value:i,args:s,options:o})):i=yield a.fn.apply(this,e),i===J)break}catch(c){throw m("\u547D\u4EE4{}\u7684Action({})\u6267\u884C\u51FA\u9519:{}",[t.name,a.id,c]),c}}finally{yield t.executeAfterHooks({value:i,args:s,options:o,command:p})}})}}wrapperWorkDirsAction(t){let e=this;return function(){return l(this,arguments,function*(){let i=e._optionValues.workDirs;if(!i)return yield t.apply(this,Array.from(arguments));Array.isArray(i)||(i=i.split(",")),i=i.reduce((o,s)=>(typeof s=="string"&&o.push(...s.split(",")),o),[]);for(let o of i){let s=process.cwd();try{V.isAbsolute(o)||(o=V.join(s,o)),I.existsSync(o)&&I.statSync(o).isDirectory()?(m("\u5207\u6362\u5230\u5DE5\u4F5C\u76EE\u5F55:{}",o),process.chdir(o),yield t.apply(this,Array.from(arguments))):m("\u65E0\u6548\u7684\u5DE5\u4F5C\u76EE\u5F55:{}",o)}finally{process.chdir(s)}}})}}getOption(t){return this.options.find(e=>e.name()==t)}before(t,e=!0){return this._beforeHooks.push([t,e]),this}executeBeforeHooks(t){return l(this,null,function*(){let e=this.beforeHooks.map(([i,o])=>[i,o,this]);this.getAncestorCommands().forEach(i=>{e.unshift(...i.beforeHooks.map(([o,s])=>[o,s,i]))});for(let[i,o,s]of e)o&&(yield i.call(s,t))})}after(t,e=!0){return this._afterHooks.push([t,e]),this}executeAfterHooks(t){return l(this,null,function*(){let e=this.afterHooks.map(([i,o])=>[i,o,this]);this.getAncestorCommands().forEach(i=>{e.push(...i.afterHooks.map(([o,s])=>[o,s,i]))});for(let[i,o,s]of e)o&&(yield i.call(s,t))})}preActionHook(t){return l(this,null,function*(){if(this.isEnablePrompts()){let e=[...this.generateAutoPrompts(),...this._customPrompts];if(e.length>0){let i=yield S(e);Object.entries(i).forEach(([o,s])=>{t.setOptionValue(o,s)})}}})}isEnablePrompts(){return E()?!1:this._enable_prompts}generateAutoPrompts(){let e=this.options.filter(i=>!i.hidden&&i.__MIX_OPTION__).map(i=>i.getPrompt(this._optionValues[i.attributeName()])).filter(i=>i);return m("\u547D\u4EE4<{}>\u81EA\u52A8\u751F\u6210{}\u4E2A\u9009\u9879\u63D0\u793A:{}",[this.name(),e.length,e.map(i=>`${i.name}(${i.type})`).join(",")]),e}option(t,e,i){let o=new M(t,e,i);return o.required&&!this.isEnablePrompts()&&(o.mandatory=!0),this.addOption(o)}prompt(t){return this._customPrompts.push(...Array.isArray(t)?t:[t]),this}selectCommands(){return l(this,null,function*(){let t=this.commands.map(o=>({title:`${o.description()}(${o.name()})`,value:o.name()})),e=yield S({type:"select",name:"command",message:"\u8BF7\u9009\u62E9\u547D\u4EE4:",choices:t}),i=this.commands.find(o=>o.name()===e.command);yield i==null?void 0:i.parseAsync([e.command],{from:"user"})})}disablePrompts(){return this._enable_prompts=!1,this}enablePrompts(){return this._enable_prompts=!0,this}};import{getPackageJson as Q}from"flex-tools/package/getPackageJson";import{getPackageRootPath as Y}from"flex-tools/package/getPackageRootPath";import{globSync as Z}from"glob";import v from"node:fs";import u from"node:path";function L(r){let n=this.options.include;if(!(n instanceof RegExp))return[];let{dependencies:t={},devDependencies:e={},peerDependencies:i={},optionalDependencies:o={},bundleDependencies:s={}}=Q(r);return[...Object.keys(t),...Object.keys(e),...Object.keys(i),...Object.keys(o),...Object.keys(s)].filter(a=>a!=="@voerka/cli"&&n.test(a))}function N(r,n){return(n?Array.isArray(n)?n:[n]:[]).some(e=>typeof e=="string"?new RegExp(e).test(r):e instanceof RegExp?e.test(r):!1)}function $(r,n){let t=this.options.include,e=this.options.exclude;if(!t)return[];let i=Y(n||process.cwd()),o=r?u.dirname(g.resolve(r,{paths:[i]})):i;if(!o)return m("MixCli\u53EA\u80FD\u8FD0\u884C\u5728Nodejs\u73AF\u5883"),[];let s=L.call(this,o),p=[];return n!==void 0&&p.push(u.join(o,this.options.cliDir)),s.filter(a=>N(a,t)&&!N(a,e)).forEach(a=>{m("\u5339\u914D\u5305:{}",`${r?a+" <- "+r:a}`);try{let c=u.dirname(g.resolve(a,{paths:o?[o]:[process.cwd()]})),y=u.join(c,this.options.cliDir),O=L.call(this,c);p.push(...O.reduce((h,d)=>(m("\u5339\u914D\u5305:{}",`${d} <- ${a}`),h.push(...$.call(this,d,c)),h),[])),v.existsSync(y)&&p.push(y)}catch(c){m("\u89E3\u6790\u5305<{}>\u8DEF\u5F84\u51FA\u9519\uFF1A{}",[a,c.stack])}}),[...new Set(p)]}function B(r){return l(this,null,function*(){let n=$.call(r),t=[],e=[];n.forEach(i=>{Z("*",{cwd:i,absolute:!0}).forEach(o=>{if(u.basename(o).startsWith("_"))return;let p=u.extname(o).toLowerCase();[".js",".cjs",".mjs"].includes(p)?e.push(o):v.statSync(o).isDirectory()&&(e.push(u.join(o,"index.js")),e.push(u.join(o,"index.cjs")),e.push(u.join(o,"index.mjs")))})});for(let i of e)if(v.existsSync(i))try{if(m("\u5BFC\u5165\u547D\u4EE4:{}",i),i.endsWith(".cjs")||i.endsWith(".js"))t.push(yield H(i));else if(i.endsWith(".mjs")){let o=yield import(`file://${i}`);t.push(o.default)}}catch(o){m(o)}return t})}import{asyncSignal as it}from"flex-tools/async/asyncSignal";import ot from"string.prototype.replaceall";ot.shim();var q=class extends tt{constructor(t){super();this.findSignals=[];this.options=et({name:"mixcli",package:null,cliDir:"cli",prompt:"auto",ignoreError:!1},t),this.createRootCommand()}get context(){return this.options.context}get name(){return this.options.name}get isDisabledPrompts(){return this.root.rawArgs.includes("--no-prompts")}installCommands(){return l(this,null,function*(){let t=yield B(this);for(let e of t)try{if(typeof e=="function"){let i=e(this);i=i?Array.isArray(i)?i:[i]:[],this.register(()=>i)}}catch(i){m("\u6CE8\u518C\u547D\u4EE4\u5931\u8D25:{}",i.stack)}})}createRootCommand(){this.root=new P(this.name),this.root.helpOption("-h, --help").action(()=>{this.options.logo&&f.log(x(this.options.logo,2)),console.log();let t=this.options.title||this.options.name;Array.isArray(t)?f.log(String(t[0]).firstUpper(),[...t.slice(1)]):f.log(`${t.firstUpper()} Version: {}`,this.options.version),this.options.description&&f.log(f.colors.darkGray(this.options.description)),console.log(),this.root.help()}),b(this.root),this.options.before&&this.root.hook("preAction",this.options.before),this.options.after&&this.root.hook("postAction",this.options.after)}addHelp(t,{pos:e="beforeAll",alignIndent:i=!0}){i&&(t=x(t,i)),this.root.addHelpText(e,t)}register(t){if(typeof t=="function"){let e=t(this),i=e instanceof Array?e:e==null?[]:[e];for(let o of i)o.__MIX_COMMAND__?this.hasCommand(o.name())?f.error(`Command <${o.name()}> has been registered!`):(m("\u6CE8\u518C\u547D\u4EE4:{}",o.fullname),this.root.addCommand(o),o._cli=this,this.emit("register",o.fullname,!0)):f.error(`Command <${o.toString()}> is not a valid command!`)}else f.error("Invalid command")}hasCommand(t){return this.root.commands.some(e=>e.name()==t)}get(t){let e=t.split("."),i=this.root,o;for(;e.length>0;){let s=e.shift(),p=i.commands.find(a=>a.name()==s);p&&e.length==0&&(o=p),i=p}return o}find(t){let e=this.get(t);if(e)return Promise.resolve(e);{let i=it();return this.findSignals.push(i),new Promise(o=>{let s;s=this.on("register",p=>{p==`${this.name}.${t}`&&(s.off(),i.resolve(),this.findSignals=this.findSignals.filter(a=>a!=i),o(this.get(t)))},{objectify:!0})})}}exists(t){return t in this.root.commands?!0:this.get(t)!=null}run(){this.installCommands().then(()=>Promise.all(this.findSignals.map(t=>t(1e4))).then(()=>{this.root.parseAsync(process.argv)}))}};export{J as BREAK,q as MixCli,P as MixCommand,M as MixOption,C as MixOptionPrompt,b as addBuiltInOptions,x as fixIndent,ct as getId,pt as hyphenToCamelCase,H as importModule,D as isDebug,E as isDisablePrompts,m as outputDebug,rt as outputStr,T as promptTypeMap,at as showError,K as supportedPromptTypes};
4
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/command.ts","../src/option.ts","../src/prompt.ts","../src/utils.ts","../src/finder.ts"],"sourcesContent":["#!/usr/bin/env node\nimport \"flex-tools/string\"\nimport { LiteEvent, LiteEventSubscriber } from \"flex-tools/events/liteEvent\"\nimport { Command } from \"commander\"\nimport logsets from \"logsets\"\n\nimport { assignObject } from \"flex-tools/object/assignObject\"\nimport { MixCommand } from \"./command\"\nimport { addBuiltInOptions, fixIndent, outputDebug } from './utils';\nimport { findCommands } from \"./finder\"\nimport { asyncSignal } from \"flex-tools/async/asyncSignal\"\n// @ts-ignore\nimport replaceAll from 'string.prototype.replaceall' \nreplaceAll.shim() \n\nexport interface MixCliOptions{\n name:string,\n title?:string | (string | boolean | number)[],\n description?:string,\n version?:string\n // 定义显示帮助信息\n logo?:string ,\n // 在根命令执行前执行==commander的preAction\n before?:(thisCommand:Command,actionCommand:Command)=>void,\n // 在根命令执行后执行==commander的postAction\n after?:(thisCommand:Command,actionCommand:Command)=>void, \n // flexcli运行时会在当前工程的package.json的依赖中查找以prefix/开头的包,然后自动加载其cli目录下的命令\n // 例如:prefix=myapp,则会自动加载flex-cli-xxx包中的cli目录下的命令\n // 如prefix=myapp, cliPath=\"cmds\",则会自动加载flex-cli-xxx包中的cmds目录下的命令\n include?:string | RegExp | string[] | RegExp[],\n // 忽略查找正则表达式\n exclude?:string | RegExp | string[] | RegExp[],\n // flexcli会在当前工程的以prefix/开头下查找命令声明\n // / pattern默认值是cli,即会在当前工程的以prefix/开头的包下查找cli目录下的命令\n // 指定cli所在的目录,默认值是cli,要遍历该目录下的所有js文件作为命令导出\n cliDir?:string \n context?:Record<string,any> // 传递给命令的共享上下文,所有命令均可要使用 \n // 默认是否启用交互提示, auto当没有值时,会根据当前是否在终端中运行来决定是否启用交互提示\n // 为false时,禁用所有交互提示,为true时,启用所有交互提示 \n prompt?:'auto' | boolean \n ignoreError?:boolean\n}\n\n \n \n\nexport type MixCliCommand = (cli:MixCli)=>MixCommand | MixCommand[] | void\n\n\nexport type MixCliEvents = \n \"register\" // 当命令注册时触发\n\nexport class MixCli extends LiteEvent<any,MixCliEvents>{\n options:Required<MixCliOptions> \n root!:MixCommand \n private findSignals:any[]=[]\n constructor(options?:MixCliOptions){\n super()\n this.options= assignObject({\n name : \"mixcli\",\n package : null,\n cliDir : \"cli\",\n prompt : 'auto',\n ignoreError: false\n },options) as Required<MixCliOptions> \n this.createRootCommand() \n } \n get context(){return this.options.context}\n get name(){return this.options.name}\n /**\n * 是否禁用了所有的交互提示\n */\n get isDisabledPrompts(){\n return(this.root as any).rawArgs.includes(\"--no-prompts\") \n } \n /**\n * 扫描当前工程的依赖,加载匹配include的依赖下的命令\n */\n private async installCommands(){\n const cmders = await findCommands(this)\n for(let cmder of cmders){\n try{\n if(typeof(cmder)===\"function\"){\n let cmds = cmder(this)\n cmds = cmds ? (Array.isArray(cmds) ? cmds : [cmds]) : []\n this.register(()=>cmds) \n }\n }catch(e:any){\n outputDebug(\"注册命令失败:{}\",e.stack)\n }\n }\n } \n /**\n * 创建根命令\n * \n */\n private createRootCommand(){\n this.root = new MixCommand(this.name);\n this.root \n .helpOption('-h, --help')\n .action(()=>{ \n if(this.options.logo) logsets.log(fixIndent(this.options.logo,2))\n console.log()\n // 显示标题\n let title = this.options.title|| this.options.name\n if(Array.isArray(title)){\n logsets.log(String(title[0]).firstUpper(),[...title.slice(1)])\n }else{\n logsets.log(`${title.firstUpper()} Version: {}`,this.options.version)\n } \n // @ts-ignore\n if(this.options.description) logsets.log(logsets.colors.darkGray(this.options.description)) \n console.log()\n this.root.help() \n }) \n addBuiltInOptions(this.root)\n if(this.options.before) this.root.hook('preAction',this.options.before)\n if(this.options.after) this.root.hook('postAction',this.options.after) \n } \n /**\n * 添加帮助选项\n * \n * @param text 帮助文本\n * @param position 显示位置,可选值:before|after|beforeAll|afterAll\n * @param fixIndent 是否自动修正缩进,如果为true,则会自动修正缩进,当显示多行时文本时,会自动修正缩进\n * \n */\n public addHelp(text:string,{pos='beforeAll',alignIndent=true}:{pos:'before'|'after' | 'beforeAll' | 'afterAll',alignIndent?:boolean | number}){\n if(alignIndent) text = fixIndent(text,alignIndent)\n this.root.addHelpText(pos,text)\n }\n\n /**\n * 注册一个命令\n * @param cmd \n */\n register(cmd:MixCliCommand){\n if(typeof(cmd)==\"function\"){\n let result = cmd(this)\n let cmds = result instanceof Array ? result : (result==undefined ? [] : [result])\n for(let cmd of cmds){\n // 为什么不用cmd instanceof MixCommand来判断是否是一个有效的命令?\n // 因为当不同的包引用了与主包不一样版本的mixcli时,判断会失效,导致不能识别\n // 所以我们通过cmd.__MIX_COMMAND__来判断是否是一个有效的命令\n if(cmd.__MIX_COMMAND__){ \n if(this.hasCommand(cmd.name())){\n logsets.error(`Command <${cmd.name()}> has been registered!`)\n }else{\n outputDebug(\"注册命令:{}\",cmd.fullname)\n this.root.addCommand(cmd as Command) ;\n (cmd as any)._cli = this\n this.emit(\"register\",cmd.fullname,true)\n } \n }else{\n logsets.error(`Command <${cmd.toString()}> is not a valid command!`)\n }\n } \n }else{\n logsets.error(\"Invalid command\")\n } \n }\n\n hasCommand(name:string):boolean{\n return this.root.commands.some(c=>c.name()==name)\n }\n\n /**\n * 根据命令名称查找命令\n * \n * @remarks\n * \n * find(\"dev\")\n * find(\"dev.microservice\") 支持多级命令\n * find(\"abc\",DevCommand) 允许指定从DevCommand下开始查找abc命令\n * \n * @param name \n */\n get(name:string):MixCommand | undefined{\n const names=name.split(\".\")\n let curCmd:MixCommand = this.root\n let resultCmd:MixCommand | undefined\n while(names.length>0){\n const topName = names.shift()\n const r = curCmd.commands.find(c=>c.name()==topName) as MixCommand\n if(r && names.length==0){\n resultCmd = r\n }\n curCmd = r\n } \n return resultCmd \n }\n /**\n * 查找一个命令\n * \n * 如果命令不存在,则等待命令注册后再返回\n * \n * 在多包场景下,如果命令在其他包中注册并且该包中的命令还没注册,则会等待命令注册后再返回\n * \n * @param name \n * @returns \n */\n find(name:string):Promise<MixCommand | undefined>{\n const cmd = this.get(name)\n if(cmd){\n return Promise.resolve(cmd) \n }else{\n const signal = asyncSignal()\n this.findSignals.push(signal)\n return new Promise<MixCommand | undefined>((resolve)=>{\n let listener:LiteEventSubscriber\n listener = this.on(\"register\",(fullname:string)=>{\n if(fullname==`${this.name}.${name}`){\n listener.off()\n signal.resolve()\n this.findSignals = this.findSignals.filter(s=>s!=signal)\n resolve(this.get(name))\n }\n },{objectify:true}) as LiteEventSubscriber\n })\n } \n }\n /**\n * 判断命令是否存在\n * \n * @param name \n * @returns \n */\n exists(name:string):boolean{\n if(name in this.root.commands){\n return true\n }else{\n return this.get(name) != undefined\n }\n } \n \n /**\n * 运行命令行程序\n */\n run(){ \n // 为什么有findSignal这玩意,解决什么问题?\n // 当我们要扩展command时,通过get(\"命令名称\")来获取已经注册的命令的方式有个缺陷\n // 就是如果对命令的注册顺序有严格的要求,比如调用get('dev')时要求dev命令必须已经存在\n // 这对动态包的命令注册扩展开发体验不好\n // 所以引入find(\"命令名称\")来获取命令,该方法可以获取到后注册的命令\n // 其副作用是,在run时,可能find还没有运行到,从而导致在帮助信息里面看不到扩展的信息(实际上是已经生效的)\n // 所以我们在find里面注入一个异步信号来解决此问题\n this.installCommands().then(()=>{\n return Promise.all(this.findSignals.map(signal=>signal(10000))).then(()=>{\n this.root.parseAsync(process.argv); \n })\n }) \n }\n}\n ","import { Command, Option } from \"commander\";\nimport prompts, { PromptObject } from \"prompts\";\nimport { MixOption, type MixedOptionParams } from \"./option\";\nimport { addBuiltInOptions, isDisablePrompts, outputDebug } from \"./utils\";\nimport type { AsyncFunction } from \"flex-tools/types\"; \nimport path from \"node:path\";\nimport fs from \"node:fs\";\n\n\n\nexport type IMixCommandHookListener = ({\n\targs,\n\toptions,\n\tcommand,\n}: {\n\targs: any[];\n\toptions: Record<string, any>;\n\tcommand: MixCommand;\n}) => void | Promise<void>;\n\nexport type BeforeMixCommandHookListener = ({\n\targs,\n\toptions,\n\tcommand,\n}: {\n\targs: any[];\n\toptions: Record<string, any>;\n\tcommand: MixCommand;\n}) => void | Promise<void>;\n\nexport type AfterMixCommandHookListener = ({\n\tvalue,\n\targs,\n\toptions,\n\tcommand,\n}: {\n\tvalue: any;\n\targs: any[];\n\toptions: Record<string, any>;\n\tcommand: MixCommand;\n}) => void | Promise<void>;\n\nexport interface MixActionOptions {\n\tid: string;\n\tat: \"replace\" | \"before\" | \"after\" | \"preappend\" | \"append\" | number;\t\n\tenhance: boolean;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 函数签名类型,即采用原始的commander的action函数签名,还是mixcli的action函数签名\n}\n\nexport interface MixActionRegistry extends Omit<MixActionOptions, \"at\"> {\n\tfn: Function;\n}\n\n// 原始的Action动作函数\nexport type MixOriginalAction = (...args: any[]) => any | Promise<void>;\n\n// 增强的Action函数签名\nexport type MixEnhanceAction = ({\n\targs,\n\toptions,\n\tvalue,\n\tcommand,\n}: {\n\targs: any[];\n\toptions: Record<string, any>;\n\tvalue: any;\n\tcommand: MixCommand;\n}) => any | Promise<any>;\n\n// 执行action的返回结果\nexport const BREAK = Symbol(\"BREAK_ACTION\"); // 中止后续的action执行\n\nexport class MixCommand extends Command {\n\t__MIX_COMMAND__ = true;\n\tprivate _beforeHooks : [ BeforeMixCommandHookListener, boolean ][] = [];\n\tprivate _afterHooks : [ AfterMixCommandHookListener, boolean ][] = [];\n\tprivate _customPrompts : PromptObject[] = [];\n\tprivate _optionValues : Record<string, any> = {}; \t\t\t\t\t\t\t// 命令行输入的选项值\n\tprivate _actions : MixActionRegistry[] = []; \t\t\t\t\t\t\t// 允许多个action\n\tprivate _enable_prompts: boolean = true; \t\t\t\t\t\t\t\t\t// 是否启用交互提示\n\tconstructor(name?: string) {\n\t\tsuper(name);\t\t\n\t\t// eslint-disable-next-line no-this-alias\n\t\tconst self = this\n\t\tif (!this.isRoot) addBuiltInOptions(this); \n\t\tthis.hook(\"preAction\", async function (this: any) {\n\t\t\tself._optionValues = self.getOptionValues(this.hookedCommand);\t\t\t\n\t\t\t// @ts-ignore\n\t\t\tawait self.preActionHook.apply(self, arguments);\n\t\t});\n\t} \n\tget isRoot() { return this.parent==undefined;\t}\n\tget optionValues(){ return this._optionValues }\n\tget actions() { return this._actions; }\n\tget beforeHooks() {\treturn this._beforeHooks; }\n\tget afterHooks() {return this._afterHooks;}\n\tget fullname() {\n\t\tlet names = [this.name()];\n\t\tlet parent = this.parent;\n\t\twhile (parent) {\n\t\t\tif (parent.name() !== \"root\") {\n\t\t\t\tnames.unshift(parent.name());\n\t\t\t}\n\t\t\tparent = parent.parent;\n\t\t}\n\t\treturn names.join(\".\");\n\t}\n\n\t/**\n\t * 返回根命令\n\t */\n\troot() { \n\t\t// eslint-disable-next-line no-this-alias\n\t\tlet root:any = this;\n\t\twhile (root && root.parent != null) {\n\t\t\troot = root.parent as unknown as MixCommand;\n\t\t}\n\t\treturn root;\n\t}\n\n\n\taction(fn: MixEnhanceAction, options: MixActionOptions): this;\n\taction(fn: MixOriginalAction): this;\n\taction(): this {\n\t\tconst actionFunc = arguments[0];\n\t\tif (arguments.length == 1 && typeof actionFunc == \"function\") {\n\t\t\t// 原始方式\n\t\t\tthis._actions.push({\n\t\t\t\tid: Math.random().toString(36).substring(2),\n\t\t\t\tenhance: false,\n\t\t\t\tfn: actionFunc,\n\t\t\t});\n\t\t} else if (arguments.length == 2 && typeof actionFunc == \"function\" && typeof arguments[1] == \"object\" ) {\n\t\t\t// 增强模式\n\t\t\tconst actionFn = arguments[0];\n\t\t\tconst actionOpts: MixActionOptions = Object.assign({ at: \"append\" }, arguments[1]);\n\t\t\tif (actionOpts.at == \"replace\") this._actions = [];\n\t\t\tconst actionItem = {\n\t\t\t\tid: actionOpts.id || Math.random().toString(36).substring(2),\n\t\t\t\tenhance: actionOpts.enhance == undefined ? true : actionOpts.enhance,\n\t\t\t\tfn: actionFn,\n\t\t\t} as const;\n\t\t\tif (typeof actionOpts.at == \"number\") {\n\t\t\t\tthis._actions.splice(Number(actionOpts.at), 0, actionItem);\n\t\t\t} else if ([\"append\", \"before\"].includes(actionOpts.at)) {\n\t\t\t\tthis._actions.push(actionItem);\n\t\t\t} else if ([\"preappend\", \"after\"].includes(actionOpts.at)) {\n\t\t\t\tthis._actions.splice(0, 0, actionItem);\n\t\t\t} else {\n\t\t\t\tthis._actions.push(actionItem);\n\t\t\t}\n\t\t} else {\n\t\t\tconsole.log(\"[mixcli] action params error\");\n\t\t}\n\t\treturn super.action(this.getWrapperedAction());\n\t}\n\n\t/**\n\t * 读取命令配置值,包括父命令提供的配置选项\n\t * @param command\n\t */\n\tprivate getOptionValues(command: MixCommand) {\n\t\tconst opts = {};\n\t\t// eslint-disable-next-line no-this-alias\n\t\tlet parent: any = command;\n\t\twhile (parent) {\n\t\t\tObject.assign(opts, (parent as MixCommand).optionValues);\n\t\t\tparent = parent.parent;\n\t\t}\n\t\treturn opts;\n\t}\n\t/**\n\t * 本函数在运行时子类进行action生成该命令的action\n\t */\n\tprivate getWrapperedAction() {\n\t\treturn this.wrapperWorkDirsAction(this.wrapperChainActions());\n\t}\n\n\t/**\n\t * 向上查找所有祖先命令\n\t */\n\tprivate getAncestorCommands(): MixCommand[] {\n\t\tlet cmds: MixCommand[] = [];\n\t\t// eslint-disable-next-line no-this-alias\n\t\tlet cmd: MixCommand | null = this;\n\t\twhile (cmd) {\n\t\t\tcmd = cmd.parent as unknown as MixCommand;\n\t\t\tif (cmd) {\n\t\t\t\tcmds.push(cmd);\n\t\t\t}\n\t\t}\n\t\treturn cmds;\n\t}\n\t/***\n\t * 将所有actions包装成一个链式调用的函数\n\t */\n\tprivate wrapperChainActions() {\n\t\t// eslint-disable-next-line no-this-alias\n\t\tconst self = this;\n\t\treturn async function (this: any) {\n\t\t\tconst args = Array.from(arguments); // 原始输入的参数\n\t\t\tlet preValue: any; // 保存上一个action的返回值\n\t\t\t//解析参数, 0-1个参数为options,最后一个参数为command\n\t\t\tlet actionOpts: Record<string, any> = {},\n\t\t\t\tactionArgs: any[] = [],\n\t\t\t\tcmd: any;\n\t\t\tif (args.length >= 2) {\n\t\t\t\tcmd = args[args.length - 1]; // 最后一个command\n\t\t\t\tactionOpts = args[args.length - 2];\n\t\t\t\tactionArgs = args.slice(0, args.length - 2);\n\t\t\t}\n\t\t\tawait self.executeBeforeHooks({ args: actionArgs, options: actionOpts, command: cmd });\n\t\t\ttry {\n\t\t\t\tfor (let action of self._actions) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (action.enhance) {\n\t\t\t\t\t\t\t// 增强模式\n\t\t\t\t\t\t\toutputDebug(\"执行<{}>: args={}, options={}\", () => [\n\t\t\t\t\t\t\t\tself.name(),\n\t\t\t\t\t\t\t\tactionArgs,\n\t\t\t\t\t\t\t\tactionOpts,\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\tpreValue = await action.fn.call(this, {\n\t\t\t\t\t\t\t\tcommand: cmd,\n\t\t\t\t\t\t\t\tvalue : preValue,\n\t\t\t\t\t\t\t\targs : actionArgs,\n\t\t\t\t\t\t\t\toptions: actionOpts,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// 原始模式\n\t\t\t\t\t\t\tpreValue = await action.fn.apply(this, args);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (preValue === BREAK) break;\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\toutputDebug(\"命令{}的Action({})执行出错:{}\", [self.name, action.id, e]);\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tawait self.executeAfterHooks({\n\t\t\t\t\tvalue: preValue,\n\t\t\t\t\targs: actionArgs,\n\t\t\t\t\toptions: actionOpts,\n\t\t\t\t\tcommand: cmd,\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t}\n\t/**\n\t * 当传入--work-dirs时用来处理工作目录\n\t */\n\tprivate wrapperWorkDirsAction(fn: AsyncFunction) {\n\t\t// eslint-disable-next-line no-this-alias\n\t\tconst self = this;\n\t\treturn async function (this: any) {\n\t\t\tlet workDirs = self._optionValues.workDirs;\n\t\t\t// 未指定工作目录参数\n\t\t\tif (!workDirs) {\n\t\t\t\treturn await fn.apply(this, Array.from(arguments));\n\t\t\t}\n\t\t\tif (!Array.isArray(workDirs)) workDirs = workDirs.split(\",\");\n\t\t\tworkDirs = workDirs.reduce((dirs: any[], dir: string) => {\n\t\t\t\tif (typeof dir == \"string\") dirs.push(...dir.split(\",\"));\n\t\t\t\treturn dirs;\n\t\t\t}, []);\n\t\t\tfor (let workDir of workDirs) {\n\t\t\t\tconst cwd = process.cwd();\n\t\t\t\ttry {\n\t\t\t\t\tif (!path.isAbsolute(workDir)) workDir = path.join(cwd, workDir);\n\t\t\t\t\tif (fs.existsSync(workDir) && fs.statSync(workDir).isDirectory()) {\n\t\t\t\t\t\toutputDebug(\"切换到工作目录:{}\", workDir);\n\t\t\t\t\t\tprocess.chdir(workDir); // 切换\n\t\t\t\t\t\tawait fn.apply(this, Array.from(arguments));\n\t\t\t\t\t} else {\n\t\t\t\t\t\toutputDebug(\"无效的工作目录:{}\", workDir);\n\t\t\t\t\t} \n\t\t\t\t} finally {\n\t\t\t\t\tprocess.chdir(cwd);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\tgetOption(name: string): MixOption {\n\t\treturn this.options.find((option) => option.name() == name) as unknown as MixOption;\n\t}\n\t/**\n\t * 添加一个Before钩子\n\t * @param listener\n\t * @param scope =false时代表只在本命令执行,=true时代表在本命令及其子命令执行\n\t * @returns\n\t */\n\tbefore(listener: BeforeMixCommandHookListener, scope: boolean = true) {\n\t\tthis._beforeHooks.push([listener, scope]);\n\t\treturn this;\n\t}\n\tprivate async executeBeforeHooks(args: any) {\n\t\tconst hooks: [BeforeMixCommandHookListener, boolean, MixCommand][] = this.beforeHooks.map(\n\t\t\t([hook, scope]) => [hook, scope, this]\n\t\t);\n\t\tthis.getAncestorCommands().forEach((cmd: MixCommand) => {\n\t\t\thooks.unshift(\n\t\t\t\t...cmd.beforeHooks.map(([hook, scope]) => {\n\t\t\t\t\treturn [hook, scope, cmd] as [BeforeMixCommandHookListener, boolean, MixCommand];\n\t\t\t\t})\n\t\t\t);\n\t\t});\n\t\tfor (let [hook, scope, cmd] of hooks) {\n\t\t\tif (!scope) continue;\n\t\t\tawait hook.call(cmd, args);\n\t\t}\n\t}\n\t/**\n\t * 添加一个After钩子\n\t * @param listener\n\t * @param scope =false时代表只在本命令执行,=true时代表在本命令及其子命令执行\n\t * @returns\n\t */\n\tafter(listener: AfterMixCommandHookListener, scope: boolean = true) {\n\t\tthis._afterHooks.push([listener, scope]);\n\t\treturn this;\n\t}\n\n\tprivate async executeAfterHooks(args: any) {\n\t\tconst hooks: [AfterMixCommandHookListener, boolean, MixCommand][] = this.afterHooks.map(\n\t\t\t([hook, scope]) => [hook, scope, this]\n\t\t);\n\t\tthis.getAncestorCommands().forEach((cmd: MixCommand) => {\n\t\t\thooks.push(\n\t\t\t\t...cmd.afterHooks.map(([hook, scope]) => {\n\t\t\t\t\treturn [hook, scope, cmd] as [BeforeMixCommandHookListener, boolean, MixCommand];\n\t\t\t\t})\n\t\t\t);\n\t\t});\n\t\tfor (let [hook, scope, cmd] of hooks) {\n\t\t\tif (!scope) continue; //=false时不执行\n\t\t\tawait hook.call(cmd, args);\n\t\t}\n\t}\n\tprivate async preActionHook(thisCommand: Command) {\n\t\tif (this.isEnablePrompts()) {\n\t\t\t// 自动生成提示\n\t\t\tconst questions: PromptObject[] = [\n\t\t\t\t...this.generateAutoPrompts(),\n\t\t\t\t...this._customPrompts,\n\t\t\t];\n\t\t\t// 用户提示\n\t\t\tif (questions.length > 0) {\n\t\t\t\tconst results = await prompts(questions);\n\t\t\t\tObject.entries(results).forEach(([key, value]) => {\n\t\t\t\t\tthisCommand.setOptionValue(key, value);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate isEnablePrompts() {\n\t\tif (isDisablePrompts()) {\t\t\t\n\t\t\treturn false;// 命令行参数禁用了提示,优先级最高\n\t\t} else {\n\t\t\treturn this._enable_prompts;\n\t\t}\n\t}\n\n\t/**\n\t * 生成选项自动提示\n\t *\n\t * @remarks\n\t * 要求所有未提供默认值的Option自动生成提示\n\t *\n\t * - 未提供默认值,并且是必选的参数Option\n\t * - 指定了choices但未提供有效值的Option\n\t *\n\t */\n\tprivate generateAutoPrompts(): PromptObject[] {\n\t\tconst options = this.options as unknown as MixOption[];\n\t\tconst optionPromports = options\n\t\t\t.filter((option) => !option.hidden && option.__MIX_OPTION__)\n\t\t\t.map((option) => option.getPrompt(this._optionValues[option.attributeName()]))\n\t\t\t.filter((prompt) => prompt) as PromptObject[];\n\t\t\t\n\t\toutputDebug(\"命令<{}>自动生成{}个选项提示:{}\", [\n\t\t\tthis.name(),\n\t\t\toptionPromports.length,\n\t\t\toptionPromports.map((prompt) => `${prompt.name}(${prompt.type})`).join(\",\"),\n\t\t]);\n\t\treturn optionPromports;\n\t} \n\n\t// @ts-ignore\n\toption( flags: string, description: string, options?: MixedOptionParams ):this{ \n \t\tconst option = new MixOption(flags, description, options);\n\t\tif (option.required && !this.isEnablePrompts()) option.mandatory = true;\t\t\n\t\treturn this.addOption(option as unknown as Option) \n\t}\n\n\t/**\n\t * 添加提示\n\t *\n\t * @remarks\n\t *\n\t * 添加一些自定义提示 \n\t *\n\t * @param questions\n\t * @returns\n\t */\n\tprompt(questions: PromptObject | PromptObject[]) {\n\t\tthis._customPrompts.push(...(Array.isArray(questions) ? questions : [questions]));\n\t\treturn this;\n\t}\n\n\t/**\n\t *\n\t * 选择命令并执行\n\t *\n\t * @remorks\n\t *\n\t * 当命令具有多个子命令时,并且没有提供默认子命令时,提示用户选择一个子命令\n\t *\n\t */\n\tasync selectCommands() {\n\t\tconst choices = this.commands.map((command) => ({\n\t\t\ttitle: `${command.description()}(${command.name()})`,\n\t\t\tvalue: command.name(),\n\t\t}));\n\t\tconst result = await prompts({\n\t\t\ttype : \"select\",\n\t\t\tname : \"command\",\n\t\t\tmessage: \"请选择命令:\",\n\t\t\tchoices,\n\t\t});\n\t\t// 重新解析命令行参数标志,\n\t\tconst command = this.commands.find((command) => command.name() === result.command);\n\t\tawait command?.parseAsync([result.command], { from: \"user\" });\n\t}\n\t/**\n\t * 禁用/启用所有提示\n\t */\n\tdisablePrompts() {\n\t\tthis._enable_prompts = false;\n\t\treturn this;\n\t}\n\t/**\n\t * 启用所有提示\n\t */\n\tenablePrompts() {\n\t\tthis._enable_prompts = true;\n\t\treturn this;\n\t}\n}\n\n\n\n// 编写一个类型号用来表示Commander的Option flags字面量类型","import { Option, OptionValues } from 'commander'\nimport { PromptObject } from 'prompts'\nimport { PromptChoice, MixOptionPrompt,PromptParams } from './prompt'\n \n\nexport interface MixedOptionParams {\n required? : boolean; // A value must be supplied when the option is specified.\n optional? : boolean; // A value is optional when the option is specified.\n variadic? : boolean; \n mandatory? : boolean; // The option must have a value after parsing, which usually means it must be specified on command line.\n negate? : boolean;\n default? : any;\n defaultDescription? : string;\n conflicts? : string | string[];\n argParser? : unknown;\n implies? : OptionValues\n envVar? : string;\n parseArg? : <T>(value: string, previous: T) => T;\n hidden? : boolean;\n choices? : (string | PromptChoice )[] | ((pre:any,answers:any)=>(string | PromptChoice)[]);\n validate? : (value: any) => boolean;\n preset? : unknown;\n prompt? : PromptParams\n}\n\n\nexport class MixOption extends Option{\n __MIX_OPTION__ = true\n prompt? : MixOptionPrompt \n constructor(flags: string, description: string,public params?: MixedOptionParams) {\n super(flags, description) \n this._setOption(params || {}) \n this.prompt = new MixOptionPrompt(this,params?.prompt) \n } \n private _setOption(params:MixedOptionParams){ \n if(params.default) this.default(params.default,params.defaultDescription)\n if(params.conflicts) this.conflicts(params.conflicts)\n if(params.envVar) this.env(params.envVar)\n if(params.parseArg) this.argParser(params.parseArg) \n if(params.hidden) this.hidden = params.hidden\n if(params.mandatory) this.makeOptionMandatory(params.mandatory)\n if(params.implies) this.implies(params.implies) \n if(params.optional) this.optional=params.optional\n if(params.variadic) this.variadic = params.variadic\n if(params.negate) this.negate = params.negate\n if(params.preset) this.preset(params.preset)\n if(params.required) this.required = params.required \n if(Array.isArray(params.choices)) this.choices(params.choices.map(choice=>typeof(choice)=='string' ? choice : choice.value))\n } \n \n /**\n * 返回选项的提示对象\n * \n * @remarks \n * @param inputValue \n * @returns \n */\n getPrompt(inputValue?:any): PromptObject | undefined {\n return this.prompt?.get(inputValue)\n } \n}","import { isPlainObject } from \"flex-tools/typecheck/isPlainObject\"\nimport { isNumber } from \"flex-tools/typecheck/isNumber\"\n\nimport { PromptObject } from \"prompts\" \nimport { outputDebug } from \"./utils\"\nimport { MixOption } from \"./option\" \n\nexport type PromptType = \"text\" | \"password\" | \"invisible\" | \"number\"| \"confirm\"| \"list\" \n | \"toggle\"| \"select\" | \"multiselect\" | \"autocomplete\" | \"date\" | \"autocompleteMultiselect\"\n\nexport type PromptParam = 'auto' | boolean | PromptType | PromptObject\nexport type InputPromptParam = PromptParam | ((value:any)=>PromptParam) | boolean\nexport type PromptParamDefaultValue = string | boolean | string[] \n\nexport const promptTypeMap:Record<string,string> = {\n boolean: \"confirm\",\n string : \"text\",\n number : \"number\", \n array : \"list\", \n date : \"date\"\n} \n\nexport const supportedPromptTypes = [\n \"text\",\n \"password\",\n \"invisible\", \n \"number\", \n \"confirm\" , \n \"list\", \n \"toggle\" , \n \"select\" , \n \"multiselect\" , \n \"autocomplete\" , \n \"date\" , \n \"autocompleteMultiselect\"\n]\n\nexport interface PromptChoice {\n title : string;\n value? : any;\n disabled? : boolean | undefined;\n selected? : boolean | undefined;\n description?: string | undefined;\n}\n\n \nexport type PromptParams = Omit<PromptObject,'name'> | PromptType | boolean | 'auto' | undefined \n\n/**\n * 负责生成prompt对象\n * \n */\nexport class MixOptionPrompt{\n params?: PromptParams\n constructor(public cliOption:MixOption,promptParams?:PromptParams){ \n this.params = promptParams\n }\n /**\n * 返回输入的是否是有效的prompt类型\n * @param type \n * @returns \n */\n isValidPromptType(type:any){\n return supportedPromptTypes.includes(String(type))\n }\n /**\n * 推断是否需要提示\n * \n * 1. 显式指定prompt=true或者提示类型,或者提示对象,则需要提示\n * \n * \n */\n isNeedPrompt(input:any,defaultValue?:any){\n \n const params = this.params\n\n const inputValue = input || defaultValue\n\n // 是否有输入值,即在命令行输入了值\n const hasInput = !(inputValue === undefined)\n \n // 1. 显式指定了_prompt为true,则需要提示,后续进行提示类型的推断,可能不会准确\n if(params === true) return true\n if(params === false) return false \n if(params === 'auto') return !hasInput\n\n // 2. 提供了一个prompt对象,并且没有在命令行输入值,则需要提示\n if(isPlainObject(params)){\n return !hasInput\n }\n\n // 3. 指定了内置的prompt类型,如prompt='password',则使用password类型提示输入\n if(typeof(params) == 'string' && this.isValidPromptType(params)){\n return true\n }\n\n // 4. 指定了可选值,但是没有输入值,则需要提示\n const isOptional = /(\\<s*\\w\\s*\\>)/.test(this.cliOption.flags) \n if(isOptional) return !hasInput\n \n // 4. 判断输入是否有效,则显示提示\n if(this.cliOption.argChoices && this.cliOption.argChoices.indexOf(inputValue) == -1){\n return true\n } \n return !hasInput\n\n }\n \n private _getChoices(){\n let choices:(string | PromptChoice)[] | ((pre:any,answers:any)=>(string | PromptChoice)[]) = []\n let choicesParam = this.cliOption.params?.choices\n if(this.cliOption.argChoices){\n choices = this.cliOption.argChoices.map(choice=>{\n if(typeof(choice)=='string'){\n return {title:choice,value:choice}\n }else{\n return choice\n }\n })\n }else if(choicesParam){\n choices = typeof(choicesParam)=='function' ? choicesParam : [] \n }else{\n return []\n } \n return choices\n } \n\n /**\n * 自动推断prompt类型\n * \n * \n * \n * @param inputValue 从命令行输入的值\n */\n infer(inputValue?:any){\n\n const { variadic, defaultValue } = this.cliOption\n\n const input = inputValue || defaultValue\n\n // 如果选择指定了\"-p [value]或[value...]\",则使用text类型,如果没有要求输入值,则使用confirm类型\n let promptType:PromptType = 'text'\n\n const params = this.params\n\n if(this.isValidPromptType(params)){ // 显式指定了prompt类型,m则以指定的类型为准 \n promptType = params as PromptType\n }else if(isPlainObject(params)){ // 显式指定了prompt对象\n promptType = (params as PromptObject).type as PromptType\n }else{ // 自动推断prompt类型\n \n const isListType = /(\\[\\s*\\w+\\.\\.\\.\\s*])|(\\<\\s*\\w+\\.\\.\\.\\s*>)/.test(this.cliOption.flags)\n const isTextType = /(\\<s*\\w+\\s*\\>)|(\\[\\w+\\])/.test(this.cliOption.flags) \n const isBooleanType = !/(\\[\\s*\\w+s*])|(\\<\\s*\\w+\\s*>)/.test(this.cliOption.flags)\n const isNumberType = isNumber(defaultValue)\n const isDate = defaultValue && defaultValue instanceof Date\n\n // 根据默认值的类型推断\n const datatype:string = Array.isArray(input) ? 'array' : \n input instanceof Date ? 'date' :\n typeof(input) \n\n const optionParams = this.cliOption.params\n\n if(optionParams && optionParams.choices){\n const choices = optionParams.choices\n if(isBooleanType && (Array.isArray(choices) && choices.length==2)){\n promptType = 'toggle'\n }else{\n promptType = variadic ? 'multiselect' : 'select'\n } \n }else if(isListType){ // 提供多个可选值时\n promptType = 'list'\n }else if(isDate){\n promptType = 'date'\n }else if(isNumberType){\n promptType = 'number'\n }else if(isTextType){ // 提供一个可选值时\n promptType = 'text' \n }else if(isBooleanType || typeof(defaultValue)==='boolean'){\n promptType = 'confirm'\n }else if(datatype in promptTypeMap){\n promptType = promptTypeMap[datatype] as PromptType\n }\n }\n outputDebug(\"选项<{}> -> 提示类型<{}>\",[this.cliOption.name(),promptType])\n return promptType\n }\n /**\n * 返回生成prompt对象\n * \n * @param inputValue 从命令行输入的值\n */\n get(inputValue?:any){\n\n const { description, defaultValue } = this.cliOption\n \n let input = inputValue || defaultValue\n\n // 1. 判断是否需要启用提示\n if(!this.isNeedPrompt(input,defaultValue)) return\n\n // 2. 推断prompt类型\n const promptType = this.infer(inputValue)\n\n const prompt = {\n type : promptType, \n name : this.cliOption.attributeName(),\n message: description,\n initial: input,\n ...typeof(this.params) == 'object' ? this.params : {}\n } as PromptObject\n\n\n // 指定了验证函数,用来验证输入值是否有效\n prompt.validate = this.cliOption.params?.validate\n\n if(promptType=='multiselect') prompt.instructions=false\n prompt.choices = prompt.choices || this._getChoices() as any \n\n if(['select','multiselect'].includes(promptType)){ \n\n }else if(promptType=='toggle'){ \n if(Array.isArray(prompt.choices)){\n if(!prompt.active) prompt.active = prompt.choices[0].value\n if(!prompt.inactive) prompt.inactive = prompt.choices[1].value \n }\n }\n\n if(input && typeof(prompt.initial)!='function'){\n if(prompt.choices && Array.isArray(prompt.choices)){\n if(promptType=='select'){\n const index = Array.isArray(prompt.choices) ? prompt.choices.findIndex(item=>item.value==input) : -1\n if(index!=-1){\n prompt.initial = index\n }\n }else if(promptType=='multiselect'){ \n prompt.choices.forEach((item)=>{\n if(Array.isArray(input) && input.includes(item.value)){\n item.selected = true\n }else if(item.value==input){\n item.selected = true\n }\n })\n }\n }\n }\n\n return prompt\n }\n\n\n}"," import logsets from \"logsets\" \n\n\n/**\n * \n * 在控制台输出一个字符串\n * 本方法会将字符串中的每一行空格去掉\n * \n * @remarks\n * \n * outputStr(String.raw`\n * a\n * b`)\n * \n * 会输出\n * a\n * b\n *\n * 此功能可以用于输出多行字符串时,保持代码的缩进格式,而不会影响输出结果\n * \n * @param str : 要输出的字符串\n * @param vars : 用于替换字符串中的变量\n * \n */\nexport function outputStr(str:string,vars?:Record<string,any> | any[]){ \n logsets.log(fixIndent(str),vars)\n}\n\n/**\n * 修正多行字符串的缩进\n * \n * @param text \n * @param indent \n * @returns \n */\nexport function fixIndent(text:string,indent?:boolean | number):string{\n let indentValue = (indent==undefined || indent===true) ? 0 : (typeof(indent)=='number' ? indent : -1)\n if(indentValue==-1) return text // 不修正缩进\n let lines:string[] = text.split(\"\\n\")\n let minSpaceCount = lines.reduce<number>((minCount,line,index)=>{\n if(index==0) return minCount\n const spaceCount = line.match(/^\\s*/)?.[0].length || 0\n return Math.min(minCount,spaceCount)\n },9999)\n lines = lines.map(line=>line.substring(minSpaceCount))\n return lines.join(\"\\n\")\n}\n\n/**\n * 增加内置选项\n * @param command \n */\nexport function addBuiltInOptions(command:any){ \n command.option(\"--work-dirs <values...>\",\"指定工作目录\",{hidden:true,optional:true,required:true,prompt:false})\n command.option(\"--disable-prompts\",\"禁用所有交互提示\",{hidden:true,prompt:false}) \n command.option(\"--debug-cli\",\"显示调试信息\",{hidden:true,prompt:false})\n}\n\n\n/**\n * 是否命令行中包含了--debug-cli选项\n */\nexport function isDebug(){\n return process.argv.includes(\"--debug-cli\")\n}\n\n\nexport function isDisablePrompts(){ \n return process.argv.includes(\"--disable-prompts\")\n}\n\n/**\n * 打印调试信息\n * @param message \n * @param args \n */\nexport function outputDebug(message:string,...args:any[]){ \n let vars = (args.length == 1 && typeof(args[0])=='function') ? args[0]() : args\n if(isDebug()) logsets.log(`[MixCli] ${message}`,...vars)\n}\n \n\nexport function showError(e:any){\n if(isDebug()){\n outputDebug(\"导入命令<>出错:{}\",e.stack)\n }else{\n console.error(e)\n } \n\n}\n\n// 编写一个函数,用于将使用-分隔的字符串转换为驼峰式\nexport function hyphenToCamelCase(str:string){\n return str.replace(/-([a-z])/g,(_,letter)=>letter.toUpperCase())\n}\n\nexport function getId(){\n return Math.random().toString(36).substr(2)\n}\n\n\nexport async function importModule(file:string){\n let module \n try{\n module = require(file)\n }catch(e:any){ \n const cmd = await import(`file://${file}`)\n module = cmd.default \n throw e\n }\n return module\n}\n","import { getPackageJson } from \"flex-tools/package/getPackageJson\"\nimport { getPackageRootPath } from 'flex-tools/package/getPackageRootPath';\nimport type { MixCli } from './cli';\nimport { globSync } from 'glob'\nimport { MixCliCommand } from './cli';\nimport { importModule, outputDebug } from './utils';\nimport fs from \"node:fs\"\nimport path from \"node:path\"\n\n\n/**\n * \n * 在当前工程中查找符合FlexCli.prefix约定的命令 \n * \n * - 读取当前包的package.json\n * - 找出所有以cli.prefix开头的依赖\n * - 加载这些依赖的目录下的匹配cli.pattern的命令\n * - 加载加载这样命令\n * \n */\n \n\nexport function getMatchedDependencies(this:MixCli,entry:string):string[]{\n const pacakgeMacher = this.options.include\n if(!(pacakgeMacher instanceof RegExp)) return []\n \n // 找出当前包的所有依赖\n const { dependencies={},devDependencies={},peerDependencies={},optionalDependencies={},bundleDependencies={} } = getPackageJson(entry)\n const packageNames = [\n ...Object.keys(dependencies),\n ...Object.keys(devDependencies),\n ...Object.keys(peerDependencies),\n ...Object.keys(optionalDependencies),\n ...Object.keys(bundleDependencies)\n ]\n return packageNames.filter(name=>name!==\"@voerka/cli\" && pacakgeMacher.test(name))\n}\n\nfunction isMatched(str:string,reg?:string | RegExp | string[] | RegExp[]):boolean{\n // let regexps:RegExp[]=[]\n const regexps = reg ? (Array.isArray(reg) ? reg : [reg]) : []\n return regexps.some(regexp=>{\n if(typeof regexp === \"string\"){\n return (new RegExp(regexp)).test(str)\n }else if(regexp instanceof RegExp){\n return regexp.test(str)\n }else{\n return false\n }\n })\n}\n\nexport function findCliPaths(this:MixCli,packageName?:string ,entry?:string):string[]{\n const includeMacher = this.options.include\n const excludeMacher = this.options.exclude\n if(!includeMacher) return []\n const packageRoot = getPackageRootPath(entry || process.cwd())\n const packagePath = packageName ? path.dirname(require.resolve(packageName,{paths:[packageRoot as string]})) : packageRoot\n\n if(!packagePath) {\n outputDebug(\"MixCli只能运行在Nodejs环境\" )\n return []\n }\n\n // 找出当前包的所有依赖\n const packageNames = getMatchedDependencies.call(this,packagePath)\n\n const cliDirs:string[]=[]\n \n if(entry!==undefined) cliDirs.push(path.join(packagePath,this.options.cliDir))\n packageNames.filter(name=>{\n return isMatched(name,includeMacher) && !isMatched(name,excludeMacher) \n })\n .forEach(name=>{\n outputDebug(\"匹配包:{}\",`${packageName ? name+\" <- \"+packageName : name}`)\n try{\n const packageEntry = path.dirname(require.resolve(name,{paths:packagePath ? [packagePath] : [process.cwd()]}))\n const packageCliDir =path.join(packageEntry,this.options.cliDir!) \n // 查找当前包的所属工程的依赖\n let dependencies = getMatchedDependencies.call(this,packageEntry)\n cliDirs.push(...dependencies.reduce<string[]>((result,dependencie)=>{\n outputDebug(\"匹配包:{}\",`${dependencie} <- ${name}`)\n result.push(...findCliPaths.call(this,dependencie,packageEntry))\n return result\n },[])) \n if(fs.existsSync(packageCliDir)){\n cliDirs.push(packageCliDir)\n }\n }catch(e:any){\n outputDebug(\"解析包<{}>路径出错:{}\",[name,e.stack])\n } \n })\n // 由于一些包可能存在循环依赖,所以需要去重\n return [...new Set(cliDirs)]\n}\n\n\n/**\n * \n * 扫描当前工程中所有符合条件的命令\n * \n * @param cli \n * \n */\nexport async function findCommands(cli:MixCli){ \n const cliDirs = findCliPaths.call(cli)\n const commands:MixCliCommand[] = []\n const files = [] as string[]\n cliDirs.forEach(dir=>{\n globSync(\"*\",{\n cwd:dir,\n absolute :true \n }).forEach((file:string)=>{ \n const baseName = path.basename(file) \n if(baseName.startsWith(\"_\")) return\n const ext = path.extname(file).toLowerCase()\n if([\".js\",\".cjs\",\".mjs\"].includes(ext)){\n files.push(file)\n }else if(fs.statSync(file).isDirectory()){\n files.push(path.join(file,\"index.js\"))\n files.push(path.join(file,\"index.cjs\"))\n files.push(path.join(file,\"index.mjs\"))\n }\n })\n })\n for(let file of files){ \n if(!fs.existsSync(file)) continue\n try{\n outputDebug(\"导入命令:{}\",file)\n if(file.endsWith(\".cjs\") || file.endsWith(\".js\")){\n commands.push(await importModule(file))\n }else if(file.endsWith(\".mjs\")){\n const cmd = await import(`file://${file}`)\n commands.push(cmd.default)\n } \n }catch(e:any){\n outputDebug(e) \n }\n }\n return commands\n}\n\n"],"mappings":"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","names":["LiteEvent","logsets","assignObject","Command","prompts","Option","isPlainObject","isNumber","logsets","outputStr","str","vars","logsets","fixIndent","text","indent","lines","minSpaceCount","minCount","line","index","_a","spaceCount","addBuiltInOptions","command","isDebug","isDisablePrompts","outputDebug","message","args","showError","e","hyphenToCamelCase","_","letter","getId","importModule","file","__async","module","__require","promptTypeMap","supportedPromptTypes","MixOptionPrompt","cliOption","promptParams","type","input","defaultValue","params","inputValue","hasInput","isPlainObject","_a","choices","choicesParam","choice","variadic","promptType","isListType","isTextType","isBooleanType","isNumberType","isNumber","isDate","datatype","optionParams","outputDebug","description","prompt","__spreadValues","index","item","MixOption","Option","flags","description","params","MixOptionPrompt","choice","inputValue","_a","path","fs","BREAK","MixCommand","Command","name","self","addBuiltInOptions","__async","names","parent","root","actionFunc","actionFn","actionOpts","actionItem","command","opts","cmds","cmd","args","preValue","actionArgs","action","outputDebug","e","fn","workDirs","dirs","dir","workDir","cwd","path","fs","option","listener","scope","hooks","hook","thisCommand","questions","results","prompts","key","value","isDisablePrompts","optionPromports","prompt","flags","description","options","MixOption","choices","result","getPackageJson","getPackageRootPath","globSync","fs","path","getMatchedDependencies","entry","pacakgeMacher","dependencies","devDependencies","peerDependencies","optionalDependencies","bundleDependencies","getPackageJson","name","isMatched","str","reg","regexp","findCliPaths","packageName","includeMacher","excludeMacher","packageRoot","getPackageRootPath","packagePath","path","__require","outputDebug","packageNames","cliDirs","packageEntry","packageCliDir","result","dependencie","fs","e","findCommands","cli","__async","commands","files","dir","globSync","file","ext","importModule","cmd","asyncSignal","replaceAll","replaceAll","MixCli","LiteEvent","options","assignObject","__async","cmders","findCommands","cmder","cmds","e","outputDebug","MixCommand","logsets","fixIndent","title","addBuiltInOptions","text","pos","alignIndent","cmd","result","name","c","names","curCmd","resultCmd","topName","r","signal","asyncSignal","resolve","listener","fullname","s"]}
package/package.json CHANGED
@@ -1,14 +1,12 @@
1
1
  {
2
2
  "name": "mixcli",
3
- "version": "3.2.2",
3
+ "version": "3.2.4",
4
4
  "description": "Develop command line tool scaffolding for monorepo",
5
5
  "repository": "https://github.com/zhangfisher/mixcli.git",
6
6
  "homepage": "https://zhangfisher.github.io/mixcli/",
7
7
  "main": "./dist/index.js",
8
- "type": "module",
9
- "publishConfig": {
10
- "access": "public"
11
- },
8
+ "module": "./dist/index.mjs",
9
+ "types": "./dist/index.d.ts",
12
10
  "access": "public",
13
11
  "files": [
14
12
  "dist",
@@ -19,7 +17,8 @@
19
17
  "keywords": [
20
18
  "commander",
21
19
  "prompts",
22
- "cli"
20
+ "cli",
21
+ "command line"
23
22
  ],
24
23
  "author": "zhangfisher",
25
24
  "license": "ISC",
@@ -47,13 +46,11 @@
47
46
  "scripts": {
48
47
  "build": "tsup",
49
48
  "build:watch": "tsup --watch",
50
- "release": "changeset version && changeset publish && copy CHANGELOG.md docs\\CHANGELOG.md",
49
+ "release": "changeset version && changeset publish",
51
50
  "docs:dev": "vitepress dev docs",
52
51
  "docs:build": "vitepress build docs",
53
52
  "docs:preview": "vitepress preview docs",
54
53
  "sync": "cnpm sync mixcli",
55
54
  "changeset": "changeset"
56
- },
57
- "module": "./dist/index.mjs",
58
- "types": "./dist/index.d.ts"
55
+ }
59
56
  }
package/src/command.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Command, Option } from "commander";
2
2
  import prompts, { PromptObject } from "prompts";
3
3
  import { MixOption, type MixedOptionParams } from "./option";
4
- import { addBuiltInOptions, hyphenToCamelCase, isDisablePrompts, outputDebug } from "./utils";
4
+ import { addBuiltInOptions, isDisablePrompts, outputDebug } from "./utils";
5
5
  import type { AsyncFunction } from "flex-tools/types";
6
6
  import path from "node:path";
7
7
  import fs from "node:fs";
package/src/utils.ts CHANGED
@@ -1,7 +1,4 @@
1
- import fs from "fs-extra"
2
- import path from "node:path"
3
- import { promisify } from "flex-tools/func/promisify"
4
- import logsets from "logsets"
1
+ import logsets from "logsets"
5
2
 
6
3
 
7
4
  /**
@@ -81,33 +78,7 @@ export function outputDebug(message:string,...args:any[]){
81
78
  let vars = (args.length == 1 && typeof(args[0])=='function') ? args[0]() : args
82
79
  if(isDebug()) logsets.log(`[MixCli] ${message}`,...vars)
83
80
  }
84
-
85
- export const fileExists = promisify(fs.exists,{
86
- parseCallback:(results)=>{
87
- return results[0]
88
- }
89
- })
90
- export const readFile = promisify(fs.readFile)
91
- export const writeFile = promisify(fs.writeFile)
92
- export const mkdir = promisify(fs.mkdir)
93
81
 
94
- /**
95
- * 创建目录
96
- *
97
- *
98
- *
99
- * @param {String[]} dirs 要创建的目录列表,类型为字符串数组
100
- * @param callback 创建目录过程中的回调函数,类型为异步函数,接收一个参数 dir,表示当前正在创建的目录
101
- * @returns 该函数返回一个 Promise 对象,表示创建目录的操作是否完成
102
- */
103
- export async function mkDirs(dirs:string[],{callback,base}:{callback?:Function,base?:string}){
104
- if(!Array.isArray(dirs)) throw new Error("dirs参数必须为字符串数组")
105
- for(let dir of dirs){
106
- if(!path.isAbsolute(dir)) dir = path.join(base || process.cwd(),dir)
107
- if(typeof(callback)=='function') callback(dir)
108
- await mkdir(dir,{recursive:true})
109
- }
110
- }
111
82
 
112
83
  export function showError(e:any){
113
84
  if(isDebug()){
@@ -132,13 +103,10 @@ export async function importModule(file:string){
132
103
  let module
133
104
  try{
134
105
  module = require(file)
135
- }catch(e:any){
136
- try{
137
- const cmd = await import(`file://${file}`)
138
- module = cmd.default
139
- }catch(e:any){
140
- throw e
141
- }
106
+ }catch(e:any){
107
+ const cmd = await import(`file://${file}`)
108
+ module = cmd.default
109
+ throw e
142
110
  }
143
111
  return module
144
112
  }
package/dist/index.cjs DELETED
@@ -1,4 +0,0 @@
1
- "use strict";var pt=Object.create;var y=Object.defineProperty;var ct=Object.getOwnPropertyDescriptor;var mt=Object.getOwnPropertyNames,$=Object.getOwnPropertySymbols,lt=Object.getPrototypeOf,q=Object.prototype.hasOwnProperty,ut=Object.prototype.propertyIsEnumerable;var B=(r,n,t)=>n in r?y(r,n,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[n]=t,F=(r,n)=>{for(var t in n||(n={}))q.call(n,t)&&B(r,t,n[t]);if($)for(var t of $(n))ut.call(n,t)&&B(r,t,n[t]);return r};var ft=(r,n)=>{for(var t in n)y(r,t,{get:n[t],enumerable:!0})},W=(r,n,t,i)=>{if(n&&typeof n=="object"||typeof n=="function")for(let e of mt(n))!q.call(r,e)&&e!==t&&y(r,e,{get:()=>n[e],enumerable:!(i=ct(n,e))||i.enumerable});return r};var u=(r,n,t)=>(t=r!=null?pt(lt(r)):{},W(n||!r||!r.__esModule?y(t,"default",{value:r,enumerable:!0}):t,r)),dt=r=>W(y({},"__esModule",{value:!0}),r);var l=(r,n,t)=>new Promise((i,e)=>{var o=a=>{try{p(t.next(a))}catch(c){e(c)}},s=a=>{try{p(t.throw(a))}catch(c){e(c)}},p=a=>a.done?i(a.value):Promise.resolve(a.value).then(o,s);p((t=t.apply(r,n)).next())});var Ot={};ft(Ot,{BREAK:()=>J,MixCli:()=>L,MixCommand:()=>v,MixOption:()=>O,MixOptionPrompt:()=>P,addBuiltInOptions:()=>M,fileExists:()=>gt,fixIndent:()=>C,getId:()=>Pt,hyphenToCamelCase:()=>Mt,importModule:()=>H,isDebug:()=>D,isDisablePrompts:()=>E,mkDirs:()=>bt,mkdir:()=>X,outputDebug:()=>m,outputStr:()=>ht,promptTypeMap:()=>T,readFile:()=>yt,showError:()=>Ct,supportedPromptTypes:()=>K,writeFile:()=>xt});module.exports=dt(Ot);var Xt=require("flex-tools/string"),nt=require("flex-tools/events/liteEvent"),d=u(require("logsets"),1),rt=require("flex-tools/object/assignObject");var G=require("commander"),S=u(require("prompts"),1);var z=require("commander");var R=require("flex-tools/typecheck/isPlainObject"),U=require("flex-tools/typecheck/isNumber");var x=u(require("fs-extra"),1),_=u(require("path"),1),b=require("flex-tools/func/promisify"),j=u(require("logsets"),1);function ht(r,n){j.default.log(C(r),n)}function C(r,n){if((n==null||n===!0?0:typeof n=="number"?n:-1)==-1)return r;let i=r.split(`
2
- `),e=i.reduce((o,s,p)=>{var c;if(p==0)return o;let a=((c=s.match(/^\s*/))==null?void 0:c[0].length)||0;return Math.min(o,a)},9999);return i=i.map(o=>o.substring(e)),i.join(`
3
- `)}function M(r){r.option("--work-dirs <values...>","\u6307\u5B9A\u5DE5\u4F5C\u76EE\u5F55",{hidden:!0,optional:!0,required:!0,prompt:!1}),r.option("--disable-prompts","\u7981\u7528\u6240\u6709\u4EA4\u4E92\u63D0\u793A",{hidden:!0,prompt:!1}),r.option("--debug-cli","\u663E\u793A\u8C03\u8BD5\u4FE1\u606F",{hidden:!0,prompt:!1})}function D(){return process.argv.includes("--debug-cli")}function E(){return process.argv.includes("--disable-prompts")}function m(r,...n){let t=n.length==1&&typeof n[0]=="function"?n[0]():n;D()&&j.default.log(`[MixCli] ${r}`,...t)}var gt=(0,b.promisify)(x.default.exists,{parseCallback:r=>r[0]}),yt=(0,b.promisify)(x.default.readFile),xt=(0,b.promisify)(x.default.writeFile),X=(0,b.promisify)(x.default.mkdir);function bt(i,e){return l(this,arguments,function*(r,{callback:n,base:t}){if(!Array.isArray(r))throw new Error("dirs\u53C2\u6570\u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32\u6570\u7EC4");for(let o of r)_.default.isAbsolute(o)||(o=_.default.join(t||process.cwd(),o)),typeof n=="function"&&n(o),yield X(o,{recursive:!0})})}function Ct(r){D()?m("\u5BFC\u5165\u547D\u4EE4<>\u51FA\u9519:{}",r.stack):console.error(r)}function Mt(r){return r.replace(/-([a-z])/g,(n,t)=>t.toUpperCase())}function Pt(){return Math.random().toString(36).substr(2)}function H(r){return l(this,null,function*(){let n;try{n=require(r)}catch(t){try{n=(yield import(`file://${r}`)).default}catch(i){throw i}}return n})}var T={boolean:"confirm",string:"text",number:"number",array:"list",date:"date"},K=["text","password","invisible","number","confirm","list","toggle","select","multiselect","autocomplete","date","autocompleteMultiselect"],P=class{constructor(n,t){this.cliOption=n;this.params=t}isValidPromptType(n){return K.includes(String(n))}isNeedPrompt(n,t){let i=this.params,e=n||t,o=e!==void 0;return i===!0?!0:i===!1?!1:i==="auto"||(0,R.isPlainObject)(i)?!o:typeof i=="string"&&this.isValidPromptType(i)?!0:/(\<s*\w\s*\>)/.test(this.cliOption.flags)?!o:this.cliOption.argChoices&&this.cliOption.argChoices.indexOf(e)==-1?!0:!o}_getChoices(){var i;let n=[],t=(i=this.cliOption.params)==null?void 0:i.choices;if(this.cliOption.argChoices)n=this.cliOption.argChoices.map(e=>typeof e=="string"?{title:e,value:e}:e);else if(t)n=typeof t=="function"?t:[];else return[];return n}infer(n){let{variadic:t,defaultValue:i}=this.cliOption,e=n||i,o="text",s=this.params;if(this.isValidPromptType(s))o=s;else if((0,R.isPlainObject)(s))o=s.type;else{let p=/(\[\s*\w+\.\.\.\s*])|(\<\s*\w+\.\.\.\s*>)/.test(this.cliOption.flags),a=/(\<s*\w+\s*\>)|(\[\w+\])/.test(this.cliOption.flags),c=!/(\[\s*\w+s*])|(\<\s*\w+\s*>)/.test(this.cliOption.flags),A=(0,U.isNumber)(i),w=i&&i instanceof Date,g=Array.isArray(e)?"array":e instanceof Date?"date":typeof e,h=this.cliOption.params;if(h&&h.choices){let N=h.choices;c&&Array.isArray(N)&&N.length==2?o="toggle":o=t?"multiselect":"select"}else p?o="list":w?o="date":A?o="number":a?o="text":c||typeof i=="boolean"?o="confirm":g in T&&(o=T[g])}return m("\u9009\u9879<{}> -> \u63D0\u793A\u7C7B\u578B<{}>",[this.cliOption.name(),o]),o}get(n){var p;let{description:t,defaultValue:i}=this.cliOption,e=n||i;if(!this.isNeedPrompt(e,i))return;let o=this.infer(n),s=F({type:o,name:this.cliOption.attributeName(),message:t,initial:e},typeof this.params=="object"?this.params:{});if(s.validate=(p=this.cliOption.params)==null?void 0:p.validate,o=="multiselect"&&(s.instructions=!1),s.choices=s.choices||this._getChoices(),["select","multiselect"].includes(o)||o=="toggle"&&Array.isArray(s.choices)&&(s.active||(s.active=s.choices[0].value),s.inactive||(s.inactive=s.choices[1].value)),e&&typeof s.initial!="function"&&s.choices&&Array.isArray(s.choices))if(o=="select"){let a=Array.isArray(s.choices)?s.choices.findIndex(c=>c.value==e):-1;a!=-1&&(s.initial=a)}else o=="multiselect"&&s.choices.forEach(a=>{(Array.isArray(e)&&e.includes(a.value)||a.value==e)&&(a.selected=!0)});return s}};var O=class extends z.Option{constructor(t,i,e){super(t,i);this.params=e;this.__MIX_OPTION__=!0;this._setOption(e||{}),this.prompt=new P(this,e==null?void 0:e.prompt)}_setOption(t){t.default&&this.default(t.default,t.defaultDescription),t.conflicts&&this.conflicts(t.conflicts),t.envVar&&this.env(t.envVar),t.parseArg&&this.argParser(t.parseArg),t.hidden&&(this.hidden=t.hidden),t.mandatory&&this.makeOptionMandatory(t.mandatory),t.implies&&this.implies(t.implies),t.optional&&(this.optional=t.optional),t.variadic&&(this.variadic=t.variadic),t.negate&&(this.negate=t.negate),t.preset&&this.preset(t.preset),t.required&&(this.required=t.required),Array.isArray(t.choices)&&this.choices(t.choices.map(i=>typeof i=="string"?i:i.value))}getPrompt(t){var i;return(i=this.prompt)==null?void 0:i.get(t)}};var V=u(require("path"),1),I=u(require("fs"),1);var J=Symbol("BREAK_ACTION"),v=class extends G.Command{constructor(t){super(t);this.__MIX_COMMAND__=!0;this._beforeHooks=[];this._afterHooks=[];this._customPrompts=[];this._optionValues={};this._actions=[];this._enable_prompts=!0;let i=this;this.isRoot||M(this),this.hook("preAction",function(){return l(this,arguments,function*(){i._optionValues=i.getOptionValues(this.hookedCommand),yield i.preActionHook.apply(i,arguments)})})}get isRoot(){return this.parent==null}get optionValues(){return this._optionValues}get actions(){return this._actions}get beforeHooks(){return this._beforeHooks}get afterHooks(){return this._afterHooks}get fullname(){let t=[this.name()],i=this.parent;for(;i;)i.name()!=="root"&&t.unshift(i.name()),i=i.parent;return t.join(".")}root(){let t=this;for(;t&&t.parent!=null;)t=t.parent;return t}action(){let t=arguments[0];if(arguments.length==1&&typeof t=="function")this._actions.push({id:Math.random().toString(36).substring(2),enhance:!1,fn:t});else if(arguments.length==2&&typeof t=="function"&&typeof arguments[1]=="object"){let i=arguments[0],e=Object.assign({at:"append"},arguments[1]);e.at=="replace"&&(this._actions=[]);let o={id:e.id||Math.random().toString(36).substring(2),enhance:e.enhance==null?!0:e.enhance,fn:i};typeof e.at=="number"?this._actions.splice(Number(e.at),0,o):["append","before"].includes(e.at)?this._actions.push(o):["preappend","after"].includes(e.at)?this._actions.splice(0,0,o):this._actions.push(o)}else console.log("[mixcli] action params error");return super.action(this.getWrapperedAction())}getOptionValues(t){let i={},e=t;for(;e;)Object.assign(i,e.optionValues),e=e.parent;return i}getWrapperedAction(){return this.wrapperWorkDirsAction(this.wrapperChainActions())}getAncestorCommands(){let t=[],i=this;for(;i;)i=i.parent,i&&t.push(i);return t}wrapperChainActions(){let t=this;return function(){return l(this,arguments,function*(){let i=Array.from(arguments),e,o={},s=[],p;i.length>=2&&(p=i[i.length-1],o=i[i.length-2],s=i.slice(0,i.length-2)),yield t.executeBeforeHooks({args:s,options:o,command:p});try{for(let a of t._actions)try{if(a.enhance?(m("\u6267\u884C<{}>: args={}, options={}",()=>[t.name(),s,o]),e=yield a.fn.call(this,{command:p,value:e,args:s,options:o})):e=yield a.fn.apply(this,i),e===J)break}catch(c){throw m("\u547D\u4EE4{}\u7684Action({})\u6267\u884C\u51FA\u9519:{}",[t.name,a.id,c]),c}}finally{yield t.executeAfterHooks({value:e,args:s,options:o,command:p})}})}}wrapperWorkDirsAction(t){let i=this;return function(){return l(this,arguments,function*(){let e=i._optionValues.workDirs;if(!e)return yield t.apply(this,Array.from(arguments));Array.isArray(e)||(e=e.split(",")),e=e.reduce((o,s)=>(typeof s=="string"&&o.push(...s.split(",")),o),[]);for(let o of e){let s=process.cwd();try{V.default.isAbsolute(o)||(o=V.default.join(s,o)),I.default.existsSync(o)&&I.default.statSync(o).isDirectory()?(m("\u5207\u6362\u5230\u5DE5\u4F5C\u76EE\u5F55:{}",o),process.chdir(o),yield t.apply(this,Array.from(arguments))):m("\u65E0\u6548\u7684\u5DE5\u4F5C\u76EE\u5F55:{}",o)}finally{process.chdir(s)}}})}}getOption(t){return this.options.find(i=>i.name()==t)}before(t,i=!0){return this._beforeHooks.push([t,i]),this}executeBeforeHooks(t){return l(this,null,function*(){let i=this.beforeHooks.map(([e,o])=>[e,o,this]);this.getAncestorCommands().forEach(e=>{i.unshift(...e.beforeHooks.map(([o,s])=>[o,s,e]))});for(let[e,o,s]of i)o&&(yield e.call(s,t))})}after(t,i=!0){return this._afterHooks.push([t,i]),this}executeAfterHooks(t){return l(this,null,function*(){let i=this.afterHooks.map(([e,o])=>[e,o,this]);this.getAncestorCommands().forEach(e=>{i.push(...e.afterHooks.map(([o,s])=>[o,s,e]))});for(let[e,o,s]of i)o&&(yield e.call(s,t))})}preActionHook(t){return l(this,null,function*(){if(this.isEnablePrompts()){let i=[...this.generateAutoPrompts(),...this._customPrompts];if(i.length>0){let e=yield(0,S.default)(i);Object.entries(e).forEach(([o,s])=>{t.setOptionValue(o,s)})}}})}isEnablePrompts(){return E()?!1:this._enable_prompts}generateAutoPrompts(){let i=this.options.filter(e=>!e.hidden&&e.__MIX_OPTION__).map(e=>e.getPrompt(this._optionValues[e.attributeName()])).filter(e=>e);return m("\u547D\u4EE4<{}>\u81EA\u52A8\u751F\u6210{}\u4E2A\u9009\u9879\u63D0\u793A:{}",[this.name(),i.length,i.map(e=>`${e.name}(${e.type})`).join(",")]),i}option(t,i,e){let o=new O(t,i,e);return o.required&&!this.isEnablePrompts()&&(o.mandatory=!0),this.addOption(o)}prompt(t){return this._customPrompts.push(...Array.isArray(t)?t:[t]),this}selectCommands(){return l(this,null,function*(){let t=this.commands.map(o=>({title:`${o.description()}(${o.name()})`,value:o.name()})),i=yield(0,S.default)({type:"select",name:"command",message:"\u8BF7\u9009\u62E9\u547D\u4EE4:",choices:t}),e=this.commands.find(o=>o.name()===i.command);yield e==null?void 0:e.parseAsync([i.command],{from:"user"})})}disablePrompts(){return this._enable_prompts=!1,this}enablePrompts(){return this._enable_prompts=!0,this}};var Z=require("flex-tools/package/getPackageJson"),tt=require("flex-tools/package/getPackageRootPath"),et=require("glob");var k=u(require("fs"),1),f=u(require("path"),1);function Q(r){let n=this.options.include;if(!(n instanceof RegExp))return[];let{dependencies:t={},devDependencies:i={},peerDependencies:e={},optionalDependencies:o={},bundleDependencies:s={}}=(0,Z.getPackageJson)(r);return[...Object.keys(t),...Object.keys(i),...Object.keys(e),...Object.keys(o),...Object.keys(s)].filter(a=>a!=="@voerka/cli"&&n.test(a))}function Y(r,n){return(n?Array.isArray(n)?n:[n]:[]).some(i=>typeof i=="string"?new RegExp(i).test(r):i instanceof RegExp?i.test(r):!1)}function it(r,n){let t=this.options.include,i=this.options.exclude;if(!t)return[];let e=(0,tt.getPackageRootPath)(n||process.cwd()),o=r?f.default.dirname(require.resolve(r,{paths:[e]})):e;if(!o)return m("MixCli\u53EA\u80FD\u8FD0\u884C\u5728Nodejs\u73AF\u5883"),[];let s=Q.call(this,o),p=[];return n!==void 0&&p.push(f.default.join(o,this.options.cliDir)),s.filter(a=>Y(a,t)&&!Y(a,i)).forEach(a=>{m("\u5339\u914D\u5305:{}",`${r?a+" <- "+r:a}`);try{let c=f.default.dirname(require.resolve(a,{paths:o?[o]:[process.cwd()]})),A=f.default.join(c,this.options.cliDir),w=Q.call(this,c);p.push(...w.reduce((g,h)=>(m("\u5339\u914D\u5305:{}",`${h} <- ${a}`),g.push(...it.call(this,h,c)),g),[])),k.default.existsSync(A)&&p.push(A)}catch(c){m("\u89E3\u6790\u5305<{}>\u8DEF\u5F84\u51FA\u9519\uFF1A{}",[a,c.stack])}}),[...new Set(p)]}function ot(r){return l(this,null,function*(){let n=it.call(r),t=[],i=[];n.forEach(e=>{(0,et.globSync)("*",{cwd:e,absolute:!0}).forEach(o=>{if(f.default.basename(o).startsWith("_"))return;let p=f.default.extname(o).toLowerCase();[".js",".cjs",".mjs"].includes(p)?i.push(o):k.default.statSync(o).isDirectory()&&(i.push(f.default.join(o,"index.js")),i.push(f.default.join(o,"index.cjs")),i.push(f.default.join(o,"index.mjs")))})});for(let e of i)if(k.default.existsSync(e))try{if(m("\u5BFC\u5165\u547D\u4EE4:{}",e),e.endsWith(".cjs")||e.endsWith(".js"))t.push(yield H(e));else if(e.endsWith(".mjs")){let o=yield import(`file://${e}`);t.push(o.default)}}catch(o){m(o)}return t})}var st=require("flex-tools/async/asyncSignal"),at=u(require("string.prototype.replaceall"),1);at.default.shim();var L=class extends nt.LiteEvent{constructor(t){super();this.findSignals=[];this.options=(0,rt.assignObject)({name:"mixcli",package:null,cliDir:"cli",prompt:"auto",ignoreError:!1},t),this.createRootCommand()}get context(){return this.options.context}get name(){return this.options.name}get isDisabledPrompts(){return this.root.rawArgs.includes("--no-prompts")}installCommands(){return l(this,null,function*(){let t=yield ot(this);for(let i of t)try{if(typeof i=="function"){let e=i(this);e=e?Array.isArray(e)?e:[e]:[],this.register(()=>e)}}catch(e){m("\u6CE8\u518C\u547D\u4EE4\u5931\u8D25:{}",e.stack)}})}createRootCommand(){this.root=new v(this.name),this.root.helpOption("-h, --help").action(()=>{this.options.logo&&d.default.log(C(this.options.logo,2)),console.log();let t=this.options.title||this.options.name;Array.isArray(t)?d.default.log(String(t[0]).firstUpper(),[...t.slice(1)]):d.default.log(`${t.firstUpper()} Version: {}`,this.options.version),this.options.description&&d.default.log(d.default.colors.darkGray(this.options.description)),console.log(),this.root.help()}),M(this.root),this.options.before&&this.root.hook("preAction",this.options.before),this.options.after&&this.root.hook("postAction",this.options.after)}addHelp(t,{pos:i="beforeAll",alignIndent:e=!0}){e&&(t=C(t,e)),this.root.addHelpText(i,t)}register(t){if(typeof t=="function"){let i=t(this),e=i instanceof Array?i:i==null?[]:[i];for(let o of e)o.__MIX_COMMAND__?this.hasCommand(o.name())?d.default.error(`Command <${o.name()}> has been registered!`):(m("\u6CE8\u518C\u547D\u4EE4:{}",o.fullname),this.root.addCommand(o),o._cli=this,this.emit("register",o.fullname,!0)):d.default.error(`Command <${o.toString()}> is not a valid command!`)}else d.default.error("Invalid command")}hasCommand(t){return this.root.commands.some(i=>i.name()==t)}get(t){let i=t.split("."),e=this.root,o;for(;i.length>0;){let s=i.shift(),p=e.commands.find(a=>a.name()==s);p&&i.length==0&&(o=p),e=p}return o}find(t){let i=this.get(t);if(i)return Promise.resolve(i);{let e=(0,st.asyncSignal)();return this.findSignals.push(e),new Promise(o=>{let s;s=this.on("register",p=>{p==`${this.name}.${t}`&&(s.off(),e.resolve(),this.findSignals=this.findSignals.filter(a=>a!=e),o(this.get(t)))},{objectify:!0})})}}exists(t){return t in this.root.commands?!0:this.get(t)!=null}run(){this.installCommands().then(()=>Promise.all(this.findSignals.map(t=>t(1e4))).then(()=>{this.root.parseAsync(process.argv)}))}};0&&(module.exports={BREAK,MixCli,MixCommand,MixOption,MixOptionPrompt,addBuiltInOptions,fileExists,fixIndent,getId,hyphenToCamelCase,importModule,isDebug,isDisablePrompts,mkDirs,mkdir,outputDebug,outputStr,promptTypeMap,readFile,showError,supportedPromptTypes,writeFile});
4
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts","../src/cli.ts","../src/command.ts","../src/option.ts","../src/prompt.ts","../src/utils.ts","../src/finder.ts"],"sourcesContent":["export * from \"./cli\"\nexport * from \"./utils\"\nexport * from \"./command\"\nexport * from \"./option\"\nexport * from \"./prompt\"","#!/usr/bin/env node\nimport \"flex-tools/string\"\nimport { LiteEvent, LiteEventSubscriber } from \"flex-tools/events/liteEvent\"\nimport { Command } from \"commander\"\nimport logsets from \"logsets\"\n\nimport { assignObject } from \"flex-tools/object/assignObject\"\nimport { MixCommand } from \"./command\"\nimport { addBuiltInOptions, fixIndent, outputDebug } from './utils';\nimport { findCommands } from \"./finder\"\nimport { asyncSignal } from \"flex-tools/async/asyncSignal\"\n// @ts-ignore\nimport replaceAll from 'string.prototype.replaceall' \nreplaceAll.shim() \n\nexport interface MixCliOptions{\n name:string,\n title?:string | (string | boolean | number)[],\n description?:string,\n version?:string\n // 定义显示帮助信息\n logo?:string ,\n // 在根命令执行前执行==commander的preAction\n before?:(thisCommand:Command,actionCommand:Command)=>void,\n // 在根命令执行后执行==commander的postAction\n after?:(thisCommand:Command,actionCommand:Command)=>void, \n // flexcli运行时会在当前工程的package.json的依赖中查找以prefix/开头的包,然后自动加载其cli目录下的命令\n // 例如:prefix=myapp,则会自动加载flex-cli-xxx包中的cli目录下的命令\n // 如prefix=myapp, cliPath=\"cmds\",则会自动加载flex-cli-xxx包中的cmds目录下的命令\n include?:string | RegExp | string[] | RegExp[],\n // 忽略查找正则表达式\n exclude?:string | RegExp | string[] | RegExp[],\n // flexcli会在当前工程的以prefix/开头下查找命令声明\n // / pattern默认值是cli,即会在当前工程的以prefix/开头的包下查找cli目录下的命令\n // 指定cli所在的目录,默认值是cli,要遍历该目录下的所有js文件作为命令导出\n cliDir?:string \n context?:Record<string,any> // 传递给命令的共享上下文,所有命令均可要使用 \n // 默认是否启用交互提示, auto当没有值时,会根据当前是否在终端中运行来决定是否启用交互提示\n // 为false时,禁用所有交互提示,为true时,启用所有交互提示 \n prompt?:'auto' | boolean \n ignoreError?:boolean\n}\n\n \n \n\nexport type MixCliCommand = (cli:MixCli)=>MixCommand | MixCommand[] | void\n\n\nexport type MixCliEvents = \n \"register\" // 当命令注册时触发\n\nexport class MixCli extends LiteEvent<any,MixCliEvents>{\n options:Required<MixCliOptions> \n root!:MixCommand \n private findSignals:any[]=[]\n constructor(options?:MixCliOptions){\n super()\n this.options= assignObject({\n name : \"mixcli\",\n package : null,\n cliDir : \"cli\",\n prompt : 'auto',\n ignoreError: false\n },options) as Required<MixCliOptions> \n this.createRootCommand() \n } \n get context(){return this.options.context}\n get name(){return this.options.name}\n /**\n * 是否禁用了所有的交互提示\n */\n get isDisabledPrompts(){\n return(this.root as any).rawArgs.includes(\"--no-prompts\") \n } \n /**\n * 扫描当前工程的依赖,加载匹配include的依赖下的命令\n */\n private async installCommands(){\n const cmders = await findCommands(this)\n for(let cmder of cmders){\n try{\n if(typeof(cmder)===\"function\"){\n let cmds = cmder(this)\n cmds = cmds ? (Array.isArray(cmds) ? cmds : [cmds]) : []\n this.register(()=>cmds) \n }\n }catch(e:any){\n outputDebug(\"注册命令失败:{}\",e.stack)\n }\n }\n } \n /**\n * 创建根命令\n * \n */\n private createRootCommand(){\n this.root = new MixCommand(this.name);\n this.root \n .helpOption('-h, --help')\n .action(()=>{ \n if(this.options.logo) logsets.log(fixIndent(this.options.logo,2))\n console.log()\n // 显示标题\n let title = this.options.title|| this.options.name\n if(Array.isArray(title)){\n logsets.log(String(title[0]).firstUpper(),[...title.slice(1)])\n }else{\n logsets.log(`${title.firstUpper()} Version: {}`,this.options.version)\n } \n // @ts-ignore\n if(this.options.description) logsets.log(logsets.colors.darkGray(this.options.description)) \n console.log()\n this.root.help() \n }) \n addBuiltInOptions(this.root)\n if(this.options.before) this.root.hook('preAction',this.options.before)\n if(this.options.after) this.root.hook('postAction',this.options.after) \n } \n /**\n * 添加帮助选项\n * \n * @param text 帮助文本\n * @param position 显示位置,可选值:before|after|beforeAll|afterAll\n * @param fixIndent 是否自动修正缩进,如果为true,则会自动修正缩进,当显示多行时文本时,会自动修正缩进\n * \n */\n public addHelp(text:string,{pos='beforeAll',alignIndent=true}:{pos:'before'|'after' | 'beforeAll' | 'afterAll',alignIndent?:boolean | number}){\n if(alignIndent) text = fixIndent(text,alignIndent)\n this.root.addHelpText(pos,text)\n }\n\n /**\n * 注册一个命令\n * @param cmd \n */\n register(cmd:MixCliCommand){\n if(typeof(cmd)==\"function\"){\n let result = cmd(this)\n let cmds = result instanceof Array ? result : (result==undefined ? [] : [result])\n for(let cmd of cmds){\n // 为什么不用cmd instanceof MixCommand来判断是否是一个有效的命令?\n // 因为当不同的包引用了与主包不一样版本的mixcli时,判断会失效,导致不能识别\n // 所以我们通过cmd.__MIX_COMMAND__来判断是否是一个有效的命令\n if(cmd.__MIX_COMMAND__){ \n if(this.hasCommand(cmd.name())){\n logsets.error(`Command <${cmd.name()}> has been registered!`)\n }else{\n outputDebug(\"注册命令:{}\",cmd.fullname)\n this.root.addCommand(cmd as Command) ;\n (cmd as any)._cli = this\n this.emit(\"register\",cmd.fullname,true)\n } \n }else{\n logsets.error(`Command <${cmd.toString()}> is not a valid command!`)\n }\n } \n }else{\n logsets.error(\"Invalid command\")\n } \n }\n\n hasCommand(name:string):boolean{\n return this.root.commands.some(c=>c.name()==name)\n }\n\n /**\n * 根据命令名称查找命令\n * \n * @remarks\n * \n * find(\"dev\")\n * find(\"dev.microservice\") 支持多级命令\n * find(\"abc\",DevCommand) 允许指定从DevCommand下开始查找abc命令\n * \n * @param name \n */\n get(name:string):MixCommand | undefined{\n const names=name.split(\".\")\n let curCmd:MixCommand = this.root\n let resultCmd:MixCommand | undefined\n while(names.length>0){\n const topName = names.shift()\n const r = curCmd.commands.find(c=>c.name()==topName) as MixCommand\n if(r && names.length==0){\n resultCmd = r\n }\n curCmd = r\n } \n return resultCmd \n }\n /**\n * 查找一个命令\n * \n * 如果命令不存在,则等待命令注册后再返回\n * \n * 在多包场景下,如果命令在其他包中注册并且该包中的命令还没注册,则会等待命令注册后再返回\n * \n * @param name \n * @returns \n */\n find(name:string):Promise<MixCommand | undefined>{\n const cmd = this.get(name)\n if(cmd){\n return Promise.resolve(cmd) \n }else{\n const signal = asyncSignal()\n this.findSignals.push(signal)\n return new Promise<MixCommand | undefined>((resolve)=>{\n let listener:LiteEventSubscriber\n listener = this.on(\"register\",(fullname:string)=>{\n if(fullname==`${this.name}.${name}`){\n listener.off()\n signal.resolve()\n this.findSignals = this.findSignals.filter(s=>s!=signal)\n resolve(this.get(name))\n }\n },{objectify:true}) as LiteEventSubscriber\n })\n } \n }\n /**\n * 判断命令是否存在\n * \n * @param name \n * @returns \n */\n exists(name:string):boolean{\n if(name in this.root.commands){\n return true\n }else{\n return this.get(name) != undefined\n }\n } \n \n /**\n * 运行命令行程序\n */\n run(){ \n // 为什么有findSignal这玩意,解决什么问题?\n // 当我们要扩展command时,通过get(\"命令名称\")来获取已经注册的命令的方式有个缺陷\n // 就是如果对命令的注册顺序有严格的要求,比如调用get('dev')时要求dev命令必须已经存在\n // 这对动态包的命令注册扩展开发体验不好\n // 所以引入find(\"命令名称\")来获取命令,该方法可以获取到后注册的命令\n // 其副作用是,在run时,可能find还没有运行到,从而导致在帮助信息里面看不到扩展的信息(实际上是已经生效的)\n // 所以我们在find里面注入一个异步信号来解决此问题\n this.installCommands().then(()=>{\n return Promise.all(this.findSignals.map(signal=>signal(10000))).then(()=>{\n this.root.parseAsync(process.argv); \n })\n }) \n }\n}\n ","import { Command, Option } from \"commander\";\nimport prompts, { PromptObject } from \"prompts\";\nimport { MixOption, type MixedOptionParams } from \"./option\";\nimport { addBuiltInOptions, hyphenToCamelCase, isDisablePrompts, outputDebug } from \"./utils\";\nimport type { AsyncFunction } from \"flex-tools/types\"; \nimport path from \"node:path\";\nimport fs from \"node:fs\";\n\n\n\nexport type IMixCommandHookListener = ({\n\targs,\n\toptions,\n\tcommand,\n}: {\n\targs: any[];\n\toptions: Record<string, any>;\n\tcommand: MixCommand;\n}) => void | Promise<void>;\n\nexport type BeforeMixCommandHookListener = ({\n\targs,\n\toptions,\n\tcommand,\n}: {\n\targs: any[];\n\toptions: Record<string, any>;\n\tcommand: MixCommand;\n}) => void | Promise<void>;\n\nexport type AfterMixCommandHookListener = ({\n\tvalue,\n\targs,\n\toptions,\n\tcommand,\n}: {\n\tvalue: any;\n\targs: any[];\n\toptions: Record<string, any>;\n\tcommand: MixCommand;\n}) => void | Promise<void>;\n\nexport interface MixActionOptions {\n\tid: string;\n\tat: \"replace\" | \"before\" | \"after\" | \"preappend\" | \"append\" | number;\t\n\tenhance: boolean;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 函数签名类型,即采用原始的commander的action函数签名,还是mixcli的action函数签名\n}\n\nexport interface MixActionRegistry extends Omit<MixActionOptions, \"at\"> {\n\tfn: Function;\n}\n\n// 原始的Action动作函数\nexport type MixOriginalAction = (...args: any[]) => any | Promise<void>;\n\n// 增强的Action函数签名\nexport type MixEnhanceAction = ({\n\targs,\n\toptions,\n\tvalue,\n\tcommand,\n}: {\n\targs: any[];\n\toptions: Record<string, any>;\n\tvalue: any;\n\tcommand: MixCommand;\n}) => any | Promise<any>;\n\n// 执行action的返回结果\nexport const BREAK = Symbol(\"BREAK_ACTION\"); // 中止后续的action执行\n\nexport class MixCommand extends Command {\n\t__MIX_COMMAND__ = true;\n\tprivate _beforeHooks : [ BeforeMixCommandHookListener, boolean ][] = [];\n\tprivate _afterHooks : [ AfterMixCommandHookListener, boolean ][] = [];\n\tprivate _customPrompts : PromptObject[] = [];\n\tprivate _optionValues : Record<string, any> = {}; \t\t\t\t\t\t\t// 命令行输入的选项值\n\tprivate _actions : MixActionRegistry[] = []; \t\t\t\t\t\t\t// 允许多个action\n\tprivate _enable_prompts: boolean = true; \t\t\t\t\t\t\t\t\t// 是否启用交互提示\n\tconstructor(name?: string) {\n\t\tsuper(name);\t\t\n\t\t// eslint-disable-next-line no-this-alias\n\t\tconst self = this\n\t\tif (!this.isRoot) addBuiltInOptions(this); \n\t\tthis.hook(\"preAction\", async function (this: any) {\n\t\t\tself._optionValues = self.getOptionValues(this.hookedCommand);\t\t\t\n\t\t\t// @ts-ignore\n\t\t\tawait self.preActionHook.apply(self, arguments);\n\t\t});\n\t} \n\tget isRoot() { return this.parent==undefined;\t}\n\tget optionValues(){ return this._optionValues }\n\tget actions() { return this._actions; }\n\tget beforeHooks() {\treturn this._beforeHooks; }\n\tget afterHooks() {return this._afterHooks;}\n\tget fullname() {\n\t\tlet names = [this.name()];\n\t\tlet parent = this.parent;\n\t\twhile (parent) {\n\t\t\tif (parent.name() !== \"root\") {\n\t\t\t\tnames.unshift(parent.name());\n\t\t\t}\n\t\t\tparent = parent.parent;\n\t\t}\n\t\treturn names.join(\".\");\n\t}\n\n\t/**\n\t * 返回根命令\n\t */\n\troot() { \n\t\t// eslint-disable-next-line no-this-alias\n\t\tlet root:any = this;\n\t\twhile (root && root.parent != null) {\n\t\t\troot = root.parent as unknown as MixCommand;\n\t\t}\n\t\treturn root;\n\t}\n\n\n\taction(fn: MixEnhanceAction, options: MixActionOptions): this;\n\taction(fn: MixOriginalAction): this;\n\taction(): this {\n\t\tconst actionFunc = arguments[0];\n\t\tif (arguments.length == 1 && typeof actionFunc == \"function\") {\n\t\t\t// 原始方式\n\t\t\tthis._actions.push({\n\t\t\t\tid: Math.random().toString(36).substring(2),\n\t\t\t\tenhance: false,\n\t\t\t\tfn: actionFunc,\n\t\t\t});\n\t\t} else if (arguments.length == 2 && typeof actionFunc == \"function\" && typeof arguments[1] == \"object\" ) {\n\t\t\t// 增强模式\n\t\t\tconst actionFn = arguments[0];\n\t\t\tconst actionOpts: MixActionOptions = Object.assign({ at: \"append\" }, arguments[1]);\n\t\t\tif (actionOpts.at == \"replace\") this._actions = [];\n\t\t\tconst actionItem = {\n\t\t\t\tid: actionOpts.id || Math.random().toString(36).substring(2),\n\t\t\t\tenhance: actionOpts.enhance == undefined ? true : actionOpts.enhance,\n\t\t\t\tfn: actionFn,\n\t\t\t} as const;\n\t\t\tif (typeof actionOpts.at == \"number\") {\n\t\t\t\tthis._actions.splice(Number(actionOpts.at), 0, actionItem);\n\t\t\t} else if ([\"append\", \"before\"].includes(actionOpts.at)) {\n\t\t\t\tthis._actions.push(actionItem);\n\t\t\t} else if ([\"preappend\", \"after\"].includes(actionOpts.at)) {\n\t\t\t\tthis._actions.splice(0, 0, actionItem);\n\t\t\t} else {\n\t\t\t\tthis._actions.push(actionItem);\n\t\t\t}\n\t\t} else {\n\t\t\tconsole.log(\"[mixcli] action params error\");\n\t\t}\n\t\treturn super.action(this.getWrapperedAction());\n\t}\n\n\t/**\n\t * 读取命令配置值,包括父命令提供的配置选项\n\t * @param command\n\t */\n\tprivate getOptionValues(command: MixCommand) {\n\t\tconst opts = {};\n\t\t// eslint-disable-next-line no-this-alias\n\t\tlet parent: any = command;\n\t\twhile (parent) {\n\t\t\tObject.assign(opts, (parent as MixCommand).optionValues);\n\t\t\tparent = parent.parent;\n\t\t}\n\t\treturn opts;\n\t}\n\t/**\n\t * 本函数在运行时子类进行action生成该命令的action\n\t */\n\tprivate getWrapperedAction() {\n\t\treturn this.wrapperWorkDirsAction(this.wrapperChainActions());\n\t}\n\n\t/**\n\t * 向上查找所有祖先命令\n\t */\n\tprivate getAncestorCommands(): MixCommand[] {\n\t\tlet cmds: MixCommand[] = [];\n\t\t// eslint-disable-next-line no-this-alias\n\t\tlet cmd: MixCommand | null = this;\n\t\twhile (cmd) {\n\t\t\tcmd = cmd.parent as unknown as MixCommand;\n\t\t\tif (cmd) {\n\t\t\t\tcmds.push(cmd);\n\t\t\t}\n\t\t}\n\t\treturn cmds;\n\t}\n\t/***\n\t * 将所有actions包装成一个链式调用的函数\n\t */\n\tprivate wrapperChainActions() {\n\t\t// eslint-disable-next-line no-this-alias\n\t\tconst self = this;\n\t\treturn async function (this: any) {\n\t\t\tconst args = Array.from(arguments); // 原始输入的参数\n\t\t\tlet preValue: any; // 保存上一个action的返回值\n\t\t\t//解析参数, 0-1个参数为options,最后一个参数为command\n\t\t\tlet actionOpts: Record<string, any> = {},\n\t\t\t\tactionArgs: any[] = [],\n\t\t\t\tcmd: any;\n\t\t\tif (args.length >= 2) {\n\t\t\t\tcmd = args[args.length - 1]; // 最后一个command\n\t\t\t\tactionOpts = args[args.length - 2];\n\t\t\t\tactionArgs = args.slice(0, args.length - 2);\n\t\t\t}\n\t\t\tawait self.executeBeforeHooks({ args: actionArgs, options: actionOpts, command: cmd });\n\t\t\ttry {\n\t\t\t\tfor (let action of self._actions) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (action.enhance) {\n\t\t\t\t\t\t\t// 增强模式\n\t\t\t\t\t\t\toutputDebug(\"执行<{}>: args={}, options={}\", () => [\n\t\t\t\t\t\t\t\tself.name(),\n\t\t\t\t\t\t\t\tactionArgs,\n\t\t\t\t\t\t\t\tactionOpts,\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\tpreValue = await action.fn.call(this, {\n\t\t\t\t\t\t\t\tcommand: cmd,\n\t\t\t\t\t\t\t\tvalue : preValue,\n\t\t\t\t\t\t\t\targs : actionArgs,\n\t\t\t\t\t\t\t\toptions: actionOpts,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// 原始模式\n\t\t\t\t\t\t\tpreValue = await action.fn.apply(this, args);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (preValue === BREAK) break;\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\toutputDebug(\"命令{}的Action({})执行出错:{}\", [self.name, action.id, e]);\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tawait self.executeAfterHooks({\n\t\t\t\t\tvalue: preValue,\n\t\t\t\t\targs: actionArgs,\n\t\t\t\t\toptions: actionOpts,\n\t\t\t\t\tcommand: cmd,\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t}\n\t/**\n\t * 当传入--work-dirs时用来处理工作目录\n\t */\n\tprivate wrapperWorkDirsAction(fn: AsyncFunction) {\n\t\t// eslint-disable-next-line no-this-alias\n\t\tconst self = this;\n\t\treturn async function (this: any) {\n\t\t\tlet workDirs = self._optionValues.workDirs;\n\t\t\t// 未指定工作目录参数\n\t\t\tif (!workDirs) {\n\t\t\t\treturn await fn.apply(this, Array.from(arguments));\n\t\t\t}\n\t\t\tif (!Array.isArray(workDirs)) workDirs = workDirs.split(\",\");\n\t\t\tworkDirs = workDirs.reduce((dirs: any[], dir: string) => {\n\t\t\t\tif (typeof dir == \"string\") dirs.push(...dir.split(\",\"));\n\t\t\t\treturn dirs;\n\t\t\t}, []);\n\t\t\tfor (let workDir of workDirs) {\n\t\t\t\tconst cwd = process.cwd();\n\t\t\t\ttry {\n\t\t\t\t\tif (!path.isAbsolute(workDir)) workDir = path.join(cwd, workDir);\n\t\t\t\t\tif (fs.existsSync(workDir) && fs.statSync(workDir).isDirectory()) {\n\t\t\t\t\t\toutputDebug(\"切换到工作目录:{}\", workDir);\n\t\t\t\t\t\tprocess.chdir(workDir); // 切换\n\t\t\t\t\t\tawait fn.apply(this, Array.from(arguments));\n\t\t\t\t\t} else {\n\t\t\t\t\t\toutputDebug(\"无效的工作目录:{}\", workDir);\n\t\t\t\t\t} \n\t\t\t\t} finally {\n\t\t\t\t\tprocess.chdir(cwd);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\tgetOption(name: string): MixOption {\n\t\treturn this.options.find((option) => option.name() == name) as unknown as MixOption;\n\t}\n\t/**\n\t * 添加一个Before钩子\n\t * @param listener\n\t * @param scope =false时代表只在本命令执行,=true时代表在本命令及其子命令执行\n\t * @returns\n\t */\n\tbefore(listener: BeforeMixCommandHookListener, scope: boolean = true) {\n\t\tthis._beforeHooks.push([listener, scope]);\n\t\treturn this;\n\t}\n\tprivate async executeBeforeHooks(args: any) {\n\t\tconst hooks: [BeforeMixCommandHookListener, boolean, MixCommand][] = this.beforeHooks.map(\n\t\t\t([hook, scope]) => [hook, scope, this]\n\t\t);\n\t\tthis.getAncestorCommands().forEach((cmd: MixCommand) => {\n\t\t\thooks.unshift(\n\t\t\t\t...cmd.beforeHooks.map(([hook, scope]) => {\n\t\t\t\t\treturn [hook, scope, cmd] as [BeforeMixCommandHookListener, boolean, MixCommand];\n\t\t\t\t})\n\t\t\t);\n\t\t});\n\t\tfor (let [hook, scope, cmd] of hooks) {\n\t\t\tif (!scope) continue;\n\t\t\tawait hook.call(cmd, args);\n\t\t}\n\t}\n\t/**\n\t * 添加一个After钩子\n\t * @param listener\n\t * @param scope =false时代表只在本命令执行,=true时代表在本命令及其子命令执行\n\t * @returns\n\t */\n\tafter(listener: AfterMixCommandHookListener, scope: boolean = true) {\n\t\tthis._afterHooks.push([listener, scope]);\n\t\treturn this;\n\t}\n\n\tprivate async executeAfterHooks(args: any) {\n\t\tconst hooks: [AfterMixCommandHookListener, boolean, MixCommand][] = this.afterHooks.map(\n\t\t\t([hook, scope]) => [hook, scope, this]\n\t\t);\n\t\tthis.getAncestorCommands().forEach((cmd: MixCommand) => {\n\t\t\thooks.push(\n\t\t\t\t...cmd.afterHooks.map(([hook, scope]) => {\n\t\t\t\t\treturn [hook, scope, cmd] as [BeforeMixCommandHookListener, boolean, MixCommand];\n\t\t\t\t})\n\t\t\t);\n\t\t});\n\t\tfor (let [hook, scope, cmd] of hooks) {\n\t\t\tif (!scope) continue; //=false时不执行\n\t\t\tawait hook.call(cmd, args);\n\t\t}\n\t}\n\tprivate async preActionHook(thisCommand: Command) {\n\t\tif (this.isEnablePrompts()) {\n\t\t\t// 自动生成提示\n\t\t\tconst questions: PromptObject[] = [\n\t\t\t\t...this.generateAutoPrompts(),\n\t\t\t\t...this._customPrompts,\n\t\t\t];\n\t\t\t// 用户提示\n\t\t\tif (questions.length > 0) {\n\t\t\t\tconst results = await prompts(questions);\n\t\t\t\tObject.entries(results).forEach(([key, value]) => {\n\t\t\t\t\tthisCommand.setOptionValue(key, value);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate isEnablePrompts() {\n\t\tif (isDisablePrompts()) {\t\t\t\n\t\t\treturn false;// 命令行参数禁用了提示,优先级最高\n\t\t} else {\n\t\t\treturn this._enable_prompts;\n\t\t}\n\t}\n\n\t/**\n\t * 生成选项自动提示\n\t *\n\t * @remarks\n\t * 要求所有未提供默认值的Option自动生成提示\n\t *\n\t * - 未提供默认值,并且是必选的参数Option\n\t * - 指定了choices但未提供有效值的Option\n\t *\n\t */\n\tprivate generateAutoPrompts(): PromptObject[] {\n\t\tconst options = this.options as unknown as MixOption[];\n\t\tconst optionPromports = options\n\t\t\t.filter((option) => !option.hidden && option.__MIX_OPTION__)\n\t\t\t.map((option) => option.getPrompt(this._optionValues[option.attributeName()]))\n\t\t\t.filter((prompt) => prompt) as PromptObject[];\n\t\t\t\n\t\toutputDebug(\"命令<{}>自动生成{}个选项提示:{}\", [\n\t\t\tthis.name(),\n\t\t\toptionPromports.length,\n\t\t\toptionPromports.map((prompt) => `${prompt.name}(${prompt.type})`).join(\",\"),\n\t\t]);\n\t\treturn optionPromports;\n\t} \n\n\t// @ts-ignore\n\toption( flags: string, description: string, options?: MixedOptionParams ):this{ \n \t\tconst option = new MixOption(flags, description, options);\n\t\tif (option.required && !this.isEnablePrompts()) option.mandatory = true;\t\t\n\t\treturn this.addOption(option as unknown as Option) \n\t}\n\n\t/**\n\t * 添加提示\n\t *\n\t * @remarks\n\t *\n\t * 添加一些自定义提示 \n\t *\n\t * @param questions\n\t * @returns\n\t */\n\tprompt(questions: PromptObject | PromptObject[]) {\n\t\tthis._customPrompts.push(...(Array.isArray(questions) ? questions : [questions]));\n\t\treturn this;\n\t}\n\n\t/**\n\t *\n\t * 选择命令并执行\n\t *\n\t * @remorks\n\t *\n\t * 当命令具有多个子命令时,并且没有提供默认子命令时,提示用户选择一个子命令\n\t *\n\t */\n\tasync selectCommands() {\n\t\tconst choices = this.commands.map((command) => ({\n\t\t\ttitle: `${command.description()}(${command.name()})`,\n\t\t\tvalue: command.name(),\n\t\t}));\n\t\tconst result = await prompts({\n\t\t\ttype : \"select\",\n\t\t\tname : \"command\",\n\t\t\tmessage: \"请选择命令:\",\n\t\t\tchoices,\n\t\t});\n\t\t// 重新解析命令行参数标志,\n\t\tconst command = this.commands.find((command) => command.name() === result.command);\n\t\tawait command?.parseAsync([result.command], { from: \"user\" });\n\t}\n\t/**\n\t * 禁用/启用所有提示\n\t */\n\tdisablePrompts() {\n\t\tthis._enable_prompts = false;\n\t\treturn this;\n\t}\n\t/**\n\t * 启用所有提示\n\t */\n\tenablePrompts() {\n\t\tthis._enable_prompts = true;\n\t\treturn this;\n\t}\n}\n\n\n\n// 编写一个类型号用来表示Commander的Option flags字面量类型","import { Option, OptionValues } from 'commander'\nimport { PromptObject } from 'prompts'\nimport { PromptChoice, MixOptionPrompt,PromptParams } from './prompt'\n \n\nexport interface MixedOptionParams {\n required? : boolean; // A value must be supplied when the option is specified.\n optional? : boolean; // A value is optional when the option is specified.\n variadic? : boolean; \n mandatory? : boolean; // The option must have a value after parsing, which usually means it must be specified on command line.\n negate? : boolean;\n default? : any;\n defaultDescription? : string;\n conflicts? : string | string[];\n argParser? : unknown;\n implies? : OptionValues\n envVar? : string;\n parseArg? : <T>(value: string, previous: T) => T;\n hidden? : boolean;\n choices? : (string | PromptChoice )[] | ((pre:any,answers:any)=>(string | PromptChoice)[]);\n validate? : (value: any) => boolean;\n preset? : unknown;\n prompt? : PromptParams\n}\n\n\nexport class MixOption extends Option{\n __MIX_OPTION__ = true\n prompt? : MixOptionPrompt \n constructor(flags: string, description: string,public params?: MixedOptionParams) {\n super(flags, description) \n this._setOption(params || {}) \n this.prompt = new MixOptionPrompt(this,params?.prompt) \n } \n private _setOption(params:MixedOptionParams){ \n if(params.default) this.default(params.default,params.defaultDescription)\n if(params.conflicts) this.conflicts(params.conflicts)\n if(params.envVar) this.env(params.envVar)\n if(params.parseArg) this.argParser(params.parseArg) \n if(params.hidden) this.hidden = params.hidden\n if(params.mandatory) this.makeOptionMandatory(params.mandatory)\n if(params.implies) this.implies(params.implies) \n if(params.optional) this.optional=params.optional\n if(params.variadic) this.variadic = params.variadic\n if(params.negate) this.negate = params.negate\n if(params.preset) this.preset(params.preset)\n if(params.required) this.required = params.required \n if(Array.isArray(params.choices)) this.choices(params.choices.map(choice=>typeof(choice)=='string' ? choice : choice.value))\n } \n \n /**\n * 返回选项的提示对象\n * \n * @remarks \n * @param inputValue \n * @returns \n */\n getPrompt(inputValue?:any): PromptObject | undefined {\n return this.prompt?.get(inputValue)\n } \n}","import { isPlainObject } from \"flex-tools/typecheck/isPlainObject\"\nimport { isNumber } from \"flex-tools/typecheck/isNumber\"\n\nimport { PromptObject } from \"prompts\" \nimport { outputDebug } from \"./utils\"\nimport { MixOption } from \"./option\" \n\nexport type PromptType = \"text\" | \"password\" | \"invisible\" | \"number\"| \"confirm\"| \"list\" \n | \"toggle\"| \"select\" | \"multiselect\" | \"autocomplete\" | \"date\" | \"autocompleteMultiselect\"\n\nexport type PromptParam = 'auto' | boolean | PromptType | PromptObject\nexport type InputPromptParam = PromptParam | ((value:any)=>PromptParam) | boolean\nexport type PromptParamDefaultValue = string | boolean | string[] \n\nexport const promptTypeMap:Record<string,string> = {\n boolean: \"confirm\",\n string : \"text\",\n number : \"number\", \n array : \"list\", \n date : \"date\"\n} \n\nexport const supportedPromptTypes = [\n \"text\",\n \"password\",\n \"invisible\", \n \"number\", \n \"confirm\" , \n \"list\", \n \"toggle\" , \n \"select\" , \n \"multiselect\" , \n \"autocomplete\" , \n \"date\" , \n \"autocompleteMultiselect\"\n]\n\nexport interface PromptChoice {\n title : string;\n value? : any;\n disabled? : boolean | undefined;\n selected? : boolean | undefined;\n description?: string | undefined;\n}\n\n \nexport type PromptParams = Omit<PromptObject,'name'> | PromptType | boolean | 'auto' | undefined \n\n/**\n * 负责生成prompt对象\n * \n */\nexport class MixOptionPrompt{\n params?: PromptParams\n constructor(public cliOption:MixOption,promptParams?:PromptParams){ \n this.params = promptParams\n }\n /**\n * 返回输入的是否是有效的prompt类型\n * @param type \n * @returns \n */\n isValidPromptType(type:any){\n return supportedPromptTypes.includes(String(type))\n }\n /**\n * 推断是否需要提示\n * \n * 1. 显式指定prompt=true或者提示类型,或者提示对象,则需要提示\n * \n * \n */\n isNeedPrompt(input:any,defaultValue?:any){\n \n const params = this.params\n\n const inputValue = input || defaultValue\n\n // 是否有输入值,即在命令行输入了值\n const hasInput = !(inputValue === undefined)\n \n // 1. 显式指定了_prompt为true,则需要提示,后续进行提示类型的推断,可能不会准确\n if(params === true) return true\n if(params === false) return false \n if(params === 'auto') return !hasInput\n\n // 2. 提供了一个prompt对象,并且没有在命令行输入值,则需要提示\n if(isPlainObject(params)){\n return !hasInput\n }\n\n // 3. 指定了内置的prompt类型,如prompt='password',则使用password类型提示输入\n if(typeof(params) == 'string' && this.isValidPromptType(params)){\n return true\n }\n\n // 4. 指定了可选值,但是没有输入值,则需要提示\n const isOptional = /(\\<s*\\w\\s*\\>)/.test(this.cliOption.flags) \n if(isOptional) return !hasInput\n \n // 4. 判断输入是否有效,则显示提示\n if(this.cliOption.argChoices && this.cliOption.argChoices.indexOf(inputValue) == -1){\n return true\n } \n return !hasInput\n\n }\n \n private _getChoices(){\n let choices:(string | PromptChoice)[] | ((pre:any,answers:any)=>(string | PromptChoice)[]) = []\n let choicesParam = this.cliOption.params?.choices\n if(this.cliOption.argChoices){\n choices = this.cliOption.argChoices.map(choice=>{\n if(typeof(choice)=='string'){\n return {title:choice,value:choice}\n }else{\n return choice\n }\n })\n }else if(choicesParam){\n choices = typeof(choicesParam)=='function' ? choicesParam : [] \n }else{\n return []\n } \n return choices\n } \n\n /**\n * 自动推断prompt类型\n * \n * \n * \n * @param inputValue 从命令行输入的值\n */\n infer(inputValue?:any){\n\n const { variadic, defaultValue } = this.cliOption\n\n const input = inputValue || defaultValue\n\n // 如果选择指定了\"-p [value]或[value...]\",则使用text类型,如果没有要求输入值,则使用confirm类型\n let promptType:PromptType = 'text'\n\n const params = this.params\n\n if(this.isValidPromptType(params)){ // 显式指定了prompt类型,m则以指定的类型为准 \n promptType = params as PromptType\n }else if(isPlainObject(params)){ // 显式指定了prompt对象\n promptType = (params as PromptObject).type as PromptType\n }else{ // 自动推断prompt类型\n \n const isListType = /(\\[\\s*\\w+\\.\\.\\.\\s*])|(\\<\\s*\\w+\\.\\.\\.\\s*>)/.test(this.cliOption.flags)\n const isTextType = /(\\<s*\\w+\\s*\\>)|(\\[\\w+\\])/.test(this.cliOption.flags) \n const isBooleanType = !/(\\[\\s*\\w+s*])|(\\<\\s*\\w+\\s*>)/.test(this.cliOption.flags)\n const isNumberType = isNumber(defaultValue)\n const isDate = defaultValue && defaultValue instanceof Date\n\n // 根据默认值的类型推断\n const datatype:string = Array.isArray(input) ? 'array' : \n input instanceof Date ? 'date' :\n typeof(input) \n\n const optionParams = this.cliOption.params\n\n if(optionParams && optionParams.choices){\n const choices = optionParams.choices\n if(isBooleanType && (Array.isArray(choices) && choices.length==2)){\n promptType = 'toggle'\n }else{\n promptType = variadic ? 'multiselect' : 'select'\n } \n }else if(isListType){ // 提供多个可选值时\n promptType = 'list'\n }else if(isDate){\n promptType = 'date'\n }else if(isNumberType){\n promptType = 'number'\n }else if(isTextType){ // 提供一个可选值时\n promptType = 'text' \n }else if(isBooleanType || typeof(defaultValue)==='boolean'){\n promptType = 'confirm'\n }else if(datatype in promptTypeMap){\n promptType = promptTypeMap[datatype] as PromptType\n }\n }\n outputDebug(\"选项<{}> -> 提示类型<{}>\",[this.cliOption.name(),promptType])\n return promptType\n }\n /**\n * 返回生成prompt对象\n * \n * @param inputValue 从命令行输入的值\n */\n get(inputValue?:any){\n\n const { description, defaultValue } = this.cliOption\n \n let input = inputValue || defaultValue\n\n // 1. 判断是否需要启用提示\n if(!this.isNeedPrompt(input,defaultValue)) return\n\n // 2. 推断prompt类型\n const promptType = this.infer(inputValue)\n\n const prompt = {\n type : promptType, \n name : this.cliOption.attributeName(),\n message: description,\n initial: input,\n ...typeof(this.params) == 'object' ? this.params : {}\n } as PromptObject\n\n\n // 指定了验证函数,用来验证输入值是否有效\n prompt.validate = this.cliOption.params?.validate\n\n if(promptType=='multiselect') prompt.instructions=false\n prompt.choices = prompt.choices || this._getChoices() as any \n\n if(['select','multiselect'].includes(promptType)){ \n\n }else if(promptType=='toggle'){ \n if(Array.isArray(prompt.choices)){\n if(!prompt.active) prompt.active = prompt.choices[0].value\n if(!prompt.inactive) prompt.inactive = prompt.choices[1].value \n }\n }\n\n if(input && typeof(prompt.initial)!='function'){\n if(prompt.choices && Array.isArray(prompt.choices)){\n if(promptType=='select'){\n const index = Array.isArray(prompt.choices) ? prompt.choices.findIndex(item=>item.value==input) : -1\n if(index!=-1){\n prompt.initial = index\n }\n }else if(promptType=='multiselect'){ \n prompt.choices.forEach((item)=>{\n if(Array.isArray(input) && input.includes(item.value)){\n item.selected = true\n }else if(item.value==input){\n item.selected = true\n }\n })\n }\n }\n }\n\n return prompt\n }\n\n\n}","import fs from \"fs-extra\"\nimport path from \"node:path\"\nimport { promisify } from \"flex-tools/func/promisify\"\nimport logsets from \"logsets\" \n\n\n/**\n * \n * 在控制台输出一个字符串\n * 本方法会将字符串中的每一行空格去掉\n * \n * @remarks\n * \n * outputStr(String.raw`\n * a\n * b`)\n * \n * 会输出\n * a\n * b\n *\n * 此功能可以用于输出多行字符串时,保持代码的缩进格式,而不会影响输出结果\n * \n * @param str : 要输出的字符串\n * @param vars : 用于替换字符串中的变量\n * \n */\nexport function outputStr(str:string,vars?:Record<string,any> | any[]){ \n logsets.log(fixIndent(str),vars)\n}\n\n/**\n * 修正多行字符串的缩进\n * \n * @param text \n * @param indent \n * @returns \n */\nexport function fixIndent(text:string,indent?:boolean | number):string{\n let indentValue = (indent==undefined || indent===true) ? 0 : (typeof(indent)=='number' ? indent : -1)\n if(indentValue==-1) return text // 不修正缩进\n let lines:string[] = text.split(\"\\n\")\n let minSpaceCount = lines.reduce<number>((minCount,line,index)=>{\n if(index==0) return minCount\n const spaceCount = line.match(/^\\s*/)?.[0].length || 0\n return Math.min(minCount,spaceCount)\n },9999)\n lines = lines.map(line=>line.substring(minSpaceCount))\n return lines.join(\"\\n\")\n}\n\n/**\n * 增加内置选项\n * @param command \n */\nexport function addBuiltInOptions(command:any){ \n command.option(\"--work-dirs <values...>\",\"指定工作目录\",{hidden:true,optional:true,required:true,prompt:false})\n command.option(\"--disable-prompts\",\"禁用所有交互提示\",{hidden:true,prompt:false}) \n command.option(\"--debug-cli\",\"显示调试信息\",{hidden:true,prompt:false})\n}\n\n\n/**\n * 是否命令行中包含了--debug-cli选项\n */\nexport function isDebug(){\n return process.argv.includes(\"--debug-cli\")\n}\n\n\nexport function isDisablePrompts(){ \n return process.argv.includes(\"--disable-prompts\")\n}\n\n/**\n * 打印调试信息\n * @param message \n * @param args \n */\nexport function outputDebug(message:string,...args:any[]){ \n let vars = (args.length == 1 && typeof(args[0])=='function') ? args[0]() : args\n if(isDebug()) logsets.log(`[MixCli] ${message}`,...vars)\n}\n\nexport const fileExists = promisify(fs.exists,{\n parseCallback:(results)=>{\n return results[0]\n }\n})\nexport const readFile = promisify(fs.readFile)\nexport const writeFile = promisify(fs.writeFile)\nexport const mkdir = promisify(fs.mkdir)\n \n/** \n * 创建目录 \n * \n * \n * \n * @param {String[]} dirs 要创建的目录列表,类型为字符串数组 \n * @param callback 创建目录过程中的回调函数,类型为异步函数,接收一个参数 dir,表示当前正在创建的目录 \n * @returns 该函数返回一个 Promise 对象,表示创建目录的操作是否完成 \n */\nexport async function mkDirs(dirs:string[],{callback,base}:{callback?:Function,base?:string}){\n if(!Array.isArray(dirs)) throw new Error(\"dirs参数必须为字符串数组\")\n for(let dir of dirs){\n if(!path.isAbsolute(dir)) dir = path.join(base || process.cwd(),dir)\n if(typeof(callback)=='function') callback(dir)\n await mkdir(dir,{recursive:true})\n }\n}\n\nexport function showError(e:any){\n if(isDebug()){\n outputDebug(\"导入命令<>出错:{}\",e.stack)\n }else{\n console.error(e)\n } \n\n}\n\n// 编写一个函数,用于将使用-分隔的字符串转换为驼峰式\nexport function hyphenToCamelCase(str:string){\n return str.replace(/-([a-z])/g,(_,letter)=>letter.toUpperCase())\n}\n\nexport function getId(){\n return Math.random().toString(36).substr(2)\n}\n\n\nexport async function importModule(file:string){\n let module \n try{\n module = require(file)\n }catch(e:any){\n try{\n const cmd = await import(`file://${file}`)\n module = cmd.default\n }catch(e:any){\n throw e\n } \n }\n return module\n}\n","import { getPackageJson } from \"flex-tools/package/getPackageJson\"\nimport { getPackageRootPath } from 'flex-tools/package/getPackageRootPath';\nimport type { MixCli } from './cli';\nimport { globSync } from 'glob'\nimport { MixCliCommand } from './cli';\nimport { importModule, outputDebug } from './utils';\nimport fs from \"node:fs\"\nimport path from \"node:path\"\n\n\n/**\n * \n * 在当前工程中查找符合FlexCli.prefix约定的命令 \n * \n * - 读取当前包的package.json\n * - 找出所有以cli.prefix开头的依赖\n * - 加载这些依赖的目录下的匹配cli.pattern的命令\n * - 加载加载这样命令\n * \n */\n \n\nexport function getMatchedDependencies(this:MixCli,entry:string):string[]{\n const pacakgeMacher = this.options.include\n if(!(pacakgeMacher instanceof RegExp)) return []\n \n // 找出当前包的所有依赖\n const { dependencies={},devDependencies={},peerDependencies={},optionalDependencies={},bundleDependencies={} } = getPackageJson(entry)\n const packageNames = [\n ...Object.keys(dependencies),\n ...Object.keys(devDependencies),\n ...Object.keys(peerDependencies),\n ...Object.keys(optionalDependencies),\n ...Object.keys(bundleDependencies)\n ]\n return packageNames.filter(name=>name!==\"@voerka/cli\" && pacakgeMacher.test(name))\n}\n\nfunction isMatched(str:string,reg?:string | RegExp | string[] | RegExp[]):boolean{\n // let regexps:RegExp[]=[]\n const regexps = reg ? (Array.isArray(reg) ? reg : [reg]) : []\n return regexps.some(regexp=>{\n if(typeof regexp === \"string\"){\n return (new RegExp(regexp)).test(str)\n }else if(regexp instanceof RegExp){\n return regexp.test(str)\n }else{\n return false\n }\n })\n}\n\nexport function findCliPaths(this:MixCli,packageName?:string ,entry?:string):string[]{\n const includeMacher = this.options.include\n const excludeMacher = this.options.exclude\n if(!includeMacher) return []\n const packageRoot = getPackageRootPath(entry || process.cwd())\n const packagePath = packageName ? path.dirname(require.resolve(packageName,{paths:[packageRoot as string]})) : packageRoot\n\n if(!packagePath) {\n outputDebug(\"MixCli只能运行在Nodejs环境\" )\n return []\n }\n\n // 找出当前包的所有依赖\n const packageNames = getMatchedDependencies.call(this,packagePath)\n\n const cliDirs:string[]=[]\n \n if(entry!==undefined) cliDirs.push(path.join(packagePath,this.options.cliDir))\n packageNames.filter(name=>{\n return isMatched(name,includeMacher) && !isMatched(name,excludeMacher) \n })\n .forEach(name=>{\n outputDebug(\"匹配包:{}\",`${packageName ? name+\" <- \"+packageName : name}`)\n try{\n const packageEntry = path.dirname(require.resolve(name,{paths:packagePath ? [packagePath] : [process.cwd()]}))\n const packageCliDir =path.join(packageEntry,this.options.cliDir!) \n // 查找当前包的所属工程的依赖\n let dependencies = getMatchedDependencies.call(this,packageEntry)\n cliDirs.push(...dependencies.reduce<string[]>((result,dependencie)=>{\n outputDebug(\"匹配包:{}\",`${dependencie} <- ${name}`)\n result.push(...findCliPaths.call(this,dependencie,packageEntry))\n return result\n },[])) \n if(fs.existsSync(packageCliDir)){\n cliDirs.push(packageCliDir)\n }\n }catch(e:any){\n outputDebug(\"解析包<{}>路径出错:{}\",[name,e.stack])\n } \n })\n // 由于一些包可能存在循环依赖,所以需要去重\n return [...new Set(cliDirs)]\n}\n\n\n/**\n * \n * 扫描当前工程中所有符合条件的命令\n * \n * @param cli \n * \n */\nexport async function findCommands(cli:MixCli){ \n const cliDirs = findCliPaths.call(cli)\n const commands:MixCliCommand[] = []\n const files = [] as string[]\n cliDirs.forEach(dir=>{\n globSync(\"*\",{\n cwd:dir,\n absolute :true \n }).forEach((file:string)=>{ \n const baseName = path.basename(file) \n if(baseName.startsWith(\"_\")) return\n const ext = path.extname(file).toLowerCase()\n if([\".js\",\".cjs\",\".mjs\"].includes(ext)){\n files.push(file)\n }else if(fs.statSync(file).isDirectory()){\n files.push(path.join(file,\"index.js\"))\n files.push(path.join(file,\"index.cjs\"))\n files.push(path.join(file,\"index.mjs\"))\n }\n })\n })\n for(let file of files){ \n if(!fs.existsSync(file)) continue\n try{\n outputDebug(\"导入命令:{}\",file)\n if(file.endsWith(\".cjs\") || file.endsWith(\".js\")){\n commands.push(await importModule(file))\n }else if(file.endsWith(\".mjs\")){\n const cmd = await import(`file://${file}`)\n commands.push(cmd.default)\n } \n }catch(e:any){\n outputDebug(e) \n }\n }\n return commands\n}\n\n"],"mappings":"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","names":["index_exports","__export","BREAK","MixCli","MixCommand","MixOption","MixOptionPrompt","addBuiltInOptions","fileExists","fixIndent","getId","hyphenToCamelCase","importModule","isDebug","isDisablePrompts","mkDirs","mkdir","outputDebug","outputStr","promptTypeMap","readFile","showError","supportedPromptTypes","writeFile","__toCommonJS","import_string","import_liteEvent","import_logsets","import_assignObject","import_commander","import_prompts","import_commander","import_isPlainObject","import_isNumber","import_fs_extra","import_node_path","import_promisify","import_logsets","outputStr","str","vars","logsets","fixIndent","text","indent","lines","minSpaceCount","minCount","line","index","_a","spaceCount","addBuiltInOptions","command","isDebug","isDisablePrompts","outputDebug","message","args","fileExists","fs","results","readFile","writeFile","mkdir","mkDirs","_0","_1","__async","dirs","callback","base","dir","path","showError","e","hyphenToCamelCase","_","letter","getId","importModule","file","module","promptTypeMap","supportedPromptTypes","MixOptionPrompt","cliOption","promptParams","type","input","defaultValue","params","inputValue","hasInput","_a","choices","choicesParam","choice","variadic","promptType","isListType","isTextType","isBooleanType","isNumberType","isDate","datatype","optionParams","outputDebug","description","prompt","__spreadValues","index","item","MixOption","flags","description","params","MixOptionPrompt","choice","inputValue","_a","import_node_path","import_node_fs","BREAK","MixCommand","name","self","addBuiltInOptions","__async","names","parent","root","actionFunc","actionFn","actionOpts","actionItem","command","opts","cmds","cmd","args","preValue","actionArgs","action","outputDebug","e","fn","workDirs","dirs","dir","workDir","cwd","path","fs","option","listener","scope","hooks","hook","thisCommand","questions","results","prompts","key","value","isDisablePrompts","optionPromports","prompt","flags","description","options","MixOption","choices","result","import_getPackageJson","import_getPackageRootPath","import_glob","import_node_fs","import_node_path","getMatchedDependencies","entry","pacakgeMacher","dependencies","devDependencies","peerDependencies","optionalDependencies","bundleDependencies","name","isMatched","str","reg","regexp","findCliPaths","packageName","includeMacher","excludeMacher","packageRoot","packagePath","path","outputDebug","packageNames","cliDirs","packageEntry","packageCliDir","result","dependencie","fs","e","findCommands","cli","__async","commands","files","dir","file","ext","importModule","cmd","import_asyncSignal","import_string_prototype","replaceAll","MixCli","options","__async","cmders","findCommands","cmder","cmds","outputDebug","MixCommand","logsets","fixIndent","title","addBuiltInOptions","text","pos","alignIndent","cmd","result","name","c","names","curCmd","resultCmd","topName","r","signal","resolve","listener","fullname","s"]}