mixcli 3.2.0 → 3.2.2
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/index.cjs +4 -0
- package/dist/index.cjs.map +1 -0
- package/dist/{index.d.mts → index.d.cts} +67 -94
- package/dist/index.d.ts +67 -94
- package/dist/index.js +3 -1132
- package/dist/index.js.map +1 -1
- package/package.json +24 -11
- package/readme.md +8 -12
- package/src/cli.ts +8 -15
- package/src/command.ts +452 -452
- package/src/finder.ts +142 -142
- package/src/index.ts +5 -4
- package/src/option.ts +39 -81
- package/src/prompt.ts +183 -110
- package/src/utils.ts +144 -158
- package/dist/index.mjs +0 -1088
- package/dist/index.mjs.map +0 -1
- package/src/oslocate.js +0 -148
package/dist/index.cjs
ADDED
@@ -0,0 +1,4 @@
|
|
1
|
+
"use strict";var pt=Object.create;var y=Object.defineProperty;var ct=Object.getOwnPropertyDescriptor;var mt=Object.getOwnPropertyNames,$=Object.getOwnPropertySymbols,lt=Object.getPrototypeOf,q=Object.prototype.hasOwnProperty,ut=Object.prototype.propertyIsEnumerable;var B=(r,n,t)=>n in r?y(r,n,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[n]=t,F=(r,n)=>{for(var t in n||(n={}))q.call(n,t)&&B(r,t,n[t]);if($)for(var t of $(n))ut.call(n,t)&&B(r,t,n[t]);return r};var ft=(r,n)=>{for(var t in n)y(r,t,{get:n[t],enumerable:!0})},W=(r,n,t,i)=>{if(n&&typeof n=="object"||typeof n=="function")for(let e of mt(n))!q.call(r,e)&&e!==t&&y(r,e,{get:()=>n[e],enumerable:!(i=ct(n,e))||i.enumerable});return r};var u=(r,n,t)=>(t=r!=null?pt(lt(r)):{},W(n||!r||!r.__esModule?y(t,"default",{value:r,enumerable:!0}):t,r)),dt=r=>W(y({},"__esModule",{value:!0}),r);var l=(r,n,t)=>new Promise((i,e)=>{var o=a=>{try{p(t.next(a))}catch(c){e(c)}},s=a=>{try{p(t.throw(a))}catch(c){e(c)}},p=a=>a.done?i(a.value):Promise.resolve(a.value).then(o,s);p((t=t.apply(r,n)).next())});var Ot={};ft(Ot,{BREAK:()=>J,MixCli:()=>L,MixCommand:()=>v,MixOption:()=>O,MixOptionPrompt:()=>P,addBuiltInOptions:()=>M,fileExists:()=>gt,fixIndent:()=>C,getId:()=>Pt,hyphenToCamelCase:()=>Mt,importModule:()=>H,isDebug:()=>D,isDisablePrompts:()=>E,mkDirs:()=>bt,mkdir:()=>X,outputDebug:()=>m,outputStr:()=>ht,promptTypeMap:()=>T,readFile:()=>yt,showError:()=>Ct,supportedPromptTypes:()=>K,writeFile:()=>xt});module.exports=dt(Ot);var Xt=require("flex-tools/string"),nt=require("flex-tools/events/liteEvent"),d=u(require("logsets"),1),rt=require("flex-tools/object/assignObject");var G=require("commander"),S=u(require("prompts"),1);var z=require("commander");var R=require("flex-tools/typecheck/isPlainObject"),U=require("flex-tools/typecheck/isNumber");var x=u(require("fs-extra"),1),_=u(require("path"),1),b=require("flex-tools/func/promisify"),j=u(require("logsets"),1);function ht(r,n){j.default.log(C(r),n)}function C(r,n){if((n==null||n===!0?0:typeof n=="number"?n:-1)==-1)return r;let i=r.split(`
|
2
|
+
`),e=i.reduce((o,s,p)=>{var c;if(p==0)return o;let a=((c=s.match(/^\s*/))==null?void 0:c[0].length)||0;return Math.min(o,a)},9999);return i=i.map(o=>o.substring(e)),i.join(`
|
3
|
+
`)}function M(r){r.option("--work-dirs <values...>","\u6307\u5B9A\u5DE5\u4F5C\u76EE\u5F55",{hidden:!0,optional:!0,required:!0,prompt:!1}),r.option("--disable-prompts","\u7981\u7528\u6240\u6709\u4EA4\u4E92\u63D0\u793A",{hidden:!0,prompt:!1}),r.option("--debug-cli","\u663E\u793A\u8C03\u8BD5\u4FE1\u606F",{hidden:!0,prompt:!1})}function D(){return process.argv.includes("--debug-cli")}function E(){return process.argv.includes("--disable-prompts")}function m(r,...n){let t=n.length==1&&typeof n[0]=="function"?n[0]():n;D()&&j.default.log(`[MixCli] ${r}`,...t)}var gt=(0,b.promisify)(x.default.exists,{parseCallback:r=>r[0]}),yt=(0,b.promisify)(x.default.readFile),xt=(0,b.promisify)(x.default.writeFile),X=(0,b.promisify)(x.default.mkdir);function bt(i,e){return l(this,arguments,function*(r,{callback:n,base:t}){if(!Array.isArray(r))throw new Error("dirs\u53C2\u6570\u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32\u6570\u7EC4");for(let o of r)_.default.isAbsolute(o)||(o=_.default.join(t||process.cwd(),o)),typeof n=="function"&&n(o),yield X(o,{recursive:!0})})}function Ct(r){D()?m("\u5BFC\u5165\u547D\u4EE4<>\u51FA\u9519:{}",r.stack):console.error(r)}function Mt(r){return r.replace(/-([a-z])/g,(n,t)=>t.toUpperCase())}function Pt(){return Math.random().toString(36).substr(2)}function H(r){return l(this,null,function*(){let n;try{n=require(r)}catch(t){try{n=(yield import(`file://${r}`)).default}catch(i){throw i}}return n})}var T={boolean:"confirm",string:"text",number:"number",array:"list",date:"date"},K=["text","password","invisible","number","confirm","list","toggle","select","multiselect","autocomplete","date","autocompleteMultiselect"],P=class{constructor(n,t){this.cliOption=n;this.params=t}isValidPromptType(n){return K.includes(String(n))}isNeedPrompt(n,t){let i=this.params,e=n||t,o=e!==void 0;return i===!0?!0:i===!1?!1:i==="auto"||(0,R.isPlainObject)(i)?!o:typeof i=="string"&&this.isValidPromptType(i)?!0:/(\<s*\w\s*\>)/.test(this.cliOption.flags)?!o:this.cliOption.argChoices&&this.cliOption.argChoices.indexOf(e)==-1?!0:!o}_getChoices(){var i;let n=[],t=(i=this.cliOption.params)==null?void 0:i.choices;if(this.cliOption.argChoices)n=this.cliOption.argChoices.map(e=>typeof e=="string"?{title:e,value:e}:e);else if(t)n=typeof t=="function"?t:[];else return[];return n}infer(n){let{variadic:t,defaultValue:i}=this.cliOption,e=n||i,o="text",s=this.params;if(this.isValidPromptType(s))o=s;else if((0,R.isPlainObject)(s))o=s.type;else{let p=/(\[\s*\w+\.\.\.\s*])|(\<\s*\w+\.\.\.\s*>)/.test(this.cliOption.flags),a=/(\<s*\w+\s*\>)|(\[\w+\])/.test(this.cliOption.flags),c=!/(\[\s*\w+s*])|(\<\s*\w+\s*>)/.test(this.cliOption.flags),A=(0,U.isNumber)(i),w=i&&i instanceof Date,g=Array.isArray(e)?"array":e instanceof Date?"date":typeof e,h=this.cliOption.params;if(h&&h.choices){let N=h.choices;c&&Array.isArray(N)&&N.length==2?o="toggle":o=t?"multiselect":"select"}else p?o="list":w?o="date":A?o="number":a?o="text":c||typeof i=="boolean"?o="confirm":g in T&&(o=T[g])}return m("\u9009\u9879<{}> -> \u63D0\u793A\u7C7B\u578B<{}>",[this.cliOption.name(),o]),o}get(n){var p;let{description:t,defaultValue:i}=this.cliOption,e=n||i;if(!this.isNeedPrompt(e,i))return;let o=this.infer(n),s=F({type:o,name:this.cliOption.attributeName(),message:t,initial:e},typeof this.params=="object"?this.params:{});if(s.validate=(p=this.cliOption.params)==null?void 0:p.validate,o=="multiselect"&&(s.instructions=!1),s.choices=s.choices||this._getChoices(),["select","multiselect"].includes(o)||o=="toggle"&&Array.isArray(s.choices)&&(s.active||(s.active=s.choices[0].value),s.inactive||(s.inactive=s.choices[1].value)),e&&typeof s.initial!="function"&&s.choices&&Array.isArray(s.choices))if(o=="select"){let a=Array.isArray(s.choices)?s.choices.findIndex(c=>c.value==e):-1;a!=-1&&(s.initial=a)}else o=="multiselect"&&s.choices.forEach(a=>{(Array.isArray(e)&&e.includes(a.value)||a.value==e)&&(a.selected=!0)});return s}};var O=class extends z.Option{constructor(t,i,e){super(t,i);this.params=e;this.__MIX_OPTION__=!0;this._setOption(e||{}),this.prompt=new P(this,e==null?void 0:e.prompt)}_setOption(t){t.default&&this.default(t.default,t.defaultDescription),t.conflicts&&this.conflicts(t.conflicts),t.envVar&&this.env(t.envVar),t.parseArg&&this.argParser(t.parseArg),t.hidden&&(this.hidden=t.hidden),t.mandatory&&this.makeOptionMandatory(t.mandatory),t.implies&&this.implies(t.implies),t.optional&&(this.optional=t.optional),t.variadic&&(this.variadic=t.variadic),t.negate&&(this.negate=t.negate),t.preset&&this.preset(t.preset),t.required&&(this.required=t.required),Array.isArray(t.choices)&&this.choices(t.choices.map(i=>typeof i=="string"?i:i.value))}getPrompt(t){var i;return(i=this.prompt)==null?void 0:i.get(t)}};var V=u(require("path"),1),I=u(require("fs"),1);var J=Symbol("BREAK_ACTION"),v=class extends G.Command{constructor(t){super(t);this.__MIX_COMMAND__=!0;this._beforeHooks=[];this._afterHooks=[];this._customPrompts=[];this._optionValues={};this._actions=[];this._enable_prompts=!0;let i=this;this.isRoot||M(this),this.hook("preAction",function(){return l(this,arguments,function*(){i._optionValues=i.getOptionValues(this.hookedCommand),yield i.preActionHook.apply(i,arguments)})})}get isRoot(){return this.parent==null}get optionValues(){return this._optionValues}get actions(){return this._actions}get beforeHooks(){return this._beforeHooks}get afterHooks(){return this._afterHooks}get fullname(){let t=[this.name()],i=this.parent;for(;i;)i.name()!=="root"&&t.unshift(i.name()),i=i.parent;return t.join(".")}root(){let t=this;for(;t&&t.parent!=null;)t=t.parent;return t}action(){let t=arguments[0];if(arguments.length==1&&typeof t=="function")this._actions.push({id:Math.random().toString(36).substring(2),enhance:!1,fn:t});else if(arguments.length==2&&typeof t=="function"&&typeof arguments[1]=="object"){let i=arguments[0],e=Object.assign({at:"append"},arguments[1]);e.at=="replace"&&(this._actions=[]);let o={id:e.id||Math.random().toString(36).substring(2),enhance:e.enhance==null?!0:e.enhance,fn:i};typeof e.at=="number"?this._actions.splice(Number(e.at),0,o):["append","before"].includes(e.at)?this._actions.push(o):["preappend","after"].includes(e.at)?this._actions.splice(0,0,o):this._actions.push(o)}else console.log("[mixcli] action params error");return super.action(this.getWrapperedAction())}getOptionValues(t){let i={},e=t;for(;e;)Object.assign(i,e.optionValues),e=e.parent;return i}getWrapperedAction(){return this.wrapperWorkDirsAction(this.wrapperChainActions())}getAncestorCommands(){let t=[],i=this;for(;i;)i=i.parent,i&&t.push(i);return t}wrapperChainActions(){let t=this;return function(){return l(this,arguments,function*(){let i=Array.from(arguments),e,o={},s=[],p;i.length>=2&&(p=i[i.length-1],o=i[i.length-2],s=i.slice(0,i.length-2)),yield t.executeBeforeHooks({args:s,options:o,command:p});try{for(let a of t._actions)try{if(a.enhance?(m("\u6267\u884C<{}>: args={}, options={}",()=>[t.name(),s,o]),e=yield a.fn.call(this,{command:p,value:e,args:s,options:o})):e=yield a.fn.apply(this,i),e===J)break}catch(c){throw m("\u547D\u4EE4{}\u7684Action({})\u6267\u884C\u51FA\u9519:{}",[t.name,a.id,c]),c}}finally{yield t.executeAfterHooks({value:e,args:s,options:o,command:p})}})}}wrapperWorkDirsAction(t){let i=this;return function(){return l(this,arguments,function*(){let e=i._optionValues.workDirs;if(!e)return yield t.apply(this,Array.from(arguments));Array.isArray(e)||(e=e.split(",")),e=e.reduce((o,s)=>(typeof s=="string"&&o.push(...s.split(",")),o),[]);for(let o of e){let s=process.cwd();try{V.default.isAbsolute(o)||(o=V.default.join(s,o)),I.default.existsSync(o)&&I.default.statSync(o).isDirectory()?(m("\u5207\u6362\u5230\u5DE5\u4F5C\u76EE\u5F55:{}",o),process.chdir(o),yield t.apply(this,Array.from(arguments))):m("\u65E0\u6548\u7684\u5DE5\u4F5C\u76EE\u5F55:{}",o)}finally{process.chdir(s)}}})}}getOption(t){return this.options.find(i=>i.name()==t)}before(t,i=!0){return this._beforeHooks.push([t,i]),this}executeBeforeHooks(t){return l(this,null,function*(){let i=this.beforeHooks.map(([e,o])=>[e,o,this]);this.getAncestorCommands().forEach(e=>{i.unshift(...e.beforeHooks.map(([o,s])=>[o,s,e]))});for(let[e,o,s]of i)o&&(yield e.call(s,t))})}after(t,i=!0){return this._afterHooks.push([t,i]),this}executeAfterHooks(t){return l(this,null,function*(){let i=this.afterHooks.map(([e,o])=>[e,o,this]);this.getAncestorCommands().forEach(e=>{i.push(...e.afterHooks.map(([o,s])=>[o,s,e]))});for(let[e,o,s]of i)o&&(yield e.call(s,t))})}preActionHook(t){return l(this,null,function*(){if(this.isEnablePrompts()){let i=[...this.generateAutoPrompts(),...this._customPrompts];if(i.length>0){let e=yield(0,S.default)(i);Object.entries(e).forEach(([o,s])=>{t.setOptionValue(o,s)})}}})}isEnablePrompts(){return E()?!1:this._enable_prompts}generateAutoPrompts(){let i=this.options.filter(e=>!e.hidden&&e.__MIX_OPTION__).map(e=>e.getPrompt(this._optionValues[e.attributeName()])).filter(e=>e);return m("\u547D\u4EE4<{}>\u81EA\u52A8\u751F\u6210{}\u4E2A\u9009\u9879\u63D0\u793A:{}",[this.name(),i.length,i.map(e=>`${e.name}(${e.type})`).join(",")]),i}option(t,i,e){let o=new O(t,i,e);return o.required&&!this.isEnablePrompts()&&(o.mandatory=!0),this.addOption(o)}prompt(t){return this._customPrompts.push(...Array.isArray(t)?t:[t]),this}selectCommands(){return l(this,null,function*(){let t=this.commands.map(o=>({title:`${o.description()}(${o.name()})`,value:o.name()})),i=yield(0,S.default)({type:"select",name:"command",message:"\u8BF7\u9009\u62E9\u547D\u4EE4:",choices:t}),e=this.commands.find(o=>o.name()===i.command);yield e==null?void 0:e.parseAsync([i.command],{from:"user"})})}disablePrompts(){return this._enable_prompts=!1,this}enablePrompts(){return this._enable_prompts=!0,this}};var Z=require("flex-tools/package/getPackageJson"),tt=require("flex-tools/package/getPackageRootPath"),et=require("glob");var k=u(require("fs"),1),f=u(require("path"),1);function Q(r){let n=this.options.include;if(!(n instanceof RegExp))return[];let{dependencies:t={},devDependencies:i={},peerDependencies:e={},optionalDependencies:o={},bundleDependencies:s={}}=(0,Z.getPackageJson)(r);return[...Object.keys(t),...Object.keys(i),...Object.keys(e),...Object.keys(o),...Object.keys(s)].filter(a=>a!=="@voerka/cli"&&n.test(a))}function Y(r,n){return(n?Array.isArray(n)?n:[n]:[]).some(i=>typeof i=="string"?new RegExp(i).test(r):i instanceof RegExp?i.test(r):!1)}function it(r,n){let t=this.options.include,i=this.options.exclude;if(!t)return[];let e=(0,tt.getPackageRootPath)(n||process.cwd()),o=r?f.default.dirname(require.resolve(r,{paths:[e]})):e;if(!o)return m("MixCli\u53EA\u80FD\u8FD0\u884C\u5728Nodejs\u73AF\u5883"),[];let s=Q.call(this,o),p=[];return n!==void 0&&p.push(f.default.join(o,this.options.cliDir)),s.filter(a=>Y(a,t)&&!Y(a,i)).forEach(a=>{m("\u5339\u914D\u5305:{}",`${r?a+" <- "+r:a}`);try{let c=f.default.dirname(require.resolve(a,{paths:o?[o]:[process.cwd()]})),A=f.default.join(c,this.options.cliDir),w=Q.call(this,c);p.push(...w.reduce((g,h)=>(m("\u5339\u914D\u5305:{}",`${h} <- ${a}`),g.push(...it.call(this,h,c)),g),[])),k.default.existsSync(A)&&p.push(A)}catch(c){m("\u89E3\u6790\u5305<{}>\u8DEF\u5F84\u51FA\u9519\uFF1A{}",[a,c.stack])}}),[...new Set(p)]}function ot(r){return l(this,null,function*(){let n=it.call(r),t=[],i=[];n.forEach(e=>{(0,et.globSync)("*",{cwd:e,absolute:!0}).forEach(o=>{if(f.default.basename(o).startsWith("_"))return;let p=f.default.extname(o).toLowerCase();[".js",".cjs",".mjs"].includes(p)?i.push(o):k.default.statSync(o).isDirectory()&&(i.push(f.default.join(o,"index.js")),i.push(f.default.join(o,"index.cjs")),i.push(f.default.join(o,"index.mjs")))})});for(let e of i)if(k.default.existsSync(e))try{if(m("\u5BFC\u5165\u547D\u4EE4:{}",e),e.endsWith(".cjs")||e.endsWith(".js"))t.push(yield H(e));else if(e.endsWith(".mjs")){let o=yield import(`file://${e}`);t.push(o.default)}}catch(o){m(o)}return t})}var st=require("flex-tools/async/asyncSignal"),at=u(require("string.prototype.replaceall"),1);at.default.shim();var L=class extends nt.LiteEvent{constructor(t){super();this.findSignals=[];this.options=(0,rt.assignObject)({name:"mixcli",package:null,cliDir:"cli",prompt:"auto",ignoreError:!1},t),this.createRootCommand()}get context(){return this.options.context}get name(){return this.options.name}get isDisabledPrompts(){return this.root.rawArgs.includes("--no-prompts")}installCommands(){return l(this,null,function*(){let t=yield ot(this);for(let i of t)try{if(typeof i=="function"){let e=i(this);e=e?Array.isArray(e)?e:[e]:[],this.register(()=>e)}}catch(e){m("\u6CE8\u518C\u547D\u4EE4\u5931\u8D25:{}",e.stack)}})}createRootCommand(){this.root=new v(this.name),this.root.helpOption("-h, --help").action(()=>{this.options.logo&&d.default.log(C(this.options.logo,2)),console.log();let t=this.options.title||this.options.name;Array.isArray(t)?d.default.log(String(t[0]).firstUpper(),[...t.slice(1)]):d.default.log(`${t.firstUpper()} Version: {}`,this.options.version),this.options.description&&d.default.log(d.default.colors.darkGray(this.options.description)),console.log(),this.root.help()}),M(this.root),this.options.before&&this.root.hook("preAction",this.options.before),this.options.after&&this.root.hook("postAction",this.options.after)}addHelp(t,{pos:i="beforeAll",alignIndent:e=!0}){e&&(t=C(t,e)),this.root.addHelpText(i,t)}register(t){if(typeof t=="function"){let i=t(this),e=i instanceof Array?i:i==null?[]:[i];for(let o of e)o.__MIX_COMMAND__?this.hasCommand(o.name())?d.default.error(`Command <${o.name()}> has been registered!`):(m("\u6CE8\u518C\u547D\u4EE4:{}",o.fullname),this.root.addCommand(o),o._cli=this,this.emit("register",o.fullname,!0)):d.default.error(`Command <${o.toString()}> is not a valid command!`)}else d.default.error("Invalid command")}hasCommand(t){return this.root.commands.some(i=>i.name()==t)}get(t){let i=t.split("."),e=this.root,o;for(;i.length>0;){let s=i.shift(),p=e.commands.find(a=>a.name()==s);p&&i.length==0&&(o=p),e=p}return o}find(t){let i=this.get(t);if(i)return Promise.resolve(i);{let e=(0,st.asyncSignal)();return this.findSignals.push(e),new Promise(o=>{let s;s=this.on("register",p=>{p==`${this.name}.${t}`&&(s.off(),e.resolve(),this.findSignals=this.findSignals.filter(a=>a!=e),o(this.get(t)))},{objectify:!0})})}}exists(t){return t in this.root.commands?!0:this.get(t)!=null}run(){this.installCommands().then(()=>Promise.all(this.findSignals.map(t=>t(1e4))).then(()=>{this.root.parseAsync(process.argv)}))}};0&&(module.exports={BREAK,MixCli,MixCommand,MixOption,MixOptionPrompt,addBuiltInOptions,fileExists,fixIndent,getId,hyphenToCamelCase,importModule,isDebug,isDisablePrompts,mkDirs,mkdir,outputDebug,outputStr,promptTypeMap,readFile,showError,supportedPromptTypes,writeFile});
|
4
|
+
//# sourceMappingURL=index.cjs.map
|
@@ -0,0 +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 this.root.addCommand(cmd as Command) ;\n (cmd as any)._cli = this\n this.emit(\"register\",cmd.fullname,true)\n } \n }else{\n logsets.error(`Command <${cmd.toString()}> is not a valid command!`)\n }\n } \n }else{\n logsets.error(\"Invalid command\")\n } \n }\n\n hasCommand(name:string):boolean{\n return this.root.commands.some(c=>c.name()==name)\n }\n\n /**\n * 根据命令名称查找命令\n * \n * @remarks\n * \n * find(\"dev\")\n * find(\"dev.microservice\") 支持多级命令\n * find(\"abc\",DevCommand) 允许指定从DevCommand下开始查找abc命令\n * \n * @param name \n */\n get(name:string):MixCommand | undefined{\n const names=name.split(\".\")\n let curCmd:MixCommand = this.root\n let resultCmd:MixCommand | undefined\n while(names.length>0){\n const topName = names.shift()\n const r = curCmd.commands.find(c=>c.name()==topName) as MixCommand\n if(r && names.length==0){\n resultCmd = r\n }\n curCmd = r\n } \n return resultCmd \n }\n /**\n * 查找一个命令\n * \n * 如果命令不存在,则等待命令注册后再返回\n * \n * 在多包场景下,如果命令在其他包中注册并且该包中的命令还没注册,则会等待命令注册后再返回\n * \n * @param name \n * @returns \n */\n find(name:string):Promise<MixCommand | undefined>{\n const cmd = this.get(name)\n if(cmd){\n return Promise.resolve(cmd) \n }else{\n const signal = asyncSignal()\n this.findSignals.push(signal)\n return new Promise<MixCommand | undefined>((resolve)=>{\n let listener:LiteEventSubscriber\n listener = this.on(\"register\",(fullname:string)=>{\n if(fullname==`${this.name}.${name}`){\n listener.off()\n signal.resolve()\n this.findSignals = this.findSignals.filter(s=>s!=signal)\n resolve(this.get(name))\n }\n },{objectify:true}) as LiteEventSubscriber\n })\n } \n }\n /**\n * 判断命令是否存在\n * \n * @param name \n * @returns \n */\n exists(name:string):boolean{\n if(name in this.root.commands){\n return true\n }else{\n return this.get(name) != undefined\n }\n } \n \n /**\n * 运行命令行程序\n */\n run(){ \n // 为什么有findSignal这玩意,解决什么问题?\n // 当我们要扩展command时,通过get(\"命令名称\")来获取已经注册的命令的方式有个缺陷\n // 就是如果对命令的注册顺序有严格的要求,比如调用get('dev')时要求dev命令必须已经存在\n // 这对动态包的命令注册扩展开发体验不好\n // 所以引入find(\"命令名称\")来获取命令,该方法可以获取到后注册的命令\n // 其副作用是,在run时,可能find还没有运行到,从而导致在帮助信息里面看不到扩展的信息(实际上是已经生效的)\n // 所以我们在find里面注入一个异步信号来解决此问题\n this.installCommands().then(()=>{\n return Promise.all(this.findSignals.map(signal=>signal(10000))).then(()=>{\n this.root.parseAsync(process.argv); \n })\n }) \n }\n}\n ","import { Command, Option } from \"commander\";\nimport prompts, { PromptObject } from \"prompts\";\nimport { MixOption, type MixedOptionParams } from \"./option\";\nimport { addBuiltInOptions, hyphenToCamelCase, isDisablePrompts, outputDebug } from \"./utils\";\nimport type { AsyncFunction } from \"flex-tools/types\"; \nimport path from \"node:path\";\nimport fs from \"node:fs\";\n\n\n\nexport type IMixCommandHookListener = ({\n\targs,\n\toptions,\n\tcommand,\n}: {\n\targs: any[];\n\toptions: Record<string, any>;\n\tcommand: MixCommand;\n}) => void | Promise<void>;\n\nexport type BeforeMixCommandHookListener = ({\n\targs,\n\toptions,\n\tcommand,\n}: {\n\targs: any[];\n\toptions: Record<string, any>;\n\tcommand: MixCommand;\n}) => void | Promise<void>;\n\nexport type AfterMixCommandHookListener = ({\n\tvalue,\n\targs,\n\toptions,\n\tcommand,\n}: {\n\tvalue: any;\n\targs: any[];\n\toptions: Record<string, any>;\n\tcommand: MixCommand;\n}) => void | Promise<void>;\n\nexport interface MixActionOptions {\n\tid: string;\n\tat: \"replace\" | \"before\" | \"after\" | \"preappend\" | \"append\" | number;\t\n\tenhance: boolean;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 函数签名类型,即采用原始的commander的action函数签名,还是mixcli的action函数签名\n}\n\nexport interface MixActionRegistry extends Omit<MixActionOptions, \"at\"> {\n\tfn: Function;\n}\n\n// 原始的Action动作函数\nexport type MixOriginalAction = (...args: any[]) => any | Promise<void>;\n\n// 增强的Action函数签名\nexport type MixEnhanceAction = ({\n\targs,\n\toptions,\n\tvalue,\n\tcommand,\n}: {\n\targs: any[];\n\toptions: Record<string, any>;\n\tvalue: any;\n\tcommand: MixCommand;\n}) => any | Promise<any>;\n\n// 执行action的返回结果\nexport const BREAK = Symbol(\"BREAK_ACTION\"); // 中止后续的action执行\n\nexport class MixCommand extends Command {\n\t__MIX_COMMAND__ = true;\n\tprivate _beforeHooks : [ BeforeMixCommandHookListener, boolean ][] = [];\n\tprivate _afterHooks : [ AfterMixCommandHookListener, boolean ][] = [];\n\tprivate _customPrompts : PromptObject[] = [];\n\tprivate _optionValues : Record<string, any> = {}; \t\t\t\t\t\t\t// 命令行输入的选项值\n\tprivate _actions : MixActionRegistry[] = []; \t\t\t\t\t\t\t// 允许多个action\n\tprivate _enable_prompts: boolean = true; \t\t\t\t\t\t\t\t\t// 是否启用交互提示\n\tconstructor(name?: string) {\n\t\tsuper(name);\t\t\n\t\t// eslint-disable-next-line no-this-alias\n\t\tconst self = this\n\t\tif (!this.isRoot) addBuiltInOptions(this); \n\t\tthis.hook(\"preAction\", async function (this: any) {\n\t\t\tself._optionValues = self.getOptionValues(this.hookedCommand);\t\t\t\n\t\t\t// @ts-ignore\n\t\t\tawait self.preActionHook.apply(self, arguments);\n\t\t});\n\t} \n\tget isRoot() { return this.parent==undefined;\t}\n\tget optionValues(){ return this._optionValues }\n\tget actions() { return this._actions; }\n\tget beforeHooks() {\treturn this._beforeHooks; }\n\tget afterHooks() {return this._afterHooks;}\n\tget fullname() {\n\t\tlet names = [this.name()];\n\t\tlet parent = this.parent;\n\t\twhile (parent) {\n\t\t\tif (parent.name() !== \"root\") {\n\t\t\t\tnames.unshift(parent.name());\n\t\t\t}\n\t\t\tparent = parent.parent;\n\t\t}\n\t\treturn names.join(\".\");\n\t}\n\n\t/**\n\t * 返回根命令\n\t */\n\troot() { \n\t\t// eslint-disable-next-line no-this-alias\n\t\tlet root:any = this;\n\t\twhile (root && root.parent != null) {\n\t\t\troot = root.parent as unknown as MixCommand;\n\t\t}\n\t\treturn root;\n\t}\n\n\n\taction(fn: MixEnhanceAction, options: MixActionOptions): this;\n\taction(fn: MixOriginalAction): this;\n\taction(): this {\n\t\tconst actionFunc = arguments[0];\n\t\tif (arguments.length == 1 && typeof actionFunc == \"function\") {\n\t\t\t// 原始方式\n\t\t\tthis._actions.push({\n\t\t\t\tid: Math.random().toString(36).substring(2),\n\t\t\t\tenhance: false,\n\t\t\t\tfn: actionFunc,\n\t\t\t});\n\t\t} else if (arguments.length == 2 && typeof actionFunc == \"function\" && typeof arguments[1] == \"object\" ) {\n\t\t\t// 增强模式\n\t\t\tconst actionFn = arguments[0];\n\t\t\tconst actionOpts: MixActionOptions = Object.assign({ at: \"append\" }, arguments[1]);\n\t\t\tif (actionOpts.at == \"replace\") this._actions = [];\n\t\t\tconst actionItem = {\n\t\t\t\tid: actionOpts.id || Math.random().toString(36).substring(2),\n\t\t\t\tenhance: actionOpts.enhance == undefined ? true : actionOpts.enhance,\n\t\t\t\tfn: actionFn,\n\t\t\t} as const;\n\t\t\tif (typeof actionOpts.at == \"number\") {\n\t\t\t\tthis._actions.splice(Number(actionOpts.at), 0, actionItem);\n\t\t\t} else if ([\"append\", \"before\"].includes(actionOpts.at)) {\n\t\t\t\tthis._actions.push(actionItem);\n\t\t\t} else if ([\"preappend\", \"after\"].includes(actionOpts.at)) {\n\t\t\t\tthis._actions.splice(0, 0, actionItem);\n\t\t\t} else {\n\t\t\t\tthis._actions.push(actionItem);\n\t\t\t}\n\t\t} else {\n\t\t\tconsole.log(\"[mixcli] action params error\");\n\t\t}\n\t\treturn super.action(this.getWrapperedAction());\n\t}\n\n\t/**\n\t * 读取命令配置值,包括父命令提供的配置选项\n\t * @param command\n\t */\n\tprivate getOptionValues(command: MixCommand) {\n\t\tconst opts = {};\n\t\t// eslint-disable-next-line no-this-alias\n\t\tlet parent: any = command;\n\t\twhile (parent) {\n\t\t\tObject.assign(opts, (parent as MixCommand).optionValues);\n\t\t\tparent = parent.parent;\n\t\t}\n\t\treturn opts;\n\t}\n\t/**\n\t * 本函数在运行时子类进行action生成该命令的action\n\t */\n\tprivate getWrapperedAction() {\n\t\treturn this.wrapperWorkDirsAction(this.wrapperChainActions());\n\t}\n\n\t/**\n\t * 向上查找所有祖先命令\n\t */\n\tprivate getAncestorCommands(): MixCommand[] {\n\t\tlet cmds: MixCommand[] = [];\n\t\t// eslint-disable-next-line no-this-alias\n\t\tlet cmd: MixCommand | null = this;\n\t\twhile (cmd) {\n\t\t\tcmd = cmd.parent as unknown as MixCommand;\n\t\t\tif (cmd) {\n\t\t\t\tcmds.push(cmd);\n\t\t\t}\n\t\t}\n\t\treturn cmds;\n\t}\n\t/***\n\t * 将所有actions包装成一个链式调用的函数\n\t */\n\tprivate wrapperChainActions() {\n\t\t// eslint-disable-next-line no-this-alias\n\t\tconst self = this;\n\t\treturn async function (this: any) {\n\t\t\tconst args = Array.from(arguments); // 原始输入的参数\n\t\t\tlet preValue: any; // 保存上一个action的返回值\n\t\t\t//解析参数, 0-1个参数为options,最后一个参数为command\n\t\t\tlet actionOpts: Record<string, any> = {},\n\t\t\t\tactionArgs: any[] = [],\n\t\t\t\tcmd: any;\n\t\t\tif (args.length >= 2) {\n\t\t\t\tcmd = args[args.length - 1]; // 最后一个command\n\t\t\t\tactionOpts = args[args.length - 2];\n\t\t\t\tactionArgs = args.slice(0, args.length - 2);\n\t\t\t}\n\t\t\tawait self.executeBeforeHooks({ args: actionArgs, options: actionOpts, command: cmd });\n\t\t\ttry {\n\t\t\t\tfor (let action of self._actions) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (action.enhance) {\n\t\t\t\t\t\t\t// 增强模式\n\t\t\t\t\t\t\toutputDebug(\"执行<{}>: args={}, options={}\", () => [\n\t\t\t\t\t\t\t\tself.name(),\n\t\t\t\t\t\t\t\tactionArgs,\n\t\t\t\t\t\t\t\tactionOpts,\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\tpreValue = await action.fn.call(this, {\n\t\t\t\t\t\t\t\tcommand: cmd,\n\t\t\t\t\t\t\t\tvalue : preValue,\n\t\t\t\t\t\t\t\targs : actionArgs,\n\t\t\t\t\t\t\t\toptions: actionOpts,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// 原始模式\n\t\t\t\t\t\t\tpreValue = await action.fn.apply(this, args);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (preValue === BREAK) break;\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\toutputDebug(\"命令{}的Action({})执行出错:{}\", [self.name, action.id, e]);\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tawait self.executeAfterHooks({\n\t\t\t\t\tvalue: preValue,\n\t\t\t\t\targs: actionArgs,\n\t\t\t\t\toptions: actionOpts,\n\t\t\t\t\tcommand: cmd,\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t}\n\t/**\n\t * 当传入--work-dirs时用来处理工作目录\n\t */\n\tprivate wrapperWorkDirsAction(fn: AsyncFunction) {\n\t\t// eslint-disable-next-line no-this-alias\n\t\tconst self = this;\n\t\treturn async function (this: any) {\n\t\t\tlet workDirs = self._optionValues.workDirs;\n\t\t\t// 未指定工作目录参数\n\t\t\tif (!workDirs) {\n\t\t\t\treturn await fn.apply(this, Array.from(arguments));\n\t\t\t}\n\t\t\tif (!Array.isArray(workDirs)) workDirs = workDirs.split(\",\");\n\t\t\tworkDirs = workDirs.reduce((dirs: any[], dir: string) => {\n\t\t\t\tif (typeof dir == \"string\") dirs.push(...dir.split(\",\"));\n\t\t\t\treturn dirs;\n\t\t\t}, []);\n\t\t\tfor (let workDir of workDirs) {\n\t\t\t\tconst cwd = process.cwd();\n\t\t\t\ttry {\n\t\t\t\t\tif (!path.isAbsolute(workDir)) workDir = path.join(cwd, workDir);\n\t\t\t\t\tif (fs.existsSync(workDir) && fs.statSync(workDir).isDirectory()) {\n\t\t\t\t\t\toutputDebug(\"切换到工作目录:{}\", workDir);\n\t\t\t\t\t\tprocess.chdir(workDir); // 切换\n\t\t\t\t\t\tawait fn.apply(this, Array.from(arguments));\n\t\t\t\t\t} else {\n\t\t\t\t\t\toutputDebug(\"无效的工作目录:{}\", workDir);\n\t\t\t\t\t} \n\t\t\t\t} finally {\n\t\t\t\t\tprocess.chdir(cwd);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\tgetOption(name: string): MixOption {\n\t\treturn this.options.find((option) => option.name() == name) as unknown as MixOption;\n\t}\n\t/**\n\t * 添加一个Before钩子\n\t * @param listener\n\t * @param scope =false时代表只在本命令执行,=true时代表在本命令及其子命令执行\n\t * @returns\n\t */\n\tbefore(listener: BeforeMixCommandHookListener, scope: boolean = true) {\n\t\tthis._beforeHooks.push([listener, scope]);\n\t\treturn this;\n\t}\n\tprivate async executeBeforeHooks(args: any) {\n\t\tconst hooks: [BeforeMixCommandHookListener, boolean, MixCommand][] = this.beforeHooks.map(\n\t\t\t([hook, scope]) => [hook, scope, this]\n\t\t);\n\t\tthis.getAncestorCommands().forEach((cmd: MixCommand) => {\n\t\t\thooks.unshift(\n\t\t\t\t...cmd.beforeHooks.map(([hook, scope]) => {\n\t\t\t\t\treturn [hook, scope, cmd] as [BeforeMixCommandHookListener, boolean, MixCommand];\n\t\t\t\t})\n\t\t\t);\n\t\t});\n\t\tfor (let [hook, scope, cmd] of hooks) {\n\t\t\tif (!scope) continue;\n\t\t\tawait hook.call(cmd, args);\n\t\t}\n\t}\n\t/**\n\t * 添加一个After钩子\n\t * @param listener\n\t * @param scope =false时代表只在本命令执行,=true时代表在本命令及其子命令执行\n\t * @returns\n\t */\n\tafter(listener: AfterMixCommandHookListener, scope: boolean = true) {\n\t\tthis._afterHooks.push([listener, scope]);\n\t\treturn this;\n\t}\n\n\tprivate async executeAfterHooks(args: any) {\n\t\tconst hooks: [AfterMixCommandHookListener, boolean, MixCommand][] = this.afterHooks.map(\n\t\t\t([hook, scope]) => [hook, scope, this]\n\t\t);\n\t\tthis.getAncestorCommands().forEach((cmd: MixCommand) => {\n\t\t\thooks.push(\n\t\t\t\t...cmd.afterHooks.map(([hook, scope]) => {\n\t\t\t\t\treturn [hook, scope, cmd] as [BeforeMixCommandHookListener, boolean, MixCommand];\n\t\t\t\t})\n\t\t\t);\n\t\t});\n\t\tfor (let [hook, scope, cmd] of hooks) {\n\t\t\tif (!scope) continue; //=false时不执行\n\t\t\tawait hook.call(cmd, args);\n\t\t}\n\t}\n\tprivate async preActionHook(thisCommand: Command) {\n\t\tif (this.isEnablePrompts()) {\n\t\t\t// 自动生成提示\n\t\t\tconst questions: PromptObject[] = [\n\t\t\t\t...this.generateAutoPrompts(),\n\t\t\t\t...this._customPrompts,\n\t\t\t];\n\t\t\t// 用户提示\n\t\t\tif (questions.length > 0) {\n\t\t\t\tconst results = await prompts(questions);\n\t\t\t\tObject.entries(results).forEach(([key, value]) => {\n\t\t\t\t\tthisCommand.setOptionValue(key, value);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate isEnablePrompts() {\n\t\tif (isDisablePrompts()) {\t\t\t\n\t\t\treturn false;// 命令行参数禁用了提示,优先级最高\n\t\t} else {\n\t\t\treturn this._enable_prompts;\n\t\t}\n\t}\n\n\t/**\n\t * 生成选项自动提示\n\t *\n\t * @remarks\n\t * 要求所有未提供默认值的Option自动生成提示\n\t *\n\t * - 未提供默认值,并且是必选的参数Option\n\t * - 指定了choices但未提供有效值的Option\n\t *\n\t */\n\tprivate generateAutoPrompts(): PromptObject[] {\n\t\tconst options = this.options as unknown as MixOption[];\n\t\tconst optionPromports = options\n\t\t\t.filter((option) => !option.hidden && option.__MIX_OPTION__)\n\t\t\t.map((option) => option.getPrompt(this._optionValues[option.attributeName()]))\n\t\t\t.filter((prompt) => prompt) as PromptObject[];\n\t\t\t\n\t\toutputDebug(\"命令<{}>自动生成{}个选项提示:{}\", [\n\t\t\tthis.name(),\n\t\t\toptionPromports.length,\n\t\t\toptionPromports.map((prompt) => `${prompt.name}(${prompt.type})`).join(\",\"),\n\t\t]);\n\t\treturn optionPromports;\n\t} \n\n\t// @ts-ignore\n\toption( flags: string, description: string, options?: MixedOptionParams ):this{ \n \t\tconst option = new MixOption(flags, description, options);\n\t\tif (option.required && !this.isEnablePrompts()) option.mandatory = true;\t\t\n\t\treturn this.addOption(option as unknown as Option) \n\t}\n\n\t/**\n\t * 添加提示\n\t *\n\t * @remarks\n\t *\n\t * 添加一些自定义提示 \n\t *\n\t * @param questions\n\t * @returns\n\t */\n\tprompt(questions: PromptObject | PromptObject[]) {\n\t\tthis._customPrompts.push(...(Array.isArray(questions) ? questions : [questions]));\n\t\treturn this;\n\t}\n\n\t/**\n\t *\n\t * 选择命令并执行\n\t *\n\t * @remorks\n\t *\n\t * 当命令具有多个子命令时,并且没有提供默认子命令时,提示用户选择一个子命令\n\t *\n\t */\n\tasync selectCommands() {\n\t\tconst choices = this.commands.map((command) => ({\n\t\t\ttitle: `${command.description()}(${command.name()})`,\n\t\t\tvalue: command.name(),\n\t\t}));\n\t\tconst result = await prompts({\n\t\t\ttype : \"select\",\n\t\t\tname : \"command\",\n\t\t\tmessage: \"请选择命令:\",\n\t\t\tchoices,\n\t\t});\n\t\t// 重新解析命令行参数标志,\n\t\tconst command = this.commands.find((command) => command.name() === result.command);\n\t\tawait command?.parseAsync([result.command], { from: \"user\" });\n\t}\n\t/**\n\t * 禁用/启用所有提示\n\t */\n\tdisablePrompts() {\n\t\tthis._enable_prompts = false;\n\t\treturn this;\n\t}\n\t/**\n\t * 启用所有提示\n\t */\n\tenablePrompts() {\n\t\tthis._enable_prompts = true;\n\t\treturn this;\n\t}\n}\n\n\n\n// 编写一个类型号用来表示Commander的Option flags字面量类型","import { Option, OptionValues } from 'commander'\nimport { PromptObject } from 'prompts'\nimport { PromptChoice, MixOptionPrompt,PromptParams } from './prompt'\n \n\nexport interface MixedOptionParams {\n required? : boolean; // A value must be supplied when the option is specified.\n optional? : boolean; // A value is optional when the option is specified.\n variadic? : boolean; \n mandatory? : boolean; // The option must have a value after parsing, which usually means it must be specified on command line.\n negate? : boolean;\n default? : any;\n defaultDescription? : string;\n conflicts? : string | string[];\n argParser? : unknown;\n implies? : OptionValues\n envVar? : string;\n parseArg? : <T>(value: string, previous: T) => T;\n hidden? : boolean;\n choices? : (string | PromptChoice )[] | ((pre:any,answers:any)=>(string | PromptChoice)[]);\n validate? : (value: any) => boolean;\n preset? : unknown;\n prompt? : PromptParams\n}\n\n\nexport class MixOption extends Option{\n __MIX_OPTION__ = true\n prompt? : MixOptionPrompt \n constructor(flags: string, description: string,public params?: MixedOptionParams) {\n super(flags, description) \n this._setOption(params || {}) \n this.prompt = new MixOptionPrompt(this,params?.prompt) \n } \n private _setOption(params:MixedOptionParams){ \n if(params.default) this.default(params.default,params.defaultDescription)\n if(params.conflicts) this.conflicts(params.conflicts)\n if(params.envVar) this.env(params.envVar)\n if(params.parseArg) this.argParser(params.parseArg) \n if(params.hidden) this.hidden = params.hidden\n if(params.mandatory) this.makeOptionMandatory(params.mandatory)\n if(params.implies) this.implies(params.implies) \n if(params.optional) this.optional=params.optional\n if(params.variadic) this.variadic = params.variadic\n if(params.negate) this.negate = params.negate\n if(params.preset) this.preset(params.preset)\n if(params.required) this.required = params.required \n if(Array.isArray(params.choices)) this.choices(params.choices.map(choice=>typeof(choice)=='string' ? choice : choice.value))\n } \n \n /**\n * 返回选项的提示对象\n * \n * @remarks \n * @param inputValue \n * @returns \n */\n getPrompt(inputValue?:any): PromptObject | undefined {\n return this.prompt?.get(inputValue)\n } \n}","import { isPlainObject } from \"flex-tools/typecheck/isPlainObject\"\nimport { isNumber } from \"flex-tools/typecheck/isNumber\"\n\nimport { PromptObject } from \"prompts\" \nimport { outputDebug } from \"./utils\"\nimport { MixOption } from \"./option\" \n\nexport type PromptType = \"text\" | \"password\" | \"invisible\" | \"number\"| \"confirm\"| \"list\" \n | \"toggle\"| \"select\" | \"multiselect\" | \"autocomplete\" | \"date\" | \"autocompleteMultiselect\"\n\nexport type PromptParam = 'auto' | boolean | PromptType | PromptObject\nexport type InputPromptParam = PromptParam | ((value:any)=>PromptParam) | boolean\nexport type PromptParamDefaultValue = string | boolean | string[] \n\nexport const promptTypeMap:Record<string,string> = {\n boolean: \"confirm\",\n string : \"text\",\n number : \"number\", \n array : \"list\", \n date : \"date\"\n} \n\nexport const supportedPromptTypes = [\n \"text\",\n \"password\",\n \"invisible\", \n \"number\", \n \"confirm\" , \n \"list\", \n \"toggle\" , \n \"select\" , \n \"multiselect\" , \n \"autocomplete\" , \n \"date\" , \n \"autocompleteMultiselect\"\n]\n\nexport interface PromptChoice {\n title : string;\n value? : any;\n disabled? : boolean | undefined;\n selected? : boolean | undefined;\n description?: string | undefined;\n}\n\n \nexport type PromptParams = Omit<PromptObject,'name'> | PromptType | boolean | 'auto' | undefined \n\n/**\n * 负责生成prompt对象\n * \n */\nexport class MixOptionPrompt{\n params?: PromptParams\n constructor(public cliOption:MixOption,promptParams?:PromptParams){ \n this.params = promptParams\n }\n /**\n * 返回输入的是否是有效的prompt类型\n * @param type \n * @returns \n */\n isValidPromptType(type:any){\n return supportedPromptTypes.includes(String(type))\n }\n /**\n * 推断是否需要提示\n * \n * 1. 显式指定prompt=true或者提示类型,或者提示对象,则需要提示\n * \n * \n */\n isNeedPrompt(input:any,defaultValue?:any){\n \n const params = this.params\n\n const inputValue = input || defaultValue\n\n // 是否有输入值,即在命令行输入了值\n const hasInput = !(inputValue === undefined)\n \n // 1. 显式指定了_prompt为true,则需要提示,后续进行提示类型的推断,可能不会准确\n if(params === true) return true\n if(params === false) return false \n if(params === 'auto') return !hasInput\n\n // 2. 提供了一个prompt对象,并且没有在命令行输入值,则需要提示\n if(isPlainObject(params)){\n return !hasInput\n }\n\n // 3. 指定了内置的prompt类型,如prompt='password',则使用password类型提示输入\n if(typeof(params) == 'string' && this.isValidPromptType(params)){\n return true\n }\n\n // 4. 指定了可选值,但是没有输入值,则需要提示\n const isOptional = /(\\<s*\\w\\s*\\>)/.test(this.cliOption.flags) \n if(isOptional) return !hasInput\n \n // 4. 判断输入是否有效,则显示提示\n if(this.cliOption.argChoices && this.cliOption.argChoices.indexOf(inputValue) == -1){\n return true\n } \n return !hasInput\n\n }\n \n private _getChoices(){\n let choices:(string | PromptChoice)[] | ((pre:any,answers:any)=>(string | PromptChoice)[]) = []\n let choicesParam = this.cliOption.params?.choices\n if(this.cliOption.argChoices){\n choices = this.cliOption.argChoices.map(choice=>{\n if(typeof(choice)=='string'){\n return {title:choice,value:choice}\n }else{\n return choice\n }\n })\n }else if(choicesParam){\n choices = typeof(choicesParam)=='function' ? choicesParam : [] \n }else{\n return []\n } \n return choices\n } \n\n /**\n * 自动推断prompt类型\n * \n * \n * \n * @param inputValue 从命令行输入的值\n */\n infer(inputValue?:any){\n\n const { variadic, defaultValue } = this.cliOption\n\n const input = inputValue || defaultValue\n\n // 如果选择指定了\"-p [value]或[value...]\",则使用text类型,如果没有要求输入值,则使用confirm类型\n let promptType:PromptType = 'text'\n\n const params = this.params\n\n if(this.isValidPromptType(params)){ // 显式指定了prompt类型,m则以指定的类型为准 \n promptType = params as PromptType\n }else if(isPlainObject(params)){ // 显式指定了prompt对象\n promptType = (params as PromptObject).type as PromptType\n }else{ // 自动推断prompt类型\n \n const isListType = /(\\[\\s*\\w+\\.\\.\\.\\s*])|(\\<\\s*\\w+\\.\\.\\.\\s*>)/.test(this.cliOption.flags)\n const isTextType = /(\\<s*\\w+\\s*\\>)|(\\[\\w+\\])/.test(this.cliOption.flags) \n const isBooleanType = !/(\\[\\s*\\w+s*])|(\\<\\s*\\w+\\s*>)/.test(this.cliOption.flags)\n const isNumberType = isNumber(defaultValue)\n const isDate = defaultValue && defaultValue instanceof Date\n\n // 根据默认值的类型推断\n const datatype:string = Array.isArray(input) ? 'array' : \n input instanceof Date ? 'date' :\n typeof(input) \n\n const optionParams = this.cliOption.params\n\n if(optionParams && optionParams.choices){\n const choices = optionParams.choices\n if(isBooleanType && (Array.isArray(choices) && choices.length==2)){\n promptType = 'toggle'\n }else{\n promptType = variadic ? 'multiselect' : 'select'\n } \n }else if(isListType){ // 提供多个可选值时\n promptType = 'list'\n }else if(isDate){\n promptType = 'date'\n }else if(isNumberType){\n promptType = 'number'\n }else if(isTextType){ // 提供一个可选值时\n promptType = 'text' \n }else if(isBooleanType || typeof(defaultValue)==='boolean'){\n promptType = 'confirm'\n }else if(datatype in promptTypeMap){\n promptType = promptTypeMap[datatype] as PromptType\n }\n }\n outputDebug(\"选项<{}> -> 提示类型<{}>\",[this.cliOption.name(),promptType])\n return promptType\n }\n /**\n * 返回生成prompt对象\n * \n * @param inputValue 从命令行输入的值\n */\n get(inputValue?:any){\n\n const { description, defaultValue } = this.cliOption\n \n let input = inputValue || defaultValue\n\n // 1. 判断是否需要启用提示\n if(!this.isNeedPrompt(input,defaultValue)) return\n\n // 2. 推断prompt类型\n const promptType = this.infer(inputValue)\n\n const prompt = {\n type : promptType, \n name : this.cliOption.attributeName(),\n message: description,\n initial: input,\n ...typeof(this.params) == 'object' ? this.params : {}\n } as PromptObject\n\n\n // 指定了验证函数,用来验证输入值是否有效\n prompt.validate = this.cliOption.params?.validate\n\n if(promptType=='multiselect') prompt.instructions=false\n prompt.choices = prompt.choices || this._getChoices() as any \n\n if(['select','multiselect'].includes(promptType)){ \n\n }else if(promptType=='toggle'){ \n if(Array.isArray(prompt.choices)){\n if(!prompt.active) prompt.active = prompt.choices[0].value\n if(!prompt.inactive) prompt.inactive = prompt.choices[1].value \n }\n }\n\n if(input && typeof(prompt.initial)!='function'){\n if(prompt.choices && Array.isArray(prompt.choices)){\n if(promptType=='select'){\n const index = Array.isArray(prompt.choices) ? prompt.choices.findIndex(item=>item.value==input) : -1\n if(index!=-1){\n prompt.initial = index\n }\n }else if(promptType=='multiselect'){ \n prompt.choices.forEach((item)=>{\n if(Array.isArray(input) && input.includes(item.value)){\n item.selected = true\n }else if(item.value==input){\n item.selected = true\n }\n })\n }\n }\n }\n\n return prompt\n }\n\n\n}","import fs from \"fs-extra\"\nimport path from \"node:path\"\nimport { promisify } from \"flex-tools/func/promisify\"\nimport logsets from \"logsets\" \n\n\n/**\n * \n * 在控制台输出一个字符串\n * 本方法会将字符串中的每一行空格去掉\n * \n * @remarks\n * \n * outputStr(String.raw`\n * a\n * b`)\n * \n * 会输出\n * a\n * b\n *\n * 此功能可以用于输出多行字符串时,保持代码的缩进格式,而不会影响输出结果\n * \n * @param str : 要输出的字符串\n * @param vars : 用于替换字符串中的变量\n * \n */\nexport function outputStr(str:string,vars?:Record<string,any> | any[]){ \n logsets.log(fixIndent(str),vars)\n}\n\n/**\n * 修正多行字符串的缩进\n * \n * @param text \n * @param indent \n * @returns \n */\nexport function fixIndent(text:string,indent?:boolean | number):string{\n let indentValue = (indent==undefined || indent===true) ? 0 : (typeof(indent)=='number' ? indent : -1)\n if(indentValue==-1) return text // 不修正缩进\n let lines:string[] = text.split(\"\\n\")\n let minSpaceCount = lines.reduce<number>((minCount,line,index)=>{\n if(index==0) return minCount\n const spaceCount = line.match(/^\\s*/)?.[0].length || 0\n return Math.min(minCount,spaceCount)\n },9999)\n lines = lines.map(line=>line.substring(minSpaceCount))\n return lines.join(\"\\n\")\n}\n\n/**\n * 增加内置选项\n * @param command \n */\nexport function addBuiltInOptions(command:any){ \n command.option(\"--work-dirs <values...>\",\"指定工作目录\",{hidden:true,optional:true,required:true,prompt:false})\n command.option(\"--disable-prompts\",\"禁用所有交互提示\",{hidden:true,prompt:false}) \n command.option(\"--debug-cli\",\"显示调试信息\",{hidden:true,prompt:false})\n}\n\n\n/**\n * 是否命令行中包含了--debug-cli选项\n */\nexport function isDebug(){\n return process.argv.includes(\"--debug-cli\")\n}\n\n\nexport function isDisablePrompts(){ \n return process.argv.includes(\"--disable-prompts\")\n}\n\n/**\n * 打印调试信息\n * @param message \n * @param args \n */\nexport function outputDebug(message:string,...args:any[]){ \n let vars = (args.length == 1 && typeof(args[0])=='function') ? args[0]() : args\n if(isDebug()) logsets.log(`[MixCli] ${message}`,...vars)\n}\n\nexport const fileExists = promisify(fs.exists,{\n parseCallback:(results)=>{\n return results[0]\n }\n})\nexport const readFile = promisify(fs.readFile)\nexport const writeFile = promisify(fs.writeFile)\nexport const mkdir = promisify(fs.mkdir)\n \n/** \n * 创建目录 \n * \n * \n * \n * @param {String[]} dirs 要创建的目录列表,类型为字符串数组 \n * @param callback 创建目录过程中的回调函数,类型为异步函数,接收一个参数 dir,表示当前正在创建的目录 \n * @returns 该函数返回一个 Promise 对象,表示创建目录的操作是否完成 \n */\nexport async function mkDirs(dirs:string[],{callback,base}:{callback?:Function,base?:string}){\n if(!Array.isArray(dirs)) throw new Error(\"dirs参数必须为字符串数组\")\n for(let dir of dirs){\n if(!path.isAbsolute(dir)) dir = path.join(base || process.cwd(),dir)\n if(typeof(callback)=='function') callback(dir)\n await mkdir(dir,{recursive:true})\n }\n}\n\nexport function showError(e:any){\n if(isDebug()){\n outputDebug(\"导入命令<>出错:{}\",e.stack)\n }else{\n console.error(e)\n } \n\n}\n\n// 编写一个函数,用于将使用-分隔的字符串转换为驼峰式\nexport function hyphenToCamelCase(str:string){\n return str.replace(/-([a-z])/g,(_,letter)=>letter.toUpperCase())\n}\n\nexport function getId(){\n return Math.random().toString(36).substr(2)\n}\n\n\nexport async function importModule(file:string){\n let module \n try{\n module = require(file)\n }catch(e:any){\n try{\n const cmd = await import(`file://${file}`)\n module = cmd.default\n }catch(e:any){\n throw e\n } \n }\n return module\n}\n","import { getPackageJson } from \"flex-tools/package/getPackageJson\"\nimport { getPackageRootPath } from 'flex-tools/package/getPackageRootPath';\nimport type { MixCli } from './cli';\nimport { globSync } from 'glob'\nimport { MixCliCommand } from './cli';\nimport { importModule, outputDebug } from './utils';\nimport fs from \"node:fs\"\nimport path from \"node:path\"\n\n\n/**\n * \n * 在当前工程中查找符合FlexCli.prefix约定的命令 \n * \n * - 读取当前包的package.json\n * - 找出所有以cli.prefix开头的依赖\n * - 加载这些依赖的目录下的匹配cli.pattern的命令\n * - 加载加载这样命令\n * \n */\n \n\nexport function getMatchedDependencies(this:MixCli,entry:string):string[]{\n const pacakgeMacher = this.options.include\n if(!(pacakgeMacher instanceof RegExp)) return []\n \n // 找出当前包的所有依赖\n const { dependencies={},devDependencies={},peerDependencies={},optionalDependencies={},bundleDependencies={} } = getPackageJson(entry)\n const packageNames = [\n ...Object.keys(dependencies),\n ...Object.keys(devDependencies),\n ...Object.keys(peerDependencies),\n ...Object.keys(optionalDependencies),\n ...Object.keys(bundleDependencies)\n ]\n return packageNames.filter(name=>name!==\"@voerka/cli\" && pacakgeMacher.test(name))\n}\n\nfunction isMatched(str:string,reg?:string | RegExp | string[] | RegExp[]):boolean{\n // let regexps:RegExp[]=[]\n const regexps = reg ? (Array.isArray(reg) ? reg : [reg]) : []\n return regexps.some(regexp=>{\n if(typeof regexp === \"string\"){\n return (new RegExp(regexp)).test(str)\n }else if(regexp instanceof RegExp){\n return regexp.test(str)\n }else{\n return false\n }\n })\n}\n\nexport function findCliPaths(this:MixCli,packageName?:string ,entry?:string):string[]{\n const includeMacher = this.options.include\n const excludeMacher = this.options.exclude\n if(!includeMacher) return []\n const packageRoot = getPackageRootPath(entry || process.cwd())\n const packagePath = packageName ? path.dirname(require.resolve(packageName,{paths:[packageRoot as string]})) : packageRoot\n\n if(!packagePath) {\n outputDebug(\"MixCli只能运行在Nodejs环境\" )\n return []\n }\n\n // 找出当前包的所有依赖\n const packageNames = getMatchedDependencies.call(this,packagePath)\n\n const cliDirs:string[]=[]\n \n if(entry!==undefined) cliDirs.push(path.join(packagePath,this.options.cliDir))\n packageNames.filter(name=>{\n return isMatched(name,includeMacher) && !isMatched(name,excludeMacher) \n })\n .forEach(name=>{\n outputDebug(\"匹配包:{}\",`${packageName ? name+\" <- \"+packageName : name}`)\n try{\n const packageEntry = path.dirname(require.resolve(name,{paths:packagePath ? [packagePath] : [process.cwd()]}))\n const packageCliDir =path.join(packageEntry,this.options.cliDir!) \n // 查找当前包的所属工程的依赖\n let dependencies = getMatchedDependencies.call(this,packageEntry)\n cliDirs.push(...dependencies.reduce<string[]>((result,dependencie)=>{\n outputDebug(\"匹配包:{}\",`${dependencie} <- ${name}`)\n result.push(...findCliPaths.call(this,dependencie,packageEntry))\n return result\n },[])) \n if(fs.existsSync(packageCliDir)){\n cliDirs.push(packageCliDir)\n }\n }catch(e:any){\n outputDebug(\"解析包<{}>路径出错:{}\",[name,e.stack])\n } \n })\n // 由于一些包可能存在循环依赖,所以需要去重\n return [...new Set(cliDirs)]\n}\n\n\n/**\n * \n * 扫描当前工程中所有符合条件的命令\n * \n * @param cli \n * \n */\nexport async function findCommands(cli:MixCli){ \n const cliDirs = findCliPaths.call(cli)\n const commands:MixCliCommand[] = []\n const files = [] as string[]\n cliDirs.forEach(dir=>{\n globSync(\"*\",{\n cwd:dir,\n absolute :true \n }).forEach((file:string)=>{ \n const baseName = path.basename(file) \n if(baseName.startsWith(\"_\")) return\n const ext = path.extname(file).toLowerCase()\n if([\".js\",\".cjs\",\".mjs\"].includes(ext)){\n files.push(file)\n }else if(fs.statSync(file).isDirectory()){\n files.push(path.join(file,\"index.js\"))\n files.push(path.join(file,\"index.cjs\"))\n files.push(path.join(file,\"index.mjs\"))\n }\n })\n })\n for(let file of files){ \n if(!fs.existsSync(file)) continue\n try{\n outputDebug(\"导入命令:{}\",file)\n if(file.endsWith(\".cjs\") || file.endsWith(\".js\")){\n commands.push(await importModule(file))\n }else if(file.endsWith(\".mjs\")){\n const cmd = await import(`file://${file}`)\n commands.push(cmd.default)\n } \n }catch(e:any){\n outputDebug(e) \n }\n }\n return commands\n}\n\n"],"mappings":"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","names":["index_exports","__export","BREAK","MixCli","MixCommand","MixOption","MixOptionPrompt","addBuiltInOptions","fileExists","fixIndent","getId","hyphenToCamelCase","importModule","isDebug","isDisablePrompts","mkDirs","mkdir","outputDebug","outputStr","promptTypeMap","readFile","showError","supportedPromptTypes","writeFile","__toCommonJS","import_string","import_liteEvent","import_logsets","import_assignObject","import_commander","import_prompts","import_commander","import_isPlainObject","import_isNumber","import_fs_extra","import_node_path","import_promisify","import_logsets","outputStr","str","vars","logsets","fixIndent","text","indent","lines","minSpaceCount","minCount","line","index","_a","spaceCount","addBuiltInOptions","command","isDebug","isDisablePrompts","outputDebug","message","args","fileExists","fs","results","readFile","writeFile","mkdir","mkDirs","_0","_1","__async","dirs","callback","base","dir","path","showError","e","hyphenToCamelCase","_","letter","getId","importModule","file","module","promptTypeMap","supportedPromptTypes","MixOptionPrompt","cliOption","promptParams","type","input","defaultValue","params","inputValue","hasInput","_a","choices","choicesParam","choice","variadic","promptType","isListType","isTextType","isBooleanType","isNumberType","isDate","datatype","optionParams","outputDebug","description","prompt","__spreadValues","index","item","MixOption","flags","description","params","MixOptionPrompt","choice","inputValue","_a","import_node_path","import_node_fs","BREAK","MixCommand","name","self","addBuiltInOptions","__async","names","parent","root","actionFunc","actionFn","actionOpts","actionItem","command","opts","cmds","cmd","args","preValue","actionArgs","action","outputDebug","e","fn","workDirs","dirs","dir","workDir","cwd","path","fs","option","listener","scope","hooks","hook","thisCommand","questions","results","prompts","key","value","isDisablePrompts","optionPromports","prompt","flags","description","options","MixOption","choices","result","import_getPackageJson","import_getPackageRootPath","import_glob","import_node_fs","import_node_path","getMatchedDependencies","entry","pacakgeMacher","dependencies","devDependencies","peerDependencies","optionalDependencies","bundleDependencies","name","isMatched","str","reg","regexp","findCliPaths","packageName","includeMacher","excludeMacher","packageRoot","packagePath","path","outputDebug","packageNames","cliDirs","packageEntry","packageCliDir","result","dependencie","fs","e","findCommands","cli","__async","commands","files","dir","file","ext","importModule","cmd","import_asyncSignal","import_string_prototype","replaceAll","MixCli","options","__async","cmders","findCommands","cmder","cmds","outputDebug","MixCommand","logsets","fixIndent","title","addBuiltInOptions","text","pos","alignIndent","cmd","result","name","c","names","curCmd","resultCmd","topName","r","signal","resolve","listener","fullname","s"]}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { LiteEvent } from 'flex-tools/events/liteEvent';
|
2
|
-
import { Option, Command } from 'commander';
|
2
|
+
import { OptionValues, Option, Command } from 'commander';
|
3
3
|
import { PromptObject } from 'prompts';
|
4
4
|
import * as flex_tools__ from 'flex-tools/*';
|
5
5
|
|
@@ -7,6 +7,8 @@ type PromptType = "text" | "password" | "invisible" | "number" | "confirm" | "li
|
|
7
7
|
type PromptParam = 'auto' | boolean | PromptType | PromptObject;
|
8
8
|
type InputPromptParam = PromptParam | ((value: any) => PromptParam) | boolean;
|
9
9
|
type PromptParamDefaultValue = string | boolean | string[];
|
10
|
+
declare const promptTypeMap: Record<string, string>;
|
11
|
+
declare const supportedPromptTypes: string[];
|
10
12
|
interface PromptChoice {
|
11
13
|
title: string;
|
12
14
|
value?: any;
|
@@ -14,128 +16,112 @@ interface PromptChoice {
|
|
14
16
|
selected?: boolean | undefined;
|
15
17
|
description?: string | undefined;
|
16
18
|
}
|
17
|
-
|
18
|
-
required?: boolean;
|
19
|
-
optional?: boolean;
|
20
|
-
default?: PromptParamDefaultValue;
|
21
|
-
choices?: (PromptChoice | any)[];
|
22
|
-
prompt?: InputPromptParam;
|
23
|
-
validate?: (value: any) => boolean;
|
24
|
-
}
|
25
|
-
interface IPromptable {
|
26
|
-
name(): string;
|
27
|
-
description?: string;
|
28
|
-
flags: string;
|
29
|
-
promptChoices?: PromptChoice[];
|
30
|
-
argChoices?: string[];
|
31
|
-
variadic?: boolean;
|
32
|
-
defaultValue?: PromptParamDefaultValue;
|
33
|
-
input?: any;
|
34
|
-
required?: boolean;
|
35
|
-
validate?: (value: any) => boolean;
|
36
|
-
getPrompt(inputValue?: any): PromptObject | undefined;
|
37
|
-
}
|
19
|
+
type PromptParams = Omit<PromptObject, 'name'> | PromptType | boolean | 'auto' | undefined;
|
38
20
|
/**
|
39
21
|
* 负责生成prompt对象
|
40
22
|
*
|
41
23
|
*/
|
42
|
-
declare class
|
43
|
-
|
44
|
-
|
45
|
-
constructor(
|
24
|
+
declare class MixOptionPrompt {
|
25
|
+
cliOption: MixOption;
|
26
|
+
params?: PromptParams;
|
27
|
+
constructor(cliOption: MixOption, promptParams?: PromptParams);
|
46
28
|
/**
|
47
29
|
* 返回输入的是否是有效的prompt类型
|
48
30
|
* @param type
|
49
31
|
* @returns
|
50
32
|
*/
|
51
|
-
|
33
|
+
isValidPromptType(type: any): boolean;
|
52
34
|
/**
|
53
35
|
* 推断是否需要提示
|
54
36
|
*
|
37
|
+
* 1. 显式指定prompt=true或者提示类型,或者提示对象,则需要提示
|
38
|
+
*
|
39
|
+
*
|
55
40
|
*/
|
56
|
-
|
41
|
+
isNeedPrompt(input: any, defaultValue?: any): boolean;
|
42
|
+
private _getChoices;
|
57
43
|
/**
|
58
|
-
*
|
44
|
+
* 自动推断prompt类型
|
45
|
+
*
|
46
|
+
*
|
59
47
|
*
|
60
48
|
* @param inputValue 从命令行输入的值
|
61
49
|
*/
|
62
|
-
|
50
|
+
infer(inputValue?: any): PromptType;
|
63
51
|
/**
|
64
|
-
*
|
52
|
+
* 返回生成prompt对象
|
65
53
|
*
|
66
54
|
* @param inputValue 从命令行输入的值
|
67
55
|
*/
|
68
|
-
|
56
|
+
get(inputValue?: any): PromptObject<string> | undefined;
|
69
57
|
}
|
70
58
|
|
71
|
-
interface MixedOptionParams
|
72
|
-
|
59
|
+
interface MixedOptionParams {
|
60
|
+
required?: boolean;
|
61
|
+
optional?: boolean;
|
62
|
+
variadic?: boolean;
|
63
|
+
mandatory?: boolean;
|
64
|
+
negate?: boolean;
|
65
|
+
default?: any;
|
73
66
|
defaultDescription?: string;
|
74
67
|
conflicts?: string | string[];
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
68
|
+
argParser?: unknown;
|
69
|
+
implies?: OptionValues;
|
70
|
+
envVar?: string;
|
71
|
+
parseArg?: <T>(value: string, previous: T) => T;
|
72
|
+
hidden?: boolean;
|
73
|
+
choices?: (string | PromptChoice)[] | ((pre: any, answers: any) => (string | PromptChoice)[]);
|
74
|
+
validate?: (value: any) => boolean;
|
75
|
+
preset?: unknown;
|
76
|
+
prompt?: PromptParams;
|
82
77
|
}
|
83
|
-
declare class MixOption extends Option
|
78
|
+
declare class MixOption extends Option {
|
79
|
+
params?: MixedOptionParams | undefined;
|
84
80
|
__MIX_OPTION__: boolean;
|
85
|
-
prompt?:
|
86
|
-
|
87
|
-
private
|
88
|
-
constructor(flags: string, description?: string | undefined, optsOrDefault?: any);
|
89
|
-
validate(value: any): boolean;
|
90
|
-
choices(values: (PromptChoice | string)[]): void;
|
91
|
-
private resetChoices;
|
92
|
-
addChoice(value: PromptChoice | string): void;
|
93
|
-
removeChoice(value: any): void;
|
94
|
-
clearChoice(): void;
|
81
|
+
prompt?: MixOptionPrompt;
|
82
|
+
constructor(flags: string, description: string, params?: MixedOptionParams | undefined);
|
83
|
+
private _setOption;
|
95
84
|
/**
|
96
85
|
* 返回选项的提示对象
|
97
86
|
*
|
98
87
|
* @remarks
|
99
|
-
*
|
100
|
-
*
|
101
|
-
*
|
102
88
|
* @param inputValue
|
103
89
|
* @returns
|
104
90
|
*/
|
105
91
|
getPrompt(inputValue?: any): PromptObject | undefined;
|
106
92
|
}
|
107
93
|
|
108
|
-
type
|
94
|
+
type IMixCommandHookListener = ({ args, options, command, }: {
|
109
95
|
args: any[];
|
110
96
|
options: Record<string, any>;
|
111
97
|
command: MixCommand;
|
112
98
|
}) => void | Promise<void>;
|
113
|
-
type
|
99
|
+
type BeforeMixCommandHookListener = ({ args, options, command, }: {
|
114
100
|
args: any[];
|
115
101
|
options: Record<string, any>;
|
116
102
|
command: MixCommand;
|
117
103
|
}) => void | Promise<void>;
|
118
|
-
type
|
104
|
+
type AfterMixCommandHookListener = ({ value, args, options, command, }: {
|
119
105
|
value: any;
|
120
106
|
args: any[];
|
121
107
|
options: Record<string, any>;
|
122
108
|
command: MixCommand;
|
123
109
|
}) => void | Promise<void>;
|
124
|
-
interface
|
110
|
+
interface MixActionOptions {
|
125
111
|
id: string;
|
126
112
|
at: "replace" | "before" | "after" | "preappend" | "append" | number;
|
127
113
|
enhance: boolean;
|
128
114
|
}
|
129
|
-
interface
|
115
|
+
interface MixActionRegistry extends Omit<MixActionOptions, "at"> {
|
130
116
|
fn: Function;
|
131
117
|
}
|
132
|
-
type
|
133
|
-
type
|
118
|
+
type MixOriginalAction = (...args: any[]) => any | Promise<void>;
|
119
|
+
type MixEnhanceAction = ({ args, options, value, command, }: {
|
134
120
|
args: any[];
|
135
121
|
options: Record<string, any>;
|
136
122
|
value: any;
|
137
123
|
command: MixCommand;
|
138
|
-
}) =>
|
124
|
+
}) => any | Promise<any>;
|
139
125
|
declare const BREAK: unique symbol;
|
140
126
|
declare class MixCommand extends Command {
|
141
127
|
__MIX_COMMAND__: boolean;
|
@@ -146,20 +132,18 @@ declare class MixCommand extends Command {
|
|
146
132
|
private _actions;
|
147
133
|
private _enable_prompts;
|
148
134
|
constructor(name?: string);
|
149
|
-
/**
|
150
|
-
* 是否是根命令
|
151
|
-
*/
|
152
135
|
get isRoot(): boolean;
|
153
|
-
get
|
154
|
-
get
|
155
|
-
get
|
136
|
+
get optionValues(): Record<string, any>;
|
137
|
+
get actions(): MixActionRegistry[];
|
138
|
+
get beforeHooks(): [BeforeMixCommandHookListener, boolean][];
|
139
|
+
get afterHooks(): [AfterMixCommandHookListener, boolean][];
|
156
140
|
get fullname(): string;
|
157
141
|
/**
|
158
142
|
* 返回根命令
|
159
143
|
*/
|
160
|
-
root():
|
161
|
-
action(fn:
|
162
|
-
action(fn:
|
144
|
+
root(): any;
|
145
|
+
action(fn: MixEnhanceAction, options: MixActionOptions): this;
|
146
|
+
action(fn: MixOriginalAction): this;
|
163
147
|
/**
|
164
148
|
* 读取命令配置值,包括父命令提供的配置选项
|
165
149
|
* @param command
|
@@ -188,7 +172,7 @@ declare class MixCommand extends Command {
|
|
188
172
|
* @param scope =false时代表只在本命令执行,=true时代表在本命令及其子命令执行
|
189
173
|
* @returns
|
190
174
|
*/
|
191
|
-
before(listener:
|
175
|
+
before(listener: BeforeMixCommandHookListener, scope?: boolean): this;
|
192
176
|
private executeBeforeHooks;
|
193
177
|
/**
|
194
178
|
* 添加一个After钩子
|
@@ -196,7 +180,7 @@ declare class MixCommand extends Command {
|
|
196
180
|
* @param scope =false时代表只在本命令执行,=true时代表在本命令及其子命令执行
|
197
181
|
* @returns
|
198
182
|
*/
|
199
|
-
after(listener:
|
183
|
+
after(listener: AfterMixCommandHookListener, scope?: boolean): this;
|
200
184
|
private executeAfterHooks;
|
201
185
|
private preActionHook;
|
202
186
|
private isEnablePrompts;
|
@@ -204,14 +188,14 @@ declare class MixCommand extends Command {
|
|
204
188
|
* 生成选项自动提示
|
205
189
|
*
|
206
190
|
* @remarks
|
207
|
-
*
|
191
|
+
* 要求所有未提供默认值的Option自动生成提示
|
208
192
|
*
|
209
193
|
* - 未提供默认值,并且是必选的参数Option
|
210
194
|
* - 指定了choices但未提供有效值的Option
|
211
195
|
*
|
212
196
|
*/
|
213
197
|
private generateAutoPrompts;
|
214
|
-
option(flags: string, description
|
198
|
+
option(flags: string, description: string, options?: MixedOptionParams): this;
|
215
199
|
/**
|
216
200
|
* 添加提示
|
217
201
|
*
|
@@ -219,9 +203,7 @@ declare class MixCommand extends Command {
|
|
219
203
|
*
|
220
204
|
* 添加一些自定义提示
|
221
205
|
*
|
222
|
-
*
|
223
206
|
* @param questions
|
224
|
-
* @param show 是否显示提示信息,auto表示只有在用户没有提供option的值时才显示提示信息,always表示总是显示提示信息,never表示不显示提示信息
|
225
207
|
* @returns
|
226
208
|
*/
|
227
209
|
prompt(questions: PromptObject | PromptObject[]): this;
|
@@ -239,6 +221,9 @@ declare class MixCommand extends Command {
|
|
239
221
|
* 禁用/启用所有提示
|
240
222
|
*/
|
241
223
|
disablePrompts(): this;
|
224
|
+
/**
|
225
|
+
* 启用所有提示
|
226
|
+
*/
|
242
227
|
enablePrompts(): this;
|
243
228
|
}
|
244
229
|
|
@@ -261,7 +246,7 @@ type MixCliCommand = (cli: MixCli) => MixCommand | MixCommand[] | void;
|
|
261
246
|
type MixCliEvents = "register";
|
262
247
|
declare class MixCli extends LiteEvent<any, MixCliEvents> {
|
263
248
|
options: Required<MixCliOptions>;
|
264
|
-
root:
|
249
|
+
root: MixCommand;
|
265
250
|
private findSignals;
|
266
251
|
constructor(options?: MixCliOptions);
|
267
252
|
get context(): Record<string, any>;
|
@@ -331,12 +316,6 @@ declare class MixCli extends LiteEvent<any, MixCliEvents> {
|
|
331
316
|
* 运行命令行程序
|
332
317
|
*/
|
333
318
|
run(): void;
|
334
|
-
/**
|
335
|
-
* 创建一个命令
|
336
|
-
*
|
337
|
-
*
|
338
|
-
*/
|
339
|
-
create(): void;
|
340
319
|
}
|
341
320
|
|
342
321
|
/**
|
@@ -378,7 +357,7 @@ declare function addBuiltInOptions(command: any): void;
|
|
378
357
|
* 是否命令行中包含了--debug-cli选项
|
379
358
|
*/
|
380
359
|
declare function isDebug(): boolean;
|
381
|
-
declare function
|
360
|
+
declare function isDisablePrompts(): boolean;
|
382
361
|
/**
|
383
362
|
* 打印调试信息
|
384
363
|
* @param message
|
@@ -389,13 +368,6 @@ declare const fileExists: flex_tools__.AsyncFunction;
|
|
389
368
|
declare const readFile: flex_tools__.AsyncFunction;
|
390
369
|
declare const writeFile: flex_tools__.AsyncFunction;
|
391
370
|
declare const mkdir: flex_tools__.AsyncFunction;
|
392
|
-
/**
|
393
|
-
* 基于artTemplate模板生成文件
|
394
|
-
*
|
395
|
-
* @param {*} tmplFile
|
396
|
-
* @param {*} vars
|
397
|
-
*/
|
398
|
-
declare function createFileByTemplate(targetFile: string, tmplFile: string, vars?: Record<string, any>): Promise<string>;
|
399
371
|
/**
|
400
372
|
* 创建目录
|
401
373
|
*
|
@@ -410,7 +382,8 @@ declare function mkDirs(dirs: string[], { callback, base }: {
|
|
410
382
|
base?: string;
|
411
383
|
}): Promise<void>;
|
412
384
|
declare function showError(e: any): void;
|
385
|
+
declare function hyphenToCamelCase(str: string): string;
|
413
386
|
declare function getId(): string;
|
414
387
|
declare function importModule(file: string): Promise<any>;
|
415
388
|
|
416
|
-
export { type
|
389
|
+
export { type AfterMixCommandHookListener, BREAK, type BeforeMixCommandHookListener, type IMixCommandHookListener, type InputPromptParam, type MixActionOptions, type MixActionRegistry, MixCli, type MixCliCommand, type MixCliEvents, type MixCliOptions, MixCommand, type MixEnhanceAction, MixOption, MixOptionPrompt, type MixOriginalAction, type MixedOptionParams, type PromptChoice, type PromptParam, type PromptParamDefaultValue, type PromptParams, type PromptType, addBuiltInOptions, fileExists, fixIndent, getId, hyphenToCamelCase, importModule, isDebug, isDisablePrompts, mkDirs, mkdir, outputDebug, outputStr, promptTypeMap, readFile, showError, supportedPromptTypes, writeFile };
|