breadc 0.2.0 → 0.4.1

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 CHANGED
@@ -2,7 +2,13 @@
2
2
 
3
3
  [![version](https://img.shields.io/npm/v/breadc?color=rgb%2850%2C203%2C86%29&label=Breadc)](https://www.npmjs.com/package/breadc) [![CI](https://github.com/yjl9903/Breadc/actions/workflows/ci.yml/badge.svg)](https://github.com/yjl9903/Breadc/actions/workflows/ci.yml)
4
4
 
5
- Yet another Command Line Application Framework powered by [minimist](https://www.npmjs.com/package/minimist), but with fully [TypeScript](https://www.typescriptlang.org/) support.
5
+ Yet another Command Line Application Framework powered by [minimist](https://www.npmjs.com/package/minimist), but with fully strong [TypeScript](https://www.typescriptlang.org/) support.
6
+
7
+ ## Features
8
+
9
+ + ⚡️ **Light-weight**: Only 61 kB.
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
+ + 💻 **TypeScript Infer**: IDE will automatically infer the type of your command action function.
6
12
 
7
13
  ## Installation
8
14
 
@@ -18,11 +24,11 @@ Try [./examples/echo.ts](./examples/echo.ts).
18
24
  import Breadc from 'breadc'
19
25
 
20
26
  const cli = Breadc('echo', { version: '1.0.0' })
21
- .option('--host <host>')
22
- .option('--port <port>')
27
+ .option('--host [host]', { default: 'localhost' })
28
+ .option('--port [port]', { construct: (port) => (port ? +port : 3000) });
23
29
 
24
30
  cli
25
- .command('[message]')
31
+ .command('[message]', 'Say something!')
26
32
  .action((message, option) => {
27
33
  const host = option.host;
28
34
  const port = option.port;
package/dist/index.cjs CHANGED
@@ -3,37 +3,283 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  const kolorist = require('kolorist');
6
- const minimist = require('minimist');
7
- const createDebug = require('debug');
8
6
 
9
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
10
8
 
11
9
  const kolorist__default = /*#__PURE__*/_interopDefaultLegacy(kolorist);
12
- const minimist__default = /*#__PURE__*/_interopDefaultLegacy(minimist);
13
- const createDebug__default = /*#__PURE__*/_interopDefaultLegacy(createDebug);
10
+
11
+ var minimist = function (args, opts) {
12
+ if (!opts) opts = {};
13
+
14
+ var flags = { bools : {}, strings : {}, unknownFn: null };
15
+
16
+ if (typeof opts['unknown'] === 'function') {
17
+ flags.unknownFn = opts['unknown'];
18
+ }
19
+
20
+ if (typeof opts['boolean'] === 'boolean' && opts['boolean']) {
21
+ flags.allBools = true;
22
+ } else {
23
+ [].concat(opts['boolean']).filter(Boolean).forEach(function (key) {
24
+ flags.bools[key] = true;
25
+ });
26
+ }
27
+
28
+ var aliases = {};
29
+ Object.keys(opts.alias || {}).forEach(function (key) {
30
+ aliases[key] = [].concat(opts.alias[key]);
31
+ aliases[key].forEach(function (x) {
32
+ aliases[x] = [key].concat(aliases[key].filter(function (y) {
33
+ return x !== y;
34
+ }));
35
+ });
36
+ });
37
+
38
+ [].concat(opts.string).filter(Boolean).forEach(function (key) {
39
+ flags.strings[key] = true;
40
+ if (aliases[key]) {
41
+ flags.strings[aliases[key]] = true;
42
+ }
43
+ });
44
+
45
+ var defaults = opts['default'] || {};
46
+
47
+ var argv = { _ : [] };
48
+ Object.keys(flags.bools).forEach(function (key) {
49
+ setArg(key, defaults[key] === undefined ? false : defaults[key]);
50
+ });
51
+
52
+ var notFlags = [];
53
+
54
+ if (args.indexOf('--') !== -1) {
55
+ notFlags = args.slice(args.indexOf('--')+1);
56
+ args = args.slice(0, args.indexOf('--'));
57
+ }
58
+
59
+ function argDefined(key, arg) {
60
+ return (flags.allBools && /^--[^=]+$/.test(arg)) ||
61
+ flags.strings[key] || flags.bools[key] || aliases[key];
62
+ }
63
+
64
+ function setArg (key, val, arg) {
65
+ if (arg && flags.unknownFn && !argDefined(key, arg)) {
66
+ if (flags.unknownFn(arg) === false) return;
67
+ }
68
+
69
+ var value = !flags.strings[key] && isNumber(val)
70
+ ? Number(val) : val
71
+ ;
72
+ setKey(argv, key.split('.'), value);
73
+
74
+ (aliases[key] || []).forEach(function (x) {
75
+ setKey(argv, x.split('.'), value);
76
+ });
77
+ }
78
+
79
+ function setKey (obj, keys, value) {
80
+ var o = obj;
81
+ for (var i = 0; i < keys.length-1; i++) {
82
+ var key = keys[i];
83
+ if (isConstructorOrProto(o, key)) return;
84
+ if (o[key] === undefined) o[key] = {};
85
+ if (o[key] === Object.prototype || o[key] === Number.prototype
86
+ || o[key] === String.prototype) o[key] = {};
87
+ if (o[key] === Array.prototype) o[key] = [];
88
+ o = o[key];
89
+ }
90
+
91
+ var key = keys[keys.length - 1];
92
+ if (isConstructorOrProto(o, key)) return;
93
+ if (o === Object.prototype || o === Number.prototype
94
+ || o === String.prototype) o = {};
95
+ if (o === Array.prototype) o = [];
96
+ if (o[key] === undefined || flags.bools[key] || typeof o[key] === 'boolean') {
97
+ o[key] = value;
98
+ }
99
+ else if (Array.isArray(o[key])) {
100
+ o[key].push(value);
101
+ }
102
+ else {
103
+ o[key] = [ o[key], value ];
104
+ }
105
+ }
106
+
107
+ function aliasIsBoolean(key) {
108
+ return aliases[key].some(function (x) {
109
+ return flags.bools[x];
110
+ });
111
+ }
112
+
113
+ for (var i = 0; i < args.length; i++) {
114
+ var arg = args[i];
115
+
116
+ if (/^--.+=/.test(arg)) {
117
+ // Using [\s\S] instead of . because js doesn't support the
118
+ // 'dotall' regex modifier. See:
119
+ // http://stackoverflow.com/a/1068308/13216
120
+ var m = arg.match(/^--([^=]+)=([\s\S]*)$/);
121
+ var key = m[1];
122
+ var value = m[2];
123
+ if (flags.bools[key]) {
124
+ value = value !== 'false';
125
+ }
126
+ setArg(key, value, arg);
127
+ }
128
+ else if (/^--no-.+/.test(arg)) {
129
+ var key = arg.match(/^--no-(.+)/)[1];
130
+ setArg(key, false, arg);
131
+ }
132
+ else if (/^--.+/.test(arg)) {
133
+ var key = arg.match(/^--(.+)/)[1];
134
+ var next = args[i + 1];
135
+ if (next !== undefined && !/^-/.test(next)
136
+ && !flags.bools[key]
137
+ && !flags.allBools
138
+ && (aliases[key] ? !aliasIsBoolean(key) : true)) {
139
+ setArg(key, next, arg);
140
+ i++;
141
+ }
142
+ else if (/^(true|false)$/.test(next)) {
143
+ setArg(key, next === 'true', arg);
144
+ i++;
145
+ }
146
+ else {
147
+ setArg(key, flags.strings[key] ? '' : true, arg);
148
+ }
149
+ }
150
+ else if (/^-[^-]+/.test(arg)) {
151
+ var letters = arg.slice(1,-1).split('');
152
+
153
+ var broken = false;
154
+ for (var j = 0; j < letters.length; j++) {
155
+ var next = arg.slice(j+2);
156
+
157
+ if (next === '-') {
158
+ setArg(letters[j], next, arg);
159
+ continue;
160
+ }
161
+
162
+ if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) {
163
+ setArg(letters[j], next.split('=')[1], arg);
164
+ broken = true;
165
+ break;
166
+ }
167
+
168
+ if (/[A-Za-z]/.test(letters[j])
169
+ && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
170
+ setArg(letters[j], next, arg);
171
+ broken = true;
172
+ break;
173
+ }
174
+
175
+ if (letters[j+1] && letters[j+1].match(/\W/)) {
176
+ setArg(letters[j], arg.slice(j+2), arg);
177
+ broken = true;
178
+ break;
179
+ }
180
+ else {
181
+ setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg);
182
+ }
183
+ }
184
+
185
+ var key = arg.slice(-1)[0];
186
+ if (!broken && key !== '-') {
187
+ if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1])
188
+ && !flags.bools[key]
189
+ && (aliases[key] ? !aliasIsBoolean(key) : true)) {
190
+ setArg(key, args[i+1], arg);
191
+ i++;
192
+ }
193
+ else if (args[i+1] && /^(true|false)$/.test(args[i+1])) {
194
+ setArg(key, args[i+1] === 'true', arg);
195
+ i++;
196
+ }
197
+ else {
198
+ setArg(key, flags.strings[key] ? '' : true, arg);
199
+ }
200
+ }
201
+ }
202
+ else {
203
+ if (!flags.unknownFn || flags.unknownFn(arg) !== false) {
204
+ argv._.push(
205
+ flags.strings['_'] || !isNumber(arg) ? arg : Number(arg)
206
+ );
207
+ }
208
+ if (opts.stopEarly) {
209
+ argv._.push.apply(argv._, args.slice(i + 1));
210
+ break;
211
+ }
212
+ }
213
+ }
214
+
215
+ Object.keys(defaults).forEach(function (key) {
216
+ if (!hasKey(argv, key.split('.'))) {
217
+ setKey(argv, key.split('.'), defaults[key]);
218
+
219
+ (aliases[key] || []).forEach(function (x) {
220
+ setKey(argv, x.split('.'), defaults[key]);
221
+ });
222
+ }
223
+ });
224
+
225
+ if (opts['--']) {
226
+ argv['--'] = new Array();
227
+ notFlags.forEach(function(key) {
228
+ argv['--'].push(key);
229
+ });
230
+ }
231
+ else {
232
+ notFlags.forEach(function(key) {
233
+ argv._.push(key);
234
+ });
235
+ }
236
+
237
+ return argv;
238
+ };
239
+
240
+ function hasKey (obj, keys) {
241
+ var o = obj;
242
+ keys.slice(0,-1).forEach(function (key) {
243
+ o = (o[key] || {});
244
+ });
245
+
246
+ var key = keys[keys.length - 1];
247
+ return key in o;
248
+ }
249
+
250
+ function isNumber (x) {
251
+ if (typeof x === 'number') return true;
252
+ if (/^0x[0-9a-f]+$/i.test(x)) return true;
253
+ return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x);
254
+ }
255
+
256
+
257
+ function isConstructorOrProto (obj, key) {
258
+ return key === 'constructor' && typeof obj[key] === 'function' || key === '__proto__';
259
+ }
14
260
 
