mixcli 3.2.0 → 3.2.1

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.js CHANGED
@@ -1,1133 +1,4 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
7
- var __getProtoOf = Object.getPrototypeOf;
8
- var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
10
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
11
- var __spreadValues = (a, b) => {
12
- for (var prop in b || (b = {}))
13
- if (__hasOwnProp.call(b, prop))
14
- __defNormalProp(a, prop, b[prop]);
15
- if (__getOwnPropSymbols)
16
- for (var prop of __getOwnPropSymbols(b)) {
17
- if (__propIsEnum.call(b, prop))
18
- __defNormalProp(a, prop, b[prop]);
19
- }
20
- return a;
21
- };
22
- var __export = (target, all) => {
23
- for (var name in all)
24
- __defProp(target, name, { get: all[name], enumerable: true });
25
- };
26
- var __copyProps = (to, from, except, desc) => {
27
- if (from && typeof from === "object" || typeof from === "function") {
28
- for (let key of __getOwnPropNames(from))
29
- if (!__hasOwnProp.call(to, key) && key !== except)
30
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
31
- }
32
- return to;
33
- };
34
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
35
- // If the importer is in node compatibility mode or this is not an ESM
36
- // file that has been converted to a CommonJS file using a Babel-
37
- // compatible transform (i.e. "__esModule" has not been set), then set
38
- // "default" to the CommonJS "module.exports" for node compatibility.
39
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
40
- mod
41
- ));
42
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
43
- var __async = (__this, __arguments, generator) => {
44
- return new Promise((resolve, reject) => {
45
- var fulfilled = (value) => {
46
- try {
47
- step(generator.next(value));
48
- } catch (e) {
49
- reject(e);
50
- }
51
- };
52
- var rejected = (value) => {
53
- try {
54
- step(generator.throw(value));
55
- } catch (e) {
56
- reject(e);
57
- }
58
- };
59
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
60
- step((generator = generator.apply(__this, __arguments)).next());
61
- });
62
- };
63
-
64
- // src/index.ts
65
- var src_exports = {};
66
- __export(src_exports, {
67
- BREAK: () => BREAK,
68
- MixCli: () => MixCli,
69
- MixCommand: () => MixCommand,
70
- MixOption: () => MixOption,
71
- addBuiltInOptions: () => addBuiltInOptions,
72
- createFileByTemplate: () => createFileByTemplate,
73
- fileExists: () => fileExists,
74
- fixIndent: () => fixIndent,
75
- getId: () => getId,
76
- importModule: () => importModule,
77
- isDebug: () => isDebug,
78
- isEnablePrompts: () => isEnablePrompts,
79
- mkDirs: () => mkDirs,
80
- mkdir: () => mkdir,
81
- outputDebug: () => outputDebug,
82
- outputStr: () => outputStr,
83
- readFile: () => readFile,
84
- showError: () => showError,
85
- writeFile: () => writeFile
86
- });
87
- module.exports = __toCommonJS(src_exports);
88
-
89
- // src/cli.ts
90
- var import_string = require("flex-tools/string");
91
- var import_liteEvent = require("flex-tools/events/liteEvent");
92
- var import_logsets2 = __toESM(require("logsets"));
93
- var import_assignObject = require("flex-tools/object/assignObject");
94
-
95
- // src/command.ts
96
- var import_commander2 = require("commander");
97
- var import_prompts = __toESM(require("prompts"));
98
-
99
- // src/option.ts
100
- var import_commander = require("commander");
101
-
102
- // src/utils.ts
103
- var import_art_template = __toESM(require("art-template"));
104
- var import_fs_extra = __toESM(require("fs-extra"));
105
- var import_node_path = __toESM(require("path"));
106
- var import_promisify = require("flex-tools/func/promisify");
107
- var import_logsets = __toESM(require("logsets"));
108
- function outputStr(str, vars) {
109
- import_logsets.default.log(fixIndent(str), vars);
110
- }
111
- function fixIndent(text, indent) {
112
- let indentValue = indent == void 0 || indent === true ? 0 : typeof indent == "number" ? indent : -1;
113
- if (indentValue == -1)
114
- return text;
115
- let lines = text.split("\n");
116
- let minSpaceCount = lines.reduce((minCount, line, index) => {
117
- var _a;
118
- if (index == 0)
119
- return minCount;
120
- const spaceCount = ((_a = line.match(/^\s*/)) == null ? void 0 : _a[0].length) || 0;
121
- return Math.min(minCount, spaceCount);
122
- }, 9999);
123
- lines = lines.map((line) => line.substring(minSpaceCount));
124
- return lines.join("\n");
125
- }
126
- function addBuiltInOptions(command) {
127
- command.option("--work-dirs <values...>", "\u6307\u5B9A\u5DE5\u4F5C\u76EE\u5F55", { hidden: true, optional: true, required: true, prompt: false });
128
- command.option("--disable-prompts", "\u7981\u7528\u6240\u6709\u4EA4\u4E92\u63D0\u793A", { hidden: true, prompt: false });
129
- command.option("--debug-cli", "\u663E\u793A\u8C03\u8BD5\u4FE1\u606F", { hidden: true, prompt: false });
130
- }
131
- function isDebug() {
132
- return process.argv.includes("--debug-cli");
133
- }
134
- function isEnablePrompts() {
135
- return !process.argv.includes("--disable-prompts");
136
- }
137
- function outputDebug(message, ...args) {
138
- let vars = args.length == 1 && typeof args[0] == "function" ? args[0]() : args;
139
- if (isDebug())
140
- import_logsets.default.log(`[MixCli] ${message}`, ...vars);
141
- }
142
- var fileExists = (0, import_promisify.promisify)(import_fs_extra.default.exists, {
143
- parseCallback: (results) => {
144
- return results[0];
145
- }
146
- });
147
- var readFile = (0, import_promisify.promisify)(import_fs_extra.default.readFile);
148
- var writeFile = (0, import_promisify.promisify)(import_fs_extra.default.writeFile);
149
- var mkdir = (0, import_promisify.promisify)(import_fs_extra.default.mkdir);
150
- function createFileByTemplate(_0, _1) {
151
- return __async(this, arguments, function* (targetFile, tmplFile, vars = {}) {
152
- tmplFile = import_node_path.default.isAbsolute(tmplFile) ? tmplFile : import_node_path.default.join(process.cwd(), tmplFile);
153
- if (!import_fs_extra.default.existsSync(tmplFile)) {
154
- throw new Error("\u6A21\u677F\u6587\u4EF6\u4E0D\u5B58\u5728:" + tmplFile);
155
- }
156
- targetFile = import_node_path.default.isAbsolute(targetFile) ? targetFile : import_node_path.default.join(process.cwd(), targetFile);
157
- const outPath = import_node_path.default.dirname(targetFile);
158
- if (!(yield fileExists(outPath))) {
159
- yield mkdir(outPath, { recursive: true });
160
- }
161
- const template = (0, import_art_template.default)(tmplFile, yield readFile(tmplFile, { encoding: "utf-8" }));
162
- yield writeFile(targetFile, template(vars), { encoding: "utf-8" });
163
- return targetFile;
164
- });
165
- }
166
- function mkDirs(_0, _1) {
167
- return __async(this, arguments, function* (dirs, { callback, base }) {
168
- if (!Array.isArray(dirs))
169
- throw new Error("dirs\u53C2\u6570\u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32\u6570\u7EC4");
170
- for (let dir of dirs) {
171
- if (!import_node_path.default.isAbsolute(dir))
172
- dir = import_node_path.default.join(base || process.cwd(), dir);
173
- if (typeof callback == "function")
174
- callback(dir);
175
- yield mkdir(dir, { recursive: true });
176
- }
177
- });
178
- }
179
- function showError(e) {
180
- if (isDebug()) {
181
- outputDebug("\u5BFC\u5165\u547D\u4EE4<>\u51FA\u9519:{}", e.stack);
182
- } else {
183
- console.error(e);
184
- }
185
- }
186
- function getId() {
187
- return Math.random().toString(36).substr(2);
188
- }
189
- function importModule(file) {
190
- return __async(this, null, function* () {
191
- let module2;
192
- try {
193
- module2 = require(file);
194
- } catch (e) {
195
- try {
196
- const cmd = yield import(`file://${file}`);
197
- module2 = cmd.default;
198
- } catch (e2) {
199
- throw e2;
200
- }
201
- }
202
- return module2;
203
- });
204
- }
205
-
206
- // src/prompt.ts
207
- var promptTypeMap = {
208
- boolean: "confirm",
209
- string: "text",
210
- number: "number",
211
- array: "list"
212
- };
213
- var supportedPromptTypes = ["text", "password", "invisible", "number", "confirm", "list", "toggle", "select", "multiselect", "autocomplete", "date", "autocompleteMultiselect"];
214
- var PromptManager = class {
215
- // 对应的FlexOption或FlexArgument
216
- constructor(promptable, promptArgs) {
217
- this._promptable = promptable;
218
- this.args = promptArgs === void 0 ? "auto" : promptArgs;
219
- }
220
- /**
221
- * 返回输入的是否是有效的prompt类型
222
- * @param type
223
- * @returns
224
- */
225
- isValid(type) {
226
- return supportedPromptTypes.includes(String(type));
227
- }
228
- /**
229
- * 推断是否需要提示
230
- *
231
- */
232
- isNeed(input, defaultValue) {
233
- const promptArg = this.args;
234
- const inputValue = input || defaultValue;
235
- const hasInput = !(inputValue === void 0);
236
- if (promptArg === true)
237
- return true;
238
- if (promptArg === false)
239
- return false;
240
- if (typeof promptArg == "object") {
241
- return !hasInput;
242
- }
243
- if (typeof promptArg == "string" && supportedPromptTypes.includes(promptArg)) {
244
- return !hasInput;
245
- }
246
- if (this._promptable.argChoices && this._promptable.argChoices.indexOf(inputValue) == -1) {
247
- return true;
248
- }
249
- return !hasInput;
250
- }
251
- /**
252
- * 返回生成prompt对象
253
- *
254
- * @param inputValue 从命令行输入的值
255
- */
256
- get(inputValue) {
257
- const { description, promptChoices, validate, defaultValue } = this._promptable;
258
- let input = inputValue || defaultValue;
259
- if (!this.isNeed(input, defaultValue))
260
- return;
261
- let promptType = this.infer(inputValue);
262
- const prompt = __spreadValues({
263
- type: promptType,
264
- name: this._promptable.name(),
265
- message: description,
266
- initial: input
267
- }, typeof this.args == "object" ? this.args : {});
268
- prompt.validate = validate == null ? void 0 : validate.bind(this._promptable);
269
- if (promptType == "multiselect")
270
- prompt.instructions = false;
271
- if (["select", "multiselect"].includes(promptType)) {
272
- let index = promptChoices == null ? void 0 : promptChoices.findIndex((item) => item.value == input);
273
- prompt.initial = index == -1 ? void 0 : index;
274
- }
275
- if (Array.isArray(promptChoices)) {
276
- prompt.choices = promptChoices;
277
- }
278
- return prompt;
279
- }
280
- /**
281
- * 推断prompt类型
282
- *
283
- * @param inputValue 从命令行输入的值
284
- */
285
- infer(inputValue) {
286
- const { argChoices, variadic, defaultValue } = this._promptable;
287
- let input = inputValue || defaultValue;
288
- let promptType = /(\<[\w\.]+\>)|(\[[\w\.]+\])/.test(this._promptable.flags) ? "text" : "confirm";
289
- let promptArg = this.args;
290
- if (this.isValid(promptArg)) {
291
- promptType = promptArg;
292
- } else {
293
- if (typeof promptArg == "object") {
294
- promptType = promptArg.type;
295
- } else {
296
- if (argChoices) {
297
- promptType = variadic ? "multiselect" : "select";
298
- } else {
299
- const datatype = Array.isArray(defaultValue) ? "array" : typeof defaultValue;
300
- if (Array.isArray(input) || variadic) {
301
- promptType = "list";
302
- } else {
303
- if (datatype in promptTypeMap) {
304
- promptType = promptTypeMap[datatype];
305
- }
306
- }
307
- }
308
- }
309
- }
310
- outputDebug("\u9009\u9879<{}> -> \u63D0\u793A\u7C7B\u578B<{}>", [this._promptable.name(), promptType]);
311
- return promptType;
312
- }
313
- };
314
-
315
- // src/option.ts
316
- var MixOption = class extends import_commander.Option {
317
- constructor(flags, description, optsOrDefault) {
318
- super(flags, description);
319
- this.__MIX_OPTION__ = true;
320
- let params = {};
321
- if (arguments.length == 3 && typeof arguments[2] == "object") {
322
- params = Object.assign({}, arguments[2]);
323
- } else if (arguments.length == 3) {
324
- params.default = arguments[2];
325
- }
326
- if (params.prompt === void 0)
327
- params.prompt = "auto";
328
- if (params.default)
329
- this.default(params.default, params.defaultDescription);
330
- if (params.choices)
331
- this.choices(params.choices);
332
- if (params.conflicts)
333
- this.conflicts(params.conflicts);
334
- if (params.env)
335
- this.env(params.env);
336
- if (params.argParser)
337
- this.argParser(params.argParser);
338
- if (params.hideHelp)
339
- this.hideHelp(params.hideHelp);
340
- if (params.hidden)
341
- this.hidden = params.hidden;
342
- if (params.mandatory)
343
- this.makeOptionMandatory(params.mandatory);
344
- if (params.implies)
345
- this.implies(params.implies);
346
- if (params.optional)
347
- this.optional = params.optional;
348
- if (typeof params.validate == "function")
349
- this._validate = params.validate.bind(this);
350
- if (params.required) {
351
- this.required = params.required;
352
- if (!this._validate)
353
- this._validate = (value) => String(value).length > 0;
354
- }
355
- this.prompt = new PromptManager(this, params.prompt);
356
- }
357
- validate(value) {
358
- if (typeof this._validate == "function") {
359
- return this._validate(value);
360
- } else {
361
- return true;
362
- }
363
- }
364
- // @ts-ignore
365
- choices(values) {
366
- if (!this.promptChoices) {
367
- this.promptChoices = values.map((choice) => {
368
- if (typeof choice == "object") {
369
- return choice;
370
- } else {
371
- return { title: choice, value: choice };
372
- }
373
- });
374
- }
375
- super.choices(this.promptChoices.map((item) => item.value));
376
- }
377
- resetChoices() {
378
- super.choices(this.promptChoices.map((item) => item.value));
379
- }
380
- addChoice(value) {
381
- if (!this.promptChoices || !Array.isArray(this.promptChoices))
382
- this.promptChoices = [];
383
- this.promptChoices.push(typeof value == "string" ? { title: value, value } : value);
384
- this.resetChoices();
385
- }
386
- removeChoice(value) {
387
- var _a;
388
- this.promptChoices = (_a = this.promptChoices) == null ? void 0 : _a.filter((choice) => choice.value !== value);
389
- this.resetChoices();
390
- }
391
- clearChoice() {
392
- this.promptChoices = [];
393
- this.resetChoices();
394
- }
395
- /**
396
- * 返回选项的提示对象
397
- *
398
- * @remarks
399
- *
400
- *
401
- *
402
- * @param inputValue
403
- * @returns
404
- */
405
- getPrompt(inputValue) {
406
- var _a;
407
- return (_a = this.prompt) == null ? void 0 : _a.get(inputValue);
408
- }
409
- };
410
-
411
- // src/command.ts
412
- var import_node_path2 = __toESM(require("path"));
413
- var import_node_fs = __toESM(require("fs"));
414
- var BREAK = Symbol("BREAK_ACTION");
415
- var MixCommand = class extends import_commander2.Command {
416
- // 是否启用交互提示
417
- constructor(name) {
418
- super(name);
419
- this.__MIX_COMMAND__ = true;
420
- this._beforeHooks = [];
421
- this._afterHooks = [];
422
- this._customPrompts = [];
423
- this._optionValues = {};
424
- // 命令行输入的选项值
425
- this._actions = [];
426
- // 允许多个action
427
- this._enable_prompts = true;
428
- const self = this;
429
- if (!this.isRoot)
430
- addBuiltInOptions(this);
431
- this.hook("preAction", function() {
432
- return __async(this, arguments, function* () {
433
- self._optionValues = self.getOptionValues(this.hookedCommand);
434
- try {
435
- yield self.preActionHook.apply(self, arguments);
436
- } catch (e) {
437
- }
438
- });
439
- });
440
- }
441
- /**
442
- * 是否是根命令
443
- */
444
- get isRoot() {
445
- return !!!this.parent;
446
- }
447
- get actions() {
448
- return this._actions;
449
- }
450
- get beforeHooks() {
451
- return this._beforeHooks;
452
- }
453
- get afterHooks() {
454
- return this._afterHooks;
455
- }
456
- get fullname() {
457
- let names = [this.name()];
458
- let parent = this.parent;
459
- while (parent) {
460
- if (parent.name() !== "root") {
461
- names.unshift(parent.name());
462
- }
463
- parent = parent.parent;
464
- }
465
- return names.join(".");
466
- }
467
- /**
468
- * 返回根命令
469
- */
470
- root() {
471
- let root = this;
472
- while (root && root.parent != null) {
473
- root = root.parent;
474
- }
475
- return root;
476
- }
477
- action(fn) {
478
- const actionFunc = arguments[0];
479
- if (arguments.length == 1 && typeof actionFunc == "function") {
480
- this._actions.push({
481
- id: Math.random().toString(36).substring(2),
482
- enhance: false,
483
- fn: actionFunc
484
- });
485
- } else if (arguments.length == 2 && typeof actionFunc == "function" && typeof arguments[1] == "object") {
486
- const actionFn = arguments[0];
487
- const actionOpts = Object.assign({ at: "append" }, arguments[1]);
488
- if (actionOpts.at == "replace")
489
- this._actions = [];
490
- const actionItem = {
491
- id: actionOpts.id || Math.random().toString(36).substring(2),
492
- enhance: actionOpts.enhance == void 0 ? true : actionOpts.enhance,
493
- fn: actionFn
494
- };
495
- if (typeof actionOpts.at == "number") {
496
- this._actions.splice(Number(actionOpts.at), 0, actionItem);
497
- } else if (["append", "before"].includes(actionOpts.at)) {
498
- this._actions.push(actionItem);
499
- } else if (["preappend", "after"].includes(actionOpts.at)) {
500
- this._actions.splice(0, 0, actionItem);
501
- } else {
502
- this._actions.push(actionItem);
503
- }
504
- } else {
505
- console.log("[mixcli] action params error");
506
- }
507
- return super.action(this.getWrapperedAction());
508
- }
509
- /**
510
- * 读取命令配置值,包括父命令提供的配置选项
511
- * @param command
512
- */
513
- getOptionValues(command) {
514
- let opts = {};
515
- let parent = command;
516
- while (parent) {
517
- Object.assign(opts, parent._optionValues);
518
- parent = parent.parent;
519
- }
520
- return opts;
521
- }
522
- /**
523
- * 本函数在运行时子类进行action生成该命令的action
524
- */
525
- getWrapperedAction() {
526
- return this.wrapperWorkDirsAction(this.wrapperChainActions());
527
- }
528
- /**
529
- * 向上查找所有祖先命令
530
- */
531
- getAncestorCommands() {
532
- let cmds = [];
533
- let cmd = this;
534
- while (cmd) {
535
- cmd = cmd.parent;
536
- if (cmd) {
537
- cmds.push(cmd);
538
- }
539
- }
540
- return cmds;
541
- }
542
- /***
543
- * 将所有actions包装成一个链式调用的函数
544
- */
545
- wrapperChainActions() {
546
- const self = this;
547
- return function() {
548
- return __async(this, arguments, function* () {
549
- const args = Array.from(arguments);
550
- let preValue;
551
- let actionOpts = {}, actionArgs = [], cmd;
552
- if (args.length >= 2) {
553
- cmd = args[args.length - 1];
554
- actionOpts = args[args.length - 2];
555
- actionArgs = args.slice(0, args.length - 2);
556
- }
557
- yield self.executeBeforeHooks({ args: actionArgs, options: actionOpts, command: cmd });
558
- try {
559
- for (let action of self._actions) {
560
- try {
561
- if (action.enhance) {
562
- outputDebug("\u6267\u884C<{}>: args={}, options={}", () => [
563
- self.name(),
564
- actionArgs,
565
- actionOpts
566
- ]);
567
- preValue = yield action.fn.call(this, {
568
- command: cmd,
569
- value: preValue,
570
- args: actionArgs,
571
- options: actionOpts
572
- });
573
- } else {
574
- preValue = yield action.fn.apply(this, args);
575
- }
576
- if (preValue === BREAK)
577
- break;
578
- } catch (e) {
579
- outputDebug("\u547D\u4EE4{}\u7684Action({})\u6267\u884C\u51FA\u9519:{}", [self.name, action.id, e]);
580
- throw e;
581
- }
582
- }
583
- } finally {
584
- yield self.executeAfterHooks({
585
- value: preValue,
586
- args: actionArgs,
587
- options: actionOpts,
588
- command: cmd
589
- });
590
- }
591
- });
592
- };
593
- }
594
- /**
595
- * 当传入--work-dirs时用来处理工作目录
596
- */
597
- wrapperWorkDirsAction(fn) {
598
- const self = this;
599
- return function() {
600
- return __async(this, arguments, function* () {
601
- let workDirs = self._optionValues.workDirs;
602
- if (!workDirs) {
603
- return yield fn.apply(this, Array.from(arguments));
604
- }
605
- if (!Array.isArray(workDirs))
606
- workDirs = workDirs.split(",");
607
- workDirs = workDirs.reduce((dirs, dir) => {
608
- if (typeof dir == "string")
609
- dirs.push(...dir.split(","));
610
- return dirs;
611
- }, []);
612
- for (let workDir of workDirs) {
613
- const cwd = process.cwd();
614
- try {
615
- if (!import_node_path2.default.isAbsolute(workDir))
616
- workDir = import_node_path2.default.join(cwd, workDir);
617
- if (import_node_fs.default.existsSync(workDir) && import_node_fs.default.statSync(workDir).isDirectory()) {
618
- outputDebug("\u5207\u6362\u5230\u5DE5\u4F5C\u76EE\u5F55:{}", workDir);
619
- process.chdir(workDir);
620
- yield fn.apply(this, Array.from(arguments));
621
- } else {
622
- outputDebug("\u65E0\u6548\u7684\u5DE5\u4F5C\u76EE\u5F55:{}", workDir);
623
- }
624
- } catch (e) {
625
- throw e;
626
- } finally {
627
- process.chdir(cwd);
628
- }
629
- }
630
- });
631
- };
632
- }
633
- getOption(name) {
634
- return this.options.find((option) => option.name() == name);
635
- }
636
- /**
637
- * 添加一个Before钩子
638
- * @param listener
639
- * @param scope =false时代表只在本命令执行,=true时代表在本命令及其子命令执行
640
- * @returns
641
- */
642
- before(listener, scope = true) {
643
- this._beforeHooks.push([listener, scope]);
644
- return this;
645
- }
646
- executeBeforeHooks(args) {
647
- return __async(this, null, function* () {
648
- const hooks = this.beforeHooks.map(
649
- ([hook, scope]) => [hook, scope, this]
650
- );
651
- this.getAncestorCommands().forEach((cmd) => {
652
- hooks.unshift(
653
- ...cmd.beforeHooks.map(([hook, scope]) => {
654
- return [hook, scope, cmd];
655
- })
656
- );
657
- });
658
- for (let [hook, scope, cmd] of hooks) {
659
- if (!scope)
660
- continue;
661
- yield hook.call(cmd, args);
662
- }
663
- });
664
- }
665
- /**
666
- * 添加一个After钩子
667
- * @param listener
668
- * @param scope =false时代表只在本命令执行,=true时代表在本命令及其子命令执行
669
- * @returns
670
- */
671
- after(listener, scope = true) {
672
- this._afterHooks.push([listener, scope]);
673
- return this;
674
- }
675
- executeAfterHooks(args) {
676
- return __async(this, null, function* () {
677
- const hooks = this.afterHooks.map(
678
- ([hook, scope]) => [hook, scope, this]
679
- );
680
- this.getAncestorCommands().forEach((cmd) => {
681
- hooks.push(
682
- ...cmd.afterHooks.map(([hook, scope]) => {
683
- return [hook, scope, cmd];
684
- })
685
- );
686
- });
687
- for (let [hook, scope, cmd] of hooks) {
688
- if (!scope)
689
- continue;
690
- yield hook.call(cmd, args);
691
- }
692
- });
693
- }
694
- preActionHook(thisCommand, actionCommand) {
695
- return __async(this, null, function* () {
696
- if (this.isEnablePrompts()) {
697
- const questions = [
698
- ...this.generateAutoPrompts(),
699
- ...this._customPrompts
700
- ];
701
- if (questions.length > 0) {
702
- const results = yield (0, import_prompts.default)(questions);
703
- Object.entries(results).forEach(([key, value]) => {
704
- thisCommand.setOptionValue(key, value);
705
- });
706
- }
707
- }
708
- });
709
- }
710
- isEnablePrompts() {
711
- if (isEnablePrompts() === false) {
712
- return false;
713
- } else {
714
- return this._enable_prompts;
715
- }
716
- }
717
- /**
718
- * 生成选项自动提示
719
- *
720
- * @remarks
721
- * FlexCli要求所有未提供默认值的Option自动生成提示
722
- *
723
- * - 未提供默认值,并且是必选的参数Option
724
- * - 指定了choices但未提供有效值的Option
725
- *
726
- */
727
- generateAutoPrompts() {
728
- const options = this.options;
729
- const optionPromports = options.filter((option) => !option.hidden && option.__MIX_OPTION__).map((option) => option.getPrompt(this._optionValues[option.name()])).filter((prompt) => prompt);
730
- outputDebug("\u547D\u4EE4<{}>\u81EA\u52A8\u751F\u6210{}\u4E2A\u9009\u9879\u63D0\u793A:{}", [
731
- this.name(),
732
- optionPromports.length,
733
- optionPromports.map((prompt) => `${prompt.name}(${prompt.type})`).join(",")
734
- ]);
735
- return optionPromports;
736
- }
737
- option(flags, description, options) {
738
- const option = new MixOption(...arguments);
739
- if (option.required && !this.isEnablePrompts())
740
- option.mandatory = true;
741
- return this.addOption(option);
742
- }
743
- /**
744
- * 添加提示
745
- *
746
- * @remarks
747
- *
748
- * 添加一些自定义提示
749
- *
750
- *
751
- * @param questions
752
- * @param show 是否显示提示信息,auto表示只有在用户没有提供option的值时才显示提示信息,always表示总是显示提示信息,never表示不显示提示信息
753
- * @returns
754
- */
755
- prompt(questions) {
756
- this._customPrompts.push(...Array.isArray(questions) ? questions : [questions]);
757
- return this;
758
- }
759
- /**
760
- *
761
- * 选择命令并执行
762
- *
763
- * @remorks
764
- *
765
- * 当命令具有多个子命令时,并且没有提供默认子命令时,提示用户选择一个子命令
766
- *
767
- */
768
- selectCommands() {
769
- return __async(this, null, function* () {
770
- const choices = this.commands.map((command2) => ({
771
- title: `${command2.description()}(${command2.name()})`,
772
- value: command2.name()
773
- }));
774
- const result = yield (0, import_prompts.default)({
775
- type: "select",
776
- name: "command",
777
- message: "\u8BF7\u9009\u62E9\u547D\u4EE4:",
778
- choices
779
- });
780
- const command = this.commands.find((command2) => command2.name() === result.command);
781
- yield command == null ? void 0 : command.parseAsync([result.command], { from: "user" });
782
- });
783
- }
784
- /**
785
- * 禁用/启用所有提示
786
- */
787
- disablePrompts() {
788
- this._enable_prompts = false;
789
- return this;
790
- }
791
- enablePrompts() {
792
- this._enable_prompts = true;
793
- return this;
794
- }
795
- };
796
-
797
- // src/finder.ts
798
- var import_getPackageJson = require("flex-tools/package/getPackageJson");
799
- var import_getPackageRootPath = require("flex-tools/package/getPackageRootPath");
800
- var import_glob = require("glob");
801
- var import_node_fs2 = __toESM(require("fs"));
802
- var import_node_path3 = __toESM(require("path"));
803
- function getMatchedDependencies(entry) {
804
- const pacakgeMacher = this.options.include;
805
- if (!(pacakgeMacher instanceof RegExp))
806
- return [];
807
- const { dependencies = {}, devDependencies = {}, peerDependencies = {}, optionalDependencies = {}, bundleDependencies = {} } = (0, import_getPackageJson.getPackageJson)(entry);
808
- const packageNames = [
809
- ...Object.keys(dependencies),
810
- ...Object.keys(devDependencies),
811
- ...Object.keys(peerDependencies),
812
- ...Object.keys(optionalDependencies),
813
- ...Object.keys(bundleDependencies)
814
- ];
815
- return packageNames.filter((name) => name !== "@voerka/cli" && pacakgeMacher.test(name));
816
- }
817
- function isMatched(str, reg) {
818
- const regexps = reg ? Array.isArray(reg) ? reg : [reg] : [];
819
- return regexps.some((regexp) => {
820
- if (typeof regexp === "string") {
821
- return new RegExp(regexp).test(str);
822
- } else if (regexp instanceof RegExp) {
823
- return regexp.test(str);
824
- } else {
825
- return false;
826
- }
827
- });
828
- }
829
- function findCliPaths(packageName, entry) {
830
- const includeMacher = this.options.include;
831
- const excludeMacher = this.options.exclude;
832
- if (!includeMacher)
833
- return [];
834
- const packageRoot = (0, import_getPackageRootPath.getPackageRootPath)(entry || process.cwd());
835
- const packagePath = packageName ? import_node_path3.default.dirname(require.resolve(packageName, { paths: [packageRoot] })) : packageRoot;
836
- if (!packagePath) {
837
- outputDebug("MixCli\u53EA\u80FD\u8FD0\u884C\u5728Nodejs\u73AF\u5883");
838
- return [];
839
- }
840
- const packageNames = getMatchedDependencies.call(this, packagePath);
841
- const cliDirs = [];
842
- if (entry !== void 0)
843
- cliDirs.push(import_node_path3.default.join(packagePath, this.options.cliDir));
844
- packageNames.filter((name) => {
845
- return isMatched(name, includeMacher) && !isMatched(name, excludeMacher);
846
- }).forEach((name) => {
847
- outputDebug("\u5339\u914D\u5305:{}", `${packageName ? name + " <- " + packageName : name}`);
848
- try {
849
- const packageEntry = import_node_path3.default.dirname(require.resolve(name, { paths: packagePath ? [packagePath] : [process.cwd()] }));
850
- const packageCliDir = import_node_path3.default.join(packageEntry, this.options.cliDir);
851
- let dependencies = getMatchedDependencies.call(this, packageEntry);
852
- cliDirs.push(...dependencies.reduce((result, dependencie) => {
853
- outputDebug("\u5339\u914D\u5305:{}", `${dependencie} <- ${name}`);
854
- result.push(...findCliPaths.call(this, dependencie, packageEntry));
855
- return result;
856
- }, []));
857
- if (import_node_fs2.default.existsSync(packageCliDir)) {
858
- cliDirs.push(packageCliDir);
859
- }
860
- } catch (e) {
861
- outputDebug("\u89E3\u6790\u5305<{}>\u8DEF\u5F84\u51FA\u9519\uFF1A{}", [name, e.stack]);
862
- }
863
- });
864
- return [...new Set(cliDirs)];
865
- }
866
- function findCommands(cli) {
867
- return __async(this, null, function* () {
868
- const cliDirs = findCliPaths.call(cli);
869
- const commands = [];
870
- const files = [];
871
- cliDirs.forEach((dir) => {
872
- (0, import_glob.globSync)("*", {
873
- cwd: dir,
874
- absolute: true
875
- }).forEach((file) => {
876
- const baseName = import_node_path3.default.basename(file);
877
- if (baseName.startsWith("_"))
878
- return;
879
- const ext = import_node_path3.default.extname(file).toLowerCase();
880
- if ([".js", ".cjs", ".mjs"].includes(ext)) {
881
- files.push(file);
882
- } else if (import_node_fs2.default.statSync(file).isDirectory()) {
883
- files.push(import_node_path3.default.join(file, "index.js"));
884
- files.push(import_node_path3.default.join(file, "index.cjs"));
885
- files.push(import_node_path3.default.join(file, "index.mjs"));
886
- }
887
- });
888
- });
889
- for (let file of files) {
890
- if (!import_node_fs2.default.existsSync(file))
891
- continue;
892
- try {
893
- outputDebug("\u5BFC\u5165\u547D\u4EE4:{}", file);
894
- if (file.endsWith(".cjs") || file.endsWith(".js")) {
895
- commands.push(yield importModule(file));
896
- } else if (file.endsWith(".mjs")) {
897
- const cmd = yield import(`file://${file}`);
898
- commands.push(cmd.default);
899
- }
900
- } catch (e) {
901
- outputDebug(e);
902
- }
903
- }
904
- return commands;
905
- });
906
- }
907
-
908
- // src/cli.ts
909
- var import_asyncSignal = require("flex-tools/async/asyncSignal");
910
- var import_string_prototype = __toESM(require("string.prototype.replaceall"));
911
- import_string_prototype.default.shim();
912
- var MixCli = class extends import_liteEvent.LiteEvent {
913
- constructor(options) {
914
- super();
915
- this.findSignals = [];
916
- this.options = (0, import_assignObject.assignObject)({
917
- name: "mixcli",
918
- package: null,
919
- cliDir: "cli",
920
- prompt: "auto",
921
- ignoreError: false
922
- }, options);
923
- this.createRootCommand();
924
- }
925
- get context() {
926
- return this.options.context;
927
- }
928
- get name() {
929
- return this.options.name;
930
- }
931
- /**
932
- * 是否禁用了所有的交互提示
933
- */
934
- get isDisabledPrompts() {
935
- return this.root.rawArgs.includes("--no-prompts");
936
- }
937
- /**
938
- * 扫描当前工程的依赖,加载匹配include的依赖下的命令
939
- */
940
- installCommands() {
941
- return __async(this, null, function* () {
942
- const cmders = yield findCommands(this);
943
- for (let cmder of cmders) {
944
- try {
945
- if (typeof cmder === "function") {
946
- let cmds = cmder(this);
947
- cmds = cmds ? Array.isArray(cmds) ? cmds : [cmds] : [];
948
- this.register(() => cmds);
949
- }
950
- } catch (e) {
951
- outputDebug("\u6CE8\u518C\u547D\u4EE4\u5931\u8D25:{}", e.stack);
952
- }
953
- }
954
- });
955
- }
956
- /**
957
- * 创建根命令
958
- *
959
- */
960
- createRootCommand() {
961
- this.root = new MixCommand(this.name);
962
- this.root.helpOption("-h, --help").action(() => {
963
- if (this.options.logo)
964
- import_logsets2.default.log(fixIndent(this.options.logo, 2));
965
- console.log();
966
- let title = this.options.title || this.options.name;
967
- if (Array.isArray(title)) {
968
- import_logsets2.default.log(String(title[0]).firstUpper(), [...title.slice(1)]);
969
- } else {
970
- import_logsets2.default.log(`${title.firstUpper()} Version: {}`, this.options.version);
971
- }
972
- if (this.options.description)
973
- import_logsets2.default.log(import_logsets2.default.colors.darkGray(this.options.description));
974
- console.log();
975
- this.root.help();
976
- });
977
- addBuiltInOptions(this.root);
978
- if (this.options.before)
979
- this.root.hook("preAction", this.options.before);
980
- if (this.options.after)
981
- this.root.hook("postAction", this.options.after);
982
- }
983
- /**
984
- * 添加帮助选项
985
- *
986
- * @param text 帮助文本
987
- * @param position 显示位置,可选值:before|after|beforeAll|afterAll
988
- * @param fixIndent 是否自动修正缩进,如果为true,则会自动修正缩进,当显示多行时文本时,会自动修正缩进
989
- *
990
- */
991
- addHelp(text, { pos = "beforeAll", alignIndent = true }) {
992
- if (alignIndent)
993
- text = fixIndent(text, alignIndent);
994
- this.root.addHelpText(pos, text);
995
- }
996
- /**
997
- * 注册一个命令
998
- * @param cmd
999
- */
1000
- register(cmd) {
1001
- if (typeof cmd == "function") {
1002
- let result = cmd(this);
1003
- let cmds = result instanceof Array ? result : result == void 0 ? [] : [result];
1004
- for (let cmd2 of cmds) {
1005
- if (cmd2.__MIX_COMMAND__) {
1006
- if (this.hasCommand(cmd2.name())) {
1007
- import_logsets2.default.error(`Command <${cmd2.name()}> has been registered!`);
1008
- } else {
1009
- outputDebug("\u6CE8\u518C\u547D\u4EE4:{}", cmd2.fullname);
1010
- this.root.addCommand(cmd2);
1011
- cmd2._cli = this;
1012
- this.emit("register", cmd2.fullname, true);
1013
- }
1014
- } else {
1015
- import_logsets2.default.error(`Command <${cmd2.toString()}> is not a valid command!`);
1016
- }
1017
- }
1018
- } else {
1019
- import_logsets2.default.error("Invalid command");
1020
- }
1021
- }
1022
- hasCommand(name) {
1023
- return this.root.commands.some((c) => c.name() == name);
1024
- }
1025
- /**
1026
- * 根据命令名称查找命令
1027
- *
1028
- * @remarks
1029
- *
1030
- * find("dev")
1031
- * find("dev.microservice") 支持多级命令
1032
- * find("abc",DevCommand) 允许指定从DevCommand下开始查找abc命令
1033
- *
1034
- * @param name
1035
- */
1036
- get(name) {
1037
- const names = name.split(".");
1038
- let curCmd = this.root;
1039
- let resultCmd;
1040
- while (names.length > 0) {
1041
- const topName = names.shift();
1042
- const r = curCmd.commands.find((c) => c.name() == topName);
1043
- if (r && names.length == 0) {
1044
- resultCmd = r;
1045
- }
1046
- curCmd = r;
1047
- }
1048
- return resultCmd;
1049
- }
1050
- /**
1051
- * 查找一个命令
1052
- *
1053
- * 如果命令不存在,则等待命令注册后再返回
1054
- *
1055
- * 在多包场景下,如果命令在其他包中注册并且该包中的命令还没注册,则会等待命令注册后再返回
1056
- *
1057
- * @param name
1058
- * @returns
1059
- */
1060
- find(name) {
1061
- const cmd = this.get(name);
1062
- if (cmd) {
1063
- return Promise.resolve(cmd);
1064
- } else {
1065
- const signal = (0, import_asyncSignal.asyncSignal)();
1066
- this.findSignals.push(signal);
1067
- return new Promise((resolve) => {
1068
- let listener;
1069
- listener = this.on("register", (fullname) => {
1070
- if (fullname == `${this.name}.${name}`) {
1071
- listener.off();
1072
- signal.resolve();
1073
- this.findSignals = this.findSignals.filter((s) => s != signal);
1074
- resolve(this.get(name));
1075
- }
1076
- }, { objectify: true });
1077
- });
1078
- }
1079
- }
1080
- /**
1081
- * 判断命令是否存在
1082
- *
1083
- * @param name
1084
- * @returns
1085
- */
1086
- exists(name) {
1087
- if (name in this.root.commands) {
1088
- return true;
1089
- } else {
1090
- return this.get(name) != void 0;
1091
- }
1092
- }
1093
- /**
1094
- * 运行命令行程序
1095
- */
1096
- run() {
1097
- this.installCommands().then(() => {
1098
- return Promise.all(this.findSignals.map((signal) => signal(1e4))).then(() => {
1099
- this.root.parseAsync(process.argv);
1100
- });
1101
- });
1102
- }
1103
- /**
1104
- * 创建一个命令
1105
- *
1106
- *
1107
- */
1108
- create() {
1109
- }
1110
- };
1111
- // Annotate the CommonJS export names for ESM import in node:
1112
- 0 && (module.exports = {
1113
- BREAK,
1114
- MixCli,
1115
- MixCommand,
1116
- MixOption,
1117
- addBuiltInOptions,
1118
- createFileByTemplate,
1119
- fileExists,
1120
- fixIndent,
1121
- getId,
1122
- importModule,
1123
- isDebug,
1124
- isEnablePrompts,
1125
- mkDirs,
1126
- mkdir,
1127
- outputDebug,
1128
- outputStr,
1129
- readFile,
1130
- showError,
1131
- writeFile
1132
- });
1
+ var U=Object.defineProperty;var _=Object.getOwnPropertySymbols;var K=Object.prototype.hasOwnProperty,z=Object.prototype.propertyIsEnumerable;var j=(s,n,t)=>n in s?U(s,n,{enumerable:!0,configurable:!0,writable:!0,value:t}):s[n]=t,D=(s,n)=>{for(var t in n||(n={}))K.call(n,t)&&j(s,t,n[t]);if(_)for(var t of _(n))z.call(n,t)&&j(s,t,n[t]);return s};var g=(s=>typeof require!="undefined"?require:typeof Proxy!="undefined"?new Proxy(s,{get:(n,t)=>(typeof require!="undefined"?require:n)[t]}):s)(function(s){if(typeof require!="undefined")return require.apply(this,arguments);throw Error('Dynamic require of "'+s+'" is not supported')});var l=(s,n,t)=>new Promise((e,i)=>{var o=a=>{try{p(t.next(a))}catch(c){i(c)}},r=a=>{try{p(t.throw(a))}catch(c){i(c)}},p=a=>a.done?e(a.value):Promise.resolve(a.value).then(o,r);p((t=t.apply(s,n)).next())});import"flex-tools/string";import{LiteEvent as nt}from"flex-tools/events/liteEvent";import f from"logsets";import{assignObject as rt}from"flex-tools/object/assignObject";import{Command as Z}from"commander";import L from"prompts";import{Option as Y}from"commander";import{isPlainObject as V}from"flex-tools/typecheck/isPlainObject";import{isNumber as J}from"flex-tools/typecheck/isNumber";import x from"fs-extra";import E from"node:path";import{promisify as b}from"flex-tools/func/promisify";import H from"logsets";function ft(s,n){H.log(C(s),n)}function C(s,n){if((n==null||n===!0?0:typeof n=="number"?n:-1)==-1)return s;let e=s.split(`
2
+ `),i=e.reduce((o,r,p)=>{var c;if(p==0)return o;let a=((c=r.match(/^\s*/))==null?void 0:c[0].length)||0;return Math.min(o,a)},9999);return e=e.map(o=>o.substring(i)),e.join(`
3
+ `)}function M(s){s.option("--work-dirs <values...>","\u6307\u5B9A\u5DE5\u4F5C\u76EE\u5F55",{hidden:!0,optional:!0,required:!0,prompt:!1}),s.option("--disable-prompts","\u7981\u7528\u6240\u6709\u4EA4\u4E92\u63D0\u793A",{hidden:!0,prompt:!1}),s.option("--debug-cli","\u663E\u793A\u8C03\u8BD5\u4FE1\u606F",{hidden:!0,prompt:!1})}function R(){return process.argv.includes("--debug-cli")}function T(){return process.argv.includes("--disable-prompts")}function m(s,...n){let t=n.length==1&&typeof n[0]=="function"?n[0]():n;R()&&H.log(`[MixCli] ${s}`,...t)}var dt=b(x.exists,{parseCallback:s=>s[0]}),ht=b(x.readFile),gt=b(x.writeFile),G=b(x.mkdir);function yt(e,i){return l(this,arguments,function*(s,{callback:n,base:t}){if(!Array.isArray(s))throw new Error("dirs\u53C2\u6570\u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32\u6570\u7EC4");for(let o of s)E.isAbsolute(o)||(o=E.join(t||process.cwd(),o)),typeof n=="function"&&n(o),yield G(o,{recursive:!0})})}function xt(s){R()?m("\u5BFC\u5165\u547D\u4EE4<>\u51FA\u9519:{}",s.stack):console.error(s)}function bt(s){return s.replace(/-([a-z])/g,(n,t)=>t.toUpperCase())}function Ct(){return Math.random().toString(36).substr(2)}function S(s){return l(this,null,function*(){let n;try{n=g(s)}catch(t){try{n=(yield import(`file://${s}`)).default}catch(e){throw e}}return n})}var I={boolean:"confirm",string:"text",number:"number",array:"list",date:"date"},Q=["text","password","invisible","number","confirm","list","toggle","select","multiselect","autocomplete","date","autocompleteMultiselect"],P=class{constructor(n,t){this.cliOption=n;this.params=t}isValidPromptType(n){return Q.includes(String(n))}isNeedPrompt(n,t){let e=this.params,i=n||t,o=i!==void 0;return e===!0?!0:e===!1?!1:e==="auto"||V(e)?!o:typeof e=="string"&&this.isValidPromptType(e)?!0:/(\<s*\w\s*\>)/.test(this.cliOption.flags)?!o:this.cliOption.argChoices&&this.cliOption.argChoices.indexOf(i)==-1?!0:!o}_getChoices(){var e;let n=[],t=(e=this.cliOption.params)==null?void 0:e.choices;if(this.cliOption.argChoices)n=this.cliOption.argChoices.map(i=>typeof i=="string"?{title:i,value:i}:i);else if(t)n=typeof t=="function"?t:[];else return[];return n}infer(n){let{variadic:t,defaultValue:e}=this.cliOption,i=n||e,o="text",r=this.params;if(this.isValidPromptType(r))o=r;else if(V(r))o=r.type;else{let p=/(\[\s*\w+\.\.\.\s*])|(\<\s*\w+\.\.\.\s*>)/.test(this.cliOption.flags),a=/(\<s*\w+\s*\>)|(\[\w+\])/.test(this.cliOption.flags),c=!/(\[\s*\w+s*])|(\<\s*\w+\s*>)/.test(this.cliOption.flags),y=J(e),A=e&&e instanceof Date,h=Array.isArray(i)?"array":i instanceof Date?"date":typeof i,d=this.cliOption.params;if(d&&d.choices){let w=d.choices;c&&Array.isArray(w)&&w.length==2?o="toggle":o=t?"multiselect":"select"}else p?o="list":A?o="date":y?o="number":a?o="text":c||typeof e=="boolean"?o="confirm":h in I&&(o=I[h])}return m("\u9009\u9879<{}> -> \u63D0\u793A\u7C7B\u578B<{}>",[this.cliOption.name(),o]),o}get(n){var p;let{description:t,defaultValue:e}=this.cliOption,i=n||e;if(!this.isNeedPrompt(i,e))return;let o=this.infer(n),r=D({type:o,name:this.cliOption.attributeName(),message:t,initial:i},typeof this.params=="object"?this.params:{});if(r.validate=(p=this.cliOption.params)==null?void 0:p.validate,o=="multiselect"&&(r.instructions=!1),r.choices=r.choices||this._getChoices(),["select","multiselect"].includes(o)||o=="toggle"&&Array.isArray(r.choices)&&(r.active||(r.active=r.choices[0].value),r.inactive||(r.inactive=r.choices[1].value)),i&&typeof r.initial!="function"&&r.choices&&Array.isArray(r.choices))if(o=="select"){let a=Array.isArray(r.choices)?r.choices.findIndex(c=>c.value==i):-1;a!=-1&&(r.initial=a)}else o=="multiselect"&&r.choices.forEach(a=>{(Array.isArray(i)&&i.includes(a.value)||a.value==i)&&(a.selected=!0)});return r}};var O=class extends Y{constructor(t,e,i){super(t,e);this.params=i;this.__MIX_OPTION__=!0;this._setOption(i||{}),this.prompt=new P(this,i==null?void 0:i.prompt)}_setOption(t){t.default&&this.default(t.default,t.defaultDescription),t.conflicts&&this.conflicts(t.conflicts),t.envVar&&this.env(t.envVar),t.parseArg&&this.argParser(t.parseArg),t.hidden&&(this.hidden=t.hidden),t.mandatory&&this.makeOptionMandatory(t.mandatory),t.implies&&this.implies(t.implies),t.optional&&(this.optional=t.optional),t.variadic&&(this.variadic=t.variadic),t.negate&&(this.negate=t.negate),t.preset&&this.preset(t.preset),t.required&&(this.required=t.required),Array.isArray(t.choices)&&this.choices(t.choices.map(e=>typeof e=="string"?e:e.value))}getPrompt(t){var e;return(e=this.prompt)==null?void 0:e.get(t)}};import N from"node:path";import $ from"node:fs";var tt=Symbol("BREAK_ACTION"),v=class extends Z{constructor(t){super(t);this.__MIX_COMMAND__=!0;this._beforeHooks=[];this._afterHooks=[];this._customPrompts=[];this._optionValues={};this._actions=[];this._enable_prompts=!0;let e=this;this.isRoot||M(this),this.hook("preAction",function(){return l(this,arguments,function*(){e._optionValues=e.getOptionValues(this.hookedCommand),yield e.preActionHook.apply(e,arguments)})})}get isRoot(){return this.parent==null}get optionValues(){return this._optionValues}get actions(){return this._actions}get beforeHooks(){return this._beforeHooks}get afterHooks(){return this._afterHooks}get fullname(){let t=[this.name()],e=this.parent;for(;e;)e.name()!=="root"&&t.unshift(e.name()),e=e.parent;return t.join(".")}root(){let t=this;for(;t&&t.parent!=null;)t=t.parent;return t}action(){let t=arguments[0];if(arguments.length==1&&typeof t=="function")this._actions.push({id:Math.random().toString(36).substring(2),enhance:!1,fn:t});else if(arguments.length==2&&typeof t=="function"&&typeof arguments[1]=="object"){let e=arguments[0],i=Object.assign({at:"append"},arguments[1]);i.at=="replace"&&(this._actions=[]);let o={id:i.id||Math.random().toString(36).substring(2),enhance:i.enhance==null?!0:i.enhance,fn:e};typeof i.at=="number"?this._actions.splice(Number(i.at),0,o):["append","before"].includes(i.at)?this._actions.push(o):["preappend","after"].includes(i.at)?this._actions.splice(0,0,o):this._actions.push(o)}else console.log("[mixcli] action params error");return super.action(this.getWrapperedAction())}getOptionValues(t){let e={},i=t;for(;i;)Object.assign(e,i.optionValues),i=i.parent;return e}getWrapperedAction(){return this.wrapperWorkDirsAction(this.wrapperChainActions())}getAncestorCommands(){let t=[],e=this;for(;e;)e=e.parent,e&&t.push(e);return t}wrapperChainActions(){let t=this;return function(){return l(this,arguments,function*(){let e=Array.from(arguments),i,o={},r=[],p;e.length>=2&&(p=e[e.length-1],o=e[e.length-2],r=e.slice(0,e.length-2)),yield t.executeBeforeHooks({args:r,options:o,command:p});try{for(let a of t._actions)try{if(a.enhance?(m("\u6267\u884C<{}>: args={}, options={}",()=>[t.name(),r,o]),i=yield a.fn.call(this,{command:p,value:i,args:r,options:o})):i=yield a.fn.apply(this,e),i===tt)break}catch(c){throw m("\u547D\u4EE4{}\u7684Action({})\u6267\u884C\u51FA\u9519:{}",[t.name,a.id,c]),c}}finally{yield t.executeAfterHooks({value:i,args:r,options:o,command:p})}})}}wrapperWorkDirsAction(t){let e=this;return function(){return l(this,arguments,function*(){let i=e._optionValues.workDirs;if(!i)return yield t.apply(this,Array.from(arguments));Array.isArray(i)||(i=i.split(",")),i=i.reduce((o,r)=>(typeof r=="string"&&o.push(...r.split(",")),o),[]);for(let o of i){let r=process.cwd();try{N.isAbsolute(o)||(o=N.join(r,o)),$.existsSync(o)&&$.statSync(o).isDirectory()?(m("\u5207\u6362\u5230\u5DE5\u4F5C\u76EE\u5F55:{}",o),process.chdir(o),yield t.apply(this,Array.from(arguments))):m("\u65E0\u6548\u7684\u5DE5\u4F5C\u76EE\u5F55:{}",o)}finally{process.chdir(r)}}})}}getOption(t){return this.options.find(e=>e.name()==t)}before(t,e=!0){return this._beforeHooks.push([t,e]),this}executeBeforeHooks(t){return l(this,null,function*(){let e=this.beforeHooks.map(([i,o])=>[i,o,this]);this.getAncestorCommands().forEach(i=>{e.unshift(...i.beforeHooks.map(([o,r])=>[o,r,i]))});for(let[i,o,r]of e)o&&(yield i.call(r,t))})}after(t,e=!0){return this._afterHooks.push([t,e]),this}executeAfterHooks(t){return l(this,null,function*(){let e=this.afterHooks.map(([i,o])=>[i,o,this]);this.getAncestorCommands().forEach(i=>{e.push(...i.afterHooks.map(([o,r])=>[o,r,i]))});for(let[i,o,r]of e)o&&(yield i.call(r,t))})}preActionHook(t){return l(this,null,function*(){if(this.isEnablePrompts()){let e=[...this.generateAutoPrompts(),...this._customPrompts];if(e.length>0){let i=yield L(e);Object.entries(i).forEach(([o,r])=>{t.setOptionValue(o,r)})}}})}isEnablePrompts(){return T()?!1:this._enable_prompts}generateAutoPrompts(){let e=this.options.filter(i=>!i.hidden&&i.__MIX_OPTION__).map(i=>i.getPrompt(this._optionValues[i.attributeName()])).filter(i=>i);return m("\u547D\u4EE4<{}>\u81EA\u52A8\u751F\u6210{}\u4E2A\u9009\u9879\u63D0\u793A:{}",[this.name(),e.length,e.map(i=>`${i.name}(${i.type})`).join(",")]),e}option(t,e,i){let o=new O(t,e,i);return o.required&&!this.isEnablePrompts()&&(o.mandatory=!0),this.addOption(o)}prompt(t){return this._customPrompts.push(...Array.isArray(t)?t:[t]),this}selectCommands(){return l(this,null,function*(){let t=this.commands.map(o=>({title:`${o.description()}(${o.name()})`,value:o.name()})),e=yield L({type:"select",name:"command",message:"\u8BF7\u9009\u62E9\u547D\u4EE4:",choices:t}),i=this.commands.find(o=>o.name()===e.command);yield i==null?void 0:i.parseAsync([e.command],{from:"user"})})}disablePrompts(){return this._enable_prompts=!1,this}enablePrompts(){return this._enable_prompts=!0,this}};import{getPackageJson as et}from"flex-tools/package/getPackageJson";import{getPackageRootPath as it}from"flex-tools/package/getPackageRootPath";import{globSync as ot}from"glob";import k from"node:fs";import u from"node:path";function B(s){let n=this.options.include;if(!(n instanceof RegExp))return[];let{dependencies:t={},devDependencies:e={},peerDependencies:i={},optionalDependencies:o={},bundleDependencies:r={}}=et(s);return[...Object.keys(t),...Object.keys(e),...Object.keys(i),...Object.keys(o),...Object.keys(r)].filter(a=>a!=="@voerka/cli"&&n.test(a))}function q(s,n){return(n?Array.isArray(n)?n:[n]:[]).some(e=>typeof e=="string"?new RegExp(e).test(s):e instanceof RegExp?e.test(s):!1)}function F(s,n){let t=this.options.include,e=this.options.exclude;if(!t)return[];let i=it(n||process.cwd()),o=s?u.dirname(g.resolve(s,{paths:[i]})):i;if(!o)return m("MixCli\u53EA\u80FD\u8FD0\u884C\u5728Nodejs\u73AF\u5883"),[];let r=B.call(this,o),p=[];return n!==void 0&&p.push(u.join(o,this.options.cliDir)),r.filter(a=>q(a,t)&&!q(a,e)).forEach(a=>{m("\u5339\u914D\u5305:{}",`${s?a+" <- "+s:a}`);try{let c=u.dirname(g.resolve(a,{paths:o?[o]:[process.cwd()]})),y=u.join(c,this.options.cliDir),A=B.call(this,c);p.push(...A.reduce((h,d)=>(m("\u5339\u914D\u5305:{}",`${d} <- ${a}`),h.push(...F.call(this,d,c)),h),[])),k.existsSync(y)&&p.push(y)}catch(c){m("\u89E3\u6790\u5305<{}>\u8DEF\u5F84\u51FA\u9519\uFF1A{}",[a,c.stack])}}),[...new Set(p)]}function W(s){return l(this,null,function*(){let n=F.call(s),t=[],e=[];n.forEach(i=>{ot("*",{cwd:i,absolute:!0}).forEach(o=>{if(u.basename(o).startsWith("_"))return;let p=u.extname(o).toLowerCase();[".js",".cjs",".mjs"].includes(p)?e.push(o):k.statSync(o).isDirectory()&&(e.push(u.join(o,"index.js")),e.push(u.join(o,"index.cjs")),e.push(u.join(o,"index.mjs")))})});for(let i of e)if(k.existsSync(i))try{if(m("\u5BFC\u5165\u547D\u4EE4:{}",i),i.endsWith(".cjs")||i.endsWith(".js"))t.push(yield S(i));else if(i.endsWith(".mjs")){let o=yield import(`file://${i}`);t.push(o.default)}}catch(o){m(o)}return t})}import{asyncSignal as st}from"flex-tools/async/asyncSignal";import at from"string.prototype.replaceall";at.shim();var X=class extends nt{constructor(t){super();this.findSignals=[];this.options=rt({name:"mixcli",package:null,cliDir:"cli",prompt:"auto",ignoreError:!1},t),this.createRootCommand()}get context(){return this.options.context}get name(){return this.options.name}get isDisabledPrompts(){return this.root.rawArgs.includes("--no-prompts")}installCommands(){return l(this,null,function*(){let t=yield W(this);for(let e of t)try{if(typeof e=="function"){let i=e(this);i=i?Array.isArray(i)?i:[i]:[],this.register(()=>i)}}catch(i){m("\u6CE8\u518C\u547D\u4EE4\u5931\u8D25:{}",i.stack)}})}createRootCommand(){this.root=new v(this.name),this.root.helpOption("-h, --help").action(()=>{this.options.logo&&f.log(C(this.options.logo,2)),console.log();let t=this.options.title||this.options.name;Array.isArray(t)?f.log(String(t[0]).firstUpper(),[...t.slice(1)]):f.log(`${t.firstUpper()} Version: {}`,this.options.version),this.options.description&&f.log(f.colors.darkGray(this.options.description)),console.log(),this.root.help()}),M(this.root),this.options.before&&this.root.hook("preAction",this.options.before),this.options.after&&this.root.hook("postAction",this.options.after)}addHelp(t,{pos:e="beforeAll",alignIndent:i=!0}){i&&(t=C(t,i)),this.root.addHelpText(e,t)}register(t){if(typeof t=="function"){let e=t(this),i=e instanceof Array?e:e==null?[]:[e];for(let o of i)o.__MIX_COMMAND__?this.hasCommand(o.name())?f.error(`Command <${o.name()}> has been registered!`):(m("\u6CE8\u518C\u547D\u4EE4:{}",o.fullname),this.root.addCommand(o),o._cli=this,this.emit("register",o.fullname,!0)):f.error(`Command <${o.toString()}> is not a valid command!`)}else f.error("Invalid command")}hasCommand(t){return this.root.commands.some(e=>e.name()==t)}get(t){let e=t.split("."),i=this.root,o;for(;e.length>0;){let r=e.shift(),p=i.commands.find(a=>a.name()==r);p&&e.length==0&&(o=p),i=p}return o}find(t){let e=this.get(t);if(e)return Promise.resolve(e);{let i=st();return this.findSignals.push(i),new Promise(o=>{let r;r=this.on("register",p=>{p==`${this.name}.${t}`&&(r.off(),i.resolve(),this.findSignals=this.findSignals.filter(a=>a!=i),o(this.get(t)))},{objectify:!0})})}}exists(t){return t in this.root.commands?!0:this.get(t)!=null}run(){this.installCommands().then(()=>Promise.all(this.findSignals.map(t=>t(1e4))).then(()=>{this.root.parseAsync(process.argv)}))}};export{tt as BREAK,X as MixCli,v as MixCommand,O as MixOption,P as MixOptionPrompt,M as addBuiltInOptions,dt as fileExists,C as fixIndent,Ct as getId,bt as hyphenToCamelCase,S as importModule,R as isDebug,T as isDisablePrompts,yt as mkDirs,G as mkdir,m as outputDebug,ft as outputStr,I as promptTypeMap,ht as readFile,xt as showError,Q as supportedPromptTypes,gt as writeFile};
1133
4
  //# sourceMappingURL=index.js.map