mixcli 3.2.6 → 3.2.7
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/command.ts +11 -4
- package/src/prompt.ts +17 -1
package/dist/index.d.mts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
"use strict";var st=Object.create;var x=Object.defineProperty;var rt=Object.getOwnPropertyDescriptor;var at=Object.getOwnPropertyNames,N=Object.getOwnPropertySymbols,pt=Object.getPrototypeOf
|
1
|
+
"use strict";var st=Object.create;var x=Object.defineProperty;var rt=Object.getOwnPropertyDescriptor;var at=Object.getOwnPropertyNames,N=Object.getOwnPropertySymbols,pt=Object.getPrototypeOf,$=Object.prototype.hasOwnProperty,ct=Object.prototype.propertyIsEnumerable;var L=(s,n,t)=>n in s?x(s,n,{enumerable:!0,configurable:!0,writable:!0,value:t}):s[n]=t,B=(s,n)=>{for(var t in n||(n={}))$.call(n,t)&&L(s,t,n[t]);if(N)for(var t of N(n))ct.call(n,t)&&L(s,t,n[t]);return s};var lt=(s,n)=>{for(var t in n)x(s,t,{get:n[t],enumerable:!0})},W=(s,n,t,i)=>{if(n&&typeof n=="object"||typeof n=="function")for(let e of at(n))!$.call(s,e)&&e!==t&&x(s,e,{get:()=>n[e],enumerable:!(i=rt(n,e))||i.enumerable});return s};var d=(s,n,t)=>(t=s!=null?st(pt(s)):{},W(n||!s||!s.__esModule?x(t,"default",{value:s,enumerable:!0}):t,s)),mt=s=>W(x({},"__esModule",{value:!0}),s);var m=(s,n,t)=>new Promise((i,e)=>{var o=p=>{try{a(t.next(p))}catch(c){e(c)}},r=p=>{try{a(t.throw(p))}catch(c){e(c)}},a=p=>p.done?i(p.value):Promise.resolve(p.value).then(o,r);a((t=t.apply(s,n)).next())});var yt={};lt(yt,{BREAK:()=>K,MixCli:()=>S,MixCommand:()=>M,MixOption:()=>O,MixOptionPrompt:()=>C,addBuiltInOptions:()=>P,fixIndent:()=>b,getId:()=>gt,hyphenToCamelCase:()=>ht,importModule:()=>j,isBuildInOption:()=>ft,isDebug:()=>_,isDisablePrompts:()=>w,isUndefined:()=>D,outputDebug:()=>l,outputStr:()=>ut,promptTypeMap:()=>H,showError:()=>dt,supportedPromptTypes:()=>F});module.exports=mt(yt);var Lt=require("flex-tools/string"),et=require("flex-tools/events/liteEvent"),f=d(require("logsets")),it=require("flex-tools/object/assignObject");var X=require("commander"),R=d(require("prompts"));var U=require("commander");var E=require("flex-tools/typecheck/isPlainObject"),q=require("flex-tools/typecheck/isNumber");var k=d(require("logsets"));function ut(s,n){k.default.log(b(s),n)}function b(s,n){if((n==null||n===!0?0:typeof n=="number"?n:-1)==-1)return s;let i=s.split(`
|
2
2
|
`),e=i.reduce((o,r,a)=>{var c;if(a==0)return o;let p=((c=r.match(/^\s*/))==null?void 0:c[0].length)||0;return Math.min(o,p)},9999);return i=i.map(o=>o.substring(e)),i.join(`
|
3
|
-
`)}function P(s){let n={hidden:!0,optional:!0,prompt:!1};s.option("--work-dirs [values...]","\u6307\u5B9A\u5DE5\u4F5C\u76EE\u5F55",Object.assign({},n)),s.option("--disable-prompts","\u7981\u7528\u6240\u6709\u4EA4\u4E92\u63D0\u793A",Object.assign({},n)),s.option("--debug-cli","\u663E\u793A\u8C03\u8BD5\u4FE1\u606F",Object.assign({},n))}function ft(s){return s.flags.startsWith("--work-dirs")||s.flags.startsWith("--disable-prompts")||s.flags.startsWith("--debug-cli")}function w(){return process.argv.includes("--debug-cli")}function _(){return process.argv.includes("--disable-prompts")}function l(s,...n){let t=n.length==1&&typeof n[0]=="function"?n[0]():n;w()&&k.default.log(`[MixCli] ${s}`,...t)}function dt(s){w()?l("\u5BFC\u5165\u547D\u4EE4<>\u51FA\u9519:{}",s.stack):console.error(s)}function ht(s){return s.replace(/-([a-z])/g,(n,t)=>t.toUpperCase())}function gt(){return Math.random().toString(36).substr(2)}function j(s){return m(this,null,function*(){let n;try{n=require(s)}catch(t){throw n=(yield import(`file://${s}`)).default,t}return n})}function D(s){return s==null}var H={boolean:"confirm",string:"text",number:"number",array:"list",date:"date"},F=["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 F.includes(String(n))}isNeedPrompt(n,t,i){if(i===!1)return!1;if(i===!0)return!0;let e=this.params,o=n||t,r=o!==void 0;return e===!0?!0:e===!1?!1:e==="auto"||(0,E.isPlainObject)(e)?!r:typeof e=="string"&&this.isValidPromptType(e)?!0:/(\<s*\w\s*\>)/.test(this.cliOption.flags)?!r:this.cliOption.argChoices&&this.cliOption.argChoices.indexOf(o)==-1?!0:!r}_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",r=this.params;if(this.isValidPromptType(r))o=r;else if((0,E.isPlainObject)(r))o=r.type;else{let a=/(\[\s*\w+\.\.\.\s*])|(\<\s*\w+\.\.\.\s*>)/.test(this.cliOption.flags),p=/(\<s*\w+\s*\>)|(\[\w+\])/.test(this.cliOption.flags),c=!/(\[\s*\w+s*])|(\<\s*\w+\s*>)/.test(this.cliOption.flags),h=(0,q.isNumber)(i),A=i&&i instanceof Date,y=Array.isArray(e)?"array":e instanceof Date?"date":typeof e,g=this.cliOption.params;if(g&&g.choices){let I=g.choices;c&&Array.isArray(I)&&I.length==2?o="toggle":o=t?"multiselect":"select"}else a?o="list":A?o="date":h?o="number":p?o="text":c||typeof i=="boolean"?o="confirm":y in H&&(o=H[y])}return l("\u9009\u9879<{}> -> \u63D0\u793A\u7C7B\u578B<{}>",[this.cliOption.name(),o]),o}get(n,t){var p;let{description:i,defaultValue:e}=this.cliOption,o=n||e;if(!this.isNeedPrompt(o,e,t))return;let r=this.infer(n),a=$({type:r,name:this.cliOption.attributeName(),message:i,initial:o},typeof this.params=="object"?this.params:{});if(a.validate=(p=this.cliOption.params)==null?void 0:p.validate,r=="multiselect"&&(a.instructions=!1),a.choices=a.choices||this._getChoices(),["select","multiselect"].includes(r)||r=="toggle"&&Array.isArray(a.choices)&&(a.active||(a.active=a.choices[0].value),a.inactive||(a.inactive=a.choices[1].value)),o&&typeof a.initial!="function"&&a.choices&&Array.isArray(a.choices))if(r=="select"){let c=Array.isArray(a.choices)?a.choices.findIndex(h=>h.value==o):-1;c!=-1&&(a.initial=c)}else r=="multiselect"&&a.choices.forEach(c=>{(Array.isArray(o)&&o.includes(c.value)||c.value==o)&&(c.selected=!0)});return a}};var M=class extends U.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){D(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,i){var e;return(e=this.prompt)==null?void 0:e.get(t,i)}};var V=d(require("path")),T=d(require("fs"));var K=Symbol("BREAK_ACTION"),O=class extends X.Command{constructor(t){super(t);this.__MIX_COMMAND__=!0;this._beforeHooks=[];this._afterHooks=[];this._customPrompts=[];this._optionValues={};this._actions=[];let i=this;this.hook("preAction",function(){return m(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 m(this,arguments,function*(){let i=Array.from(arguments),e,o={},r=[],a;i.length>=2&&(a=i[i.length-1],o=i[i.length-2],r=i.slice(0,i.length-2)),yield t.executeBeforeHooks({args:r,options:o,command:a});try{for(let p of t._actions)try{if(p.enhance?(l("\u6267\u884C<{}>: args={}, options={}",()=>[t.name(),r,o]),e=yield p.fn.call(this,{command:a,value:e,args:r,options:o})):e=yield p.fn.apply(this,i),e===K)break}catch(c){throw l("\u547D\u4EE4{}\u7684Action({})\u6267\u884C\u51FA\u9519:{}",[t.name,p.id,c]),c}}finally{yield t.executeAfterHooks({value:e,args:r,options:o,command:a})}})}}wrapperWorkDirsAction(t){let i=this;return function(){return m(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,r)=>(typeof r=="string"&&o.push(...r.split(",")),o),[]);for(let o of e){let r=process.cwd();try{V.default.isAbsolute(o)||(o=V.default.join(r,o)),T.default.existsSync(o)&&T.default.statSync(o).isDirectory()?(l("\u5207\u6362\u5230\u5DE5\u4F5C\u76EE\u5F55:{}",o),process.chdir(o),yield t.apply(this,Array.from(arguments))):l("\u65E0\u6548\u7684\u5DE5\u4F5C\u76EE\u5F55:{}",o)}finally{process.chdir(r)}}})}}getOption(t){return this.options.find(i=>i.name()==t)}before(t,i=!0){return this._beforeHooks.push([t,i]),this}executeBeforeHooks(t){return m(this,null,function*(){let i=this.beforeHooks.map(([e,o])=>[e,o,this]);this.getAncestorCommands().forEach(e=>{i.unshift(...e.beforeHooks.map(([o,r])=>[o,r,e]))});for(let[e,o,r]of i)o&&(yield e.call(r,t))})}after(t,i=!0){return this._afterHooks.push([t,i]),this}executeAfterHooks(t){return m(this,null,function*(){let i=this.afterHooks.map(([e,o])=>[e,o,this]);this.getAncestorCommands().forEach(e=>{i.push(...e.afterHooks.map(([o,r])=>[o,r,e]))});for(let[e,o,r]of i)o&&(yield e.call(r,t))})}preActionHook(t){return m(this,null,function*(){if(this.isEnablePrompts()){let i=[...this.generateAutoPrompts(),...this._customPrompts];if(i.length>0){let e=yield(0,R.default)(i);Object.entries(e).forEach(([o,r])=>{t.setOptionValue(o,r)})}}})}isEnablePrompts(){return _()?!1:this._enable_prompts}generateAutoPrompts(){let i=this.options.filter(e=>!e.hidden&&e.__MIX_OPTION__).map(e=>{let o=this._enable_prompts;return e.getPrompt(this._optionValues[e.attributeName()],o)}).filter(e=>e);return l("\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),r=o.attributeName();return r in this._optionValues&&o.default(this._optionValues[r]),o.required&&!this.isEnablePrompts()&&(o.mandatory=!0),this.addOption(o)}initial(t){return Object.assign(this._optionValues,t),this}prompt(t){return this._customPrompts.push(...Array.isArray(t)?t:[t]),this}selectCommands(){return m(this,null,function*(){let t=this.commands.map(o=>({title:`${o.description()}(${o.name()})`,value:o.name()})),i=yield(0,R.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 J=require("flex-tools/package/getPackageJson"),Q=require("flex-tools/package/getPackageRootPath"),Y=require("glob");var v=d(require("fs")),u=d(require("path"));function z(s){let n=this.options.include;if(!(n instanceof RegExp))return[];let{dependencies:t={},devDependencies:i={},peerDependencies:e={},optionalDependencies:o={},bundleDependencies:r={}}=(0,J.getPackageJson)(s);return[...Object.keys(t),...Object.keys(i),...Object.keys(e),...Object.keys(o),...Object.keys(r)].filter(p=>p!=="@voerka/cli"&&n.test(p))}function G(s,n){return(n?Array.isArray(n)?n:[n]:[]).some(i=>typeof i=="string"?new RegExp(i).test(s):i instanceof RegExp?i.test(s):!1)}function Z(s,n){let t=this.options.include,i=this.options.exclude;if(!t)return[];let e=(0,Q.getPackageRootPath)(n||process.cwd()),o=s?u.default.dirname(require.resolve(s,{paths:[e]})):e;if(!o)return l("MixCli\u53EA\u80FD\u8FD0\u884C\u5728Nodejs\u73AF\u5883"),[];let r=z.call(this,o),a=[];return n!==void 0&&a.push(u.default.join(o,this.options.cliDir)),r.filter(p=>G(p,t)&&!G(p,i)).forEach(p=>{l("\u5339\u914D\u5305:{}",`${s?p+" <- "+s:p}`);try{let c=u.default.dirname(require.resolve(p,{paths:o?[o]:[process.cwd()]})),h=u.default.join(c,this.options.cliDir),A=z.call(this,c);a.push(...A.reduce((y,g)=>(l("\u5339\u914D\u5305:{}",`${g} <- ${p}`),y.push(...Z.call(this,g,c)),y),[])),v.default.existsSync(h)&&a.push(h)}catch(c){l("\u89E3\u6790\u5305<{}>\u8DEF\u5F84\u51FA\u9519\uFF1A{}",[p,c.stack])}}),[...new Set(a)]}function tt(s){return m(this,null,function*(){let n=Z.call(s),t=[],i=[];n.forEach(e=>{(0,Y.globSync)("*",{cwd:e,absolute:!0}).forEach(o=>{if(u.default.basename(o).startsWith("_"))return;let a=u.default.extname(o).toLowerCase();[".js",".cjs",".mjs"].includes(a)?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(l("\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){l(o)}return t})}var ot=require("flex-tools/async/asyncSignal"),nt=d(require("string.prototype.replaceall"));nt.default.shim();var S=class extends et.LiteEvent{constructor(t){super();this.findSignals=[];this.options=(0,it.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 m(this,null,function*(){let t=yield tt(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){l("\u6CE8\u518C\u547D\u4EE4\u5931\u8D25:{}",e.stack)}})}createRootCommand(){this.root=new O(this.name),this.root.helpOption("-h, --help").action(()=>{this.options.logo&&f.default.log(b(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()}),P(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=b(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!`):(l("\u6CE8\u518C\u547D\u4EE4:{}",o.fullname),this.root.addCommand(o),P(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 r=i.shift(),a=e.commands.find(p=>p.name()==r);a&&i.length==0&&(o=a),e=a}return o}find(t){let i=this.get(t);if(i)return Promise.resolve(i);{let e=(0,ot.asyncSignal)();return this.findSignals.push(e),new Promise(o=>{let r;r=this.on("register",a=>{a==`${this.name}.${t}`&&(r.off(),e.resolve(),this.findSignals=this.findSignals.filter(p=>p!=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,isBuildInOption,isDebug,isDisablePrompts,isUndefined,outputDebug,outputStr,promptTypeMap,showError,supportedPromptTypes});
|
3
|
+
`)}function P(s){let n={hidden:!0,optional:!0,prompt:!1};s.option("--work-dirs [values...]","\u6307\u5B9A\u5DE5\u4F5C\u76EE\u5F55",Object.assign({},n)),s.option("--disable-prompts","\u7981\u7528\u6240\u6709\u4EA4\u4E92\u63D0\u793A",Object.assign({},n)),s.option("--debug-cli","\u663E\u793A\u8C03\u8BD5\u4FE1\u606F",Object.assign({},n))}function ft(s){return s.flags.startsWith("--work-dirs")||s.flags.startsWith("--disable-prompts")||s.flags.startsWith("--debug-cli")}function _(){return process.argv.includes("--debug-cli")}function w(){return process.argv.includes("--disable-prompts")}function l(s,...n){let t=n.length==1&&typeof n[0]=="function"?n[0]():n;_()&&k.default.log(`[MixCli] ${s}`,...t)}function dt(s){_()?l("\u5BFC\u5165\u547D\u4EE4<>\u51FA\u9519:{}",s.stack):console.error(s)}function ht(s){return s.replace(/-([a-z])/g,(n,t)=>t.toUpperCase())}function gt(){return Math.random().toString(36).substr(2)}function j(s){return m(this,null,function*(){let n;try{n=require(s)}catch(t){throw n=(yield import(`file://${s}`)).default,t}return n})}function D(s){return s==null}var H={boolean:"confirm",string:"text",number:"number",array:"list",date:"date"},F=["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 F.includes(String(n))}isNeedPrompt(n,t,i){if(i===!1)return!1;if(i===!0)return!0;let e=this.params,o=n||t,r=o!==void 0;return e===!0?!0:e===!1?!1:e==="auto"||(0,E.isPlainObject)(e)?!r:typeof e=="string"&&this.isValidPromptType(e)?!0:/(\<s*\w\s*\>)/.test(this.cliOption.flags)?!r:this.cliOption.argChoices&&this.cliOption.argChoices.indexOf(o)==-1?!0:!r}_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",r=this.params;if(this.isValidPromptType(r))o=r;else if((0,E.isPlainObject)(r))o=r.type;else{let a=/(\[\s*\w+\.\.\.\s*])|(\<\s*\w+\.\.\.\s*>)/.test(this.cliOption.flags),p=/(\<s*\w+\s*\>)|(\[\w+\])/.test(this.cliOption.flags),c=!/(\[\s*\w+s*])|(\<\s*\w+\s*>)/.test(this.cliOption.flags),h=(0,q.isNumber)(i),A=i&&i instanceof Date,y=Array.isArray(e)?"array":e instanceof Date?"date":typeof e,g=this.cliOption.params;if(g&&g.choices){let I=g.choices;c&&Array.isArray(I)&&I.length==2?o="toggle":o=t?"multiselect":"select"}else a?o="list":A?o="date":h?o="number":p?o="text":c||typeof i=="boolean"?o="confirm":y in H&&(o=H[y])}return l("\u9009\u9879<{}> -> \u63D0\u793A\u7C7B\u578B<{}>",[this.cliOption.name(),o]),o}_validateInputValue(n){if(this.cliOption.argChoices){let t=this.cliOption.argChoices;if(Array.isArray(n))return n.filter(i=>t.indexOf(i)>=0);if(t.indexOf(n)!=-1)return n}else return n}get(n,t){var p;let{description:i,defaultValue:e}=this.cliOption,o=this._validateInputValue(n)||e;if(!this.isNeedPrompt(o,e,t))return;let r=this.infer(n),a=B({type:r,name:this.cliOption.attributeName(),message:i,initial:o},typeof this.params=="object"?this.params:{});if(a.validate=(p=this.cliOption.params)==null?void 0:p.validate,r=="multiselect"&&(a.instructions=!1),a.choices=a.choices||this._getChoices(),["select","multiselect"].includes(r)||r=="toggle"&&Array.isArray(a.choices)&&(a.active||(a.active=a.choices[0].value),a.inactive||(a.inactive=a.choices[1].value)),o&&typeof a.initial!="function"&&a.choices&&Array.isArray(a.choices))if(r=="select"){let c=Array.isArray(a.choices)?a.choices.findIndex(h=>h.value==o):-1;c!=-1&&(a.initial=c)}else r=="multiselect"&&a.choices.forEach(c=>{(Array.isArray(o)&&o.includes(c.value)||c.value==o)&&(c.selected=!0)});return a}};var O=class extends U.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){D(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,i){var e;return(e=this.prompt)==null?void 0:e.get(t,i)}};var T=d(require("path")),V=d(require("fs"));var K=Symbol("BREAK_ACTION"),M=class extends X.Command{constructor(t){super(t);this.__MIX_COMMAND__=!0;this._beforeHooks=[];this._afterHooks=[];this._customPrompts=[];this._optionValues={};this._actions=[];let i=this;this.hook("preAction",function(){return m(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 m(this,arguments,function*(){let i=Array.from(arguments),e,o={},r=[],a;i.length>=2&&(a=i[i.length-1],o=i[i.length-2],r=i.slice(0,i.length-2)),yield t.executeBeforeHooks({args:r,options:o,command:a});try{for(let p of t._actions)try{if(p.enhance?(l("\u6267\u884C<{}>: args={}, options={}",()=>[t.name(),r,o]),e=yield p.fn.call(this,{command:a,value:e,args:r,options:o})):e=yield p.fn.apply(this,i),e===K)break}catch(c){throw l("\u547D\u4EE4{}\u7684Action({})\u6267\u884C\u51FA\u9519:{}",[t.name,p.id,c]),c}}finally{yield t.executeAfterHooks({value:e,args:r,options:o,command:a})}})}}wrapperWorkDirsAction(t){let i=this;return function(){return m(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,r)=>(typeof r=="string"&&o.push(...r.split(",")),o),[]);for(let o of e){let r=process.cwd();try{T.default.isAbsolute(o)||(o=T.default.join(r,o)),V.default.existsSync(o)&&V.default.statSync(o).isDirectory()?(l("\u5207\u6362\u5230\u5DE5\u4F5C\u76EE\u5F55:{}",o),process.chdir(o),yield t.apply(this,Array.from(arguments))):l("\u65E0\u6548\u7684\u5DE5\u4F5C\u76EE\u5F55:{}",o)}finally{process.chdir(r)}}})}}getOption(t){return this.options.find(i=>i.name()==t)}before(t,i=!0){return this._beforeHooks.push([t,i]),this}executeBeforeHooks(t){return m(this,null,function*(){let i=this.beforeHooks.map(([e,o])=>[e,o,this]);this.getAncestorCommands().forEach(e=>{i.unshift(...e.beforeHooks.map(([o,r])=>[o,r,e]))});for(let[e,o,r]of i)o&&(yield e.call(r,t))})}after(t,i=!0){return this._afterHooks.push([t,i]),this}executeAfterHooks(t){return m(this,null,function*(){let i=this.afterHooks.map(([e,o])=>[e,o,this]);this.getAncestorCommands().forEach(e=>{i.push(...e.afterHooks.map(([o,r])=>[o,r,e]))});for(let[e,o,r]of i)o&&(yield e.call(r,t))})}preActionHook(t){return m(this,null,function*(){if(this.isEnablePrompts()){let i=[...this.generateAutoPrompts(),...this._customPrompts];if(i.length>0){let e=yield(0,R.default)(i);Object.entries(e).forEach(([o,r])=>{t.setOptionValue(o,r)})}}})}isEnablePrompts(){return w()?!1:this._enable_prompts}generateAutoPrompts(){let i=this.options.filter(e=>!e.hidden&&e.__MIX_OPTION__).map(e=>{let o=this._enable_prompts;return e.getPrompt(this._optionValues[e.attributeName()],o)}).filter(e=>e);return l("\u547D\u4EE4<{}>\u81EA\u52A8\u751F\u6210{}\u4E2A\u9009\u9879\u63D0\u793A:{}",[this.name(),i.length,i.map(e=>`${e.name}(${e.type})`).join(",")]),i}option(t,i,e){let o=new O(t,i,e),r=o.attributeName();if(r in this._optionValues){let a=this._optionValues[r];o.argChoices?o.argChoices.includes(a)&&o.default(a):a!=null&&o.default(a)}return o.required&&(o.mandatory=!1),this.addOption(o)}initial(t){return Object.assign(this._optionValues,t),this}prompt(t){return this._customPrompts.push(...Array.isArray(t)?t:[t]),this}selectCommands(){return m(this,null,function*(){let t=this.commands.map(o=>({title:`${o.description()}(${o.name()})`,value:o.name()})),i=yield(0,R.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 J=require("flex-tools/package/getPackageJson"),Q=require("flex-tools/package/getPackageRootPath"),Y=require("glob");var v=d(require("fs")),u=d(require("path"));function z(s){let n=this.options.include;if(!(n instanceof RegExp))return[];let{dependencies:t={},devDependencies:i={},peerDependencies:e={},optionalDependencies:o={},bundleDependencies:r={}}=(0,J.getPackageJson)(s);return[...Object.keys(t),...Object.keys(i),...Object.keys(e),...Object.keys(o),...Object.keys(r)].filter(p=>p!=="@voerka/cli"&&n.test(p))}function G(s,n){return(n?Array.isArray(n)?n:[n]:[]).some(i=>typeof i=="string"?new RegExp(i).test(s):i instanceof RegExp?i.test(s):!1)}function Z(s,n){let t=this.options.include,i=this.options.exclude;if(!t)return[];let e=(0,Q.getPackageRootPath)(n||process.cwd()),o=s?u.default.dirname(require.resolve(s,{paths:[e]})):e;if(!o)return l("MixCli\u53EA\u80FD\u8FD0\u884C\u5728Nodejs\u73AF\u5883"),[];let r=z.call(this,o),a=[];return n!==void 0&&a.push(u.default.join(o,this.options.cliDir)),r.filter(p=>G(p,t)&&!G(p,i)).forEach(p=>{l("\u5339\u914D\u5305:{}",`${s?p+" <- "+s:p}`);try{let c=u.default.dirname(require.resolve(p,{paths:o?[o]:[process.cwd()]})),h=u.default.join(c,this.options.cliDir),A=z.call(this,c);a.push(...A.reduce((y,g)=>(l("\u5339\u914D\u5305:{}",`${g} <- ${p}`),y.push(...Z.call(this,g,c)),y),[])),v.default.existsSync(h)&&a.push(h)}catch(c){l("\u89E3\u6790\u5305<{}>\u8DEF\u5F84\u51FA\u9519\uFF1A{}",[p,c.stack])}}),[...new Set(a)]}function tt(s){return m(this,null,function*(){let n=Z.call(s),t=[],i=[];n.forEach(e=>{(0,Y.globSync)("*",{cwd:e,absolute:!0}).forEach(o=>{if(u.default.basename(o).startsWith("_"))return;let a=u.default.extname(o).toLowerCase();[".js",".cjs",".mjs"].includes(a)?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(l("\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){l(o)}return t})}var ot=require("flex-tools/async/asyncSignal"),nt=d(require("string.prototype.replaceall"));nt.default.shim();var S=class extends et.LiteEvent{constructor(t){super();this.findSignals=[];this.options=(0,it.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 m(this,null,function*(){let t=yield tt(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){l("\u6CE8\u518C\u547D\u4EE4\u5931\u8D25:{}",e.stack)}})}createRootCommand(){this.root=new M(this.name),this.root.helpOption("-h, --help").action(()=>{this.options.logo&&f.default.log(b(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()}),P(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=b(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!`):(l("\u6CE8\u518C\u547D\u4EE4:{}",o.fullname),this.root.addCommand(o),P(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 r=i.shift(),a=e.commands.find(p=>p.name()==r);a&&i.length==0&&(o=a),e=a}return o}find(t){let i=this.get(t);if(i)return Promise.resolve(i);{let e=(0,ot.asyncSignal)();return this.findSignals.push(e),new Promise(o=>{let r;r=this.on("register",a=>{a==`${this.name}.${t}`&&(r.off(),e.resolve(),this.findSignals=this.findSignals.filter(p=>p!=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,isBuildInOption,isDebug,isDisablePrompts,isUndefined,outputDebug,outputStr,promptTypeMap,showError,supportedPromptTypes});
|
4
4
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/cli.ts","../src/command.ts","../src/option.ts","../src/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\n this.root.addCommand(cmd as Command) ;\n \n addBuiltInOptions(cmd as any);\n\n (cmd as any)._cli = this\n \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 | undefined \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\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;\t\t// 命令行参数禁用了提示,优先级最高\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) => {\n\t\t\t\tconst isEnablePrompt = this._enable_prompts;\n\t\t\t\treturn option.getPrompt(this._optionValues[option.attributeName()],isEnablePrompt)\n\t\t\t})\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\t\n\t\tconst optionName = option.attributeName()\n\t\tif(optionName in this._optionValues){\n\t\t\toption.default(this._optionValues[optionName]);\n\t\t}\n\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\tinitial(values:Record<string,any>){\n\t\tObject.assign(this._optionValues,values)\n\t\treturn this\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 ","import { Option, OptionValues } from 'commander'\nimport { PromptObject } from 'prompts'\nimport { PromptChoice, MixOptionPrompt,PromptParams } from './prompt'\nimport { isUndefined } from './utils'\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(!isUndefined(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,enable?:boolean): PromptObject | undefined {\n return this.prompt?.get(inputValue,enable)\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,enable?:boolean){\n \n if(enable === false) return false\n if(enable === true) return true\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\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,enable?:boolean){\n\n const { description, defaultValue } = this.cliOption\n \n let input = inputValue || defaultValue\n\n // 1. 判断是否需要启用提示\n if(!this.isNeedPrompt(input,defaultValue,enable)) 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 const opts = {hidden:true,optional:true,prompt:false}\n command.option(\"--work-dirs [values...]\",\"指定工作目录\",Object.assign({},opts))\n command.option(\"--disable-prompts\",\"禁用所有交互提示\",Object.assign({},opts)) \n command.option(\"--debug-cli\",\"显示调试信息\",Object.assign({},opts))\n}\n\nexport function isBuildInOption(option:any){\n return option.flags.startsWith(\"--work-dirs\") || option.flags.startsWith(\"--disable-prompts\") || option.flags.startsWith(\"--debug-cli\")\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\n\nexport function isUndefined(value:any){\n return value==undefined\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","isBuildInOption","isDebug","isDisablePrompts","isUndefined","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","opts","isBuildInOption","option","isDebug","isDisablePrompts","outputDebug","message","args","showError","e","hyphenToCamelCase","_","letter","getId","importModule","file","__async","module","isUndefined","value","promptTypeMap","supportedPromptTypes","MixOptionPrompt","cliOption","promptParams","type","input","defaultValue","enable","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","isUndefined","choice","inputValue","enable","_a","import_node_path","import_node_fs","BREAK","MixCommand","name","self","__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","isEnablePrompt","prompt","flags","description","options","MixOption","optionName","values","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"]}
|
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\n this.root.addCommand(cmd as Command) ;\n \n addBuiltInOptions(cmd as any);\n\n (cmd as any)._cli = this\n \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 { 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 | undefined \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\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;\t\t// 命令行参数禁用了提示,优先级最高\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) => {\n\t\t\t\tconst isEnablePrompt = this._enable_prompts;\n\t\t\t\treturn option.getPrompt(this._optionValues[option.attributeName()],isEnablePrompt)\n\t\t\t})\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\t\n\t\tconst optionName = option.attributeName()\n\t\tif(optionName in this._optionValues){\n\t\t\tconst val = this._optionValues[optionName]\n\t\t\tif(option.argChoices){\n\t\t\t\tif(option.argChoices.includes(val)){\n\t\t\t\t\toption.default(val)\n\t\t\t\t}\n\t\t\t}else if(val!=undefined){\n\t\t\t\toption.default(val)\n\t\t\t}\n\t\t}\n\n\t\tif (option.required) option.mandatory = false;\n\t\treturn this.addOption(option as unknown as Option) \n\t}\n\n\tinitial(values:Record<string,any>){\n\t\tObject.assign(this._optionValues,values)\n\t\treturn this\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 ","import { Option, OptionValues } from 'commander'\nimport { PromptObject } from 'prompts'\nimport { PromptChoice, MixOptionPrompt,PromptParams } from './prompt'\nimport { isUndefined } from './utils'\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(!isUndefined(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,enable?:boolean): PromptObject | undefined {\n return this.prompt?.get(inputValue,enable)\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,enable?:boolean){\n \n if(enable === false) return false\n if(enable === true) return true\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\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 private _validateInputValue(inputValue:any){\n if(this.cliOption.argChoices){\n const argChoices = this.cliOption.argChoices\n if(Array.isArray(inputValue)){\n return inputValue.filter((item:any)=>{\n return argChoices.indexOf(item) >= 0\n })\n }else{\n if(argChoices.indexOf(inputValue) != -1) return inputValue\n }\n }else{\n return inputValue\n }\n }\n\n /**\n * 返回生成prompt对象\n * \n * @param inputValue 从命令行输入的值\n */\n get(inputValue?:any,enable?:boolean){\n\n const { description, defaultValue } = this.cliOption\n \n let input = this._validateInputValue(inputValue) || defaultValue\n\n // 1. 判断是否需要启用提示\n if(!this.isNeedPrompt(input,defaultValue,enable)) 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 const opts = {hidden:true,optional:true,prompt:false}\n command.option(\"--work-dirs [values...]\",\"指定工作目录\",Object.assign({},opts))\n command.option(\"--disable-prompts\",\"禁用所有交互提示\",Object.assign({},opts)) \n command.option(\"--debug-cli\",\"显示调试信息\",Object.assign({},opts))\n}\n\nexport function isBuildInOption(option:any){\n return option.flags.startsWith(\"--work-dirs\") || option.flags.startsWith(\"--disable-prompts\") || option.flags.startsWith(\"--debug-cli\")\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\n\nexport function isUndefined(value:any){\n return value==undefined\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","isBuildInOption","isDebug","isDisablePrompts","isUndefined","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","opts","isBuildInOption","option","isDebug","isDisablePrompts","outputDebug","message","args","showError","e","hyphenToCamelCase","_","letter","getId","importModule","file","__async","module","isUndefined","value","promptTypeMap","supportedPromptTypes","MixOptionPrompt","cliOption","promptParams","type","input","defaultValue","enable","params","inputValue","hasInput","_a","choices","choicesParam","choice","variadic","promptType","isListType","isTextType","isBooleanType","isNumberType","isDate","datatype","optionParams","outputDebug","argChoices","item","description","prompt","__spreadValues","index","MixOption","flags","description","params","MixOptionPrompt","isUndefined","choice","inputValue","enable","_a","import_node_path","import_node_fs","BREAK","MixCommand","name","self","__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","isEnablePrompt","prompt","flags","description","options","MixOption","optionName","val","values","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
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
var F=Object.defineProperty;var k=Object.getOwnPropertySymbols;var U=Object.prototype.hasOwnProperty,X=Object.prototype.propertyIsEnumerable;var
|
1
|
+
var F=Object.defineProperty;var k=Object.getOwnPropertySymbols;var U=Object.prototype.hasOwnProperty,X=Object.prototype.propertyIsEnumerable;var _=(s,n,t)=>n in s?F(s,n,{enumerable:!0,configurable:!0,writable:!0,value:t}):s[n]=t,w=(s,n)=>{for(var t in n||(n={}))U.call(n,t)&&_(s,t,n[t]);if(k)for(var t of k(n))X.call(n,t)&&_(s,t,n[t]);return s};var y=(s=>typeof require!="undefined"?require:typeof Proxy!="undefined"?new Proxy(s,{get:(n,t)=>(typeof require!="undefined"?require:n)[t]}):s)(function(s){if(typeof require!="undefined")return require.apply(this,arguments);throw Error('Dynamic require of "'+s+'" is not supported')});var m=(s,n,t)=>new Promise((i,e)=>{var o=p=>{try{a(t.next(p))}catch(c){e(c)}},r=p=>{try{a(t.throw(p))}catch(c){e(c)}},a=p=>p.done?i(p.value):Promise.resolve(p.value).then(o,r);a((t=t.apply(s,n)).next())});import"flex-tools/string";import{LiteEvent as et}from"flex-tools/events/liteEvent";import f from"logsets";import{assignObject as it}from"flex-tools/object/assignObject";import{Command as J}from"commander";import S from"prompts";import{Option as G}from"commander";import{isPlainObject as T}from"flex-tools/typecheck/isPlainObject";import{isNumber as K}from"flex-tools/typecheck/isNumber";import j from"logsets";function at(s,n){j.log(x(s),n)}function x(s,n){if((n==null||n===!0?0:typeof n=="number"?n:-1)==-1)return s;let i=s.split(`
|
2
2
|
`),e=i.reduce((o,r,a)=>{var c;if(a==0)return o;let p=((c=r.match(/^\s*/))==null?void 0:c[0].length)||0;return Math.min(o,p)},9999);return i=i.map(o=>o.substring(e)),i.join(`
|
3
|
-
`)}function P(s){let n={hidden:!0,optional:!0,prompt:!1};s.option("--work-dirs [values...]","\u6307\u5B9A\u5DE5\u4F5C\u76EE\u5F55",Object.assign({},n)),s.option("--disable-prompts","\u7981\u7528\u6240\u6709\u4EA4\u4E92\u63D0\u793A",Object.assign({},n)),s.option("--debug-cli","\u663E\u793A\u8C03\u8BD5\u4FE1\u606F",Object.assign({},n))}function pt(s){return s.flags.startsWith("--work-dirs")||s.flags.startsWith("--disable-prompts")||s.flags.startsWith("--debug-cli")}function D(){return process.argv.includes("--debug-cli")}function E(){return process.argv.includes("--disable-prompts")}function l(s,...n){let t=n.length==1&&typeof n[0]=="function"?n[0]():n;D()&&j.log(`[MixCli] ${s}`,...t)}function ct(s){D()?l("\u5BFC\u5165\u547D\u4EE4<>\u51FA\u9519:{}",s.stack):console.error(s)}function lt(s){return s.replace(/-([a-z])/g,(n,t)=>t.toUpperCase())}function mt(){return Math.random().toString(36).substr(2)}function H(s){return m(this,null,function*(){let n;try{n=y(s)}catch(t){throw n=(yield import(`file://${s}`)).default,t}return n})}function R(s){return s==null}var T={boolean:"confirm",string:"text",number:"number",array:"list",date:"date"},z=["text","password","invisible","number","confirm","list","toggle","select","multiselect","autocomplete","date","autocompleteMultiselect"],b=class{constructor(n,t){this.cliOption=n;this.params=t}isValidPromptType(n){return z.includes(String(n))}isNeedPrompt(n,t,i){if(i===!1)return!1;if(i===!0)return!0;let e=this.params,o=n||t,r=o!==void 0;return e===!0?!0:e===!1?!1:e==="auto"||V(e)?!r:typeof e=="string"&&this.isValidPromptType(e)?!0:/(\<s*\w\s*\>)/.test(this.cliOption.flags)?!r:this.cliOption.argChoices&&this.cliOption.argChoices.indexOf(o)==-1?!0:!r}_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",r=this.params;if(this.isValidPromptType(r))o=r;else if(V(r))o=r.type;else{let a=/(\[\s*\w+\.\.\.\s*])|(\<\s*\w+\.\.\.\s*>)/.test(this.cliOption.flags),p=/(\<s*\w+\s*\>)|(\[\w+\])/.test(this.cliOption.flags),c=!/(\[\s*\w+s*])|(\<\s*\w+\s*>)/.test(this.cliOption.flags),d=K(i),O=i&&i instanceof Date,g=Array.isArray(e)?"array":e instanceof Date?"date":typeof e,h=this.cliOption.params;if(h&&h.choices){let A=h.choices;c&&Array.isArray(A)&&A.length==2?o="toggle":o=t?"multiselect":"select"}else a?o="list":O?o="date":d?o="number":p?o="text":c||typeof i=="boolean"?o="confirm":g in T&&(o=T[g])}return l("\u9009\u9879<{}> -> \u63D0\u793A\u7C7B\u578B<{}>",[this.cliOption.name(),o]),o}get(n,t){var p;let{description:i,defaultValue:e}=this.cliOption,o=n||e;if(!this.isNeedPrompt(o,e,t))return;let r=this.infer(n),a=_({type:r,name:this.cliOption.attributeName(),message:i,initial:o},typeof this.params=="object"?this.params:{});if(a.validate=(p=this.cliOption.params)==null?void 0:p.validate,r=="multiselect"&&(a.instructions=!1),a.choices=a.choices||this._getChoices(),["select","multiselect"].includes(r)||r=="toggle"&&Array.isArray(a.choices)&&(a.active||(a.active=a.choices[0].value),a.inactive||(a.inactive=a.choices[1].value)),o&&typeof a.initial!="function"&&a.choices&&Array.isArray(a.choices))if(r=="select"){let c=Array.isArray(a.choices)?a.choices.findIndex(d=>d.value==o):-1;c!=-1&&(a.initial=c)}else r=="multiselect"&&a.choices.forEach(c=>{(Array.isArray(o)&&o.includes(c.value)||c.value==o)&&(c.selected=!0)});return a}};var C=class extends G{constructor(t,i,e){super(t,i);this.params=e;this.__MIX_OPTION__=!0;this._setOption(e||{}),this.prompt=new b(this,e==null?void 0:e.prompt)}_setOption(t){R(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,i){var e;return(e=this.prompt)==null?void 0:e.get(t,i)}};import I from"node:path";import N from"node:fs";var Q=Symbol("BREAK_ACTION"),M=class extends J{constructor(t){super(t);this.__MIX_COMMAND__=!0;this._beforeHooks=[];this._afterHooks=[];this._customPrompts=[];this._optionValues={};this._actions=[];let i=this;this.hook("preAction",function(){return m(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 m(this,arguments,function*(){let i=Array.from(arguments),e,o={},r=[],a;i.length>=2&&(a=i[i.length-1],o=i[i.length-2],r=i.slice(0,i.length-2)),yield t.executeBeforeHooks({args:r,options:o,command:a});try{for(let p of t._actions)try{if(p.enhance?(l("\u6267\u884C<{}>: args={}, options={}",()=>[t.name(),r,o]),e=yield p.fn.call(this,{command:a,value:e,args:r,options:o})):e=yield p.fn.apply(this,i),e===Q)break}catch(c){throw l("\u547D\u4EE4{}\u7684Action({})\u6267\u884C\u51FA\u9519:{}",[t.name,p.id,c]),c}}finally{yield t.executeAfterHooks({value:e,args:r,options:o,command:a})}})}}wrapperWorkDirsAction(t){let i=this;return function(){return m(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,r)=>(typeof r=="string"&&o.push(...r.split(",")),o),[]);for(let o of e){let r=process.cwd();try{I.isAbsolute(o)||(o=I.join(r,o)),N.existsSync(o)&&N.statSync(o).isDirectory()?(l("\u5207\u6362\u5230\u5DE5\u4F5C\u76EE\u5F55:{}",o),process.chdir(o),yield t.apply(this,Array.from(arguments))):l("\u65E0\u6548\u7684\u5DE5\u4F5C\u76EE\u5F55:{}",o)}finally{process.chdir(r)}}})}}getOption(t){return this.options.find(i=>i.name()==t)}before(t,i=!0){return this._beforeHooks.push([t,i]),this}executeBeforeHooks(t){return m(this,null,function*(){let i=this.beforeHooks.map(([e,o])=>[e,o,this]);this.getAncestorCommands().forEach(e=>{i.unshift(...e.beforeHooks.map(([o,r])=>[o,r,e]))});for(let[e,o,r]of i)o&&(yield e.call(r,t))})}after(t,i=!0){return this._afterHooks.push([t,i]),this}executeAfterHooks(t){return m(this,null,function*(){let i=this.afterHooks.map(([e,o])=>[e,o,this]);this.getAncestorCommands().forEach(e=>{i.push(...e.afterHooks.map(([o,r])=>[o,r,e]))});for(let[e,o,r]of i)o&&(yield e.call(r,t))})}preActionHook(t){return m(this,null,function*(){if(this.isEnablePrompts()){let i=[...this.generateAutoPrompts(),...this._customPrompts];if(i.length>0){let e=yield S(i);Object.entries(e).forEach(([o,r])=>{t.setOptionValue(o,r)})}}})}isEnablePrompts(){return E()?!1:this._enable_prompts}generateAutoPrompts(){let i=this.options.filter(e=>!e.hidden&&e.__MIX_OPTION__).map(e=>{let o=this._enable_prompts;return e.getPrompt(this._optionValues[e.attributeName()],o)}).filter(e=>e);return l("\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 C(t,i,e),r=o.attributeName();return r in this._optionValues&&o.default(this._optionValues[r]),o.required&&!this.isEnablePrompts()&&(o.mandatory=!0),this.addOption(o)}initial(t){return Object.assign(this._optionValues,t),this}prompt(t){return this._customPrompts.push(...Array.isArray(t)?t:[t]),this}selectCommands(){return m(this,null,function*(){let t=this.commands.map(o=>({title:`${o.description()}(${o.name()})`,value:o.name()})),i=yield S({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}};import{getPackageJson as Y}from"flex-tools/package/getPackageJson";import{getPackageRootPath as Z}from"flex-tools/package/getPackageRootPath";import{globSync as tt}from"glob";import v from"node:fs";import u from"node:path";function L(s){let n=this.options.include;if(!(n instanceof RegExp))return[];let{dependencies:t={},devDependencies:i={},peerDependencies:e={},optionalDependencies:o={},bundleDependencies:r={}}=Y(s);return[...Object.keys(t),...Object.keys(i),...Object.keys(e),...Object.keys(o),...Object.keys(r)].filter(p=>p!=="@voerka/cli"&&n.test(p))}function B(s,n){return(n?Array.isArray(n)?n:[n]:[]).some(i=>typeof i=="string"?new RegExp(i).test(s):i instanceof RegExp?i.test(s):!1)}function $(s,n){let t=this.options.include,i=this.options.exclude;if(!t)return[];let e=Z(n||process.cwd()),o=s?u.dirname(y.resolve(s,{paths:[e]})):e;if(!o)return l("MixCli\u53EA\u80FD\u8FD0\u884C\u5728Nodejs\u73AF\u5883"),[];let r=L.call(this,o),a=[];return n!==void 0&&a.push(u.join(o,this.options.cliDir)),r.filter(p=>B(p,t)&&!B(p,i)).forEach(p=>{l("\u5339\u914D\u5305:{}",`${s?p+" <- "+s:p}`);try{let c=u.dirname(y.resolve(p,{paths:o?[o]:[process.cwd()]})),d=u.join(c,this.options.cliDir),O=L.call(this,c);a.push(...O.reduce((g,h)=>(l("\u5339\u914D\u5305:{}",`${h} <- ${p}`),g.push(...$.call(this,h,c)),g),[])),v.existsSync(d)&&a.push(d)}catch(c){l("\u89E3\u6790\u5305<{}>\u8DEF\u5F84\u51FA\u9519\uFF1A{}",[p,c.stack])}}),[...new Set(a)]}function W(s){return m(this,null,function*(){let n=$.call(s),t=[],i=[];n.forEach(e=>{tt("*",{cwd:e,absolute:!0}).forEach(o=>{if(u.basename(o).startsWith("_"))return;let a=u.extname(o).toLowerCase();[".js",".cjs",".mjs"].includes(a)?i.push(o):v.statSync(o).isDirectory()&&(i.push(u.join(o,"index.js")),i.push(u.join(o,"index.cjs")),i.push(u.join(o,"index.mjs")))})});for(let e of i)if(v.existsSync(e))try{if(l("\u5BFC\u5165\u547D\u4EE4:{}",e),e.endsWith(".cjs")||e.endsWith(".js"))t.push(yield H(e));else if(e.endsWith(".mjs")){let o=yield import(`file://${e}`);t.push(o.default)}}catch(o){l(o)}return t})}import{asyncSignal as ot}from"flex-tools/async/asyncSignal";import nt from"string.prototype.replaceall";nt.shim();var q=class extends et{constructor(t){super();this.findSignals=[];this.options=it({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 m(this,null,function*(){let t=yield W(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){l("\u6CE8\u518C\u547D\u4EE4\u5931\u8D25:{}",e.stack)}})}createRootCommand(){this.root=new M(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()}),P(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.error(`Command <${o.name()}> has been registered!`):(l("\u6CE8\u518C\u547D\u4EE4:{}",o.fullname),this.root.addCommand(o),P(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(i=>i.name()==t)}get(t){let i=t.split("."),e=this.root,o;for(;i.length>0;){let r=i.shift(),a=e.commands.find(p=>p.name()==r);a&&i.length==0&&(o=a),e=a}return o}find(t){let i=this.get(t);if(i)return Promise.resolve(i);{let e=ot();return this.findSignals.push(e),new Promise(o=>{let r;r=this.on("register",a=>{a==`${this.name}.${t}`&&(r.off(),e.resolve(),this.findSignals=this.findSignals.filter(p=>p!=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)}))}};export{Q as BREAK,q as MixCli,M as MixCommand,C as MixOption,b as MixOptionPrompt,P as addBuiltInOptions,x as fixIndent,mt as getId,lt as hyphenToCamelCase,H as importModule,pt as isBuildInOption,D as isDebug,E as isDisablePrompts,R as isUndefined,l as outputDebug,at as outputStr,T as promptTypeMap,ct as showError,z as supportedPromptTypes};
|
3
|
+
`)}function P(s){let n={hidden:!0,optional:!0,prompt:!1};s.option("--work-dirs [values...]","\u6307\u5B9A\u5DE5\u4F5C\u76EE\u5F55",Object.assign({},n)),s.option("--disable-prompts","\u7981\u7528\u6240\u6709\u4EA4\u4E92\u63D0\u793A",Object.assign({},n)),s.option("--debug-cli","\u663E\u793A\u8C03\u8BD5\u4FE1\u606F",Object.assign({},n))}function pt(s){return s.flags.startsWith("--work-dirs")||s.flags.startsWith("--disable-prompts")||s.flags.startsWith("--debug-cli")}function D(){return process.argv.includes("--debug-cli")}function E(){return process.argv.includes("--disable-prompts")}function l(s,...n){let t=n.length==1&&typeof n[0]=="function"?n[0]():n;D()&&j.log(`[MixCli] ${s}`,...t)}function ct(s){D()?l("\u5BFC\u5165\u547D\u4EE4<>\u51FA\u9519:{}",s.stack):console.error(s)}function lt(s){return s.replace(/-([a-z])/g,(n,t)=>t.toUpperCase())}function mt(){return Math.random().toString(36).substr(2)}function H(s){return m(this,null,function*(){let n;try{n=y(s)}catch(t){throw n=(yield import(`file://${s}`)).default,t}return n})}function R(s){return s==null}var V={boolean:"confirm",string:"text",number:"number",array:"list",date:"date"},z=["text","password","invisible","number","confirm","list","toggle","select","multiselect","autocomplete","date","autocompleteMultiselect"],b=class{constructor(n,t){this.cliOption=n;this.params=t}isValidPromptType(n){return z.includes(String(n))}isNeedPrompt(n,t,i){if(i===!1)return!1;if(i===!0)return!0;let e=this.params,o=n||t,r=o!==void 0;return e===!0?!0:e===!1?!1:e==="auto"||T(e)?!r:typeof e=="string"&&this.isValidPromptType(e)?!0:/(\<s*\w\s*\>)/.test(this.cliOption.flags)?!r:this.cliOption.argChoices&&this.cliOption.argChoices.indexOf(o)==-1?!0:!r}_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",r=this.params;if(this.isValidPromptType(r))o=r;else if(T(r))o=r.type;else{let a=/(\[\s*\w+\.\.\.\s*])|(\<\s*\w+\.\.\.\s*>)/.test(this.cliOption.flags),p=/(\<s*\w+\s*\>)|(\[\w+\])/.test(this.cliOption.flags),c=!/(\[\s*\w+s*])|(\<\s*\w+\s*>)/.test(this.cliOption.flags),d=K(i),M=i&&i instanceof Date,g=Array.isArray(e)?"array":e instanceof Date?"date":typeof e,h=this.cliOption.params;if(h&&h.choices){let A=h.choices;c&&Array.isArray(A)&&A.length==2?o="toggle":o=t?"multiselect":"select"}else a?o="list":M?o="date":d?o="number":p?o="text":c||typeof i=="boolean"?o="confirm":g in V&&(o=V[g])}return l("\u9009\u9879<{}> -> \u63D0\u793A\u7C7B\u578B<{}>",[this.cliOption.name(),o]),o}_validateInputValue(n){if(this.cliOption.argChoices){let t=this.cliOption.argChoices;if(Array.isArray(n))return n.filter(i=>t.indexOf(i)>=0);if(t.indexOf(n)!=-1)return n}else return n}get(n,t){var p;let{description:i,defaultValue:e}=this.cliOption,o=this._validateInputValue(n)||e;if(!this.isNeedPrompt(o,e,t))return;let r=this.infer(n),a=w({type:r,name:this.cliOption.attributeName(),message:i,initial:o},typeof this.params=="object"?this.params:{});if(a.validate=(p=this.cliOption.params)==null?void 0:p.validate,r=="multiselect"&&(a.instructions=!1),a.choices=a.choices||this._getChoices(),["select","multiselect"].includes(r)||r=="toggle"&&Array.isArray(a.choices)&&(a.active||(a.active=a.choices[0].value),a.inactive||(a.inactive=a.choices[1].value)),o&&typeof a.initial!="function"&&a.choices&&Array.isArray(a.choices))if(r=="select"){let c=Array.isArray(a.choices)?a.choices.findIndex(d=>d.value==o):-1;c!=-1&&(a.initial=c)}else r=="multiselect"&&a.choices.forEach(c=>{(Array.isArray(o)&&o.includes(c.value)||c.value==o)&&(c.selected=!0)});return a}};var C=class extends G{constructor(t,i,e){super(t,i);this.params=e;this.__MIX_OPTION__=!0;this._setOption(e||{}),this.prompt=new b(this,e==null?void 0:e.prompt)}_setOption(t){R(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,i){var e;return(e=this.prompt)==null?void 0:e.get(t,i)}};import I from"node:path";import N from"node:fs";var Q=Symbol("BREAK_ACTION"),O=class extends J{constructor(t){super(t);this.__MIX_COMMAND__=!0;this._beforeHooks=[];this._afterHooks=[];this._customPrompts=[];this._optionValues={};this._actions=[];let i=this;this.hook("preAction",function(){return m(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 m(this,arguments,function*(){let i=Array.from(arguments),e,o={},r=[],a;i.length>=2&&(a=i[i.length-1],o=i[i.length-2],r=i.slice(0,i.length-2)),yield t.executeBeforeHooks({args:r,options:o,command:a});try{for(let p of t._actions)try{if(p.enhance?(l("\u6267\u884C<{}>: args={}, options={}",()=>[t.name(),r,o]),e=yield p.fn.call(this,{command:a,value:e,args:r,options:o})):e=yield p.fn.apply(this,i),e===Q)break}catch(c){throw l("\u547D\u4EE4{}\u7684Action({})\u6267\u884C\u51FA\u9519:{}",[t.name,p.id,c]),c}}finally{yield t.executeAfterHooks({value:e,args:r,options:o,command:a})}})}}wrapperWorkDirsAction(t){let i=this;return function(){return m(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,r)=>(typeof r=="string"&&o.push(...r.split(",")),o),[]);for(let o of e){let r=process.cwd();try{I.isAbsolute(o)||(o=I.join(r,o)),N.existsSync(o)&&N.statSync(o).isDirectory()?(l("\u5207\u6362\u5230\u5DE5\u4F5C\u76EE\u5F55:{}",o),process.chdir(o),yield t.apply(this,Array.from(arguments))):l("\u65E0\u6548\u7684\u5DE5\u4F5C\u76EE\u5F55:{}",o)}finally{process.chdir(r)}}})}}getOption(t){return this.options.find(i=>i.name()==t)}before(t,i=!0){return this._beforeHooks.push([t,i]),this}executeBeforeHooks(t){return m(this,null,function*(){let i=this.beforeHooks.map(([e,o])=>[e,o,this]);this.getAncestorCommands().forEach(e=>{i.unshift(...e.beforeHooks.map(([o,r])=>[o,r,e]))});for(let[e,o,r]of i)o&&(yield e.call(r,t))})}after(t,i=!0){return this._afterHooks.push([t,i]),this}executeAfterHooks(t){return m(this,null,function*(){let i=this.afterHooks.map(([e,o])=>[e,o,this]);this.getAncestorCommands().forEach(e=>{i.push(...e.afterHooks.map(([o,r])=>[o,r,e]))});for(let[e,o,r]of i)o&&(yield e.call(r,t))})}preActionHook(t){return m(this,null,function*(){if(this.isEnablePrompts()){let i=[...this.generateAutoPrompts(),...this._customPrompts];if(i.length>0){let e=yield S(i);Object.entries(e).forEach(([o,r])=>{t.setOptionValue(o,r)})}}})}isEnablePrompts(){return E()?!1:this._enable_prompts}generateAutoPrompts(){let i=this.options.filter(e=>!e.hidden&&e.__MIX_OPTION__).map(e=>{let o=this._enable_prompts;return e.getPrompt(this._optionValues[e.attributeName()],o)}).filter(e=>e);return l("\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 C(t,i,e),r=o.attributeName();if(r in this._optionValues){let a=this._optionValues[r];o.argChoices?o.argChoices.includes(a)&&o.default(a):a!=null&&o.default(a)}return o.required&&(o.mandatory=!1),this.addOption(o)}initial(t){return Object.assign(this._optionValues,t),this}prompt(t){return this._customPrompts.push(...Array.isArray(t)?t:[t]),this}selectCommands(){return m(this,null,function*(){let t=this.commands.map(o=>({title:`${o.description()}(${o.name()})`,value:o.name()})),i=yield S({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}};import{getPackageJson as Y}from"flex-tools/package/getPackageJson";import{getPackageRootPath as Z}from"flex-tools/package/getPackageRootPath";import{globSync as tt}from"glob";import v from"node:fs";import u from"node:path";function L(s){let n=this.options.include;if(!(n instanceof RegExp))return[];let{dependencies:t={},devDependencies:i={},peerDependencies:e={},optionalDependencies:o={},bundleDependencies:r={}}=Y(s);return[...Object.keys(t),...Object.keys(i),...Object.keys(e),...Object.keys(o),...Object.keys(r)].filter(p=>p!=="@voerka/cli"&&n.test(p))}function $(s,n){return(n?Array.isArray(n)?n:[n]:[]).some(i=>typeof i=="string"?new RegExp(i).test(s):i instanceof RegExp?i.test(s):!1)}function B(s,n){let t=this.options.include,i=this.options.exclude;if(!t)return[];let e=Z(n||process.cwd()),o=s?u.dirname(y.resolve(s,{paths:[e]})):e;if(!o)return l("MixCli\u53EA\u80FD\u8FD0\u884C\u5728Nodejs\u73AF\u5883"),[];let r=L.call(this,o),a=[];return n!==void 0&&a.push(u.join(o,this.options.cliDir)),r.filter(p=>$(p,t)&&!$(p,i)).forEach(p=>{l("\u5339\u914D\u5305:{}",`${s?p+" <- "+s:p}`);try{let c=u.dirname(y.resolve(p,{paths:o?[o]:[process.cwd()]})),d=u.join(c,this.options.cliDir),M=L.call(this,c);a.push(...M.reduce((g,h)=>(l("\u5339\u914D\u5305:{}",`${h} <- ${p}`),g.push(...B.call(this,h,c)),g),[])),v.existsSync(d)&&a.push(d)}catch(c){l("\u89E3\u6790\u5305<{}>\u8DEF\u5F84\u51FA\u9519\uFF1A{}",[p,c.stack])}}),[...new Set(a)]}function W(s){return m(this,null,function*(){let n=B.call(s),t=[],i=[];n.forEach(e=>{tt("*",{cwd:e,absolute:!0}).forEach(o=>{if(u.basename(o).startsWith("_"))return;let a=u.extname(o).toLowerCase();[".js",".cjs",".mjs"].includes(a)?i.push(o):v.statSync(o).isDirectory()&&(i.push(u.join(o,"index.js")),i.push(u.join(o,"index.cjs")),i.push(u.join(o,"index.mjs")))})});for(let e of i)if(v.existsSync(e))try{if(l("\u5BFC\u5165\u547D\u4EE4:{}",e),e.endsWith(".cjs")||e.endsWith(".js"))t.push(yield H(e));else if(e.endsWith(".mjs")){let o=yield import(`file://${e}`);t.push(o.default)}}catch(o){l(o)}return t})}import{asyncSignal as ot}from"flex-tools/async/asyncSignal";import nt from"string.prototype.replaceall";nt.shim();var q=class extends et{constructor(t){super();this.findSignals=[];this.options=it({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 m(this,null,function*(){let t=yield W(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){l("\u6CE8\u518C\u547D\u4EE4\u5931\u8D25:{}",e.stack)}})}createRootCommand(){this.root=new O(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()}),P(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.error(`Command <${o.name()}> has been registered!`):(l("\u6CE8\u518C\u547D\u4EE4:{}",o.fullname),this.root.addCommand(o),P(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(i=>i.name()==t)}get(t){let i=t.split("."),e=this.root,o;for(;i.length>0;){let r=i.shift(),a=e.commands.find(p=>p.name()==r);a&&i.length==0&&(o=a),e=a}return o}find(t){let i=this.get(t);if(i)return Promise.resolve(i);{let e=ot();return this.findSignals.push(e),new Promise(o=>{let r;r=this.on("register",a=>{a==`${this.name}.${t}`&&(r.off(),e.resolve(),this.findSignals=this.findSignals.filter(p=>p!=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)}))}};export{Q as BREAK,q as MixCli,O as MixCommand,C as MixOption,b as MixOptionPrompt,P as addBuiltInOptions,x as fixIndent,mt as getId,lt as hyphenToCamelCase,H as importModule,pt as isBuildInOption,D as isDebug,E as isDisablePrompts,R as isUndefined,l as outputDebug,at as outputStr,V as promptTypeMap,ct as showError,z as supportedPromptTypes};
|
4
4
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.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\n this.root.addCommand(cmd as Command) ;\n \n addBuiltInOptions(cmd as any);\n\n (cmd as any)._cli = this\n \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 | undefined \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\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;\t\t// 命令行参数禁用了提示,优先级最高\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) => {\n\t\t\t\tconst isEnablePrompt = this._enable_prompts;\n\t\t\t\treturn option.getPrompt(this._optionValues[option.attributeName()],isEnablePrompt)\n\t\t\t})\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\t\n\t\tconst optionName = option.attributeName()\n\t\tif(optionName in this._optionValues){\n\t\t\toption.default(this._optionValues[optionName]);\n\t\t}\n\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\tinitial(values:Record<string,any>){\n\t\tObject.assign(this._optionValues,values)\n\t\treturn this\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 ","import { Option, OptionValues } from 'commander'\nimport { PromptObject } from 'prompts'\nimport { PromptChoice, MixOptionPrompt,PromptParams } from './prompt'\nimport { isUndefined } from './utils'\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(!isUndefined(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,enable?:boolean): PromptObject | undefined {\n return this.prompt?.get(inputValue,enable)\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,enable?:boolean){\n \n if(enable === false) return false\n if(enable === true) return true\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\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,enable?:boolean){\n\n const { description, defaultValue } = this.cliOption\n \n let input = inputValue || defaultValue\n\n // 1. 判断是否需要启用提示\n if(!this.isNeedPrompt(input,defaultValue,enable)) 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 const opts = {hidden:true,optional:true,prompt:false}\n command.option(\"--work-dirs [values...]\",\"指定工作目录\",Object.assign({},opts))\n command.option(\"--disable-prompts\",\"禁用所有交互提示\",Object.assign({},opts)) \n command.option(\"--debug-cli\",\"显示调试信息\",Object.assign({},opts))\n}\n\nexport function isBuildInOption(option:any){\n return option.flags.startsWith(\"--work-dirs\") || option.flags.startsWith(\"--disable-prompts\") || option.flags.startsWith(\"--debug-cli\")\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\n\nexport function isUndefined(value:any){\n return value==undefined\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":"m0BACA,MAAO,oBACP,OAAS,aAAAA,OAAsC,8BAE/C,OAAOC,MAAc,UAErB,OAAS,gBAAAC,OAAoB,iCCN7B,OAAS,WAAAC,MAAuB,YAChC,OAAOC,MAA+B,UCDtC,OAAS,UAAAC,MAA4B,YCArC,OAAS,iBAAAC,MAAqB,qCAC9B,OAAS,YAAAC,MAAiB,gCCDzB,OAAOC,MAAa,UAwBd,SAASC,GAAUC,EAAWC,EAAiC,CAClEC,EAAQ,IAAIC,EAAUH,CAAG,EAAEC,CAAI,CACnC,CASO,SAASE,EAAUC,EAAYC,EAAgC,CAElE,IADmBA,GAAQ,MAAaA,IAAS,GAAQ,EAAK,OAAOA,GAAS,SAAWA,EAAS,KAClF,GAAI,OAAOD,EAC3B,IAAIE,EAAiBF,EAAK,MAAM;AAAA,CAAI,EAChCG,EAAgBD,EAAM,OAAe,CAACE,EAASC,EAAKC,IAAQ,CAvCpE,IAAAC,EAwCQ,GAAGD,GAAO,EAAG,OAAOF,EACpB,IAAMI,IAAaD,EAAAF,EAAK,MAAM,MAAM,IAAjB,YAAAE,EAAqB,GAAG,SAAU,EACrD,OAAO,KAAK,IAAIH,EAASI,CAAU,CACvC,EAAE,IAAI,EACN,OAAAN,EAAQA,EAAM,IAAIG,GAAMA,EAAK,UAAUF,CAAa,CAAC,EAC9CD,EAAM,KAAK;AAAA,CAAI,CAC1B,CAMO,SAASO,EAAkBC,EAAY,CAC1C,IAAMC,EAAO,CAAC,OAAO,GAAK,SAAS,GAAK,OAAO,EAAK,EACpDD,EAAQ,OAAO,0BAA0B,uCAAS,OAAO,OAAO,CAAC,EAAEC,CAAI,CAAC,EACxED,EAAQ,OAAO,oBAAoB,mDAAW,OAAO,OAAO,CAAC,EAAEC,CAAI,CAAC,EACpED,EAAQ,OAAO,cAAc,uCAAS,OAAO,OAAO,CAAC,EAAEC,CAAI,CAAC,CAChE,CAEO,SAASC,GAAgBC,EAAW,CACvC,OAAOA,EAAO,MAAM,WAAW,aAAa,GAAKA,EAAO,MAAM,WAAW,mBAAmB,GAAKA,EAAO,MAAM,WAAW,aAAa,CAC1I,CAMO,SAASC,GAAS,CACrB,OAAO,QAAQ,KAAK,SAAS,aAAa,CAC9C,CAGO,SAASC,GAAkB,CAC9B,OAAO,QAAQ,KAAK,SAAS,mBAAmB,CACpD,CAOO,SAASC,EAAYC,KAAkBC,EAAW,CACrD,IAAIrB,EAAQqB,EAAK,QAAU,GAAK,OAAOA,EAAK,CAAC,GAAI,WAAcA,EAAK,CAAC,EAAE,EAAIA,EACxEJ,EAAQ,GAAGhB,EAAQ,IAAI,YAAYmB,CAAO,GAAG,GAAGpB,CAAI,CAC3D,CAGO,SAASsB,GAAUC,EAAM,CACzBN,EAAQ,EACPE,EAAY,4CAAcI,EAAE,KAAK,EAEjC,QAAQ,MAAMA,CAAC,CAGvB,CAGO,SAASC,GAAkBzB,EAAW,CACzC,OAAOA,EAAI,QAAQ,YAAY,CAAC0B,EAAEC,IAASA,EAAO,YAAY,CAAC,CACnE,CAEO,SAASC,IAAO,CACnB,OAAO,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,CAAC,CAC9C,CAGA,SAAsBC,EAAaC,EAAY,QAAAC,EAAA,sBAC3C,IAAIC,EACJ,GAAG,CACCA,EAASC,EAAQH,CAAI,CACzB,OAAON,EAAM,CAET,MAAAQ,GADY,MAAM,OAAO,UAAUF,CAAI,KAC1B,QACPN,CACV,CACA,OAAOQ,CACX,GAGO,SAASE,EAAYC,EAAU,CAClC,OAAOA,GAAO,IAClB,CD3GO,IAAMC,EAAsC,CAC/C,QAAS,UACT,OAAS,OACT,OAAS,SACT,MAAS,OACT,KAAS,MACb,EAEaC,EAAuB,CAChC,OACA,WACA,YACA,SACA,UACA,OACA,SACA,SACA,cACA,eACA,OACA,yBACJ,EAiBaC,EAAN,KAAqB,CAExB,YAAmBC,EAAoBC,EAA2B,CAA/C,eAAAD,EACf,KAAK,OAASC,CAClB,CAMA,kBAAkBC,EAAS,CACvB,OAAOJ,EAAqB,SAAS,OAAOI,CAAI,CAAC,CACrD,CAQA,aAAaC,EAAUC,EAAkBC,EAAgB,CAErD,GAAGA,IAAW,GAAO,MAAO,GAC5B,GAAGA,IAAW,GAAM,MAAO,GAE3B,IAAMC,EAAS,KAAK,OAEdC,EAAaJ,GAASC,EAGtBI,EAAaD,IAAe,OAIlC,OAAGD,IAAW,GAAa,GACxBA,IAAW,GAAc,GACzBA,IAAW,QAGXG,EAAcH,CAAM,EACZ,CAACE,EAIT,OAAOF,GAAW,UAAY,KAAK,kBAAkBA,CAAM,EAClD,GAIO,gBAAgB,KAAK,KAAK,UAAU,KAAK,EACtC,CAACE,EAGpB,KAAK,UAAU,YAAc,KAAK,UAAU,WAAW,QAAQD,CAAU,GAAK,GACtE,GAEJ,CAACC,CAEZ,CAEQ,aAAa,CAhHzB,IAAAE,EAiHQ,IAAIC,EAAyF,CAAC,EAC1FC,GAAeF,EAAA,KAAK,UAAU,SAAf,YAAAA,EAAuB,QAC1C,GAAG,KAAK,UAAU,WACdC,EAAW,KAAK,UAAU,WAAW,IAAIE,GAClC,OAAOA,GAAS,SACR,CAAC,MAAMA,EAAO,MAAMA,CAAM,EAE1BA,CAEd,UACID,EACLD,EAAU,OAAOC,GAAe,WAAaA,EAAe,CAAC,MAE7D,OAAO,CAAC,EAEZ,OAAOD,CACX,CASA,MAAMJ,EAAgB,CAElB,GAAM,CAAE,SAAAO,EAAU,aAAAV,CAAa,EAAI,KAAK,UAElCD,EAAQI,GAAcH,EAGxBW,EAAwB,OAEtBT,EAAS,KAAK,OAEpB,GAAG,KAAK,kBAAkBA,CAAM,EAC5BS,EAAaT,UACRG,EAAcH,CAAM,EACzBS,EAAcT,EAAwB,SACrC,CAED,IAAMU,EAAa,4CAA4C,KAAK,KAAK,UAAU,KAAK,EAClFC,EAAa,2BAA2B,KAAK,KAAK,UAAU,KAAK,EACjEC,EAAgB,CAAC,+BAA+B,KAAK,KAAK,UAAU,KAAK,EACzEC,EAAeC,EAAShB,CAAY,EACpCiB,EAASjB,GAAgBA,aAAwB,KAGjDkB,EAAkB,MAAM,QAAQnB,CAAK,EAAI,QAC3CA,aAAiB,KAAO,OACxB,OAAOA,EAELoB,EAAe,KAAK,UAAU,OAEpC,GAAGA,GAAgBA,EAAa,QAAQ,CACpC,IAAMZ,EAAUY,EAAa,QAC1BL,GAAkB,MAAM,QAAQP,CAAO,GAAKA,EAAQ,QAAQ,EAC3DI,EAAa,SAEbA,EAAaD,EAAW,cAAgB,QAEhD,MAASE,EACLD,EAAa,OACRM,EACLN,EAAa,OACRI,EACLJ,EAAa,SACRE,EACLF,EAAa,OACRG,GAAiB,OAAOd,GAAgB,UAC7CW,EAAa,UACRO,KAAYzB,IACjBkB,EAAalB,EAAcyB,CAAQ,EAE3C,CACA,OAAAE,EAAY,mDAAqB,CAAC,KAAK,UAAU,KAAK,EAAET,CAAU,CAAC,EAC5DA,CACX,CAMA,IAAIR,EAAgBF,EAAgB,CArMxC,IAAAK,EAuMQ,GAAM,CAAE,YAAAe,EAAa,aAAArB,CAAa,EAAI,KAAK,UAEvCD,EAAQI,GAAcH,EAG1B,GAAG,CAAC,KAAK,aAAaD,EAAMC,EAAaC,CAAM,EAAG,OAGlD,IAAMU,EAAa,KAAK,MAAMR,CAAU,EAElCmB,EAASC,EAAA,CACX,KAASZ,EACT,KAAS,KAAK,UAAU,cAAc,EACtC,QAASU,EACT,QAAStB,GACN,OAAO,KAAK,QAAW,SAAW,KAAK,OAAS,CAAC,GAmBxD,GAdAuB,EAAO,UAAWhB,EAAA,KAAK,UAAU,SAAf,YAAAA,EAAuB,SAEtCK,GAAY,gBAAeW,EAAO,aAAa,IAClDA,EAAO,QAAUA,EAAO,SAAW,KAAK,YAAY,EAEjD,CAAC,SAAS,aAAa,EAAE,SAASX,CAAU,GAEtCA,GAAY,UACd,MAAM,QAAQW,EAAO,OAAO,IACvBA,EAAO,SAAQA,EAAO,OAASA,EAAO,QAAQ,CAAC,EAAE,OACjDA,EAAO,WAAUA,EAAO,SAAWA,EAAO,QAAQ,CAAC,EAAE,QAI9DvB,GAAS,OAAOuB,EAAO,SAAU,YAC7BA,EAAO,SAAW,MAAM,QAAQA,EAAO,OAAO,EAC7C,GAAGX,GAAY,SAAS,CACpB,IAAMa,EAAQ,MAAM,QAAQF,EAAO,OAAO,EAAIA,EAAO,QAAQ,UAAUG,GAAMA,EAAK,OAAO1B,CAAK,EAAI,GAC/FyB,GAAO,KACNF,EAAO,QAAUE,EAEzB,MAASb,GAAY,eACjBW,EAAO,QAAQ,QAASG,GAAO,EACxB,MAAM,QAAQ1B,CAAK,GAAKA,EAAM,SAAS0B,EAAK,KAAK,GAE3CA,EAAK,OAAO1B,KACjB0B,EAAK,SAAW,GAExB,CAAC,EAKb,OAAOH,CACX,CAGJ,EDrOO,IAAMI,EAAN,cAAwBC,CAAM,CAGjC,YAAYC,EAAeC,EAA2BC,EAA4B,CAC9E,MAAMF,EAAOC,CAAW,EAD0B,YAAAC,EAFtD,oBAAiB,GAIb,KAAK,WAAWA,GAAU,CAAC,CAAC,EAC5B,KAAK,OAAS,IAAIC,EAAgB,KAAKD,GAAA,YAAAA,EAAQ,MAAM,CACzD,CACQ,WAAWA,EAAyB,CACpCE,EAAYF,EAAO,OAAO,GAAI,KAAK,QAAQA,EAAO,QAAQA,EAAO,kBAAkB,EACpFA,EAAO,WAAwB,KAAK,UAAUA,EAAO,SAAS,EAC9DA,EAAO,QAAwB,KAAK,IAAIA,EAAO,MAAM,EACrDA,EAAO,UAAwB,KAAK,UAAUA,EAAO,QAAQ,EAC7DA,EAAO,SAAwB,KAAK,OAAWA,EAAO,QACtDA,EAAO,WAAwB,KAAK,oBAAoBA,EAAO,SAAS,EACxEA,EAAO,SAAwB,KAAK,QAAQA,EAAO,OAAO,EAC1DA,EAAO,WAAwB,KAAK,SAASA,EAAO,UACpDA,EAAO,WAAwB,KAAK,SAAWA,EAAO,UACtDA,EAAO,SAAwB,KAAK,OAAWA,EAAO,QACtDA,EAAO,QAAwB,KAAK,OAAOA,EAAO,MAAM,EACxDA,EAAO,WAAwB,KAAK,SAAWA,EAAO,UACtD,MAAM,QAAQA,EAAO,OAAO,GAAG,KAAK,QAAQA,EAAO,QAAQ,IAAIG,GAAQ,OAAOA,GAAS,SAAWA,EAASA,EAAO,KAAK,CAAC,CAC/H,CASA,UAAUC,EAAgBC,EAA2C,CA1DzE,IAAAC,EA2DQ,OAAOA,EAAA,KAAK,SAAL,YAAAA,EAAa,IAAIF,EAAWC,EACvC,CACJ,EDxDA,OAAOE,MAAU,YACjB,OAAOC,MAAQ,UA+DR,IAAMC,EAAQ,OAAO,cAAc,EAE7BC,EAAN,cAAyBC,CAAQ,CAQvC,YAAYC,EAAe,CAC1B,MAAMA,CAAI,EARX,qBAAkB,GAClB,KAAQ,aAA+D,CAAC,EACxE,KAAQ,YAA8D,CAAC,EACvE,KAAQ,eAAkC,CAAC,EAC3C,KAAQ,cAAuC,CAAC,EAChD,KAAQ,SAAuC,CAAC,EAK/C,IAAMC,EAAO,KACb,KAAK,KAAK,YAAa,UAA2B,QAAAC,EAAA,2BACjDD,EAAK,cAAgBA,EAAK,gBAAgB,KAAK,aAAa,EAE5D,MAAMA,EAAK,cAAc,MAAMA,EAAM,SAAS,CAC/C,GAAC,CACF,CACA,IAAI,QAAS,CAAE,OAAO,KAAK,QAAQ,IAAW,CAC9C,IAAI,cAAc,CAAE,OAAO,KAAK,aAAc,CAC9C,IAAI,SAAU,CAAE,OAAO,KAAK,QAAU,CACtC,IAAI,aAAc,CAAE,OAAO,KAAK,YAAc,CAC9C,IAAI,YAAa,CAAC,OAAO,KAAK,WAAY,CAC1C,IAAI,UAAW,CACd,IAAIE,EAAQ,CAAC,KAAK,KAAK,CAAC,EACpBC,EAAS,KAAK,OAClB,KAAOA,GACFA,EAAO,KAAK,IAAM,QACrBD,EAAM,QAAQC,EAAO,KAAK,CAAC,EAE5BA,EAASA,EAAO,OAEjB,OAAOD,EAAM,KAAK,GAAG,CACtB,CAKA,MAAO,CAEN,IAAIE,EAAW,KACf,KAAOA,GAAQA,EAAK,QAAU,MAC7BA,EAAOA,EAAK,OAEb,OAAOA,CACR,CAKA,QAAe,CACd,IAAMC,EAAa,UAAU,CAAC,EAC9B,GAAI,UAAU,QAAU,GAAK,OAAOA,GAAc,WAEjD,KAAK,SAAS,KAAK,CAClB,GAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,CAAC,EAC1C,QAAS,GACT,GAAIA,CACL,CAAC,UACS,UAAU,QAAU,GAAM,OAAOA,GAAc,YAAc,OAAO,UAAU,CAAC,GAAK,SAAW,CAEzG,IAAMC,EAAW,UAAU,CAAC,EACtBC,EAA+B,OAAO,OAAO,CAAE,GAAI,QAAS,EAAG,UAAU,CAAC,CAAC,EAC7EA,EAAW,IAAM,YAAW,KAAK,SAAW,CAAC,GACjD,IAAMC,EAAa,CAClB,GAAID,EAAW,IAAM,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,CAAC,EAC3D,QAASA,EAAW,SAAW,KAAY,GAAOA,EAAW,QAC7D,GAAID,CACL,EACI,OAAOC,EAAW,IAAM,SAC3B,KAAK,SAAS,OAAO,OAAOA,EAAW,EAAE,EAAG,EAAGC,CAAU,EAC/C,CAAC,SAAU,QAAQ,EAAE,SAASD,EAAW,EAAE,EACrD,KAAK,SAAS,KAAKC,CAAU,EACnB,CAAC,YAAa,OAAO,EAAE,SAASD,EAAW,EAAE,EACvD,KAAK,SAAS,OAAO,EAAG,EAAGC,CAAU,EAErC,KAAK,SAAS,KAAKA,CAAU,CAE/B,MACC,QAAQ,IAAI,8BAA8B,EAE3C,OAAO,MAAM,OAAO,KAAK,mBAAmB,CAAC,CAC9C,CAMQ,gBAAgBC,EAAqB,CAC5C,IAAMC,EAAO,CAAC,EAEVP,EAAcM,EAClB,KAAON,GACN,OAAO,OAAOO,EAAOP,EAAsB,YAAY,EACvDA,EAASA,EAAO,OAEjB,OAAOO,CACR,CAIQ,oBAAqB,CAC5B,OAAO,KAAK,sBAAsB,KAAK,oBAAoB,CAAC,CAC7D,CAKQ,qBAAoC,CAC3C,IAAIC,EAAqB,CAAC,EAEtBC,EAAyB,KAC7B,KAAOA,GACNA,EAAMA,EAAI,OACNA,GACHD,EAAK,KAAKC,CAAG,EAGf,OAAOD,CACR,CAIQ,qBAAsB,CAE7B,IAAMX,EAAO,KACb,OAAO,UAA2B,QAAAC,EAAA,2BACjC,IAAMY,EAAO,MAAM,KAAK,SAAS,EAC7BC,EAEAP,EAAkC,CAAC,EACtCQ,EAAoB,CAAC,EACrBH,EACGC,EAAK,QAAU,IAClBD,EAAMC,EAAKA,EAAK,OAAS,CAAC,EAC1BN,EAAaM,EAAKA,EAAK,OAAS,CAAC,EACjCE,EAAaF,EAAK,MAAM,EAAGA,EAAK,OAAS,CAAC,GAE3C,MAAMb,EAAK,mBAAmB,CAAE,KAAMe,EAAY,QAASR,EAAY,QAASK,CAAI,CAAC,EACrF,GAAI,CACH,QAASI,KAAUhB,EAAK,SACvB,GAAI,CAkBH,GAjBIgB,EAAO,SAEVC,EAAY,wCAA+B,IAAM,CAChDjB,EAAK,KAAK,EACVe,EACAR,CACD,CAAC,EACDO,EAAW,MAAME,EAAO,GAAG,KAAK,KAAM,CACrC,QAASJ,EACT,MAASE,EACT,KAASC,EACT,QAASR,CACV,CAAC,GAGDO,EAAW,MAAME,EAAO,GAAG,MAAM,KAAMH,CAAI,EAExCC,IAAalB,EAAO,KACzB,OAASsB,EAAG,CACX,MAAAD,EAAY,4DAA0B,CAACjB,EAAK,KAAMgB,EAAO,GAAIE,CAAC,CAAC,EACzDA,CACP,CAEF,QAAE,CACD,MAAMlB,EAAK,kBAAkB,CAC5B,MAAOc,EACP,KAAMC,EACN,QAASR,EACT,QAASK,CACV,CAAC,CACF,CACD,GACD,CAIQ,sBAAsBO,EAAmB,CAEhD,IAAMnB,EAAO,KACb,OAAO,UAA2B,QAAAC,EAAA,2BACjC,IAAImB,EAAWpB,EAAK,cAAc,SAElC,GAAI,CAACoB,EACJ,OAAO,MAAMD,EAAG,MAAM,KAAM,MAAM,KAAK,SAAS,CAAC,EAE7C,MAAM,QAAQC,CAAQ,IAAGA,EAAWA,EAAS,MAAM,GAAG,GAC3DA,EAAWA,EAAS,OAAO,CAACC,EAAaC,KACpC,OAAOA,GAAO,UAAUD,EAAK,KAAK,GAAGC,EAAI,MAAM,GAAG,CAAC,EAChDD,GACL,CAAC,CAAC,EACL,QAASE,KAAWH,EAAU,CAC7B,IAAMI,EAAM,QAAQ,IAAI,EACxB,GAAI,CACEC,EAAK,WAAWF,CAAO,IAAGA,EAAUE,EAAK,KAAKD,EAAKD,CAAO,GAC3DG,EAAG,WAAWH,CAAO,GAAKG,EAAG,SAASH,CAAO,EAAE,YAAY,GAC9DN,EAAY,gDAAcM,CAAO,EACjC,QAAQ,MAAMA,CAAO,EACrB,MAAMJ,EAAG,MAAM,KAAM,MAAM,KAAK,SAAS,CAAC,GAE1CF,EAAY,gDAAcM,CAAO,CAEnC,QAAE,CACD,QAAQ,MAAMC,CAAG,CAClB,CACD,CACD,GACD,CACA,UAAUzB,EAAyB,CAClC,OAAO,KAAK,QAAQ,KAAM4B,GAAWA,EAAO,KAAK,GAAK5B,CAAI,CAC3D,CAOA,OAAO6B,EAAwCC,EAAiB,GAAM,CACrE,YAAK,aAAa,KAAK,CAACD,EAAUC,CAAK,CAAC,EACjC,IACR,CACc,mBAAmBhB,EAAW,QAAAZ,EAAA,sBAC3C,IAAM6B,EAA+D,KAAK,YAAY,IACrF,CAAC,CAACC,EAAMF,CAAK,IAAM,CAACE,EAAMF,EAAO,IAAI,CACtC,EACA,KAAK,oBAAoB,EAAE,QAASjB,GAAoB,CACvDkB,EAAM,QACL,GAAGlB,EAAI,YAAY,IAAI,CAAC,CAACmB,EAAMF,CAAK,IAC5B,CAACE,EAAMF,EAAOjB,CAAG,CACxB,CACF,CACD,CAAC,EACD,OAAS,CAACmB,EAAMF,EAAOjB,CAAG,IAAKkB,EACzBD,IACL,MAAME,EAAK,KAAKnB,EAAKC,CAAI,EAE3B,GAOA,MAAMe,EAAuCC,EAAiB,GAAM,CACnE,YAAK,YAAY,KAAK,CAACD,EAAUC,CAAK,CAAC,EAChC,IACR,CAEc,kBAAkBhB,EAAW,QAAAZ,EAAA,sBAC1C,IAAM6B,EAA8D,KAAK,WAAW,IACnF,CAAC,CAACC,EAAMF,CAAK,IAAM,CAACE,EAAMF,EAAO,IAAI,CACtC,EACA,KAAK,oBAAoB,EAAE,QAASjB,GAAoB,CACvDkB,EAAM,KACL,GAAGlB,EAAI,WAAW,IAAI,CAAC,CAACmB,EAAMF,CAAK,IAC3B,CAACE,EAAMF,EAAOjB,CAAG,CACxB,CACF,CACD,CAAC,EACD,OAAS,CAACmB,EAAMF,EAAOjB,CAAG,IAAKkB,EACzBD,IACL,MAAME,EAAK,KAAKnB,EAAKC,CAAI,EAE3B,GACc,cAAcmB,EAAsB,QAAA/B,EAAA,sBACjD,GAAI,KAAK,gBAAgB,EAAG,CAE3B,IAAMgC,EAA4B,CACjC,GAAG,KAAK,oBAAoB,EAC5B,GAAG,KAAK,cACT,EAEA,GAAIA,EAAU,OAAS,EAAG,CACzB,IAAMC,EAAU,MAAMC,EAAQF,CAAS,EACvC,OAAO,QAAQC,CAAO,EAAE,QAAQ,CAAC,CAACE,EAAKC,CAAK,IAAM,CACjDL,EAAY,eAAeI,EAAKC,CAAK,CACtC,CAAC,CACF,CACD,CACD,GAEQ,iBAAkB,CACzB,OAAIC,EAAiB,EACb,GAEA,KAAK,eAEd,CAYQ,qBAAsC,CAE7C,IAAMC,EADU,KAAK,QAEnB,OAAQZ,GAAW,CAACA,EAAO,QAAUA,EAAO,cAAc,EAC1D,IAAKA,GAAW,CAChB,IAAMa,EAAiB,KAAK,gBAC5B,OAAOb,EAAO,UAAU,KAAK,cAAcA,EAAO,cAAc,CAAC,EAAEa,CAAc,CAClF,CAAC,EACA,OAAQC,GAAWA,CAAM,EAE3B,OAAAxB,EAAY,8EAAwB,CACnC,KAAK,KAAK,EACVsB,EAAgB,OAChBA,EAAgB,IAAKE,GAAW,GAAGA,EAAO,IAAI,IAAIA,EAAO,IAAI,GAAG,EAAE,KAAK,GAAG,CAC3E,CAAC,EACMF,CACR,CAGA,OAAQG,EAAeC,EAAqBC,EAAkC,CAC5E,IAAMjB,EAAS,IAAIkB,EAAUH,EAAOC,EAAaC,CAAO,EAEnDE,EAAanB,EAAO,cAAc,EACxC,OAAGmB,KAAc,KAAK,eACrBnB,EAAO,QAAQ,KAAK,cAAcmB,CAAU,CAAC,EAG1CnB,EAAO,UAAY,CAAC,KAAK,gBAAgB,IAAGA,EAAO,UAAY,IAC5D,KAAK,UAAUA,CAA2B,CAClD,CAEA,QAAQoB,EAA0B,CACjC,cAAO,OAAO,KAAK,cAAcA,CAAM,EAChC,IACR,CAYA,OAAOd,EAA0C,CAChD,YAAK,eAAe,KAAK,GAAI,MAAM,QAAQA,CAAS,EAAIA,EAAY,CAACA,CAAS,CAAE,EACzE,IACR,CAWM,gBAAiB,QAAAhC,EAAA,sBACtB,IAAM+C,EAAU,KAAK,SAAS,IAAKvC,IAAa,CAC/C,MAAO,GAAGA,EAAQ,YAAY,CAAC,IAAIA,EAAQ,KAAK,CAAC,IACjD,MAAOA,EAAQ,KAAK,CACrB,EAAE,EACIwC,EAAS,MAAMd,EAAQ,CAC5B,KAAS,SACT,KAAS,UACT,QAAS,kCACT,QAAAa,CACD,CAAC,EAEKvC,EAAU,KAAK,SAAS,KAAMA,GAAYA,EAAQ,KAAK,IAAMwC,EAAO,OAAO,EACjF,MAAMxC,GAAA,YAAAA,EAAS,WAAW,CAACwC,EAAO,OAAO,EAAG,CAAE,KAAM,MAAO,EAC5D,GAIA,gBAAiB,CAChB,YAAK,gBAAkB,GAChB,IACR,CAIA,eAAgB,CACf,YAAK,gBAAkB,GAChB,IACR,CACD,EI5cA,OAAS,kBAAAC,MAAuB,oCAChC,OAAS,sBAAAC,MAA0B,wCAEnC,OAAU,YAAAC,OAAgB,OAG1B,OAAOC,MAAQ,UACf,OAAOC,MAAU,YAeV,SAASC,EAAmCC,EAAsB,CACrE,IAAMC,EAAgB,KAAK,QAAQ,QACnC,GAAG,EAAEA,aAAyB,QAAS,MAAQ,CAAC,EAGhD,GAAM,CAAE,aAAAC,EAAa,CAAC,EAAE,gBAAAC,EAAgB,CAAC,EAAE,iBAAAC,EAAiB,CAAC,EAAE,qBAAAC,EAAqB,CAAC,EAAE,mBAAAC,EAAmB,CAAC,CAAE,EAAIC,EAAeP,CAAK,EAQrI,MAPqB,CACjB,GAAG,OAAO,KAAKE,CAAY,EAC3B,GAAG,OAAO,KAAKC,CAAe,EAC9B,GAAG,OAAO,KAAKC,CAAgB,EAC/B,GAAG,OAAO,KAAKC,CAAoB,EACnC,GAAG,OAAO,KAAKC,CAAkB,CACrC,EACoB,OAAOE,GAAMA,IAAO,eAAiBP,EAAc,KAAKO,CAAI,CAAC,CACrF,CAEA,SAASC,EAAUC,EAAWC,EAAmD,CAG7E,OADgBA,EAAO,MAAM,QAAQA,CAAG,EAAIA,EAAM,CAACA,CAAG,EAAK,CAAC,GAC7C,KAAKC,GACb,OAAOA,GAAW,SACT,IAAI,OAAOA,CAAM,EAAG,KAAKF,CAAG,EAC/BE,aAAkB,OAChBA,EAAO,KAAKF,CAAG,EAEf,EAEd,CACL,CAEO,SAASG,EAAyBC,EAAqBd,EAAuB,CACjF,IAAMe,EAAgB,KAAK,QAAQ,QAC7BC,EAAgB,KAAK,QAAQ,QACnC,GAAG,CAACD,EAAe,MAAO,CAAC,EAC3B,IAAME,EAAcC,EAAmBlB,GAAS,QAAQ,IAAI,CAAC,EACvDmB,EAAcL,EAAcM,EAAK,QAAQC,EAAQ,QAAQP,EAAY,CAAC,MAAM,CAACG,CAAqB,CAAC,CAAC,CAAC,EAAIA,EAE/G,GAAG,CAACE,EACA,OAAAG,EAAY,wDAAsB,EAC3B,CAAC,EAIZ,IAAMC,EAAexB,EAAuB,KAAK,KAAKoB,CAAW,EAE3DK,EAAiB,CAAC,EAExB,OAAGxB,IAAQ,QAAWwB,EAAQ,KAAKJ,EAAK,KAAKD,EAAY,KAAK,QAAQ,MAAM,CAAC,EAC7EI,EAAa,OAAOf,GACJC,EAAUD,EAAKO,CAAa,GAAK,CAACN,EAAUD,EAAKQ,CAAa,CACzE,EACA,QAAQR,GAAM,CACXc,EAAY,wBAAS,GAAGR,EAAcN,EAAK,OAAOM,EAAeN,CAAI,EAAE,EACvE,GAAG,CACC,IAAMiB,EAAeL,EAAK,QAAQC,EAAQ,QAAQb,EAAK,CAAC,MAAMW,EAAc,CAACA,CAAW,EAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,EACvGO,EAAeN,EAAK,KAAKK,EAAa,KAAK,QAAQ,MAAO,EAE5DvB,EAAeH,EAAuB,KAAK,KAAK0B,CAAY,EAChED,EAAQ,KAAK,GAAGtB,EAAa,OAAiB,CAACyB,EAAOC,KAClDN,EAAY,wBAAS,GAAGM,CAAW,OAAOpB,CAAI,EAAE,EAChDmB,EAAO,KAAK,GAAGd,EAAa,KAAK,KAAKe,EAAYH,CAAY,CAAC,EACxDE,GACT,CAAC,CAAC,CAAC,EACFE,EAAG,WAAWH,CAAa,GAC1BF,EAAQ,KAAKE,CAAa,CAElC,OAAOI,EAAM,CACTR,EAAY,yDAAiB,CAACd,EAAKsB,EAAE,KAAK,CAAC,CAC/C,CACJ,CAAC,EAEE,CAAC,GAAG,IAAI,IAAIN,CAAO,CAAC,CAC/B,CAUA,SAAsBO,EAAaC,EAAW,QAAAC,EAAA,sBAC1C,IAAMT,EAAWX,EAAa,KAAKmB,CAAG,EAChCE,EAA2B,CAAC,EAC5BC,EAAQ,CAAC,EACfX,EAAQ,QAAQY,GAAK,CACjBC,GAAS,IAAI,CACT,IAAID,EACJ,SAAU,EACd,CAAC,EAAE,QAASE,GAAc,CAEtB,GADiBlB,EAAK,SAASkB,CAAI,EACvB,WAAW,GAAG,EAAG,OAC7B,IAAMC,EAAMnB,EAAK,QAAQkB,CAAI,EAAE,YAAY,EACxC,CAAC,MAAM,OAAO,MAAM,EAAE,SAASC,CAAG,EACjCJ,EAAM,KAAKG,CAAI,EACVT,EAAG,SAASS,CAAI,EAAE,YAAY,IACnCH,EAAM,KAAKf,EAAK,KAAKkB,EAAK,UAAU,CAAC,EACrCH,EAAM,KAAKf,EAAK,KAAKkB,EAAK,WAAW,CAAC,EACtCH,EAAM,KAAKf,EAAK,KAAKkB,EAAK,WAAW,CAAC,EAE9C,CAAC,CACL,CAAC,EACD,QAAQA,KAAQH,EACb,GAAIN,EAAG,WAAWS,CAAI,EACrB,GAAG,CAEC,GADAhB,EAAY,8BAAUgB,CAAI,EACvBA,EAAK,SAAS,MAAM,GAAKA,EAAK,SAAS,KAAK,EAC3CJ,EAAS,KAAK,MAAMM,EAAaF,CAAI,CAAC,UACjCA,EAAK,SAAS,MAAM,EAAE,CAC3B,IAAMG,EAAM,MAAM,OAAO,UAAUH,CAAI,IACvCJ,EAAS,KAAKO,EAAI,OAAO,CAC7B,CACJ,OAAOX,EAAM,CACTR,EAAYQ,CAAC,CACjB,CAEJ,OAAOI,CACX,GLlIA,OAAS,eAAAQ,OAAmB,+BAE5B,OAAOC,OAAiB,8BACxBC,GAAW,KAAK,EAuCT,IAAMC,EAAN,cAAqBC,EAA2B,CAInD,YAAYC,EAAuB,CAC/B,MAAM,EAFV,KAAQ,YAAkB,CAAC,EAGvB,KAAK,QAASC,GAAa,CACvB,KAAa,SACb,QAAa,KACb,OAAa,MACb,OAAa,OACb,YAAa,EACjB,EAAED,CAAO,EACT,KAAK,kBAAkB,CAC3B,CACA,IAAI,SAAS,CAAC,OAAO,KAAK,QAAQ,OAAO,CACzC,IAAI,MAAM,CAAC,OAAO,KAAK,QAAQ,IAAI,CAInC,IAAI,mBAAmB,CACnB,OAAO,KAAK,KAAa,QAAQ,SAAS,cAAc,CAC5D,CAIc,iBAAiB,QAAAE,EAAA,sBAC3B,IAAMC,EAAS,MAAMC,EAAa,IAAI,EACtC,QAAQC,KAASF,EACb,GAAG,CACC,GAAG,OAAOE,GAAS,WAAW,CAC1B,IAAIC,EAAOD,EAAM,IAAI,EACrBC,EAAOA,EAAS,MAAM,QAAQA,CAAI,EAAIA,EAAO,CAACA,CAAI,EAAK,CAAC,EACxD,KAAK,SAAS,IAAIA,CAAI,CAC1B,CACJ,OAAO,EAAM,CACTC,EAAY,0CAAY,EAAE,KAAK,CACnC,CAER,GAKQ,mBAAmB,CACvB,KAAK,KAAO,IAAIC,EAAW,KAAK,IAAI,EACpC,KAAK,KACA,WAAW,YAAY,EACvB,OAAO,IAAI,CACL,KAAK,QAAQ,MAAMC,EAAQ,IAAIC,EAAU,KAAK,QAAQ,KAAK,CAAC,CAAC,EAChE,QAAQ,IAAI,EAEZ,IAAIC,EAAQ,KAAK,QAAQ,OAAQ,KAAK,QAAQ,KAC3C,MAAM,QAAQA,CAAK,EAClBF,EAAQ,IAAI,OAAOE,EAAM,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,GAAGA,EAAM,MAAM,CAAC,CAAC,CAAC,EAE7DF,EAAQ,IAAI,GAAGE,EAAM,WAAW,CAAC,qBAAqB,KAAK,QAAQ,OAAO,EAG3E,KAAK,QAAQ,aAAaF,EAAQ,IAAIA,EAAQ,OAAO,SAAS,KAAK,QAAQ,WAAW,CAAC,EAC1F,QAAQ,IAAI,EACZ,KAAK,KAAK,KAAK,CACnB,CAAC,EACLG,EAAkB,KAAK,IAAI,EACxB,KAAK,QAAQ,QAAQ,KAAK,KAAK,KAAK,YAAY,KAAK,QAAQ,MAAM,EACnE,KAAK,QAAQ,OAAO,KAAK,KAAK,KAAK,aAAa,KAAK,QAAQ,KAAK,CACzE,CASO,QAAQC,EAAY,CAAC,IAAAC,EAAI,YAAY,YAAAC,EAAY,EAAI,EAAkF,CACvIA,IAAaF,EAAOH,EAAUG,EAAKE,CAAW,GACjD,KAAK,KAAK,YAAYD,EAAID,CAAI,CAClC,CAMA,SAASG,EAAkB,CACvB,GAAG,OAAOA,GAAM,WAAW,CACvB,IAAIC,EAASD,EAAI,IAAI,EACjBV,EAAOW,aAAkB,MAAQA,EAAWA,GAAQ,KAAY,CAAC,EAAK,CAACA,CAAM,EACjF,QAAQD,KAAOV,EAIPU,EAAI,gBACD,KAAK,WAAWA,EAAI,KAAK,CAAC,EACzBP,EAAQ,MAAM,YAAYO,EAAI,KAAK,CAAC,wBAAwB,GAE5DT,EAAY,8BAAUS,EAAI,QAAQ,EAElC,KAAK,KAAK,WAAWA,CAAc,EAEnCJ,EAAkBI,CAAU,EAE3BA,EAAY,KAAO,KAEpB,KAAK,KAAK,WAAWA,EAAI,SAAS,EAAI,GAG1CP,EAAQ,MAAM,YAAYO,EAAI,SAAS,CAAC,2BAA2B,CAG/E,MACIP,EAAQ,MAAM,iBAAiB,CAEvC,CAEA,WAAWS,EAAoB,CAC3B,OAAO,KAAK,KAAK,SAAS,KAAKC,GAAGA,EAAE,KAAK,GAAGD,CAAI,CACpD,CAaA,IAAIA,EAAmC,CACnC,IAAME,EAAMF,EAAK,MAAM,GAAG,EACtBG,EAAoB,KAAK,KACzBC,EACJ,KAAMF,EAAM,OAAO,GAAE,CACjB,IAAMG,EAAUH,EAAM,MAAM,EACtBI,EAAIH,EAAO,SAAS,KAAKF,GAAGA,EAAE,KAAK,GAAGI,CAAO,EAChDC,GAAKJ,EAAM,QAAQ,IAClBE,EAAYE,GAEhBH,EAASG,CACb,CACA,OAAOF,CACX,CAWA,KAAKJ,EAA4C,CAC7C,IAAMF,EAAM,KAAK,IAAIE,CAAI,EACzB,GAAGF,EACC,OAAO,QAAQ,QAAQA,CAAG,EACzB,CACD,IAAMS,EAASC,GAAY,EAC3B,YAAK,YAAY,KAAKD,CAAM,EACrB,IAAI,QAAiCE,GAAU,CAClD,IAAIC,EACJA,EAAW,KAAK,GAAG,WAAYC,GAAkB,CAC1CA,GAAU,GAAG,KAAK,IAAI,IAAIX,CAAI,KAC7BU,EAAS,IAAI,EACbH,EAAO,QAAQ,EACf,KAAK,YAAc,KAAK,YAAY,OAAOK,GAAGA,GAAGL,CAAM,EACvDE,EAAQ,KAAK,IAAIT,CAAI,CAAC,EAE9B,EAAE,CAAC,UAAU,EAAI,CAAC,CACtB,CAAC,CACL,CACJ,CAOA,OAAOA,EAAoB,CACvB,OAAGA,KAAQ,KAAK,KAAK,SACV,GAEA,KAAK,IAAIA,CAAI,GAAK,IAEjC,CAKA,KAAK,CAQD,KAAK,gBAAgB,EAAE,KAAK,IACjB,QAAQ,IAAI,KAAK,YAAY,IAAIO,GAAQA,EAAO,GAAK,CAAC,CAAC,EAAE,KAAK,IAAI,CACrE,KAAK,KAAK,WAAW,QAAQ,IAAI,CACrC,CAAC,CACJ,CACL,CACJ","names":["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","opts","isBuildInOption","option","isDebug","isDisablePrompts","outputDebug","message","args","showError","e","hyphenToCamelCase","_","letter","getId","importModule","file","__async","module","__require","isUndefined","value","promptTypeMap","supportedPromptTypes","MixOptionPrompt","cliOption","promptParams","type","input","defaultValue","enable","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","isUndefined","choice","inputValue","enable","_a","path","fs","BREAK","MixCommand","Command","name","self","__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","isEnablePrompt","prompt","flags","description","options","MixOption","optionName","values","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","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/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\n this.root.addCommand(cmd as Command) ;\n \n addBuiltInOptions(cmd as any);\n\n (cmd as any)._cli = this\n \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 { 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 | undefined \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\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;\t\t// 命令行参数禁用了提示,优先级最高\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) => {\n\t\t\t\tconst isEnablePrompt = this._enable_prompts;\n\t\t\t\treturn option.getPrompt(this._optionValues[option.attributeName()],isEnablePrompt)\n\t\t\t})\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\t\n\t\tconst optionName = option.attributeName()\n\t\tif(optionName in this._optionValues){\n\t\t\tconst val = this._optionValues[optionName]\n\t\t\tif(option.argChoices){\n\t\t\t\tif(option.argChoices.includes(val)){\n\t\t\t\t\toption.default(val)\n\t\t\t\t}\n\t\t\t}else if(val!=undefined){\n\t\t\t\toption.default(val)\n\t\t\t}\n\t\t}\n\n\t\tif (option.required) option.mandatory = false;\n\t\treturn this.addOption(option as unknown as Option) \n\t}\n\n\tinitial(values:Record<string,any>){\n\t\tObject.assign(this._optionValues,values)\n\t\treturn this\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 ","import { Option, OptionValues } from 'commander'\nimport { PromptObject } from 'prompts'\nimport { PromptChoice, MixOptionPrompt,PromptParams } from './prompt'\nimport { isUndefined } from './utils'\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(!isUndefined(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,enable?:boolean): PromptObject | undefined {\n return this.prompt?.get(inputValue,enable)\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,enable?:boolean){\n \n if(enable === false) return false\n if(enable === true) return true\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\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 private _validateInputValue(inputValue:any){\n if(this.cliOption.argChoices){\n const argChoices = this.cliOption.argChoices\n if(Array.isArray(inputValue)){\n return inputValue.filter((item:any)=>{\n return argChoices.indexOf(item) >= 0\n })\n }else{\n if(argChoices.indexOf(inputValue) != -1) return inputValue\n }\n }else{\n return inputValue\n }\n }\n\n /**\n * 返回生成prompt对象\n * \n * @param inputValue 从命令行输入的值\n */\n get(inputValue?:any,enable?:boolean){\n\n const { description, defaultValue } = this.cliOption\n \n let input = this._validateInputValue(inputValue) || defaultValue\n\n // 1. 判断是否需要启用提示\n if(!this.isNeedPrompt(input,defaultValue,enable)) 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 const opts = {hidden:true,optional:true,prompt:false}\n command.option(\"--work-dirs [values...]\",\"指定工作目录\",Object.assign({},opts))\n command.option(\"--disable-prompts\",\"禁用所有交互提示\",Object.assign({},opts)) \n command.option(\"--debug-cli\",\"显示调试信息\",Object.assign({},opts))\n}\n\nexport function isBuildInOption(option:any){\n return option.flags.startsWith(\"--work-dirs\") || option.flags.startsWith(\"--disable-prompts\") || option.flags.startsWith(\"--debug-cli\")\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\n\nexport function isUndefined(value:any){\n return value==undefined\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","opts","isBuildInOption","option","isDebug","isDisablePrompts","outputDebug","message","args","showError","e","hyphenToCamelCase","_","letter","getId","importModule","file","__async","module","__require","isUndefined","value","promptTypeMap","supportedPromptTypes","MixOptionPrompt","cliOption","promptParams","type","input","defaultValue","enable","params","inputValue","hasInput","isPlainObject","_a","choices","choicesParam","choice","variadic","promptType","isListType","isTextType","isBooleanType","isNumberType","isNumber","isDate","datatype","optionParams","outputDebug","argChoices","item","description","prompt","__spreadValues","index","MixOption","Option","flags","description","params","MixOptionPrompt","isUndefined","choice","inputValue","enable","_a","path","fs","BREAK","MixCommand","Command","name","self","__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","isEnablePrompt","prompt","flags","description","options","MixOption","optionName","val","values","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","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
package/src/command.ts
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import { Command, Option } from "commander";
|
2
2
|
import prompts, { PromptObject } from "prompts";
|
3
3
|
import { MixOption, type MixedOptionParams } from "./option";
|
4
|
-
import {
|
4
|
+
import { isDisablePrompts, outputDebug } from "./utils";
|
5
5
|
import type { AsyncFunction } from "flex-tools/types";
|
6
6
|
import path from "node:path";
|
7
7
|
import fs from "node:fs";
|
@@ -393,11 +393,18 @@ export class MixCommand extends Command {
|
|
393
393
|
|
394
394
|
const optionName = option.attributeName()
|
395
395
|
if(optionName in this._optionValues){
|
396
|
-
|
396
|
+
const val = this._optionValues[optionName]
|
397
|
+
if(option.argChoices){
|
398
|
+
if(option.argChoices.includes(val)){
|
399
|
+
option.default(val)
|
400
|
+
}
|
401
|
+
}else if(val!=undefined){
|
402
|
+
option.default(val)
|
403
|
+
}
|
397
404
|
}
|
398
405
|
|
399
|
-
if (option.required
|
400
|
-
return this.addOption(option as unknown as Option)
|
406
|
+
if (option.required) option.mandatory = false;
|
407
|
+
return this.addOption(option as unknown as Option)
|
401
408
|
}
|
402
409
|
|
403
410
|
initial(values:Record<string,any>){
|
package/src/prompt.ts
CHANGED
@@ -190,6 +190,22 @@ export class MixOptionPrompt{
|
|
190
190
|
outputDebug("选项<{}> -> 提示类型<{}>",[this.cliOption.name(),promptType])
|
191
191
|
return promptType
|
192
192
|
}
|
193
|
+
|
194
|
+
private _validateInputValue(inputValue:any){
|
195
|
+
if(this.cliOption.argChoices){
|
196
|
+
const argChoices = this.cliOption.argChoices
|
197
|
+
if(Array.isArray(inputValue)){
|
198
|
+
return inputValue.filter((item:any)=>{
|
199
|
+
return argChoices.indexOf(item) >= 0
|
200
|
+
})
|
201
|
+
}else{
|
202
|
+
if(argChoices.indexOf(inputValue) != -1) return inputValue
|
203
|
+
}
|
204
|
+
}else{
|
205
|
+
return inputValue
|
206
|
+
}
|
207
|
+
}
|
208
|
+
|
193
209
|
/**
|
194
210
|
* 返回生成prompt对象
|
195
211
|
*
|
@@ -199,7 +215,7 @@ export class MixOptionPrompt{
|
|
199
215
|
|
200
216
|
const { description, defaultValue } = this.cliOption
|
201
217
|
|
202
|
-
let input = inputValue || defaultValue
|
218
|
+
let input = this._validateInputValue(inputValue) || defaultValue
|
203
219
|
|
204
220
|
// 1. 判断是否需要启用提示
|
205
221
|
if(!this.isNeedPrompt(input,defaultValue,enable)) return
|