15
261
  function createDefaultLogger(name, logger) {
16
- if (!!logger && typeof logger === "object") {
17
- return logger;
18
- }
19
- const debug = createDebug__default(name + ":breadc");
20
- const println = !!logger && typeof logger === "function" ? logger : (message, ...args) => {
262
+ const println = !!logger && typeof logger === "function" ? logger : logger?.println ?? ((message, ...args) => {
21
263
  console.log(message, ...args);
264
+ });
265
+ const info = typeof logger === "object" && logger?.info ? logger.info : (message, ...args) => {
266
+ println(`${kolorist.blue("INFO")} ${message}`, ...args);
267
+ };
268
+ const warn = typeof logger === "object" && logger?.warn ? logger.warn : (message, ...args) => {
269
+ println(`${kolorist.yellow("WARN")} ${message}`, ...args);
270
+ };
271
+ const error = typeof logger === "object" && logger?.error ? logger.error : (message, ...args) => {
272
+ println(`${kolorist.red("ERROR")} ${message}`, ...args);
273
+ };
274
+ const debug = typeof logger === "object" && logger?.debug ? logger.debug : (message, ...args) => {
275
+ println(`${kolorist.gray(name)} ${message}`, ...args);
22
276
  };
23
277
  return {
24
278
  println,
25
- info(message, ...args) {
26
- println(`${kolorist.blue("INFO")} ${message}`, ...args);
27
- },
28
- warn(message, ...args) {
29
- println(`${kolorist.yellow("WARN")} ${message}`, ...args);
30
- },
31
- error(message, ...args) {
32
- println(`${kolorist.red("ERROR")} ${message}`, ...args);
33
- },
34
- debug(message, ...args) {
35
- debug(message, ...args);
36
- }
279
+ info,
280
+ warn,
281
+ error,
282
+ debug
37
283
  };
38
284
  }
39
285
 
@@ -57,11 +303,11 @@ const _Option = class {
57
303
  this.description = config.description ?? "";
58
304
  this.required = format.indexOf("<") !== -1;
59
305
  this.default = config.default;
60
- this.construct = config.construct ?? ((text) => text ?? config.default ?? void 0);
306
+ this.construct = config.construct;
61
307
  }
62
308
  };
