breadc 0.8.2 → 0.8.3

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
@@ -8,7 +8,7 @@ Yet another Command Line Application Framework with fully strong **[TypeScript](
8
8
 
9
9
  ## Features
10
10
 
11
- + ⚡️ **Light-weight**: Only 70 kB (Unpacked).
11
+ + ⚡️ **Light-weight**: Only 75 kB (Unpacked).
12
12
  + 📖 **East to Learn**: Breadc is basically compatible with [cac](https://github.com/cacjs/cac) and there are only 5 APIs for building a CLI application: `breadc`, `command`, `option`, `action`, `run`.
13
13
  + 💻 **TypeScript Infer**: IDE will automatically infer the type of your command action function.
14
14
 
package/dist/index.cjs CHANGED
@@ -128,6 +128,7 @@ class Token {
128
128
  return this._type = "string";
129
129
  }
130
130
  }
131
+ /* c8 ignore next 1 */
131
132
  }
132
133
  class Lexer {
133
134
  constructor(rawArgs) {
@@ -140,7 +141,7 @@ class Lexer {
140
141
  return value ? new Token(value) : void 0;
141
142
  }
142
143
  hasNext() {
143
- return this.cursor + 1 < this.rawArgs.length;
144
+ return this.cursor < this.rawArgs.length;
144
145
  }
145
146
  peek() {
146
147
  const value = this.rawArgs[this.cursor];
@@ -153,7 +154,7 @@ class Lexer {
153
154
  const value = that.rawArgs[that.cursor];
154
155
  that.cursor += 1;
155
156
  return {
156
- value: value ? new Token(value) : void 0,
157
+ value: value !== void 0 ? new Token(value) : void 0,
157
158
  done: that.cursor > that.rawArgs.length
158
159
  };
159
160
  }
@@ -340,13 +341,13 @@ const initContextOptions = (options, context) => {
340
341
  };
341
342
 
342
343
  function makeCommand(format, config, root, container) {
343
- let cursor = root;
344
344
  const args = [];
345
345
  const options = [];
346
346
  const command = {
347
347
  callback: void 0,
348
348
  format,
349
349
  description: config.description ?? "",
350
+ _default: false,
350
351
  _arguments: args,
351
352
  _options: options,
352
353
  option(format2, _config, _config2 = {}) {
@@ -355,6 +356,21 @@ function makeCommand(format, config, root, container) {
355
356
  options.push(option);
356
357
  return command;
357
358
  },
359
+ alias(format2) {
360
+ const aliasArgs = [];
361
+ const node2 = makeNode(aliasArgs);
362
+ function* g() {
363
+ for (const f of format2.split(" ")) {
364
+ yield { type: "const", name: f };
365
+ }
366
+ for (const a of args.filter((a2) => a2.type !== "const")) {
367
+ yield a;
368
+ }
369
+ return void 0;
370
+ }
371
+ insertTreeNode(aliasArgs, node2, g());
372
+ return command;
373
+ },
358
374
  action(fn) {
359
375
  command.callback = async (parsed) => {
360
376
  await container.preCommand(command, parsed);
@@ -367,78 +383,45 @@ function makeCommand(format, config, root, container) {
367
383
  };
368
384
  }
369
385
  };
370
- const node = makeTreeNode({
371
- command,
372
- init(context) {
373
- initContextOptions(options, context);
374
- },
375
- finish(context) {
376
- const rest = context.result["--"];
377
- for (let i = 0; i < args.length; i++) {
378
- if (args[i].type === "const") {
379
- if (rest[i] !== args[i].name) {
380
- throw new ParseError(`Sub-command ${args[i].name} mismatch`);
381
- }
382
- } else if (args[i].type === "require") {
383
- if (i >= rest.length) {
384
- throw new ParseError(
385
- `You must provide require argument ${args[i].name}`
386
- );
386
+ const node = makeNode(args);
387
+ insertTreeNode(args, node, parseCommandFormat(format));
388
+ return command;
389
+ function makeNode(args2) {
390
+ return makeTreeNode({
391
+ command,
392
+ init(context) {
393
+ initContextOptions(options, context);
394
+ },
395
+ finish(context) {
396
+ const rest = context.result["--"];
397
+ for (let i = 0; i < args2.length; i++) {
398
+ if (args2[i].type === "const") {
399
+ if (rest[i] !== args2[i].name) {
400
+ throw new ParseError(`Sub-command ${args2[i].name} mismatch`);
401
+ }
402
+ } else if (args2[i].type === "require") {
403
+ if (i >= rest.length) {
404
+ throw new ParseError(
405
+ `You must provide require argument ${args2[i].name}`
406
+ );
407
+ }
408
+ context.result.arguments.push(rest[i]);
409
+ } else if (args2[i].type === "optional") {
410
+ context.result.arguments.push(rest[i]);
411
+ } else if (args2[i].type === "rest") {
412
+ context.result.arguments.push(rest.splice(i));
387
413
  }
388
- context.result.arguments.push(rest[i]);
389
- } else if (args[i].type === "optional") {
390
- context.result.arguments.push(rest[i]);
391
- } else if (args[i].type === "rest") {
392
- context.result.arguments.push(rest.splice(i));
393
414
  }
415
+ context.result["--"] = rest.splice(args2.length);
394
416
  }
395
- context.result["--"] = rest.splice(args.length);
396
- }
397
- });
398
- {
399
- let state = 0;
400
- for (let i = 0; i < format.length; i++) {
401
- if (format[i] === "<") {
402
- if (state !== 0 && state !== 1) {
403
- throw new BreadcError(
404
- `Required arguments should be placed before optional or rest arguments`
405
- );
406
- }
407
- const start = i;
408
- while (i < format.length && format[i] !== ">") {
409
- i++;
410
- }
411
- const name = format.slice(start + 1, i);
412
- state = 1;
413
- args.push({ type: "require", name });
414
- } else if (format[i] === "[") {
415
- if (state !== 0 && state !== 1) {
416
- throw new BreadcError(
417
- `There is at most one optional or rest arguments`
418
- );
419
- }
420
- const start = i;
421
- while (i < format.length && format[i] !== "]") {
422
- i++;
423
- }
424
- const name = format.slice(start + 1, i);
425
- state = 2;
426
- if (name.startsWith("...")) {
427
- args.push({ type: "rest", name });
428
- } else {
429
- args.push({ type: "optional", name });
430
- }
431
- } else if (format[i] !== " ") {
432
- if (state !== 0) {
433
- throw new BreadcError(
434
- `Sub-command should be placed at the beginning`
435
- );
436
- }
437
- const start = i;
438
- while (i < format.length && format[i] !== " ") {
439
- i++;
440
- }
441
- const name = format.slice(start, i);
417
+ });
418
+ }
419
+ function insertTreeNode(args2, node2, parsed) {
420
+ let cursor = root;
421
+ for (const arg of parsed) {
422
+ args2.push(arg);
423
+ if (arg.type === "const") {
424
+ const name = arg.name;
442
425
  if (cursor.children.has(name)) {
443
426
  cursor = cursor.children.get(name);
444
427
  } else {
@@ -461,24 +444,70 @@ function makeCommand(format, config, root, container) {
461
444
  cursor.children.set(name, internalNode);
462
445
  cursor = internalNode;
463
446
  }
464
- state = 0;
465
- args.push({ type: "const", name });
466
447
  }
467
448
  }
468
449
  cursor.command = command;
469
450
  if (cursor !== root) {
470
451
  for (const [key, value] of cursor.children) {
471
- node.children.set(key, value);
452
+ node2.children.set(key, value);
472
453
  }
473
- cursor.children = node.children;
474
- cursor.next = node.next;
475
- cursor.init = node.init;
476
- cursor.finish = node.finish;
454
+ cursor.children = node2.children;
455
+ cursor.next = node2.next;
456
+ cursor.init = node2.init;
457
+ cursor.finish = node2.finish;
477
458
  } else {
478
- cursor.finish = node.finish;
459
+ command._default = true;
460
+ cursor.finish = node2.finish;
479
461
  }
480
462
  }
481
- return command;
463
+ }
464
+ function* parseCommandFormat(format) {
465
+ let state = 0;
466
+ for (let i = 0; i < format.length; i++) {
467
+ if (format[i] === "<") {
468
+ if (state !== 0 && state !== 1) {
469
+ throw new BreadcError(
470
+ `Required arguments should be placed before optional or rest arguments`
471
+ );
472
+ }
473
+ const start = i;
474
+ while (i < format.length && format[i] !== ">") {
475
+ i++;
476
+ }
477
+ const name = format.slice(start + 1, i);
478
+ state = 1;
479
+ yield { type: "require", name };
480
+ } else if (format[i] === "[") {
481
+ if (state !== 0 && state !== 1) {
482
+ throw new BreadcError(
483
+ `There is at most one optional or rest arguments`
484
+ );
485
+ }
486
+ const start = i;
487
+ while (i < format.length && format[i] !== "]") {
488
+ i++;
489
+ }
490
+ const name = format.slice(start + 1, i);
491
+ state = 2;
492
+ if (name.startsWith("...")) {
493
+ yield { type: "rest", name };
494
+ } else {
495
+ yield { type: "optional", name };
496
+ }
497
+ } else if (format[i] !== " ") {
498
+ if (state !== 0) {
499
+ throw new BreadcError(`Sub-command should be placed at the beginning`);
500
+ }
501
+ const start = i;
502
+ while (i < format.length && format[i] !== " ") {
503
+ i++;
504
+ }
505
+ const name = format.slice(start, i);
506
+ state = 0;
507
+ yield { type: "const", name };
508
+ }
509
+ }
510
+ return void 0;
482
511
  }
483
512
  function makeVersionCommand(name, config) {
484
513
  const command = {
@@ -491,11 +520,12 @@ function makeVersionCommand(name, config) {
491
520
  description: "Print version",
492
521
  _arguments: [],
493
522
  _options: [],
494
- option() {
495
- return command;
496
- },
497
- action() {
498
- }
523
+ // @ts-ignore
524
+ option: void 0,
525
+ // @ts-ignore
526
+ alias: void 0,
527
+ // @ts-ignore
528
+ action: void 0
499
529
  };
500
530
  const node = makeTreeNode({
501
531
  command,
@@ -600,11 +630,12 @@ function makeHelpCommand(name, config) {
600
630
  description: "Print help",
601
631
  _arguments: [],
602
632
  _options: [],
603
- option() {
604
- return command;
605
- },
606
- action() {
607
- }
633
+ // @ts-ignore
634
+ option: void 0,
635
+ // @ts-ignore
636
+ alias: void 0,
637
+ // @ts-ignore
638
+ action: void 0
608
639
  };
609
640
  const node = makeTreeNode({
610
641
  command,
@@ -657,7 +688,7 @@ function breadc(name, config = {}) {
657
688
  command(text, _config = {}) {
658
689
  const config2 = typeof _config === "string" ? { description: _config } : _config;
659
690
  const command = makeCommand(text, config2, root, container);
660
- if (command._arguments.length === 0 || command._arguments[0].type !== "const") {
691
+ if (command._default) {
661
692
  defaultCommand = command;
662
693
  }
663
694
  return command;
package/dist/index.d.ts CHANGED
@@ -104,10 +104,12 @@ interface Command<F extends string = string, AT extends any[] = ExtractCommand<F
104
104
  callback?: (result: ParseResult) => Promise<any>;
105
105
  format: F;
106
106
  description: string;
107
+ _default: boolean;
107
108
  _arguments: Argument[];
108
109
  _options: Option[];
109
110
  option<OF extends string = string, OT extends string | boolean = ExtractOptionType<OF>, OR extends any = ExtractOptionType<OF>>(format: OF, description?: string, option?: OptionOption<OT, OR>): Command<F, AT, CommandOption & ExtractOption<OF, OR>, GlobalOption>;
110
111
  option<OF extends string = string, OT extends string | boolean = ExtractOptionType<OF>, OR extends any = ExtractOptionType<OF>>(format: OF, option?: OptionOption<OT, OR>): Command<F, AT, CommandOption & ExtractOption<OF, OR>, GlobalOption>;
112
+ alias(format: string): Command<F, AT, CommandOption, GlobalOption>;
111
113
  action(fn: ActionFn<AT, CommandOption & GlobalOption>): void;
112
114
  }
113
115
  interface CommandOption {
package/dist/index.mjs CHANGED
@@ -124,6 +124,7 @@ class Token {
124
124
  return this._type = "string";
125
125
  }
126
126
  }
127
+ /* c8 ignore next 1 */
127
128
  }
128
129
  class Lexer {
129
130
  constructor(rawArgs) {
@@ -136,7 +137,7 @@ class Lexer {
136
137
  return value ? new Token(value) : void 0;
137
138
  }
138
139
  hasNext() {
139
- return this.cursor + 1 < this.rawArgs.length;
140
+ return this.cursor < this.rawArgs.length;
140
141
  }
141
142
  peek() {
142
143
  const value = this.rawArgs[this.cursor];
@@ -149,7 +150,7 @@ class Lexer {
149
150
  const value = that.rawArgs[that.cursor];
150
151
  that.cursor += 1;
151
152
  return {
152
- value: value ? new Token(value) : void 0,
153
+ value: value !== void 0 ? new Token(value) : void 0,
153
154
  done: that.cursor > that.rawArgs.length
154
155
  };
155
156
  }
@@ -336,13 +337,13 @@ const initContextOptions = (options, context) => {
336
337
  };
337
338
 
338
339
  function makeCommand(format, config, root, container) {
339
- let cursor = root;
340
340
  const args = [];
341
341
  const options = [];
342
342
  const command = {
343
343
  callback: void 0,
344
344
  format,
345
345
  description: config.description ?? "",
346
+ _default: false,
346
347
  _arguments: args,
347
348
  _options: options,
348
349
  option(format2, _config, _config2 = {}) {
@@ -351,6 +352,21 @@ function makeCommand(format, config, root, container) {
351
352
  options.push(option);
352
353
  return command;
353
354
  },
355
+ alias(format2) {
356
+ const aliasArgs = [];
357
+ const node2 = makeNode(aliasArgs);
358
+ function* g() {
359
+ for (const f of format2.split(" ")) {
360
+ yield { type: "const", name: f };
361
+ }
362
+ for (const a of args.filter((a2) => a2.type !== "const")) {
363
+ yield a;
364
+ }
365
+ return void 0;
366
+ }
367
+ insertTreeNode(aliasArgs, node2, g());
368
+ return command;
369
+ },
354
370
  action(fn) {
355
371
  command.callback = async (parsed) => {
356
372
  await container.preCommand(command, parsed);
@@ -363,78 +379,45 @@ function makeCommand(format, config, root, container) {
363
379
  };
364
380
  }
365
381
  };
366
- const node = makeTreeNode({
367
- command,
368
- init(context) {
369
- initContextOptions(options, context);
370
- },
371
- finish(context) {
372
- const rest = context.result["--"];
373
- for (let i = 0; i < args.length; i++) {
374
- if (args[i].type === "const") {
375
- if (rest[i] !== args[i].name) {
376
- throw new ParseError(`Sub-command ${args[i].name} mismatch`);
377
- }
378
- } else if (args[i].type === "require") {
379
- if (i >= rest.length) {
380
- throw new ParseError(
381
- `You must provide require argument ${args[i].name}`
382
- );
382
+ const node = makeNode(args);
383
+ insertTreeNode(args, node, parseCommandFormat(format));
384
+ return command;
385
+ function makeNode(args2) {
386
+ return makeTreeNode({
387
+ command,
388
+ init(context) {
389
+ initContextOptions(options, context);
390
+ },
391
+ finish(context) {
392
+ const rest = context.result["--"];
393
+ for (let i = 0; i < args2.length; i++) {
394
+ if (args2[i].type === "const") {
395
+ if (rest[i] !== args2[i].name) {
396
+ throw new ParseError(`Sub-command ${args2[i].name} mismatch`);
397
+ }
398
+ } else if (args2[i].type === "require") {
399
+ if (i >= rest.length) {
400
+ throw new ParseError(
401
+ `You must provide require argument ${args2[i].name}`
402
+ );
403
+ }
404
+ context.result.arguments.push(rest[i]);
405
+ } else if (args2[i].type === "optional") {
406
+ context.result.arguments.push(rest[i]);
407
+ } else if (args2[i].type === "rest") {
408
+ context.result.arguments.push(rest.splice(i));
383
409
  }
384
- context.result.arguments.push(rest[i]);
385
- } else if (args[i].type === "optional") {
386
- context.result.arguments.push(rest[i]);
387
- } else if (args[i].type === "rest") {
388
- context.result.arguments.push(rest.splice(i));
389
410
  }
411
+ context.result["--"] = rest.splice(args2.length);
390
412
  }
391
- context.result["--"] = rest.splice(args.length);
392
- }
393
- });
394
- {
395
- let state = 0;
396
- for (let i = 0; i < format.length; i++) {
397
- if (format[i] === "<") {
398
- if (state !== 0 && state !== 1) {
399
- throw new BreadcError(
400
- `Required arguments should be placed before optional or rest arguments`
401
- );
402
- }
403
- const start = i;
404
- while (i < format.length && format[i] !== ">") {
405
- i++;
406
- }
407
- const name = format.slice(start + 1, i);
408
- state = 1;
409
- args.push({ type: "require", name });
410
- } else if (format[i] === "[") {
411
- if (state !== 0 && state !== 1) {
412
- throw new BreadcError(
413
- `There is at most one optional or rest arguments`
414
- );
415
- }
416
- const start = i;
417
- while (i < format.length && format[i] !== "]") {
418
- i++;
419
- }
420
- const name = format.slice(start + 1, i);
421
- state = 2;
422
- if (name.startsWith("...")) {
423
- args.push({ type: "rest", name });
424
- } else {
425
- args.push({ type: "optional", name });
426
- }
427
- } else if (format[i] !== " ") {
428
- if (state !== 0) {
429
- throw new BreadcError(
430
- `Sub-command should be placed at the beginning`
431
- );
432
- }
433
- const start = i;
434
- while (i < format.length && format[i] !== " ") {
435
- i++;
436
- }
437
- const name = format.slice(start, i);
413
+ });
414
+ }
415
+ function insertTreeNode(args2, node2, parsed) {
416
+ let cursor = root;
417
+ for (const arg of parsed) {
418
+ args2.push(arg);
419
+ if (arg.type === "const") {
420
+ const name = arg.name;
438
421
  if (cursor.children.has(name)) {
439
422
  cursor = cursor.children.get(name);
440
423
  } else {
@@ -457,24 +440,70 @@ function makeCommand(format, config, root, container) {
457
440
  cursor.children.set(name, internalNode);
458
441
  cursor = internalNode;
459
442
  }
460
- state = 0;
461
- args.push({ type: "const", name });
462
443
  }
463
444
  }
464
445
  cursor.command = command;
465
446
  if (cursor !== root) {
466
447
  for (const [key, value] of cursor.children) {
467
- node.children.set(key, value);
448
+ node2.children.set(key, value);
468
449
  }
469
- cursor.children = node.children;
470
- cursor.next = node.next;
471
- cursor.init = node.init;
472
- cursor.finish = node.finish;
450
+ cursor.children = node2.children;
451
+ cursor.next = node2.next;
452
+ cursor.init = node2.init;
453
+ cursor.finish = node2.finish;
473
454
  } else {
474
- cursor.finish = node.finish;
455
+ command._default = true;
456
+ cursor.finish = node2.finish;
475
457
  }
476
458
  }
477
- return command;
459
+ }
460
+ function* parseCommandFormat(format) {
461
+ let state = 0;
462
+ for (let i = 0; i < format.length; i++) {
463
+ if (format[i] === "<") {
464
+ if (state !== 0 && state !== 1) {
465
+ throw new BreadcError(
466
+ `Required arguments should be placed before optional or rest arguments`
467
+ );
468
+ }
469
+ const start = i;
470
+ while (i < format.length && format[i] !== ">") {
471
+ i++;
472
+ }
473
+ const name = format.slice(start + 1, i);
474
+ state = 1;
475
+ yield { type: "require", name };
476
+ } else if (format[i] === "[") {
477
+ if (state !== 0 && state !== 1) {
478
+ throw new BreadcError(
479
+ `There is at most one optional or rest arguments`
480
+ );
481
+ }
482
+ const start = i;
483
+ while (i < format.length && format[i] !== "]") {
484
+ i++;
485
+ }
486
+ const name = format.slice(start + 1, i);
487
+ state = 2;
488
+ if (name.startsWith("...")) {
489
+ yield { type: "rest", name };
490
+ } else {
491
+ yield { type: "optional", name };
492
+ }
493
+ } else if (format[i] !== " ") {
494
+ if (state !== 0) {
495
+ throw new BreadcError(`Sub-command should be placed at the beginning`);
496
+ }
497
+ const start = i;
498
+ while (i < format.length && format[i] !== " ") {
499
+ i++;
500
+ }
501
+ const name = format.slice(start, i);
502
+ state = 0;
503
+ yield { type: "const", name };
504
+ }
505
+ }
506
+ return void 0;
478
507
  }
479
508
  function makeVersionCommand(name, config) {
480
509
  const command = {
@@ -487,11 +516,12 @@ function makeVersionCommand(name, config) {
487
516
  description: "Print version",
488
517
  _arguments: [],
489
518
  _options: [],
490
- option() {
491
- return command;
492
- },
493
- action() {
494
- }
519
+ // @ts-ignore
520
+ option: void 0,
521
+ // @ts-ignore
522
+ alias: void 0,
523
+ // @ts-ignore
524
+ action: void 0
495
525
  };
496
526
  const node = makeTreeNode({
497
527
  command,
@@ -596,11 +626,12 @@ function makeHelpCommand(name, config) {
596
626
  description: "Print help",
597
627
  _arguments: [],
598
628
  _options: [],
599
- option() {
600
- return command;
601
- },
602
- action() {
603
- }
629
+ // @ts-ignore
630
+ option: void 0,
631
+ // @ts-ignore
632
+ alias: void 0,
633
+ // @ts-ignore
634
+ action: void 0
604
635
  };
605
636
  const node = makeTreeNode({
606
637
  command,
@@ -653,7 +684,7 @@ function breadc(name, config = {}) {
653
684
  command(text, _config = {}) {
654
685
  const config2 = typeof _config === "string" ? { description: _config } : _config;
655
686
  const command = makeCommand(text, config2, root, container);
656
- if (command._arguments.length === 0 || command._arguments[0].type !== "const") {
687
+ if (command._default) {
657
688
  defaultCommand = command;
658
689
  }
659
690
  return command;
package/package.json CHANGED
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "name": "breadc",
3
- "version": "0.8.2",
3
+ "version": "0.8.3",
4
4
  "description": "Yet another Command Line Application Framework with fully strong TypeScript support",
5
5
  "keywords": [
6
6
  "breadc",
7
7
  "cli",
8
8
  "framework",
9
9
  "command-line",
10
- "minimist",
11
10
  "typescript"
12
11
  ],
13
12
  "homepage": "https://github.com/yjl9903/Breadc#readme",
@@ -35,7 +34,7 @@
35
34
  "dist"
36
35
  ],
37
36
  "dependencies": {
38
- "@breadc/color": "0.8.2"
37
+ "@breadc/color": "0.8.3"
39
38
  },
40
39
  "devDependencies": {
41
40
  "@types/node": "^18.11.18",