mixcli 3.2.3 → 3.2.4

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.js CHANGED
@@ -1,4 +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};
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, 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"]}
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":"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","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.3",
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",
@@ -53,7 +52,5 @@
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/dist/index.cjs DELETED
@@ -1,4 +0,0 @@
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"),1),et=require("flex-tools/object/assignObject");var X=require("commander"),H=d(require("prompts"),1);var F=require("commander");var D=require("flex-tools/typecheck/isPlainObject"),q=require("flex-tools/typecheck/isNumber");var k=d(require("logsets"),1);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"),1),T=d(require("fs"),1);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"),1),u=d(require("path"),1);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"),1);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
- //# 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, 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":["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"]}
File without changes