breadc 0.3.0 → 0.4.2

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
@@ -4,6 +4,12 @@
4
4
 
5
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
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.
12
+
7
13
  ## Installation
8
14
 
9
15
  ```bash
@@ -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;
@@ -34,7 +40,7 @@ cli.run(process.argv.slice(2))
34
40
  .catch(err => cli.logger.error(err.message))
35
41
  ```
36
42
 
37
- If you are using IDEs that support TypeScript (like [Visual Studio Code](https://code.visualstudio.com/)), move your cursor to the parameter `option` in the default command, and then you will find the `option` is automatically typed with `{ host: string | boolean, port: string | boolean }`.
43
+ If you are using IDEs that support TypeScript (like [Visual Studio Code](https://code.visualstudio.com/)), input something using `option`, and then you will find the `option` is automatically typed with `{ host: string, port: number }`. In the figure below, [Visual Studio Code](https://code.visualstudio.com/) will automatically infer that the type of `option.host` is `string` and the type of `option.port` is `number`.
38
44
 
39
45
  ![vscode](./images/vscode.png)
40
46
 
package/dist/index.cjs CHANGED
@@ -3,260 +3,12 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  const kolorist = require('kolorist');
6
+ const minimist = require('minimist');
6
7
 
7
8
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
8
9
 
9
10
  const kolorist__default = /*#__PURE__*/_interopDefaultLegacy(kolorist);
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
- }
11
+ const minimist__default = /*#__PURE__*/_interopDefaultLegacy(minimist);
260
12
 
261
13
  function createDefaultLogger(name, logger) {
262
14
  const println = !!logger && typeof logger === "function" ? logger : logger?.println ?? ((message, ...args) => {
@@ -303,11 +55,11 @@ const _Option = class {
303
55
  this.description = config.description ?? "";
304
56
  this.required = format.indexOf("<") !== -1;
305
57
  this.default = config.default;
306
- this.construct = config.construct ?? ((text) => text ?? config.default ?? void 0);
58
+ this.construct = config.construct;
307
59
  }
308
60
  };
309
61
  let Option = _Option;
310
- Option.OptionRE = /^(-[a-zA-Z], )?--([a-zA-Z.]+)( \[[a-zA-Z]+\]| <[a-zA-Z]+>)?$/;
62
+ Option.OptionRE = /^(-[a-zA-Z], )?--([a-zA-Z]+)( \[[a-zA-Z]+\]| <[a-zA-Z]+>)?$/;
311
63
 
312
64
  const _Command = class {
313
65
  constructor(format, config) {
@@ -407,6 +159,13 @@ const _Command = class {
407
159
  options[name] = void 0;
408
160
  }
409
161
  }
162
+ if (rawOption.construct) {
163
+ options[name] = rawOption.construct(options[name]);
164
+ } else if (rawOption.default) {
165
+ if (!options[name]) {
166
+ options[name] = rawOption.default;
167
+ }
168
+ }
410
169
  }
411
170
  return {
412
171
  command: this,
@@ -420,7 +179,7 @@ const _Command = class {
420
179
  }
421
180
  async run(...args) {
422
181
  if (this.actionFn) {
423
- this.actionFn(...args);
182
+ this.actionFn(...args, { logger: this.logger });
424
183
  } else {
425
184
  this.logger.warn(`You may miss action function in "${this.format}"`);
426
185
  }
@@ -580,17 +339,10 @@ class Breadc {
580
339
  }
581
340
  return map;
582
341
  }, {});
583
- const defaults = allowOptions.reduce((map, o) => {
584
- if (o.default) {
585
- map[o.name] = o.default;
586
- }
587
- return map;
588
- }, {});
589
- const argv = minimist(args, {
342
+ const argv = minimist__default(args, {
590
343
  string: allowOptions.filter((o) => o.type === "string").map((o) => o.name),
591
344
  boolean: allowOptions.filter((o) => o.type === "boolean").map((o) => o.name),
592
345
  alias,
593
- default: defaults,
594
346
  unknown: (t) => {
595
347
  if (t[0] !== "-")
596
348
  return true;
@@ -645,5 +397,5 @@ function breadc(name, option = {}) {
645
397
  }
646
398
 
647
399
  exports.kolorist = kolorist__default;
400
+ exports.minimist = minimist__default;
648
401
  exports["default"] = breadc;
649
- exports.minimist = minimist;
package/dist/index.d.ts CHANGED
@@ -1,259 +1,11 @@
1
+ import { ParsedArgs } from 'minimist';
2
+ export { default as minimist } from 'minimist';
1
3
  export { default as kolorist } from 'kolorist';
2
4
 
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<T = string> {
5
+ interface OptionConfig<F extends string, T = never> {
254
6
  description?: string;
255
7
  default?: T;
256
- construct?: (rawText?: string) => T;
8
+ construct?: (rawText: ExtractOptionType<F>) => T;
257
9
  }
258
10
  /**
259
11
  * Option
@@ -273,11 +25,11 @@ declare class Option<T extends string = string, F = string> {
273
25
  readonly description: string;
274
26
  readonly type: 'string' | 'boolean';
275
27
  readonly required: boolean;
276
- readonly construct: (rawText: string | undefined) => any;
277
- constructor(format: T, config?: OptionConfig<F>);
28
+ readonly construct?: (rawText: ExtractOptionType<T>) => F;
29
+ constructor(format: T, config?: OptionConfig<T, F>);
278
30
  }
279
31
 
280
- declare type ConditionFn = (args: minimist.ParsedArgs) => boolean;
32
+ declare type ConditionFn = (args: ParsedArgs) => boolean;
281
33
  interface CommandConfig {
282
34
  description?: string;
283
35
  }
@@ -294,11 +46,11 @@ declare class Command<F extends string = string, CommandOption extends object =
294
46
  condition?: ConditionFn;
295
47
  logger: Logger;
296
48
  });
297
- option<OF extends string, T = string>(format: OF, description: string, config?: Omit<OptionConfig<T>, 'description'>): Command<F, CommandOption & ExtractOption<OF>>;
298
- option<OF extends string, T = string>(format: OF, config?: OptionConfig<T>): Command<F, CommandOption & ExtractOption<OF>>;
49
+ option<OF extends string, T = undefined>(format: OF, description: string, config?: Omit<OptionConfig<OF, T>, 'description'>): Command<F, CommandOption & ExtractOption<OF, T>>;
50
+ option<OF extends string, T = undefined>(format: OF, config?: OptionConfig<OF, T>): Command<F, CommandOption & ExtractOption<OF, T>>;
299
51
  get hasConditionFn(): boolean;
300
- shouldRun(args: minimist.ParsedArgs): boolean;
301
- parseArgs(args: minimist.ParsedArgs, globalOptions: Option[]): ParseResult;
52
+ shouldRun(args: ParsedArgs): boolean;
53
+ parseArgs(args: ParsedArgs, globalOptions: Option[]): ParseResult;
302
54
  action(fn: ActionFn<ExtractCommand<F>, CommandOption>): this;
303
55
  run(...args: any[]): Promise<void>;
304
56
  }
@@ -322,8 +74,8 @@ interface ParseResult {
322
74
  arguments: any[];
323
75
  options: Record<string, string>;
324
76
  }
325
- declare type ExtractOption<T extends string> = {
326
- [k in ExtractOptionName<T>]: ExtractOptionType<T>;
77
+ declare type ExtractOption<T extends string, D = undefined> = {
78
+ [k in ExtractOptionName<T>]: D extends undefined ? ExtractOptionType<T> : D;
327
79
  };
328
80
  /**
329
81
  * Extract option name type
@@ -337,12 +89,15 @@ declare type ExtractOptionType<T extends string> = T extends `-${Letter}, --${in
337
89
  declare type Lowercase = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z';
338
90
  declare type Uppercase = 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z';
339
91
  declare type Letter = Lowercase | Uppercase;
340
- declare type Push<T extends any[], U> = [...T, U];
341
- declare type ActionFn<T extends any[], Option extends object = {}> = (...arg: Push<T, Option>) => void;
92
+ declare type Push<T extends any[], U, R> = [...T, U, R];
93
+ declare type Context = {
94
+ logger: Logger;
95
+ };
96
+ declare type ActionFn<T extends any[], Option extends object = {}> = (...arg: Push<T, Option, Context>) => void;
342
97
  /**
343
98
  * Max Dep: 5
344
99
  *
345
- * Generated by: npx tsx scripts/genType.ts 5
100
+ * Generated by: npx tsx examples/genType.ts 5
346
101
  */
347
102
  declare type ExtractCommand<T extends string> = T extends `<${infer P1}> <${infer P2}> <${infer P3}> <${infer P4}> [...${infer P5}]` ? [string, string, string, string, string[]] : T extends `<${infer P1}> <${infer P2}> <${infer P3}> <${infer P4}> [${infer P5}]` ? [string, string, string, string, string | undefined] : T extends `<${infer P1}> <${infer P2}> <${infer P3}> <${infer P4}> <${infer P5}>` ? [string, string, string, string, string] : T extends `${infer P1} <${infer P2}> <${infer P3}> <${infer P4}> [...${infer P5}]` ? [string, string, string, string[]] : T extends `${infer P1} <${infer P2}> <${infer P3}> <${infer P4}> [${infer P5}]` ? [string, string, string, string | undefined] : T extends `${infer P1} <${infer P2}> <${infer P3}> <${infer P4}> <${infer P5}>` ? [string, string, string, string] : T extends `${infer P1} ${infer P2} <${infer P3}> <${infer P4}> [...${infer P5}]` ? [string, string, string[]] : T extends `${infer P1} ${infer P2} <${infer P3}> <${infer P4}> [${infer P5}]` ? [string, string, string | undefined] : T extends `${infer P1} ${infer P2} <${infer P3}> <${infer P4}> <${infer P5}>` ? [string, string, string] : T extends `${infer P1} ${infer P2} ${infer P3} <${infer P4}> [...${infer P5}]` ? [string, string[]] : T extends `${infer P1} ${infer P2} ${infer P3} <${infer P4}> [${infer P5}]` ? [string, string | undefined] : T extends `${infer P1} ${infer P2} ${infer P3} <${infer P4}> <${infer P5}>` ? [string, string] : T extends `<${infer P1}> <${infer P2}> <${infer P3}> [...${infer P4}]` ? [string, string, string, string[]] : T extends `<${infer P1}> <${infer P2}> <${infer P3}> [${infer P4}]` ? [string, string, string, string | undefined] : T extends `<${infer P1}> <${infer P2}> <${infer P3}> <${infer P4}>` ? [string, string, string, string] : T extends `${infer P1} <${infer P2}> <${infer P3}> [...${infer P4}]` ? [string, string, string[]] : T extends `${infer P1} <${infer P2}> <${infer P3}> [${infer P4}]` ? [string, string, string | undefined] : T extends `${infer P1} <${infer P2}> <${infer P3}> <${infer P4}>` ? [string, string, string] : T extends `${infer P1} ${infer P2} <${infer P3}> [...${infer P4}]` ? [string, string[]] : T extends `${infer P1} ${infer P2} <${infer P3}> [${infer P4}]` ? [string, string | undefined] : T extends `${infer P1} ${infer P2} <${infer P3}> <${infer P4}>` ? [string, string] : T extends `${infer P1} ${infer P2} ${infer P3} [...${infer P4}]` ? [string[]] : T extends `${infer P1} ${infer P2} ${infer P3} [${infer P4}]` ? [string | undefined] : T extends `${infer P1} ${infer P2} ${infer P3} <${infer P4}>` ? [string] : T extends `<${infer P1}> <${infer P2}> [...${infer P3}]` ? [string, string, string[]] : T extends `<${infer P1}> <${infer P2}> [${infer P3}]` ? [string, string, string | undefined] : T extends `<${infer P1}> <${infer P2}> <${infer P3}>` ? [string, string, string] : T extends `${infer P1} <${infer P2}> [...${infer P3}]` ? [string, string[]] : T extends `${infer P1} <${infer P2}> [${infer P3}]` ? [string, string | undefined] : T extends `${infer P1} <${infer P2}> <${infer P3}>` ? [string, string] : T extends `${infer P1} ${infer P2} [...${infer P3}]` ? [string[]] : T extends `${infer P1} ${infer P2} [${infer P3}]` ? [string | undefined] : T extends `${infer P1} ${infer P2} <${infer P3}>` ? [string] : T extends `${infer P1} ${infer P2} ${infer P3}` ? [] : T extends `<${infer P1}> [...${infer P2}]` ? [string, string[]] : T extends `<${infer P1}> [${infer P2}]` ? [string, string | undefined] : T extends `<${infer P1}> <${infer P2}>` ? [string, string] : T extends `${infer P1} [...${infer P2}]` ? [string[]] : T extends `${infer P1} [${infer P2}]` ? [string | undefined] : T extends `${infer P1} <${infer P2}>` ? [string] : T extends `${infer P1} ${infer P2}` ? [] : T extends `[...${infer P1}]` ? [string[]] : T extends `[${infer P1}]` ? [string | undefined] : T extends `<${infer P1}>` ? [string] : T extends `${infer P1}` ? [] : T extends `` ? [] : never;
348
103
 
@@ -357,8 +112,8 @@ declare class Breadc<GlobalOption extends object = {}> {
357
112
  constructor(name: string, option: AppOption);
358
113
  version(): string;
359
114
  help(command?: Command): string[];
360
- option<F extends string, T = string>(format: F, description: string, config?: Omit<OptionConfig<T>, 'description'>): Breadc<GlobalOption & ExtractOption<F>>;
361
- option<F extends string, T = string>(format: F, config?: OptionConfig<T>): Breadc<GlobalOption & ExtractOption<F>>;
115
+ option<F extends string, T = undefined>(format: F, description: string, config?: Omit<OptionConfig<F, T>, 'description'>): Breadc<GlobalOption & ExtractOption<F, T>>;
116
+ option<F extends string, T = undefined>(format: F, config?: OptionConfig<F, T>): Breadc<GlobalOption & ExtractOption<F, T>>;
362
117
  command<F extends string>(format: F, description: string, config?: Omit<CommandConfig, 'description'>): Command<F, GlobalOption>;
363
118
  command<F extends string>(format: F, config?: CommandConfig): Command<F, GlobalOption>;
364
119
  parse(args: string[]): ParseResult;
@@ -367,4 +122,4 @@ declare class Breadc<GlobalOption extends object = {}> {
367
122
 
368
123
  declare function breadc(name: string, option?: AppOption): Breadc<{}>;
369
124
 
370
- export { breadc as default, minimist };
125
+ export { breadc as default };
package/dist/index.mjs CHANGED
@@ -1,255 +1,7 @@
1
1
  import { blue, yellow, red, gray } from 'kolorist';
2
2
  export { default as kolorist } from 'kolorist';
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
- }
3
+ import minimist from 'minimist';
4
+ export { default as minimist } from 'minimist';
253
5
 
254
6
  function createDefaultLogger(name, logger) {
255
7
  const println = !!logger && typeof logger === "function" ? logger : logger?.println ?? ((message, ...args) => {
@@ -296,11 +48,11 @@ const _Option = class {
296
48
  this.description = config.description ?? "";
297
49
  this.required = format.indexOf("<") !== -1;
298
50
  this.default = config.default;
299
- this.construct = config.construct ?? ((text) => text ?? config.default ?? void 0);
51
+ this.construct = config.construct;
300
52
  }
301
53
  };
302
54
  let Option = _Option;
303
- Option.OptionRE = /^(-[a-zA-Z], )?--([a-zA-Z.]+)( \[[a-zA-Z]+\]| <[a-zA-Z]+>)?$/;
55
+ Option.OptionRE = /^(-[a-zA-Z], )?--([a-zA-Z]+)( \[[a-zA-Z]+\]| <[a-zA-Z]+>)?$/;
304
56
 
305
57
  const _Command = class {
306
58
  constructor(format, config) {
@@ -400,6 +152,13 @@ const _Command = class {
400
152
  options[name] = void 0;
401
153
  }
402
154
  }
155
+ if (rawOption.construct) {
156
+ options[name] = rawOption.construct(options[name]);
157
+ } else if (rawOption.default) {
158
+ if (!options[name]) {
159
+ options[name] = rawOption.default;
160
+ }
161
+ }
403
162
  }
404
163
  return {
405
164
  command: this,
@@ -413,7 +172,7 @@ const _Command = class {
413
172
  }
414
173
  async run(...args) {
415
174
  if (this.actionFn) {
416
- this.actionFn(...args);
175
+ this.actionFn(...args, { logger: this.logger });
417
176
  } else {
418
177
  this.logger.warn(`You may miss action function in "${this.format}"`);
419
178
  }
@@ -573,17 +332,10 @@ class Breadc {
573
332
  }
574
333
  return map;
575
334
  }, {});
576
- const defaults = allowOptions.reduce((map, o) => {
577
- if (o.default) {
578
- map[o.name] = o.default;
579
- }
580
- return map;
581
- }, {});
582
335
  const argv = minimist(args, {
583
336
  string: allowOptions.filter((o) => o.type === "string").map((o) => o.name),
584
337
  boolean: allowOptions.filter((o) => o.type === "boolean").map((o) => o.name),
585
338
  alias,
586
- default: defaults,
587
339
  unknown: (t) => {
588
340
  if (t[0] !== "-")
589
341
  return true;
@@ -637,4 +389,4 @@ function breadc(name, option = {}) {
637
389
  return new Breadc(name, option);
638
390
  }
639
391
 
640
- export { breadc as default, minimist };
392
+ export { breadc as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "breadc",
3
- "version": "0.3.0",
3
+ "version": "0.4.2",
4
4
  "description": "Yet another Command Line Application Framework with fully strong TypeScript support",
5
5
  "keywords": [
6
6
  "cli",
@@ -34,23 +34,23 @@
34
34
  "dist"
35
35
  ],
36
36
  "dependencies": {
37
- "kolorist": "^1.5.1"
37
+ "kolorist": "^1.5.1",
38
+ "minimist": "^1.2.6"
38
39
  },
39
40
  "devDependencies": {
40
41
  "@types/minimist": "^1.2.2",
41
- "@types/node": "^17.0.43",
42
+ "@types/node": "^18.0.0",
42
43
  "bumpp": "^8.2.1",
43
- "minimist": "^1.2.6",
44
44
  "prettier": "^2.7.1",
45
45
  "typescript": "^4.7.4",
46
46
  "unbuild": "^0.7.4",
47
47
  "vite": "^2.9.12",
48
- "vitest": "^0.15.1"
48
+ "vitest": "^0.15.2"
49
49
  },
50
50
  "packageManager": "pnpm@7.3.0",
51
51
  "scripts": {
52
52
  "build": "unbuild",
53
- "format": "prettier --write src/**/*.ts test/*.ts examples/*.ts scripts/*.ts",
53
+ "format": "prettier --write src/**/*.ts test/*.ts examples/*.ts",
54
54
  "release": "bumpp --commit --push --tag && pnpm publish",
55
55
  "test": "vitest",
56
56
  "typecheck": "tsc --noEmit",