breadc 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,7 +7,7 @@ Yet another Command Line Application Framework powered by [minimist](https://www
7
7
  ## Features
8
8
 
9
9
  + ⚡️ **Light-weight**: Only 40 kB (Unpacked).
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`.
10
+ + 📖 **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`.
11
11
  + 💻 **TypeScript Infer**: IDE will automatically infer the type of your command action function.
12
12
 
13
13
  ## Installation
package/dist/index.cjs CHANGED
@@ -79,8 +79,14 @@ const _Command = class {
79
79
  this.arguments = pieces.filter(isArg);
80
80
  this.description = config.description ?? "";
81
81
  this.logger = config.logger;
82
- if (pieces.length > _Command.MaxDep) {
83
- this.logger.warn(`Command format string "${format}" is too long`);
82
+ {
83
+ const restArgs = this.arguments.findIndex((a) => a.startsWith("[..."));
84
+ if (restArgs !== -1 && restArgs !== this.arguments.length - 1) {
85
+ this.logger.warn(`Expand arguments ${this.arguments[restArgs]} should be placed at the last position`);
86
+ }
87
+ if (pieces.length > _Command.MaxDep) {
88
+ this.logger.warn(`Command format string "${format}" is too long`);
89
+ }
84
90
  }
85
91
  }
86
92
  get isInternal() {
@@ -132,23 +138,30 @@ const _Command = class {
132
138
  return true;
133
139
  return false;
134
140
  }
135
- parseArgs(args, globalOptions) {
136
- const argumentss = [];
137
- for (let i = 0; i < this.arguments.length; i++) {
138
- if (i < args["_"].length) {
141
+ parseArgs(argv, globalOptions) {
142
+ const pieces = argv["_"];
143
+ const args = [];
144
+ const restArgs = [];
145
+ for (let i = 0, used = 0; i <= this.arguments.length; i++) {
146
+ if (i === this.arguments.length) {
147
+ restArgs.push(...pieces.slice(used).map(String));
148
+ restArgs.push(...(argv["--"] ?? []).map(String));
149
+ } else if (i < pieces.length) {
139
150
  if (this.arguments[i].startsWith("[...")) {
140
- argumentss.push(args["_"].slice(i).map(String));
151
+ args.push(pieces.slice(i).map(String));
152
+ used = pieces.length;
141
153
  } else {
142
- argumentss.push(String(args["_"][i]));
154
+ args.push(String(pieces[i]));
155
+ used++;
143
156
  }
144
157
  } else {
145
158
  if (this.arguments[i].startsWith("<")) {
146
159
  this.logger.warn(`You should provide the argument "${this.arguments[i]}"`);
147
- argumentss.push("");
160
+ args.push("");
148
161
  } else if (this.arguments[i].startsWith("[...")) {
149
- argumentss.push([]);
162
+ args.push([]);
150
163
  } else if (this.arguments[i].startsWith("[")) {
151
- argumentss.push(void 0);
164
+ args.push(void 0);
152
165
  } else {
153
166
  this.logger.warn(`unknown format string ("${this.arguments[i]}")`);
154
167
  }
@@ -158,7 +171,7 @@ const _Command = class {
158
171
  map.set(o.name, o);
159
172
  return map;
160
173
  }, /* @__PURE__ */ new Map());
161
- const options = args;
174
+ const options = argv;
162
175
  delete options["_"];
163
176
  for (const [name, rawOption] of fullOptions) {
164
177
  if (rawOption.required) {
@@ -190,8 +203,9 @@ const _Command = class {
190
203
  }
191
204
  return {
192
205
  command: this,
193
- arguments: argumentss,
194
- options
206
+ arguments: args,
207
+ options,
208
+ "--": restArgs
195
209
  };
196
210
  }
197
211
  action(fn) {
@@ -199,9 +213,13 @@ const _Command = class {
199
213
  }
200
214
  async run(...args) {
201
215
  if (this.actionFn) {
202
- return await this.actionFn(...args, { logger: this.logger, color: kolorist__default });
216
+ return await this.actionFn(...args, {
217
+ logger: this.logger,
218
+ color: kolorist__default
219
+ });
203
220
  } else {
204
221
  this.logger.warn(`You may miss action function in ${this.format ? `"${this.format}"` : "<default command>"}`);
222
+ return void 0;
205
223
  }
206
224
  }
207
225
  };
@@ -220,7 +238,8 @@ class InternalCommand extends Command {
220
238
  return {
221
239
  command: this,
222
240
  arguments: argumentss,
223
- options: args
241
+ options: args,
242
+ "--": []
224
243
  };
225
244
  }
226
245
  }
@@ -403,6 +422,7 @@ class Breadc {
403
422
  string: allowOptions.filter((o) => o.type === "string").map((o) => o.name),
404
423
  boolean: allowOptions.filter((o) => o.type === "boolean").map((o) => o.name).concat(["help", "version"]),
405
424
  alias,
425
+ "--": true,
406
426
  unknown: (t) => {
407
427
  if (t[0] !== "-")
408
428
  return true;
@@ -431,12 +451,14 @@ class Breadc {
431
451
  const argumentss = argv["_"];
432
452
  const options = argv;
433
453
  delete options["_"];
454
+ delete options["--"];
434
455
  delete options["help"];
435
456
  delete options["version"];
436
457
  return {
437
458
  command: void 0,
438
459
  arguments: argumentss,
439
- options
460
+ options,
461
+ "--": []
440
462
  };
441
463
  }
442
464
  on(event, fn) {
@@ -446,9 +468,14 @@ class Breadc {
446
468
  const parsed = this.parse(args);
447
469
  if (parsed.command) {
448
470
  await Promise.all(this.callbacks.pre.map((fn) => fn(parsed.options)));
449
- const returnValue = await parsed.command.run(...parsed.arguments, parsed.options);
471
+ const returnValue = await parsed.command.run(...parsed.arguments, {
472
+ "--": parsed["--"],
473
+ ...parsed.options
474
+ });
450
475
  await Promise.all(this.callbacks.post.map((fn) => fn(parsed.options)));
451
476
  return returnValue;
477
+ } else {
478
+ return void 0;
452
479
  }
453
480
  }
454
481
  }
package/dist/index.d.ts CHANGED
@@ -59,7 +59,7 @@ declare class Command<F extends string = string, CommandOption extends object =
59
59
  option<OF extends string, T = undefined>(format: OF, config?: OptionConfig<OF, T>): Command<F, CommandOption & ExtractOption<OF, T>>;
60
60
  hasPrefix(parsedArgs: ParsedArgs): boolean;
61
61
  shouldRun(parsedArgs: ParsedArgs): boolean;
62
- parseArgs(args: ParsedArgs, globalOptions: Option[]): ParseResult;
62
+ parseArgs(argv: ParsedArgs, globalOptions: Option[]): ParseResult;
63
63
  action(fn: ActionFn<ExtractCommand<F>, CommandOption>): void;
64
64
  run(...args: any[]): Promise<any>;
65
65
  }
@@ -82,6 +82,7 @@ interface ParseResult {
82
82
  command: Command | undefined;
83
83
  arguments: any[];
84
84
  options: Record<string, string>;
85
+ '--': string[];
85
86
  }
86
87
  declare type ExtractOption<T extends string, D = undefined> = {
87
88
  [k in ExtractOptionName<T>]: D extends undefined ? ExtractOptionType<T> : D;
@@ -103,7 +104,9 @@ declare type Context = {
103
104
  logger: Logger;
104
105
  color: typeof kolorist;
105
106
  };
106
- declare type ActionFn<T extends any[], Option extends object = {}, R = any> = (...arg: Push<T, Option, Context>) => R | Promise<R>;
107
+ declare type ActionFn<T extends any[], Option extends object = {}, R = any> = (...arg: Push<T, Option & {
108
+ '--': string[];
109
+ }, Context>) => R | Promise<R>;
107
110
  /**
108
111
  * Max Dep: 5
109
112
  *
@@ -129,7 +132,7 @@ declare class Breadc<GlobalOption extends object = {}> {
129
132
  parse(args: string[]): ParseResult;
130
133
  private readonly callbacks;
131
134
  on(event: 'pre' | 'post', fn: (option: GlobalOption) => void | Promise<void>): void;
132
- run(args: string[]): Promise<any>;
135
+ run<T>(args: string[]): Promise<T | undefined>;
133
136
  }
134
137
 
135
138
  declare function breadc(name: string, option?: AppOption): Breadc<{}>;
package/dist/index.mjs CHANGED
@@ -72,8 +72,14 @@ const _Command = class {
72
72
  this.arguments = pieces.filter(isArg);
73
73
  this.description = config.description ?? "";
74
74
  this.logger = config.logger;
75
- if (pieces.length > _Command.MaxDep) {
76
- this.logger.warn(`Command format string "${format}" is too long`);
75
+ {
76
+ const restArgs = this.arguments.findIndex((a) => a.startsWith("[..."));
77
+ if (restArgs !== -1 && restArgs !== this.arguments.length - 1) {
78
+ this.logger.warn(`Expand arguments ${this.arguments[restArgs]} should be placed at the last position`);
79
+ }
80
+ if (pieces.length > _Command.MaxDep) {
81
+ this.logger.warn(`Command format string "${format}" is too long`);
82
+ }
77
83
  }
78
84
  }
79
85
  get isInternal() {
@@ -125,23 +131,30 @@ const _Command = class {
125
131
  return true;
126
132
  return false;
127
133
  }
128
- parseArgs(args, globalOptions) {
129
- const argumentss = [];
130
- for (let i = 0; i < this.arguments.length; i++) {
131
- if (i < args["_"].length) {
134
+ parseArgs(argv, globalOptions) {
135
+ const pieces = argv["_"];
136
+ const args = [];
137
+ const restArgs = [];
138
+ for (let i = 0, used = 0; i <= this.arguments.length; i++) {
139
+ if (i === this.arguments.length) {
140
+ restArgs.push(...pieces.slice(used).map(String));
141
+ restArgs.push(...(argv["--"] ?? []).map(String));
142
+ } else if (i < pieces.length) {
132
143
  if (this.arguments[i].startsWith("[...")) {
133
- argumentss.push(args["_"].slice(i).map(String));
144
+ args.push(pieces.slice(i).map(String));
145
+ used = pieces.length;
134
146
  } else {
135
- argumentss.push(String(args["_"][i]));
147
+ args.push(String(pieces[i]));
148
+ used++;
136
149
  }
137
150
  } else {
138
151
  if (this.arguments[i].startsWith("<")) {
139
152
  this.logger.warn(`You should provide the argument "${this.arguments[i]}"`);
140
- argumentss.push("");
153
+ args.push("");
141
154
  } else if (this.arguments[i].startsWith("[...")) {
142
- argumentss.push([]);
155
+ args.push([]);
143
156
  } else if (this.arguments[i].startsWith("[")) {
144
- argumentss.push(void 0);
157
+ args.push(void 0);
145
158
  } else {
146
159
  this.logger.warn(`unknown format string ("${this.arguments[i]}")`);
147
160
  }
@@ -151,7 +164,7 @@ const _Command = class {
151
164
  map.set(o.name, o);
152
165
  return map;
153
166
  }, /* @__PURE__ */ new Map());
154
- const options = args;
167
+ const options = argv;
155
168
  delete options["_"];
156
169
  for (const [name, rawOption] of fullOptions) {
157
170
  if (rawOption.required) {
@@ -183,8 +196,9 @@ const _Command = class {
183
196
  }
184
197
  return {
185
198
  command: this,
186
- arguments: argumentss,
187
- options
199
+ arguments: args,
200
+ options,
201
+ "--": restArgs
188
202
  };
189
203
  }
190
204
  action(fn) {
@@ -192,9 +206,13 @@ const _Command = class {
192
206
  }
193
207
  async run(...args) {
194
208
  if (this.actionFn) {
195
- return await this.actionFn(...args, { logger: this.logger, color: kolorist });
209
+ return await this.actionFn(...args, {
210
+ logger: this.logger,
211
+ color: kolorist
212
+ });
196
213
  } else {
197
214
  this.logger.warn(`You may miss action function in ${this.format ? `"${this.format}"` : "<default command>"}`);
215
+ return void 0;
198
216
  }
199
217
  }
200
218
  };
@@ -213,7 +231,8 @@ class InternalCommand extends Command {
213
231
  return {
214
232
  command: this,
215
233
  arguments: argumentss,
216
- options: args
234
+ options: args,
235
+ "--": []
217
236
  };
218
237
  }
219
238
  }
@@ -396,6 +415,7 @@ class Breadc {
396
415
  string: allowOptions.filter((o) => o.type === "string").map((o) => o.name),
397
416
  boolean: allowOptions.filter((o) => o.type === "boolean").map((o) => o.name).concat(["help", "version"]),
398
417
  alias,
418
+ "--": true,
399
419
  unknown: (t) => {
400
420
  if (t[0] !== "-")
401
421
  return true;
@@ -424,12 +444,14 @@ class Breadc {
424
444
  const argumentss = argv["_"];
425
445
  const options = argv;
426
446
  delete options["_"];
447
+ delete options["--"];
427
448
  delete options["help"];
428
449
  delete options["version"];
429
450
  return {
430
451
  command: void 0,
431
452
  arguments: argumentss,
432
- options
453
+ options,
454
+ "--": []
433
455
  };
434
456
  }
435
457
  on(event, fn) {
@@ -439,9 +461,14 @@ class Breadc {
439
461
  const parsed = this.parse(args);
440
462
  if (parsed.command) {
441
463
  await Promise.all(this.callbacks.pre.map((fn) => fn(parsed.options)));
442
- const returnValue = await parsed.command.run(...parsed.arguments, parsed.options);
464
+ const returnValue = await parsed.command.run(...parsed.arguments, {
465
+ "--": parsed["--"],
466
+ ...parsed.options
467
+ });
443
468
  await Promise.all(this.callbacks.post.map((fn) => fn(parsed.options)));
444
469
  return returnValue;
470
+ } else {
471
+ return void 0;
445
472
  }
446
473
  }
447
474
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "breadc",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Yet another Command Line Application Framework with fully strong TypeScript support",
5
5
  "keywords": [
6
6
  "cli",
@@ -44,8 +44,8 @@
44
44
  "prettier": "^2.7.1",
45
45
  "typescript": "^4.7.4",
46
46
  "unbuild": "^0.7.6",
47
- "vite": "^3.0.2",
48
- "vitest": "^0.18.1"
47
+ "vite": "^3.0.3",
48
+ "vitest": "^0.19.1"
49
49
  },
50
50
  "packageManager": "pnpm@7.5.2",
51
51
  "scripts": {