breadc 0.4.6 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.cjs +167 -123
- package/dist/index.d.ts +26 -16
- package/dist/index.mjs +165 -119
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Yet another Command Line Application Framework powered by [minimist](https://www
|
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
|
-
+ ⚡️ **Light-weight**: Only
|
|
9
|
+
+ ⚡️ **Light-weight**: Only 40 kB (Unpacked).
|
|
10
10
|
+ 📖 **East to Learn**: Breadc is basically compatible with [cac](https://github.com/cacjs/cac) and there are only 4 APIs for building a CLI application: `command`, `option`, `action`, `run`.
|
|
11
11
|
+ 💻 **TypeScript Infer**: IDE will automatically infer the type of your command action function.
|
|
12
12
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
|
-
const kolorist = require('kolorist');
|
|
6
3
|
const minimist = require('minimist');
|
|
4
|
+
const kolorist = require('kolorist');
|
|
7
5
|
|
|
8
6
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
|
|
9
7
|
|
|
10
|
-
const kolorist__default = /*#__PURE__*/_interopDefaultLegacy(kolorist);
|
|
11
8
|
const minimist__default = /*#__PURE__*/_interopDefaultLegacy(minimist);
|
|
9
|
+
const kolorist__default = /*#__PURE__*/_interopDefaultLegacy(kolorist);
|
|
10
|
+
|
|
11
|
+
function twoColumn(texts, split = " ") {
|
|
12
|
+
const left = padRight(texts.map((t) => t[0]));
|
|
13
|
+
return left.map((l, idx) => l + split + texts[idx][1]);
|
|
14
|
+
}
|
|
15
|
+
function padRight(texts, fill = " ") {
|
|
16
|
+
const length = texts.map((t) => t.length).reduce((max, l) => Math.max(max, l), 0);
|
|
17
|
+
return texts.map((t) => t + fill.repeat(length - t.length));
|
|
18
|
+
}
|
|
12
19
|
|
|
13
20
|
function createDefaultLogger(name, logger) {
|
|
14
21
|
const println = !!logger && typeof logger === "function" ? logger : logger?.println ?? ((message, ...args) => {
|
|
@@ -64,15 +71,26 @@ Option.OptionRE = /^(-[a-zA-Z0-9], )?--([a-zA-Z0-9\-]+)( \[[a-zA-Z0-9]+\]| <[a-z
|
|
|
64
71
|
const _Command = class {
|
|
65
72
|
constructor(format, config) {
|
|
66
73
|
this.options = [];
|
|
67
|
-
this.format =
|
|
68
|
-
|
|
74
|
+
this.format = format;
|
|
75
|
+
const pieces = format.split(" ").map((t) => t.trim()).filter(Boolean);
|
|
76
|
+
const prefix = pieces.filter((p) => !isArg(p));
|
|
77
|
+
this.default = prefix.length === 0;
|
|
78
|
+
this.prefix = this.default ? [] : [prefix];
|
|
79
|
+
this.arguments = pieces.filter(isArg);
|
|
69
80
|
this.description = config.description ?? "";
|
|
70
|
-
this.conditionFn = config.condition;
|
|
71
81
|
this.logger = config.logger;
|
|
72
|
-
if (
|
|
82
|
+
if (pieces.length > _Command.MaxDep) {
|
|
73
83
|
this.logger.warn(`Command format string "${format}" is too long`);
|
|
74
84
|
}
|
|
75
85
|
}
|
|
86
|
+
get isInternal() {
|
|
87
|
+
return this instanceof InternalCommand;
|
|
88
|
+
}
|
|
89
|
+
alias(command) {
|
|
90
|
+
const pieces = command.split(" ").map((t) => t.trim()).filter(Boolean);
|
|
91
|
+
this.prefix.push(pieces);
|
|
92
|
+
return this;
|
|
93
|
+
}
|
|
76
94
|
option(format, configOrDescription = "", otherConfig = {}) {
|
|
77
95
|
const config = typeof configOrDescription === "object" ? configOrDescription : { ...otherConfig, description: configOrDescription };
|
|
78
96
|
try {
|
|
@@ -83,59 +101,56 @@ const _Command = class {
|
|
|
83
101
|
}
|
|
84
102
|
return this;
|
|
85
103
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (this.conditionFn) {
|
|
91
|
-
return this.conditionFn(args);
|
|
104
|
+
hasPrefix(parsedArgs) {
|
|
105
|
+
const argv = parsedArgs["_"];
|
|
106
|
+
if (argv.length === 0) {
|
|
107
|
+
return this.default;
|
|
92
108
|
} else {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const isCmd = (t) => t[0] !== "[" && t[0] !== "<";
|
|
96
|
-
for (let i = 0; i < this.format.length; i++) {
|
|
97
|
-
if (!isCmd(this.format[i])) {
|
|
109
|
+
for (const prefix of this.prefix) {
|
|
110
|
+
if (prefix.length > 0 && prefix[0] === argv[0]) {
|
|
98
111
|
return true;
|
|
99
112
|
}
|
|
100
|
-
|
|
101
|
-
|
|
113
|
+
}
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
shouldRun(parsedArgs) {
|
|
118
|
+
const args = parsedArgs["_"];
|
|
119
|
+
for (const prefix of this.prefix) {
|
|
120
|
+
let match = true;
|
|
121
|
+
for (let i = 0; match && i < prefix.length; i++) {
|
|
122
|
+
if (args[i] !== prefix[i]) {
|
|
123
|
+
match = false;
|
|
102
124
|
}
|
|
103
125
|
}
|
|
104
|
-
|
|
126
|
+
if (match) {
|
|
127
|
+
args.splice(0, prefix.length);
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
105
130
|
}
|
|
131
|
+
if (this.default)
|
|
132
|
+
return true;
|
|
133
|
+
return false;
|
|
106
134
|
}
|
|
107
135
|
parseArgs(args, globalOptions) {
|
|
108
|
-
if (this.conditionFn) {
|
|
109
|
-
const argumentss2 = args["_"];
|
|
110
|
-
const options2 = args;
|
|
111
|
-
delete options2["_"];
|
|
112
|
-
return {
|
|
113
|
-
command: this,
|
|
114
|
-
arguments: argumentss2,
|
|
115
|
-
options: args
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
const isCmd = (t) => t[0] !== "[" && t[0] !== "<";
|
|
119
136
|
const argumentss = [];
|
|
120
|
-
for (let i = 0; i < this.
|
|
121
|
-
if (isCmd(this.format[i]))
|
|
122
|
-
continue;
|
|
137
|
+
for (let i = 0; i < this.arguments.length; i++) {
|
|
123
138
|
if (i < args["_"].length) {
|
|
124
|
-
if (this.
|
|
139
|
+
if (this.arguments[i].startsWith("[...")) {
|
|
125
140
|
argumentss.push(args["_"].slice(i).map(String));
|
|
126
141
|
} else {
|
|
127
142
|
argumentss.push(String(args["_"][i]));
|
|
128
143
|
}
|
|
129
144
|
} else {
|
|
130
|
-
if (this.
|
|
131
|
-
this.logger.warn(`You should provide the argument "${this.
|
|
132
|
-
argumentss.push(
|
|
133
|
-
} else if (this.
|
|
145
|
+
if (this.arguments[i].startsWith("<")) {
|
|
146
|
+
this.logger.warn(`You should provide the argument "${this.arguments[i]}"`);
|
|
147
|
+
argumentss.push("");
|
|
148
|
+
} else if (this.arguments[i].startsWith("[...")) {
|
|
134
149
|
argumentss.push([]);
|
|
135
|
-
} else if (this.
|
|
150
|
+
} else if (this.arguments[i].startsWith("[")) {
|
|
136
151
|
argumentss.push(void 0);
|
|
137
152
|
} else {
|
|
138
|
-
this.logger.warn(`unknown format string ("${this.
|
|
153
|
+
this.logger.warn(`unknown format string ("${this.arguments[i]}")`);
|
|
139
154
|
}
|
|
140
155
|
}
|
|
141
156
|
}
|
|
@@ -159,13 +174,14 @@ const _Command = class {
|
|
|
159
174
|
options[name] = void 0;
|
|
160
175
|
}
|
|
161
176
|
}
|
|
162
|
-
if (rawOption.
|
|
163
|
-
options[name]
|
|
164
|
-
} else if (rawOption.default) {
|
|
165
|
-
if (!options[name]) {
|
|
177
|
+
if (rawOption.default !== void 0) {
|
|
178
|
+
if (options[name] === void 0 || options[name] === false) {
|
|
166
179
|
options[name] = rawOption.default;
|
|
167
180
|
}
|
|
168
181
|
}
|
|
182
|
+
if (rawOption.construct !== void 0) {
|
|
183
|
+
options[name] = rawOption.construct(options[name]);
|
|
184
|
+
}
|
|
169
185
|
}
|
|
170
186
|
for (const key of Object.keys(options)) {
|
|
171
187
|
if (!fullOptions.has(key)) {
|
|
@@ -180,60 +196,91 @@ const _Command = class {
|
|
|
180
196
|
}
|
|
181
197
|
action(fn) {
|
|
182
198
|
this.actionFn = fn;
|
|
183
|
-
return this;
|
|
184
199
|
}
|
|
185
200
|
async run(...args) {
|
|
186
201
|
if (this.actionFn) {
|
|
187
|
-
return await this.actionFn(...args, { logger: this.logger });
|
|
202
|
+
return await this.actionFn(...args, { logger: this.logger, color: kolorist__default });
|
|
188
203
|
} else {
|
|
189
|
-
this.logger.warn(`You may miss action function in "${this.format}"`);
|
|
204
|
+
this.logger.warn(`You may miss action function in ${this.format ? `"${this.format}"` : "<default command>"}`);
|
|
190
205
|
}
|
|
191
206
|
}
|
|
192
207
|
};
|
|
193
208
|
let Command = _Command;
|
|
194
209
|
Command.MaxDep = 5;
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
210
|
+
class InternalCommand extends Command {
|
|
211
|
+
hasPrefix(_args) {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
parseArgs(args, _globalOptions) {
|
|
215
|
+
const argumentss = args["_"];
|
|
216
|
+
const options = args;
|
|
217
|
+
delete options["_"];
|
|
218
|
+
delete options["help"];
|
|
219
|
+
delete options["version"];
|
|
220
|
+
return {
|
|
221
|
+
command: this,
|
|
222
|
+
arguments: argumentss,
|
|
223
|
+
options: args
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
class HelpCommand extends InternalCommand {
|
|
228
|
+
constructor(commands, help, logger) {
|
|
229
|
+
super("-h, --help", { description: "Display this message", logger });
|
|
230
|
+
this.runCommands = [];
|
|
231
|
+
this.helpCommands = [];
|
|
232
|
+
this.commands = commands;
|
|
233
|
+
this.help = help;
|
|
234
|
+
}
|
|
235
|
+
shouldRun(args) {
|
|
236
|
+
const isRestEmpty = !args["--"]?.length;
|
|
237
|
+
if ((args.help || args.h) && isRestEmpty) {
|
|
238
|
+
if (args["_"].length > 0) {
|
|
239
|
+
for (const cmd of this.commands) {
|
|
240
|
+
if (!cmd.default && !cmd.isInternal) {
|
|
241
|
+
if (cmd.shouldRun(args)) {
|
|
242
|
+
this.runCommands.push(cmd);
|
|
243
|
+
} else if (cmd.hasPrefix(args)) {
|
|
244
|
+
this.helpCommands.push(cmd);
|
|
206
245
|
}
|
|
207
246
|
}
|
|
208
247
|
}
|
|
209
|
-
return true;
|
|
210
|
-
} else {
|
|
211
|
-
return false;
|
|
212
248
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
for (const line of breadc.help(helpCommand)) {
|
|
217
|
-
breadc.logger.println(line);
|
|
249
|
+
return true;
|
|
250
|
+
} else {
|
|
251
|
+
return false;
|
|
218
252
|
}
|
|
219
|
-
}
|
|
253
|
+
}
|
|
254
|
+
async run() {
|
|
255
|
+
const shouldHelp = this.runCommands.length > 0 ? this.runCommands : this.helpCommands;
|
|
256
|
+
for (const line of this.help(shouldHelp)) {
|
|
257
|
+
this.logger.println(line);
|
|
258
|
+
}
|
|
259
|
+
this.runCommands.splice(0);
|
|
260
|
+
this.helpCommands.splice(0);
|
|
261
|
+
}
|
|
220
262
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
263
|
+
class VersionCommand extends InternalCommand {
|
|
264
|
+
constructor(version, logger) {
|
|
265
|
+
super("-v, --version", { description: "Display version number", logger });
|
|
266
|
+
this.version = version;
|
|
267
|
+
}
|
|
268
|
+
shouldRun(args) {
|
|
269
|
+
const isEmpty = !args["_"].length && !args["--"]?.length;
|
|
270
|
+
if (args.version && isEmpty) {
|
|
271
|
+
return true;
|
|
272
|
+
} else if (args.v && isEmpty) {
|
|
273
|
+
return true;
|
|
274
|
+
} else {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
async run() {
|
|
279
|
+
this.logger.println(this.version);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
function isArg(arg) {
|
|
283
|
+
return arg[0] === "[" && arg[arg.length - 1] === "]" || arg[0] === "<" && arg[arg.length - 1] === ">";
|
|
237
284
|
}
|
|
238
285
|
|
|
239
286
|
class Breadc {
|
|
@@ -248,24 +295,16 @@ class Breadc {
|
|
|
248
295
|
this._version = option.version ?? "unknown";
|
|
249
296
|
this.description = option.description;
|
|
250
297
|
this.logger = createDefaultLogger(name, option.logger);
|
|
251
|
-
|
|
252
|
-
name: this.name,
|
|
253
|
-
version: () => this.version.call(this),
|
|
254
|
-
help: (command) => this.help.call(this, command),
|
|
255
|
-
logger: this.logger,
|
|
256
|
-
options: this.options,
|
|
257
|
-
commands: this.commands
|
|
258
|
-
};
|
|
259
|
-
this.commands.push(createVersionCommand(breadc), createHelpCommand(breadc));
|
|
298
|
+
this.commands.push(new VersionCommand(this.version(), this.logger), new HelpCommand(this.commands, this.help.bind(this), this.logger));
|
|
260
299
|
}
|
|
261
300
|
version() {
|
|
262
301
|
return `${this.name}/${this._version}`;
|
|
263
302
|
}
|
|
264
|
-
help(
|
|
303
|
+
help(commands = []) {
|
|
265
304
|
const output = [];
|
|
266
305
|
const println = (msg) => output.push(msg);
|
|
267
306
|
println(this.version());
|
|
268
|
-
if (
|
|
307
|
+
if (commands.length === 0) {
|
|
269
308
|
if (this.description) {
|
|
270
309
|
println("");
|
|
271
310
|
if (Array.isArray(this.description)) {
|
|
@@ -276,27 +315,26 @@ class Breadc {
|
|
|
276
315
|
println(this.description);
|
|
277
316
|
}
|
|
278
317
|
}
|
|
279
|
-
} else {
|
|
280
|
-
if (command.description) {
|
|
281
|
-
println("");
|
|
282
|
-
println(command.description);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
if (!command) {
|
|
286
318
|
if (this.defaultCommand) {
|
|
287
319
|
println(``);
|
|
288
320
|
println(`Usage:`);
|
|
289
|
-
println(` $ ${this.name} ${this.defaultCommand.format
|
|
321
|
+
println(` $ ${this.name} ${this.defaultCommand.format}`);
|
|
322
|
+
}
|
|
323
|
+
} else if (commands.length === 1) {
|
|
324
|
+
const command = commands[0];
|
|
325
|
+
if (command.description) {
|
|
326
|
+
println("");
|
|
327
|
+
println(command.description);
|
|
290
328
|
}
|
|
291
|
-
} else {
|
|
292
329
|
println(``);
|
|
293
330
|
println(`Usage:`);
|
|
294
|
-
println(` $ ${this.name} ${command.format
|
|
331
|
+
println(` $ ${this.name} ${command.format}`);
|
|
295
332
|
}
|
|
296
|
-
if (
|
|
333
|
+
if (commands.length !== 1) {
|
|
334
|
+
const cmdList = (commands.length === 0 ? this.commands : commands).filter((c) => !c.isInternal);
|
|
297
335
|
println(``);
|
|
298
336
|
println(`Commands:`);
|
|
299
|
-
const commandHelps =
|
|
337
|
+
const commandHelps = cmdList.map((c) => [` $ ${this.name} ${c.format}`, c.description]);
|
|
300
338
|
for (const line of twoColumn(commandHelps)) {
|
|
301
339
|
println(line);
|
|
302
340
|
}
|
|
@@ -304,7 +342,7 @@ class Breadc {
|
|
|
304
342
|
println(``);
|
|
305
343
|
println(`Options:`);
|
|
306
344
|
const optionHelps = [].concat([
|
|
307
|
-
...
|
|
345
|
+
...commands.length > 0 ? commands.flatMap((cmd) => cmd.options.map((o) => [` ${o.format}`, o.description])) : [],
|
|
308
346
|
...this.options.map((o) => [` ${o.format}`, o.description]),
|
|
309
347
|
[` -h, --help`, `Display this message`],
|
|
310
348
|
[` -v, --version`, `Display version number`]
|
|
@@ -342,15 +380,28 @@ class Breadc {
|
|
|
342
380
|
...this.options,
|
|
343
381
|
...this.commands.flatMap((c) => c.options)
|
|
344
382
|
];
|
|
383
|
+
{
|
|
384
|
+
const names = /* @__PURE__ */ new Map();
|
|
385
|
+
for (const option of allowOptions) {
|
|
386
|
+
if (names.has(option.name)) {
|
|
387
|
+
const otherOption = names.get(option.name);
|
|
388
|
+
if (otherOption.type !== option.type) {
|
|
389
|
+
this.logger.warn(`Option "${option.name}" encounters conflict`);
|
|
390
|
+
}
|
|
391
|
+
} else {
|
|
392
|
+
names.set(option.name, option);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
345
396
|
const alias = allowOptions.reduce((map, o) => {
|
|
346
397
|
if (o.shortcut) {
|
|
347
398
|
map[o.shortcut] = o.name;
|
|
348
399
|
}
|
|
349
400
|
return map;
|
|
350
|
-
}, {});
|
|
401
|
+
}, { h: "help", v: "version" });
|
|
351
402
|
const argv = minimist__default(args, {
|
|
352
403
|
string: allowOptions.filter((o) => o.type === "string").map((o) => o.name),
|
|
353
|
-
boolean: allowOptions.filter((o) => o.type === "boolean").map((o) => o.name),
|
|
404
|
+
boolean: allowOptions.filter((o) => o.type === "boolean").map((o) => o.name).concat(["help", "version"]),
|
|
354
405
|
alias,
|
|
355
406
|
unknown: (t) => {
|
|
356
407
|
if (t[0] !== "-")
|
|
@@ -374,11 +425,14 @@ class Breadc {
|
|
|
374
425
|
}
|
|
375
426
|
}
|
|
376
427
|
if (this.defaultCommand) {
|
|
428
|
+
this.defaultCommand.shouldRun(argv);
|
|
377
429
|
return this.defaultCommand.parseArgs(argv, this.options);
|
|
378
430
|
}
|
|
379
431
|
const argumentss = argv["_"];
|
|
380
432
|
const options = argv;
|
|
381
433
|
delete options["_"];
|
|
434
|
+
delete options["help"];
|
|
435
|
+
delete options["version"];
|
|
382
436
|
return {
|
|
383
437
|
command: void 0,
|
|
384
438
|
arguments: argumentss,
|
|
@@ -398,19 +452,9 @@ class Breadc {
|
|
|
398
452
|
}
|
|
399
453
|
}
|
|
400
454
|
}
|
|
401
|
-
function twoColumn(texts, split = " ") {
|
|
402
|
-
const left = padRight(texts.map((t) => t[0]));
|
|
403
|
-
return left.map((l, idx) => l + split + texts[idx][1]);
|
|
404
|
-
}
|
|
405
|
-
function padRight(texts, fill = " ") {
|
|
406
|
-
const length = texts.map((t) => t.length).reduce((max, l) => Math.max(max, l), 0);
|
|
407
|
-
return texts.map((t) => t + fill.repeat(length - t.length));
|
|
408
|
-
}
|
|
409
455
|
|
|
410
456
|
function breadc(name, option = {}) {
|
|
411
457
|
return new Breadc(name, option);
|
|
412
458
|
}
|
|
413
459
|
|
|
414
|
-
exports
|
|
415
|
-
exports.minimist = minimist__default;
|
|
416
|
-
exports["default"] = breadc;
|
|
460
|
+
module.exports = breadc;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
|
+
import kolorist from 'kolorist';
|
|
1
2
|
import { ParsedArgs } from 'minimist';
|
|
2
|
-
export { default as minimist } from 'minimist';
|
|
3
|
-
export { default as kolorist } from 'kolorist';
|
|
4
3
|
|
|
5
4
|
interface OptionConfig<F extends string, T = never> {
|
|
5
|
+
/**
|
|
6
|
+
* Option description
|
|
7
|
+
*/
|
|
6
8
|
description?: string;
|
|
7
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Option string default value
|
|
11
|
+
*/
|
|
12
|
+
default?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Transform option text
|
|
15
|
+
*/
|
|
8
16
|
construct?: (rawText: ExtractOptionType<F>) => T;
|
|
9
17
|
}
|
|
10
18
|
/**
|
|
@@ -20,7 +28,7 @@ declare class Option<T extends string = string, F = string> {
|
|
|
20
28
|
private static OptionRE;
|
|
21
29
|
readonly name: string;
|
|
22
30
|
readonly shortcut?: string;
|
|
23
|
-
readonly default?:
|
|
31
|
+
readonly default?: string;
|
|
24
32
|
readonly format: string;
|
|
25
33
|
readonly description: string;
|
|
26
34
|
readonly type: 'string' | 'boolean';
|
|
@@ -29,29 +37,30 @@ declare class Option<T extends string = string, F = string> {
|
|
|
29
37
|
constructor(format: T, config?: OptionConfig<T, F>);
|
|
30
38
|
}
|
|
31
39
|
|
|
32
|
-
declare type ConditionFn = (args: ParsedArgs) => boolean;
|
|
33
40
|
interface CommandConfig {
|
|
34
41
|
description?: string;
|
|
35
42
|
}
|
|
36
43
|
declare class Command<F extends string = string, CommandOption extends object = {}> {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
readonly format: string[];
|
|
41
|
-
readonly default: boolean;
|
|
44
|
+
protected static MaxDep: number;
|
|
45
|
+
protected readonly logger: Logger;
|
|
46
|
+
readonly format: string;
|
|
42
47
|
readonly description: string;
|
|
48
|
+
readonly prefix: string[][];
|
|
49
|
+
readonly arguments: string[];
|
|
50
|
+
readonly default: boolean;
|
|
43
51
|
readonly options: Option[];
|
|
44
52
|
private actionFn?;
|
|
45
53
|
constructor(format: F, config: CommandConfig & {
|
|
46
|
-
condition?: ConditionFn;
|
|
47
54
|
logger: Logger;
|
|
48
55
|
});
|
|
56
|
+
get isInternal(): boolean;
|
|
57
|
+
alias(command: string): this;
|
|
49
58
|
option<OF extends string, T = undefined>(format: OF, description: string, config?: Omit<OptionConfig<OF, T>, 'description'>): Command<F, CommandOption & ExtractOption<OF, T>>;
|
|
50
59
|
option<OF extends string, T = undefined>(format: OF, config?: OptionConfig<OF, T>): Command<F, CommandOption & ExtractOption<OF, T>>;
|
|
51
|
-
|
|
52
|
-
shouldRun(
|
|
60
|
+
hasPrefix(parsedArgs: ParsedArgs): boolean;
|
|
61
|
+
shouldRun(parsedArgs: ParsedArgs): boolean;
|
|
53
62
|
parseArgs(args: ParsedArgs, globalOptions: Option[]): ParseResult;
|
|
54
|
-
action(fn: ActionFn<ExtractCommand<F>, CommandOption>):
|
|
63
|
+
action(fn: ActionFn<ExtractCommand<F>, CommandOption>): void;
|
|
55
64
|
run(...args: any[]): Promise<any>;
|
|
56
65
|
}
|
|
57
66
|
|
|
@@ -92,6 +101,7 @@ declare type Letter = Lowercase | Uppercase;
|
|
|
92
101
|
declare type Push<T extends any[], U, R> = [...T, U, R];
|
|
93
102
|
declare type Context = {
|
|
94
103
|
logger: Logger;
|
|
104
|
+
color: typeof kolorist;
|
|
95
105
|
};
|
|
96
106
|
declare type ActionFn<T extends any[], Option extends object = {}, R = any> = (...arg: Push<T, Option, Context>) => R | Promise<R>;
|
|
97
107
|
/**
|
|
@@ -105,13 +115,13 @@ declare class Breadc<GlobalOption extends object = {}> {
|
|
|
105
115
|
private readonly name;
|
|
106
116
|
private readonly _version;
|
|
107
117
|
private readonly description?;
|
|
118
|
+
readonly logger: Logger;
|
|
108
119
|
private readonly options;
|
|
109
120
|
private readonly commands;
|
|
110
121
|
private defaultCommand?;
|
|
111
|
-
readonly logger: Logger;
|
|
112
122
|
constructor(name: string, option: AppOption);
|
|
113
123
|
version(): string;
|
|
114
|
-
help(
|
|
124
|
+
help(commands?: Command[]): string[];
|
|
115
125
|
option<F extends string, T = undefined>(format: F, description: string, config?: Omit<OptionConfig<F, T>, 'description'>): Breadc<GlobalOption & ExtractOption<F, T>>;
|
|
116
126
|
option<F extends string, T = undefined>(format: F, config?: OptionConfig<F, T>): Breadc<GlobalOption & ExtractOption<F, T>>;
|
|
117
127
|
command<F extends string>(format: F, description: string, config?: Omit<CommandConfig, 'description'>): Command<F, GlobalOption>;
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import { blue, yellow, red, gray } from 'kolorist';
|
|
2
|
-
export { default as kolorist } from 'kolorist';
|
|
3
1
|
import minimist from 'minimist';
|
|
4
|
-
|
|
2
|
+
import kolorist, { blue, yellow, red, gray } from 'kolorist';
|
|
3
|
+
|
|
4
|
+
function twoColumn(texts, split = " ") {
|
|
5
|
+
const left = padRight(texts.map((t) => t[0]));
|
|
6
|
+
return left.map((l, idx) => l + split + texts[idx][1]);
|
|
7
|
+
}
|
|
8
|
+
function padRight(texts, fill = " ") {
|
|
9
|
+
const length = texts.map((t) => t.length).reduce((max, l) => Math.max(max, l), 0);
|
|
10
|
+
return texts.map((t) => t + fill.repeat(length - t.length));
|
|
11
|
+
}
|
|
5
12
|
|
|
6
13
|
function createDefaultLogger(name, logger) {
|
|
7
14
|
const println = !!logger && typeof logger === "function" ? logger : logger?.println ?? ((message, ...args) => {
|
|
@@ -57,15 +64,26 @@ Option.OptionRE = /^(-[a-zA-Z0-9], )?--([a-zA-Z0-9\-]+)( \[[a-zA-Z0-9]+\]| <[a-z
|
|
|
57
64
|
const _Command = class {
|
|
58
65
|
constructor(format, config) {
|
|
59
66
|
this.options = [];
|
|
60
|
-
this.format =
|
|
61
|
-
|
|
67
|
+
this.format = format;
|
|
68
|
+
const pieces = format.split(" ").map((t) => t.trim()).filter(Boolean);
|
|
69
|
+
const prefix = pieces.filter((p) => !isArg(p));
|
|
70
|
+
this.default = prefix.length === 0;
|
|
71
|
+
this.prefix = this.default ? [] : [prefix];
|
|
72
|
+
this.arguments = pieces.filter(isArg);
|
|
62
73
|
this.description = config.description ?? "";
|
|
63
|
-
this.conditionFn = config.condition;
|
|
64
74
|
this.logger = config.logger;
|
|
65
|
-
if (
|
|
75
|
+
if (pieces.length > _Command.MaxDep) {
|
|
66
76
|
this.logger.warn(`Command format string "${format}" is too long`);
|
|
67
77
|
}
|
|
68
78
|
}
|
|
79
|
+
get isInternal() {
|
|
80
|
+
return this instanceof InternalCommand;
|
|
81
|
+
}
|
|
82
|
+
alias(command) {
|
|
83
|
+
const pieces = command.split(" ").map((t) => t.trim()).filter(Boolean);
|
|
84
|
+
this.prefix.push(pieces);
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
69
87
|
option(format, configOrDescription = "", otherConfig = {}) {
|
|
70
88
|
const config = typeof configOrDescription === "object" ? configOrDescription : { ...otherConfig, description: configOrDescription };
|
|
71
89
|
try {
|
|
@@ -76,59 +94,56 @@ const _Command = class {
|
|
|
76
94
|
}
|
|
77
95
|
return this;
|
|
78
96
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (this.conditionFn) {
|
|
84
|
-
return this.conditionFn(args);
|
|
97
|
+
hasPrefix(parsedArgs) {
|
|
98
|
+
const argv = parsedArgs["_"];
|
|
99
|
+
if (argv.length === 0) {
|
|
100
|
+
return this.default;
|
|
85
101
|
} else {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const isCmd = (t) => t[0] !== "[" && t[0] !== "<";
|
|
89
|
-
for (let i = 0; i < this.format.length; i++) {
|
|
90
|
-
if (!isCmd(this.format[i])) {
|
|
102
|
+
for (const prefix of this.prefix) {
|
|
103
|
+
if (prefix.length > 0 && prefix[0] === argv[0]) {
|
|
91
104
|
return true;
|
|
92
105
|
}
|
|
93
|
-
|
|
94
|
-
|
|
106
|
+
}
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
shouldRun(parsedArgs) {
|
|
111
|
+
const args = parsedArgs["_"];
|
|
112
|
+
for (const prefix of this.prefix) {
|
|
113
|
+
let match = true;
|
|
114
|
+
for (let i = 0; match && i < prefix.length; i++) {
|
|
115
|
+
if (args[i] !== prefix[i]) {
|
|
116
|
+
match = false;
|
|
95
117
|
}
|
|
96
118
|
}
|
|
97
|
-
|
|
119
|
+
if (match) {
|
|
120
|
+
args.splice(0, prefix.length);
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
98
123
|
}
|
|
124
|
+
if (this.default)
|
|
125
|
+
return true;
|
|
126
|
+
return false;
|
|
99
127
|
}
|
|
100
128
|
parseArgs(args, globalOptions) {
|
|
101
|
-
if (this.conditionFn) {
|
|
102
|
-
const argumentss2 = args["_"];
|
|
103
|
-
const options2 = args;
|
|
104
|
-
delete options2["_"];
|
|
105
|
-
return {
|
|
106
|
-
command: this,
|
|
107
|
-
arguments: argumentss2,
|
|
108
|
-
options: args
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
const isCmd = (t) => t[0] !== "[" && t[0] !== "<";
|
|
112
129
|
const argumentss = [];
|
|
113
|
-
for (let i = 0; i < this.
|
|
114
|
-
if (isCmd(this.format[i]))
|
|
115
|
-
continue;
|
|
130
|
+
for (let i = 0; i < this.arguments.length; i++) {
|
|
116
131
|
if (i < args["_"].length) {
|
|
117
|
-
if (this.
|
|
132
|
+
if (this.arguments[i].startsWith("[...")) {
|
|
118
133
|
argumentss.push(args["_"].slice(i).map(String));
|
|
119
134
|
} else {
|
|
120
135
|
argumentss.push(String(args["_"][i]));
|
|
121
136
|
}
|
|
122
137
|
} else {
|
|
123
|
-
if (this.
|
|
124
|
-
this.logger.warn(`You should provide the argument "${this.
|
|
125
|
-
argumentss.push(
|
|
126
|
-
} else if (this.
|
|
138
|
+
if (this.arguments[i].startsWith("<")) {
|
|
139
|
+
this.logger.warn(`You should provide the argument "${this.arguments[i]}"`);
|
|
140
|
+
argumentss.push("");
|
|
141
|
+
} else if (this.arguments[i].startsWith("[...")) {
|
|
127
142
|
argumentss.push([]);
|
|
128
|
-
} else if (this.
|
|
143
|
+
} else if (this.arguments[i].startsWith("[")) {
|
|
129
144
|
argumentss.push(void 0);
|
|
130
145
|
} else {
|
|
131
|
-
this.logger.warn(`unknown format string ("${this.
|
|
146
|
+
this.logger.warn(`unknown format string ("${this.arguments[i]}")`);
|
|
132
147
|
}
|
|
133
148
|
}
|
|
134
149
|
}
|
|
@@ -152,13 +167,14 @@ const _Command = class {
|
|
|
152
167
|
options[name] = void 0;
|
|
153
168
|
}
|
|
154
169
|
}
|
|
155
|
-
if (rawOption.
|
|
156
|
-
options[name]
|
|
157
|
-
} else if (rawOption.default) {
|
|
158
|
-
if (!options[name]) {
|
|
170
|
+
if (rawOption.default !== void 0) {
|
|
171
|
+
if (options[name] === void 0 || options[name] === false) {
|
|
159
172
|
options[name] = rawOption.default;
|
|
160
173
|
}
|
|
161
174
|
}
|
|
175
|
+
if (rawOption.construct !== void 0) {
|
|
176
|
+
options[name] = rawOption.construct(options[name]);
|
|
177
|
+
}
|
|
162
178
|
}
|
|
163
179
|
for (const key of Object.keys(options)) {
|
|
164
180
|
if (!fullOptions.has(key)) {
|
|
@@ -173,60 +189,91 @@ const _Command = class {
|
|
|
173
189
|
}
|
|
174
190
|
action(fn) {
|
|
175
191
|
this.actionFn = fn;
|
|
176
|
-
return this;
|
|
177
192
|
}
|
|
178
193
|
async run(...args) {
|
|
179
194
|
if (this.actionFn) {
|
|
180
|
-
return await this.actionFn(...args, { logger: this.logger });
|
|
195
|
+
return await this.actionFn(...args, { logger: this.logger, color: kolorist });
|
|
181
196
|
} else {
|
|
182
|
-
this.logger.warn(`You may miss action function in "${this.format}"`);
|
|
197
|
+
this.logger.warn(`You may miss action function in ${this.format ? `"${this.format}"` : "<default command>"}`);
|
|
183
198
|
}
|
|
184
199
|
}
|
|
185
200
|
};
|
|
186
201
|
let Command = _Command;
|
|
187
202
|
Command.MaxDep = 5;
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
203
|
+
class InternalCommand extends Command {
|
|
204
|
+
hasPrefix(_args) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
parseArgs(args, _globalOptions) {
|
|
208
|
+
const argumentss = args["_"];
|
|
209
|
+
const options = args;
|
|
210
|
+
delete options["_"];
|
|
211
|
+
delete options["help"];
|
|
212
|
+
delete options["version"];
|
|
213
|
+
return {
|
|
214
|
+
command: this,
|
|
215
|
+
arguments: argumentss,
|
|
216
|
+
options: args
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
class HelpCommand extends InternalCommand {
|
|
221
|
+
constructor(commands, help, logger) {
|
|
222
|
+
super("-h, --help", { description: "Display this message", logger });
|
|
223
|
+
this.runCommands = [];
|
|
224
|
+
this.helpCommands = [];
|
|
225
|
+
this.commands = commands;
|
|
226
|
+
this.help = help;
|
|
227
|
+
}
|
|
228
|
+
shouldRun(args) {
|
|
229
|
+
const isRestEmpty = !args["--"]?.length;
|
|
230
|
+
if ((args.help || args.h) && isRestEmpty) {
|
|
231
|
+
if (args["_"].length > 0) {
|
|
232
|
+
for (const cmd of this.commands) {
|
|
233
|
+
if (!cmd.default && !cmd.isInternal) {
|
|
234
|
+
if (cmd.shouldRun(args)) {
|
|
235
|
+
this.runCommands.push(cmd);
|
|
236
|
+
} else if (cmd.hasPrefix(args)) {
|
|
237
|
+
this.helpCommands.push(cmd);
|
|
199
238
|
}
|
|
200
239
|
}
|
|
201
240
|
}
|
|
202
|
-
return true;
|
|
203
|
-
} else {
|
|
204
|
-
return false;
|
|
205
241
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
for (const line of breadc.help(helpCommand)) {
|
|
210
|
-
breadc.logger.println(line);
|
|
242
|
+
return true;
|
|
243
|
+
} else {
|
|
244
|
+
return false;
|
|
211
245
|
}
|
|
212
|
-
}
|
|
246
|
+
}
|
|
247
|
+
async run() {
|
|
248
|
+
const shouldHelp = this.runCommands.length > 0 ? this.runCommands : this.helpCommands;
|
|
249
|
+
for (const line of this.help(shouldHelp)) {
|
|
250
|
+
this.logger.println(line);
|
|
251
|
+
}
|
|
252
|
+
this.runCommands.splice(0);
|
|
253
|
+
this.helpCommands.splice(0);
|
|
254
|
+
}
|
|
213
255
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
256
|
+
class VersionCommand extends InternalCommand {
|
|
257
|
+
constructor(version, logger) {
|
|
258
|
+
super("-v, --version", { description: "Display version number", logger });
|
|
259
|
+
this.version = version;
|
|
260
|
+
}
|
|
261
|
+
shouldRun(args) {
|
|
262
|
+
const isEmpty = !args["_"].length && !args["--"]?.length;
|
|
263
|
+
if (args.version && isEmpty) {
|
|
264
|
+
return true;
|
|
265
|
+
} else if (args.v && isEmpty) {
|
|
266
|
+
return true;
|
|
267
|
+
} else {
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
async run() {
|
|
272
|
+
this.logger.println(this.version);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
function isArg(arg) {
|
|
276
|
+
return arg[0] === "[" && arg[arg.length - 1] === "]" || arg[0] === "<" && arg[arg.length - 1] === ">";
|
|
230
277
|
}
|
|
231
278
|
|
|
232
279
|
class Breadc {
|
|
@@ -241,24 +288,16 @@ class Breadc {
|
|
|
241
288
|
this._version = option.version ?? "unknown";
|
|
242
289
|
this.description = option.description;
|
|
243
290
|
this.logger = createDefaultLogger(name, option.logger);
|
|
244
|
-
|
|
245
|
-
name: this.name,
|
|
246
|
-
version: () => this.version.call(this),
|
|
247
|
-
help: (command) => this.help.call(this, command),
|
|
248
|
-
logger: this.logger,
|
|
249
|
-
options: this.options,
|
|
250
|
-
commands: this.commands
|
|
251
|
-
};
|
|
252
|
-
this.commands.push(createVersionCommand(breadc), createHelpCommand(breadc));
|
|
291
|
+
this.commands.push(new VersionCommand(this.version(), this.logger), new HelpCommand(this.commands, this.help.bind(this), this.logger));
|
|
253
292
|
}
|
|
254
293
|
version() {
|
|
255
294
|
return `${this.name}/${this._version}`;
|
|
256
295
|
}
|
|
257
|
-
help(
|
|
296
|
+
help(commands = []) {
|
|
258
297
|
const output = [];
|
|
259
298
|
const println = (msg) => output.push(msg);
|
|
260
299
|
println(this.version());
|
|
261
|
-
if (
|
|
300
|
+
if (commands.length === 0) {
|
|
262
301
|
if (this.description) {
|
|
263
302
|
println("");
|
|
264
303
|
if (Array.isArray(this.description)) {
|
|
@@ -269,27 +308,26 @@ class Breadc {
|
|
|
269
308
|
println(this.description);
|
|
270
309
|
}
|
|
271
310
|
}
|
|
272
|
-
} else {
|
|
273
|
-
if (command.description) {
|
|
274
|
-
println("");
|
|
275
|
-
println(command.description);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
if (!command) {
|
|
279
311
|
if (this.defaultCommand) {
|
|
280
312
|
println(``);
|
|
281
313
|
println(`Usage:`);
|
|
282
|
-
println(` $ ${this.name} ${this.defaultCommand.format
|
|
314
|
+
println(` $ ${this.name} ${this.defaultCommand.format}`);
|
|
315
|
+
}
|
|
316
|
+
} else if (commands.length === 1) {
|
|
317
|
+
const command = commands[0];
|
|
318
|
+
if (command.description) {
|
|
319
|
+
println("");
|
|
320
|
+
println(command.description);
|
|
283
321
|
}
|
|
284
|
-
} else {
|
|
285
322
|
println(``);
|
|
286
323
|
println(`Usage:`);
|
|
287
|
-
println(` $ ${this.name} ${command.format
|
|
324
|
+
println(` $ ${this.name} ${command.format}`);
|
|
288
325
|
}
|
|
289
|
-
if (
|
|
326
|
+
if (commands.length !== 1) {
|
|
327
|
+
const cmdList = (commands.length === 0 ? this.commands : commands).filter((c) => !c.isInternal);
|
|
290
328
|
println(``);
|
|
291
329
|
println(`Commands:`);
|
|
292
|
-
const commandHelps =
|
|
330
|
+
const commandHelps = cmdList.map((c) => [` $ ${this.name} ${c.format}`, c.description]);
|
|
293
331
|
for (const line of twoColumn(commandHelps)) {
|
|
294
332
|
println(line);
|
|
295
333
|
}
|
|
@@ -297,7 +335,7 @@ class Breadc {
|
|
|
297
335
|
println(``);
|
|
298
336
|
println(`Options:`);
|
|
299
337
|
const optionHelps = [].concat([
|
|
300
|
-
...
|
|
338
|
+
...commands.length > 0 ? commands.flatMap((cmd) => cmd.options.map((o) => [` ${o.format}`, o.description])) : [],
|
|
301
339
|
...this.options.map((o) => [` ${o.format}`, o.description]),
|
|
302
340
|
[` -h, --help`, `Display this message`],
|
|
303
341
|
[` -v, --version`, `Display version number`]
|
|
@@ -335,15 +373,28 @@ class Breadc {
|
|
|
335
373
|
...this.options,
|
|
336
374
|
...this.commands.flatMap((c) => c.options)
|
|
337
375
|
];
|
|
376
|
+
{
|
|
377
|
+
const names = /* @__PURE__ */ new Map();
|
|
378
|
+
for (const option of allowOptions) {
|
|
379
|
+
if (names.has(option.name)) {
|
|
380
|
+
const otherOption = names.get(option.name);
|
|
381
|
+
if (otherOption.type !== option.type) {
|
|
382
|
+
this.logger.warn(`Option "${option.name}" encounters conflict`);
|
|
383
|
+
}
|
|
384
|
+
} else {
|
|
385
|
+
names.set(option.name, option);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
338
389
|
const alias = allowOptions.reduce((map, o) => {
|
|
339
390
|
if (o.shortcut) {
|
|
340
391
|
map[o.shortcut] = o.name;
|
|
341
392
|
}
|
|
342
393
|
return map;
|
|
343
|
-
}, {});
|
|
394
|
+
}, { h: "help", v: "version" });
|
|
344
395
|
const argv = minimist(args, {
|
|
345
396
|
string: allowOptions.filter((o) => o.type === "string").map((o) => o.name),
|
|
346
|
-
boolean: allowOptions.filter((o) => o.type === "boolean").map((o) => o.name),
|
|
397
|
+
boolean: allowOptions.filter((o) => o.type === "boolean").map((o) => o.name).concat(["help", "version"]),
|
|
347
398
|
alias,
|
|
348
399
|
unknown: (t) => {
|
|
349
400
|
if (t[0] !== "-")
|
|
@@ -367,11 +418,14 @@ class Breadc {
|
|
|
367
418
|
}
|
|
368
419
|
}
|
|
369
420
|
if (this.defaultCommand) {
|
|
421
|
+
this.defaultCommand.shouldRun(argv);
|
|
370
422
|
return this.defaultCommand.parseArgs(argv, this.options);
|
|
371
423
|
}
|
|
372
424
|
const argumentss = argv["_"];
|
|
373
425
|
const options = argv;
|
|
374
426
|
delete options["_"];
|
|
427
|
+
delete options["help"];
|
|
428
|
+
delete options["version"];
|
|
375
429
|
return {
|
|
376
430
|
command: void 0,
|
|
377
431
|
arguments: argumentss,
|
|
@@ -391,14 +445,6 @@ class Breadc {
|
|
|
391
445
|
}
|
|
392
446
|
}
|
|
393
447
|
}
|
|
394
|
-
function twoColumn(texts, split = " ") {
|
|
395
|
-
const left = padRight(texts.map((t) => t[0]));
|
|
396
|
-
return left.map((l, idx) => l + split + texts[idx][1]);
|
|
397
|
-
}
|
|
398
|
-
function padRight(texts, fill = " ") {
|
|
399
|
-
const length = texts.map((t) => t.length).reduce((max, l) => Math.max(max, l), 0);
|
|
400
|
-
return texts.map((t) => t + fill.repeat(length - t.length));
|
|
401
|
-
}
|
|
402
448
|
|
|
403
449
|
function breadc(name, option = {}) {
|
|
404
450
|
return new Breadc(name, option);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "breadc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Yet another Command Line Application Framework with fully strong TypeScript support",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -43,11 +43,11 @@
|
|
|
43
43
|
"bumpp": "^8.2.1",
|
|
44
44
|
"prettier": "^2.7.1",
|
|
45
45
|
"typescript": "^4.7.4",
|
|
46
|
-
"unbuild": "^0.7.
|
|
47
|
-
"vite": "^
|
|
48
|
-
"vitest": "^0.
|
|
46
|
+
"unbuild": "^0.7.6",
|
|
47
|
+
"vite": "^3.0.2",
|
|
48
|
+
"vitest": "^0.18.1"
|
|
49
49
|
},
|
|
50
|
-
"packageManager": "pnpm@7.
|
|
50
|
+
"packageManager": "pnpm@7.5.2",
|
|
51
51
|
"scripts": {
|
|
52
52
|
"build": "unbuild",
|
|
53
53
|
"format": "prettier --write src/**/*.ts test/*.ts examples/*.ts",
|