63
309
  let Option = _Option;
64
- Option.OptionRE = /^(-[a-zA-Z], )?--([a-zA-Z.]+)( \[[a-zA-Z]+\]| <[a-zA-Z]+>)?$/;
310
+ Option.OptionRE = /^(-[a-zA-Z], )?--([a-zA-Z]+)( \[[a-zA-Z]+\]| <[a-zA-Z]+>)?$/;
65
311
 
66
312
  const _Command = class {
67
313
  constructor(format, config) {
@@ -161,6 +407,13 @@ const _Command = class {
161
407
  options[name] = void 0;
162
408
  }
163
409
  }
410
+ if (rawOption.construct) {
411
+ options[name] = rawOption.construct(options[name]);
412
+ } else if (rawOption.default) {
413
+ if (!options[name]) {
414
+ options[name] = rawOption.default;
415
+ }
416
+ }
164
417
  }
165
418
  return {
166
419
  command: this,
@@ -334,17 +587,10 @@ class Breadc {
334
587
  }
335
588
  return map;
336
589
  }, {});
337
- const defaults = allowOptions.reduce((map, o) => {
338
- if (o.default) {
339
- map[o.name] = o.default;
340
- }
341
- return map;
342
- }, {});
343
- const argv = minimist__default(args, {
590
+ const argv = minimist(args, {
344
591
  string: allowOptions.filter((o) => o.type === "string").map((o) => o.name),
345
592
  boolean: allowOptions.filter((o) => o.type === "boolean").map((o) => o.name),
346
593
  alias,
347
- default: defaults,
348
594
  unknown: (t) => {
349
595
  if (t[0] !== "-")
350
596
  return true;
@@ -399,6 +645,5 @@ function breadc(name, option = {}) {
399
645
  }
400
646
 
401
647
  exports.kolorist = kolorist__default;
402
- exports.minimist = minimist__default;
403
- exports.createDebug = createDebug__default;
404
648
  exports["default"] = breadc;
649
+ exports.minimist = minimist;
package/dist/index.d.ts CHANGED
@@ -1,12 +1,259 @@
1
- import { ParsedArgs } from 'minimist';
2
- export { default as minimist } from 'minimist';
3
1
  export { default as kolorist } from 'kolorist';
4
- export { default as createDebug } from 'debug';
5
2
 
6
- interface OptionConfig<T = string> {
3
+ var minimist = function (args, opts) {
4
+ if (!opts) opts = {};
5
+
6
+ var flags = { bools : {}, strings : {}, unknownFn: null };
7
+
8
+ if (typeof opts['unknown'] === 'function') {
9
+ flags.unknownFn = opts['unknown'];
10
+ }
11
+
12
+ if (typeof opts['boolean'] === 'boolean' && opts['boolean']) {
13
+ flags.allBools = true;
14
+ } else {
15
+ [].concat(opts['boolean']).filter(Boolean).forEach(function (key) {
16
+ flags.bools[key] = true;
17
+ });
18
+ }
19
+
20
+ var aliases = {};
21
+ Object.keys(opts.alias || {}).forEach(function (key) {
22
+ aliases[key] = [].concat(opts.alias[key]);
23
+ aliases[key].forEach(function (x) {
24
+ aliases[x] = [key].concat(aliases[key].filter(function (y) {
25
+ return x !== y;
26
+ }));
27
+ });
28
+ });
29
+
30
+ [].concat(opts.string).filter(Boolean).forEach(function (key) {
31
+ flags.strings[key] = true;
32
+ if (aliases[key]) {
33
+ flags.strings[aliases[key]] = true;
34
+ }
35
+ });
36
+
37
+ var defaults = opts['default'] || {};
38
+
39
+ var argv = { _ : [] };
40
+ Object.keys(flags.bools).forEach(function (key) {
41
+ setArg(key, defaults[key] === undefined ? false : defaults[key]);
42
+ });
43
+
44
+ var notFlags = [];
45
+
46
+ if (args.indexOf('--') !== -1) {
47
+ notFlags = args.slice(args.indexOf('--')+1);
48
+ args = args.slice(0, args.indexOf('--'));
49
+ }
50
+
51
+ function argDefined(key, arg) {
52
+ return (flags.allBools && /^--[^=]+$/.test(arg)) ||
53
+ flags.strings[key] || flags.bools[key] || aliases[key];
54
+ }
55
+
56
+ function setArg (key, val, arg) {
57
+ if (arg && flags.unknownFn && !argDefined(key, arg)) {
58
+ if (flags.unknownFn(arg) === false) return;
59
+ }
60
+
61
+ var value = !flags.strings[key] && isNumber(val)
62
+ ? Number(val) : val
63
+ ;
64
+ setKey(argv, key.split('.'), value);
65
+
66
+ (aliases[key] || []).forEach(function (x) {
67
+ setKey(argv, x.split('.'), value);
68
+ });
69
+ }
70
+
71
+ function setKey (obj, keys, value) {
72
+ var o = obj;
73
+ for (var i = 0; i < keys.length-1; i++) {
74
+ var key = keys[i];
75
+ if (isConstructorOrProto(o, key)) return;
76
+ if (o[key] === undefined) o[key] = {};
77
+ if (o[key] === Object.prototype || o[key] === Number.prototype
78
+ || o[key] === String.prototype) o[key] = {};
79
+ if (o[key] === Array.prototype) o[key] = [];
80
+ o = o[key];
81
+ }
82
+
83
+ var key = keys[keys.length - 1];
84
+ if (isConstructorOrProto(o, key)) return;
85
+ if (o === Object.prototype || o === Number.prototype
86
+ || o === String.prototype) o = {};
87
+ if (o === Array.prototype) o = [];
88
+ if (o[key] === undefined || flags.bools[key] || typeof o[key] === 'boolean') {
89
+ o[key] = value;
90
+ }
91
+ else if (Array.isArray(o[key])) {
92
+ o[key].push(value);
93
+ }
94
+ else {
95
+ o[key] = [ o[key], value ];
96
+ }
97
+ }
98
+
99
+ function aliasIsBoolean(key) {
100
+ return aliases[key].some(function (x) {
101
+ return flags.bools[x];
102
+ });
103
+ }
104
+
105
+ for (var i = 0; i < args.length; i++) {
106
+ var arg = args[i];
107
+
108
+ if (/^--.+=/.test(arg)) {
109
+ // Using [\s\S] instead of . because js doesn't support the
110
+ // 'dotall' regex modifier. See:
111
+ // http://stackoverflow.com/a/1068308/13216
112
+ var m = arg.match(/^--([^=]+)=([\s\S]*)$/);
113
+ var key = m[1];
114
+ var value = m[2];
115
+ if (flags.bools[key]) {
116
+ value = value !== 'false';
117
+ }
118
+ setArg(key, value, arg);
119
+ }
120
+ else if (/^--no-.+/.test(arg)) {
121
+ var key = arg.match(/^--no-(.+)/)[1];
122
+ setArg(key, false, arg);
123
+ }
124
+ else if (/^--.+/.test(arg)) {
125
+ var key = arg.match(/^--(.+)/)[1];
126
+ var next = args[i + 1];
127
+ if (next !== undefined && !/^-/.test(next)
128
+ && !flags.bools[key]
129
+ && !flags.allBools
130
+ && (aliases[key] ? !aliasIsBoolean(key) : true)) {
131
+ setArg(key, next, arg);
132
+ i++;
133
+ }
134
+ else if (/^(true|false)$/.test(next)) {
135
+ setArg(key, next === 'true', arg);
136
+ i++;
137
+ }
138
+ else {
139
+ setArg(key, flags.strings[key] ? '' : true, arg);
140
+ }
141
+ }
142
+ else if (/^-[^-]+/.test(arg)) {
143
+ var letters = arg.slice(1,-1).split('');
144
+
145
+ var broken = false;
146
+ for (var j = 0; j < letters.length; j++) {
147
+ var next = arg.slice(j+2);
148
+
149
+ if (next === '-') {
150
+ setArg(letters[j], next, arg);
151
+ continue;
152
+ }
153
+
154
+ if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) {
155
+ setArg(letters[j], next.split('=')[1], arg);
156
+ broken = true;
157
+ break;
158
+ }
159
+
160
+ if (/[A-Za-z]/.test(letters[j])
161
+ && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
162
+ setArg(letters[j], next, arg);
163
+ broken = true;
164
+ break;
165
+ }
166
+
167
+ if (letters[j+1] && letters[j+1].match(/\W/)) {
168
+ setArg(letters[j], arg.slice(j+2), arg);
169
+ broken = true;
170
+ break;
171
+ }
172
+ else {
173
+ setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg);
174
+ }
175
+ }
176
+
177
+ var key = arg.slice(-1)[0];
178
+ if (!broken && key !== '-') {
179
+ if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1])
180
+ && !flags.bools[key]
181
+ && (aliases[key] ? !aliasIsBoolean(key) : true)) {
182
+ setArg(key, args[i+1], arg);
183
+ i++;
184
+ }
185
+ else if (args[i+1] && /^(true|false)$/.test(args[i+1])) {
186
+ setArg(key, args[i+1] === 'true', arg);
187
+ i++;
188
+ }
189
+ else {
190
+ setArg(key, flags.strings[key] ? '' : true, arg);
191
+ }
192
+ }
193
+ }
194
+ else {
195
+ if (!flags.unknownFn || flags.unknownFn(arg) !== false) {
196
+ argv._.push(
197
+ flags.strings['_'] || !isNumber(arg) ? arg : Number(arg)
198
+ );
199
+ }
200
+ if (opts.stopEarly) {
201
+ argv._.push.apply(argv._, args.slice(i + 1));
202
+ break;
203
+ }
204
+ }
205
+ }
206
+
207
+ Object.keys(defaults).forEach(function (key) {
208
+ if (!hasKey(argv, key.split('.'))) {
209
+ setKey(argv, key.split('.'), defaults[key]);
210
+
211
+ (aliases[key] || []).forEach(function (x) {
212
+ setKey(argv, x.split('.'), defaults[key]);
213
+ });
214
+ }
215
+ });
216
+
217
+ if (opts['--']) {
218
+ argv['--'] = new Array();
219
+ notFlags.forEach(function(key) {
220
+ argv['--'].push(key);
221
+ });
222
+ }
223
+ else {
224
+ notFlags.forEach(function(key) {
225
+ argv._.push(key);
226
+ });
227
+ }
228
+
229
+ return argv;
230
+ };
231
+
232
+ function hasKey (obj, keys) {
233
+ var o = obj;
234
+ keys.slice(0,-1).forEach(function (key) {
235
+ o = (o[key] || {});
236
+ });
237
+
238
+ var key = keys[keys.length - 1];
239
+ return key in o;
240
+ }
241
+
242
+ function isNumber (x) {
243
+ if (typeof x === 'number') return true;
244
+ if (/^0x[0-9a-f]+$/i.test(x)) return true;
245
+ return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x);
246
+ }
247
+
248
+
249
+ function isConstructorOrProto (obj, key) {
250
+ return key === 'constructor' && typeof obj[key] === 'function' || key === '__proto__';
251
+ }
252
+
253
+ interface OptionConfig<F extends string, T = never> {
7
254
  description?: string;
8
255
  default?: T;
9
- construct?: (rawText?: string) => T;
256
+ construct?: (rawText: ExtractOptionType<F>) => T;
10
257
  }
11
258
  /**
12
259
  * Option
@@ -26,11 +273,11 @@ declare class Option<T extends string = string, F = string> {
26
273
  readonly description: string;
27
274
  readonly type: 'string' | 'boolean';
28
275
  readonly required: boolean;
29
- readonly construct: (rawText: string | undefined) => any;
30
- constructor(format: T, config?: OptionConfig<F>);
276
+ readonly construct?: (rawText: ExtractOptionType<T>) => F;
277
+ constructor(format: T, config?: OptionConfig<T, F>);
31
278
  }
32
279
 
33
- declare type ConditionFn = (args: ParsedArgs) => boolean;
280
+ declare type ConditionFn = (args: minimist.ParsedArgs) => boolean;
34
281
  interface CommandConfig {
35
282
  description?: string;
36
283
  }
@@ -47,11 +294,11 @@ declare class Command<F extends string = string, CommandOption extends object =
47
294
  condition?: ConditionFn;
48
295
  logger: Logger;
49
296
  });
50
- option<OF extends string, T = string>(format: OF, description: string, config?: Omit<OptionConfig<T>, 'description'>): Command<F, CommandOption & ExtractOption<OF>>;
51
- option<OF extends string, T = string>(format: OF, config?: OptionConfig<T>): Command<F, CommandOption & ExtractOption<OF>>;
297
+ option<OF extends string, T = undefined>(format: OF, description: string, config?: Omit<OptionConfig<OF, T>, 'description'>): Command<F, CommandOption & ExtractOption<OF, T>>;
298
+ option<OF extends string, T = undefined>(format: OF, config?: OptionConfig<OF, T>): Command<F, CommandOption & ExtractOption<OF, T>>;
52
299
  get hasConditionFn(): boolean;
53
- shouldRun(args: ParsedArgs): boolean;
54
- parseArgs(args: ParsedArgs, globalOptions: Option[]): ParseResult;
300
+ shouldRun(args: minimist.ParsedArgs): boolean;
301
+ parseArgs(args: minimist.ParsedArgs, globalOptions: Option[]): ParseResult;
55
302
  action(fn: ActionFn<ExtractCommand<F>, CommandOption>): this;
56
303
  run(...args: any[]): Promise<void>;
57
304
  }
@@ -60,7 +307,7 @@ interface AppOption {
60
307
  version?: string;
61
308
  description?: string | string[];
62
309
  help?: string | string[] | (() => string | string[]);
63
- logger?: Logger | LoggerFn;
310
+ logger?: Partial<Logger> | LoggerFn;
64
311
  }
65
312
  declare type LoggerFn = (message: string, ...args: any[]) => void;
66
313
  interface Logger {
@@ -75,8 +322,8 @@ interface ParseResult {
75
322
  arguments: any[];
76
323
  options: Record<string, string>;
77
324
  }
78
- declare type ExtractOption<T extends string> = {
79
- [k in ExtractOptionName<T>]: ExtractOptionType<T>;
325
+ declare type ExtractOption<T extends string, D = undefined> = {
326
+ [k in ExtractOptionName<T>]: D extends undefined ? ExtractOptionType<T> : D;
80
327
  };
81
328
  /**
82
329
  * Extract option name type
@@ -110,8 +357,8 @@ declare class Breadc<GlobalOption extends object = {}> {
110
357
  constructor(name: string, option: AppOption);
111
358
  version(): string;
112
359
  help(command?: Command): string[];
113
- option<F extends string, T = string>(format: F, description: string, config?: Omit<OptionConfig<T>, 'description'>): Breadc<GlobalOption & ExtractOption<F>>;
114
- option<F extends string, T = string>(format: F, config?: OptionConfig<T>): Breadc<GlobalOption & ExtractOption<F>>;
360
+ option<F extends string, T = undefined>(format: F, description: string, config?: Omit<OptionConfig<F, T>, 'description'>): Breadc<GlobalOption & ExtractOption<F, T>>;
361
+ option<F extends string, T = undefined>(format: F, config?: OptionConfig<F, T>): Breadc<GlobalOption & ExtractOption<F, T>>;
115
362
  command<F extends string>(format: F, description: string, config?: Omit<CommandConfig, 'description'>): Command<F, GlobalOption>;
116
363
  command<F extends string>(format: F, config?: CommandConfig): Command<F, GlobalOption>;
117
364
  parse(args: string[]): ParseResult;
@@ -120,4 +367,4 @@ declare class Breadc<GlobalOption extends object = {}> {
120
367
 
121
368
  declare function breadc(name: string, option?: AppOption): Breadc<{}>;
122
369
 
123
- export { breadc as default };
370
+ export { breadc as default, minimist };
package/dist/index.mjs CHANGED
@@ -1,32 +1,278 @@
1
- import { blue, yellow, red } from 'kolorist';
1
+ import { blue, yellow, red, gray } from 'kolorist';
2
2
  export { default as kolorist } from 'kolorist';
3
- import minimist from 'minimist';
4
- export { default as minimist } from 'minimist';
5
- import createDebug from 'debug';
6
- export { default as createDebug } from 'debug';
3
+
4
+ var minimist = function (args, opts) {
5
+ if (!opts) opts = {};
6
+
7
+ var flags = { bools : {}, strings : {}, unknownFn: null };
8
+
9
+ if (typeof opts['unknown'] === 'function') {
10
+ flags.unknownFn = opts['unknown'];
11
+ }
12
+
13
+ if (typeof opts['boolean'] === 'boolean' && opts['boolean']) {
14
+ flags.allBools = true;
15
+ } else {
16
+ [].concat(opts['boolean']).filter(Boolean).forEach(function (key) {
17
+ flags.bools[key] = true;
18
+ });
19
+ }
20
+
21
+ var aliases = {};
22
+ Object.keys(opts.alias || {}).forEach(function (key) {
23
+ aliases[key] = [].concat(opts.alias[key]);
24
+ aliases[key].forEach(function (x) {
25
+ aliases[x] = [key].concat(aliases[key].filter(function (y) {
26
+ return x !== y;
27
+ }));
28
+ });
29
+ });
30
+
31
+ [].concat(opts.string).filter(Boolean).forEach(function (key) {
32
+ flags.strings[key] = true;
33
+ if (aliases[key]) {
34
+ flags.strings[aliases[key]] = true;
35
+ }
36
+ });
37
+
38
+ var defaults = opts['default'] || {};
39
+
40
+ var argv = { _ : [] };
41
+ Object.keys(flags.bools).forEach(function (key) {
42
+ setArg(key, defaults[key] === undefined ? false : defaults[key]);
43
+ });
44
+
45
+ var notFlags = [];
46
+
47
+ if (args.indexOf('--') !== -1) {
48
+ notFlags = args.slice(args.indexOf('--')+1);
49
+ args = args.slice(0, args.indexOf('--'));
50
+ }
51
+
52
+ function argDefined(key, arg) {
53
+ return (flags.allBools && /^--[^=]+$/.test(arg)) ||
54
+ flags.strings[key] || flags.bools[key] || aliases[key];
55
+ }
56
+
57
+ function setArg (key, val, arg) {
58
+ if (arg && flags.unknownFn && !argDefined(key, arg)) {
59
+ if (flags.unknownFn(arg) === false) return;
60
+ }
61
+
62
+ var value = !flags.strings[key] && isNumber(val)
63
+ ? Number(val) : val
64
+ ;
65
+ setKey(argv, key.split('.'), value);
66
+
67
+ (aliases[key] || []).forEach(function (x) {
68
+ setKey(argv, x.split('.'), value);
69
+ });
70
+ }
71
+
72
+ function setKey (obj, keys, value) {
73
+ var o = obj;
74
+ for (var i = 0; i < keys.length-1; i++) {
75
+ var key = keys[i];
76
+ if (isConstructorOrProto(o, key)) return;
77
+ if (o[key] === undefined) o[key] = {};
78
+ if (o[key] === Object.prototype || o[key] === Number.prototype
79
+ || o[key] === String.prototype) o[key] = {};
80
+ if (o[key] === Array.prototype) o[key] = [];
81
+ o = o[key];
82
+ }
83
+
84
+ var key = keys[keys.length - 1];
85
+ if (isConstructorOrProto(o, key)) return;
86
+ if (o === Object.prototype || o === Number.prototype
87
+ || o === String.prototype) o = {};
88
+ if (o === Array.prototype) o = [];
89
+ if (o[key] === undefined || flags.bools[key] || typeof o[key] === 'boolean') {
90
+ o[key] = value;
91
+ }
92
+ else if (Array.isArray(o[key])) {
93
+ o[key].push(value);
94
+ }
95
+ else {
96
+ o[key] = [ o[key], value ];
97
+ }
98
+ }
99
+
100
+ function aliasIsBoolean(key) {
101
+ return aliases[key].some(function (x) {
102
+ return flags.bools[x];
103
+ });
104
+ }
105
+
106
+ for (var i = 0; i < args.length; i++) {
107
+ var arg = args[i];
108
+
109
+ if (/^--.+=/.test(arg)) {
110
+ // Using [\s\S] instead of . because js doesn't support the
111
+ // 'dotall' regex modifier. See:
112
+ // http://stackoverflow.com/a/1068308/13216
113
+ var m = arg.match(/^--([^=]+)=([\s\S]*)$/);
114
+ var key = m[1];
115
+ var value = m[2];
116
+ if (flags.bools[key]) {
117
+ value = value !== 'false';
118
+ }
119
+ setArg(key, value, arg);
120
+ }
121
+ else if (/^--no-.+/.test(arg)) {
122
+ var key = arg.match(/^--no-(.+)/)[1];
123
+ setArg(key, false, arg);
124
+ }
125
+ else if (/^--.+/.test(arg)) {
126
+ var key = arg.match(/^--(.+)/)[1];
127
+ var next = args[i + 1];
128
+ if (next !== undefined && !/^-/.test(next)
129
+ && !flags.bools[key]
130
+ && !flags.allBools
131
+ && (aliases[key] ? !aliasIsBoolean(key) : true)) {
132
+ setArg(key, next, arg);
133
+ i++;
134
+ }
135
+ else if (/^(true|false)$/.test(next)) {
136
+ setArg(key, next === 'true', arg);
137
+ i++;
138
+ }
139
+ else {
140
+ setArg(key, flags.strings[key] ? '' : true, arg);
141
+ }
142
+ }
143
+ else if (/^-[^-]+/.test(arg)) {
144
+ var letters = arg.slice(1,-1).split('');
145
+
146
+ var broken = false;
147
+ for (var j = 0; j < letters.length; j++) {
148
+ var next = arg.slice(j+2);
149
+
150
+ if (next === '-') {
151
+ setArg(letters[j], next, arg);
152
+ continue;
153
+ }
154
+
155
+ if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) {
156
+ setArg(letters[j], next.split('=')[1], arg);
157
+ broken = true;
158
+ break;
159
+ }
160
+
161
+ if (/[A-Za-z]/.test(letters[j])
162
+ && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
163
+ setArg(letters[j], next, arg);
164
+ broken = true;
165
+ break;
166
+ }
167
+
168
+ if (letters[j+1] && letters[j+1].match(/\W/)) {
169
+ setArg(letters[j], arg.slice(j+2), arg);
170
+ broken = true;
171
+ break;
172
+ }
173
+ else {
174
+ setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg);
175
+ }
176
+ }
177
+
178
+ var key = arg.slice(-1)[0];
179
+ if (!broken && key !== '-') {
180
+ if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1])
181
+ && !flags.bools[key]
182
+ && (aliases[key] ? !aliasIsBoolean(key) : true)) {
183
+ setArg(key, args[i+1], arg);
184
+ i++;
185
+ }
186
+ else if (args[i+1] && /^(true|false)$/.test(args[i+1])) {
187
+ setArg(key, args[i+1] === 'true', arg);
188
+ i++;
189
+ }
190
+ else {
191
+ setArg(key, flags.strings[key] ? '' : true, arg);
192
+ }
193
+ }
194
+ }
195
+ else {
196
+ if (!flags.unknownFn || flags.unknownFn(arg) !== false) {
197
+ argv._.push(
198
+ flags.strings['_'] || !isNumber(arg) ? arg : Number(arg)
199
+ );
200
+ }
201
+ if (opts.stopEarly) {
202
+ argv._.push.apply(argv._, args.slice(i + 1));
203
+ break;
204
+ }
205
+ }
206
+ }
207
+
208
+ Object.keys(defaults).forEach(function (key) {
209
+ if (!hasKey(argv, key.split('.'))) {
210
+ setKey(argv, key.split('.'), defaults[key]);
211
+
212
+ (aliases[key] || []).forEach(function (x) {
213
+ setKey(argv, x.split('.'), defaults[key]);
214
+ });
215
+ }
216
+ });
217
+
218
+ if (opts['--']) {
219
+ argv['--'] = new Array();
220
+ notFlags.forEach(function(key) {
221
+ argv['--'].push(key);
222
+ });
223
+ }
224
+ else {
225
+ notFlags.forEach(function(key) {
226
+ argv._.push(key);
227
+ });
228
+ }
229
+
230
+ return argv;
231
+ };
232
+
233
+ function hasKey (obj, keys) {
234
+ var o = obj;
235
+ keys.slice(0,-1).forEach(function (key) {
236
+ o = (o[key] || {});
237
+ });
238
+
239
+ var key = keys[keys.length - 1];
240
+ return key in o;
241
+ }
242
+
243
+ function isNumber (x) {
244
+ if (typeof x === 'number') return true;
245
+ if (/^0x[0-9a-f]+$/i.test(x)) return true;
246
+ return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x);
247
+ }
248
+
249
+
250
+ function isConstructorOrProto (obj, key) {
251
+ return key === 'constructor' && typeof obj[key] === 'function' || key === '__proto__';
252
+ }
7
253
 
8
254
  function createDefaultLogger(name, logger) {
9
- if (!!logger && typeof logger === "object") {
10
- return logger;
11
- }
12
- const debug = createDebug(name + ":breadc");
13
- const println = !!logger && typeof logger === "function" ? logger : (message, ...args) => {
255
+ const println = !!logger && typeof logger === "function" ? logger : logger?.println ?? ((message, ...args) => {
14
256
  console.log(message, ...args);
257
+ });
258
+ const info = typeof logger === "object" && logger?.info ? logger.info : (message, ...args) => {
259
+ println(`${blue("INFO")} ${message}`, ...args);
260
+ };
261
+ const warn = typeof logger === "object" && logger?.warn ? logger.warn : (message, ...args) => {
262
+ println(`${yellow("WARN")} ${message}`, ...args);
263
+ };
264
+ const error = typeof logger === "object" && logger?.error ? logger.error : (message, ...args) => {
265
+ println(`${red("ERROR")} ${message}`, ...args);
266
+ };
267
+ const debug = typeof logger === "object" && logger?.debug ? logger.debug : (message, ...args) => {
268
+ println(`${gray(name)} ${message}`, ...args);
15
269
  };
16
270
  return {
17
271
  println,
18
- info(message, ...args) {
19
- println(`${blue("INFO")} ${message}`, ...args);
20
- },
21
- warn(message, ...args) {
22
- println(`${yellow("WARN")} ${message}`, ...args);
23
- },
24
- error(message, ...args) {
25
- println(`${red("ERROR")} ${message}`, ...args);
26
- },
27
- debug(message, ...args) {
28
- debug(message, ...args);
29
- }
272
+ info,
273
+ warn,
274
+ error,
275
+ debug
30
276
  };
31
277
  }
32
278
 
@@ -50,11 +296,11 @@ const _Option = class {
50
296
  this.description = config.description ?? "";
51
297
  this.required = format.indexOf("<") !== -1;
52
298
  this.default = config.default;
53
- this.construct = config.construct ?? ((text) => text ?? config.default ?? void 0);
299
+ this.construct = config.construct;
54
300
  }
55
301
  };
56
302
  let Option = _Option;
57
- Option.OptionRE = /^(-[a-zA-Z], )?--([a-zA-Z.]+)( \[[a-zA-Z]+\]| <[a-zA-Z]+>)?$/;
303
+ Option.OptionRE = /^(-[a-zA-Z], )?--([a-zA-Z]+)( \[[a-zA-Z]+\]| <[a-zA-Z]+>)?$/;
58
304
 
59
305
  const _Command = class {
60
306
  constructor(format, config) {
@@ -154,6 +400,13 @@ const _Command = class {
154
400
  options[name] = void 0;
155
401
  }
156
402
  }
403
+ if (rawOption.construct) {
404
+ options[name] = rawOption.construct(options[name]);
405
+ } else if (rawOption.default) {
406
+ if (!options[name]) {
407
+ options[name] = rawOption.default;
408
+ }
409
+ }
157
410
  }
158
411
  return {
159
412
  command: this,
@@ -327,17 +580,10 @@ class Breadc {
327
580
  }
328
581
  return map;
329
582
  }, {});
330
- const defaults = allowOptions.reduce((map, o) => {
331
- if (o.default) {
332
- map[o.name] = o.default;
333
- }
334
- return map;
335
- }, {});
336
583
  const argv = minimist(args, {
337
584
  string: allowOptions.filter((o) => o.type === "string").map((o) => o.name),
338
585
  boolean: allowOptions.filter((o) => o.type === "boolean").map((o) => o.name),
339
586
  alias,
340
- default: defaults,
341
587
  unknown: (t) => {
342
588
  if (t[0] !== "-")
343
589
  return true;
@@ -391,4 +637,4 @@ function breadc(name, option = {}) {
391
637
  return new Breadc(name, option);
392
638
  }
393
639
 
394
- export { breadc as default };
640
+ export { breadc as default, minimist };
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "breadc",
3
- "version": "0.2.0",
4
- "description": "Yet another Command Line Application Framework",
3
+ "version": "0.4.1",
4
+ "description": "Yet another Command Line Application Framework with fully strong TypeScript support",
5
5
  "keywords": [
6
6
  "cli",
7
7
  "framework",
8
8
  "command-line",
9
- "minimist"
9
+ "minimist",
10
+ "typescript"
10
11
  ],
11
12
  "homepage": "https://github.com/yjl9903/Breadc#readme",
12
13
  "bugs": {
@@ -33,15 +34,13 @@
33
34
  "dist"
34
35
  ],
35
36
  "dependencies": {
36
- "debug": "^4.3.4",
37
- "kolorist": "^1.5.1",
38
- "minimist": "^1.2.6"
37
+ "kolorist": "^1.5.1"
39
38
  },
40
39
  "devDependencies": {
41
- "@types/debug": "^4.1.7",
42
40
  "@types/minimist": "^1.2.2",
43
41
  "@types/node": "^17.0.43",
44
42
  "bumpp": "^8.2.1",
43
+ "minimist": "^1.2.6",
45
44
  "prettier": "^2.7.1",
46
45
  "typescript": "^4.7.4",
47
46
  "unbuild": "^0.7.4",