bob-core 0.8.7 → 0.9.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 +272 -2
- package/dist/Cli.d.ts +6 -2
- package/dist/Cli.js +23 -6
- package/dist/Command.d.ts +4 -2
- package/dist/Command.js +19 -1
- package/dist/Command.test.d.ts +1 -0
- package/dist/Command.test.js +52 -0
- package/dist/CommandHelper.d.ts +0 -2
- package/dist/CommandHelper.js +2 -13
- package/dist/CommandParser.d.ts +11 -4
- package/dist/CommandParser.js +116 -57
- package/dist/CommandParser.test.d.ts +1 -0
- package/dist/CommandParser.test.js +144 -0
- package/dist/errors/InvalidOption.d.ts +8 -0
- package/dist/errors/InvalidOption.js +32 -0
- package/dist/errors/MissingSignatureArgument.d.ts +8 -0
- package/dist/errors/MissingSignatureArgument.js +31 -0
- package/dist/errors/MissingSignatureOption.d.ts +8 -0
- package/dist/errors/MissingSignatureOption.js +31 -0
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -1,5 +1,275 @@
|
|
|
1
|
-
# BOB - Bash Operation Buddy
|
|
1
|
+
# BOB Core - Bash Operation Buddy Core
|
|
2
2
|
|
|
3
3
|
## Introduction
|
|
4
4
|
|
|
5
|
-
BOB (Bash Operation Buddy)
|
|
5
|
+
BOB (Bash Operation Buddy) Core is a library that provides a set of functions to create your own CLI in TypeScript.
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install bob-core
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Initialize the CLI:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { CLI } from 'bob-core';
|
|
17
|
+
|
|
18
|
+
const cli = new CLI();
|
|
19
|
+
|
|
20
|
+
await cli.withCommands('./commands');
|
|
21
|
+
|
|
22
|
+
cli.run('commandName', 'arg1', 'arg2', 'arg3');
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Create a command in the `commands` folder:
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { Command } from 'bob-core';
|
|
29
|
+
|
|
30
|
+
export default class MyCommand extends Command {
|
|
31
|
+
public name = 'my-command {arg1} {--option1}';
|
|
32
|
+
public description = 'This is my command';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Define the arguments and options help
|
|
36
|
+
*
|
|
37
|
+
* Optional
|
|
38
|
+
*/
|
|
39
|
+
helpDefinition = {
|
|
40
|
+
arg1: 'This is the first argument',
|
|
41
|
+
'--option1': 'This is the first option'
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Provide examples of how to use the command
|
|
46
|
+
*
|
|
47
|
+
* Optional
|
|
48
|
+
*/
|
|
49
|
+
commandsExamples = [
|
|
50
|
+
{
|
|
51
|
+
command: 'my-command value1 --option1',
|
|
52
|
+
description: 'This is an example'
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
public async handle() {
|
|
57
|
+
console.log('Hello World');
|
|
58
|
+
console.log('Arguments:', this.argument('arg1'));
|
|
59
|
+
console.log('Options:', this.option('option1'));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Cli Help
|
|
65
|
+
|
|
66
|
+
The CLI provides a help command that displays all available commands and their descriptions.
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
node cli.js help
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Commands
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
Bob CLI x.x.x 💪
|
|
76
|
+
|
|
77
|
+
Usage:
|
|
78
|
+
command [options] [arguments]
|
|
79
|
+
|
|
80
|
+
Available commands:
|
|
81
|
+
|
|
82
|
+
help Show help
|
|
83
|
+
test test description
|
|
84
|
+
sub:
|
|
85
|
+
sub sub command description
|
|
86
|
+
sub:sub sub:sub command description
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Command help
|
|
91
|
+
|
|
92
|
+
You can also display the help of a specific command.
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
node cli.js test -h
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
Description:
|
|
100
|
+
test description
|
|
101
|
+
|
|
102
|
+
Usage:
|
|
103
|
+
test <user> [options]
|
|
104
|
+
|
|
105
|
+
Arguments:
|
|
106
|
+
user user description
|
|
107
|
+
test test description [default: null]
|
|
108
|
+
test2 [default: []] (variadic)
|
|
109
|
+
|
|
110
|
+
Options:
|
|
111
|
+
--option, -o, -b option description (boolean) [default: false]
|
|
112
|
+
--flag flag description (string) [default: null]
|
|
113
|
+
--arr arr description (array) [default: null]
|
|
114
|
+
--flag2 flag2 description (string) [default: 2]
|
|
115
|
+
--help, -h Display help for the given command. When no command is given display help for the list command (boolean)
|
|
116
|
+
|
|
117
|
+
Examples:
|
|
118
|
+
Example description 1
|
|
119
|
+
|
|
120
|
+
node cli.js test yayo --option
|
|
121
|
+
|
|
122
|
+
Example description 2
|
|
123
|
+
|
|
124
|
+
node cli.js test anothervalue --flag=2
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Depending on the command, the help will display the command signature, description, arguments, options and examples.
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
## Commands signature
|
|
131
|
+
|
|
132
|
+
The command signature is a string that defines the command name, arguments and options.
|
|
133
|
+
|
|
134
|
+
Example:
|
|
135
|
+
```typescript
|
|
136
|
+
signature = 'my-command {arg1} {arg2} {arg3} {--option1} {--option2}';
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Arguments
|
|
140
|
+
|
|
141
|
+
All user supplied arguments and options are wrapped in curly braces.
|
|
142
|
+
In the following example, the command defines three **required** arguments `arg1`, `arg2` and `arg3`.
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
signature = 'my-command {arg1} {arg2} {arg3}';
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
You may want to make an argument optional by adding a `?` after the argument name or by providing a default value with `=`.
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
signature = 'my-command {arg1} {arg2?} {arg3=defaultValue}';
|
|
152
|
+
|
|
153
|
+
handle() {
|
|
154
|
+
this.argument('arg1'); // 'value' or throw an error if not provided
|
|
155
|
+
this.argument('arg2'); // 'value' or null if not provided
|
|
156
|
+
this.argument('arg3'); // 'value' or 'defaultValue' if not provided
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
You can also define a variadic argument by adding `*` after the argument name.
|
|
161
|
+
Variadic arguments are stored in an array.
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
signature = 'my-command {arg1} {arg2*}';
|
|
165
|
+
|
|
166
|
+
handle() {
|
|
167
|
+
this.argument('arg1'); // 'value1'
|
|
168
|
+
this.argument('arg2'); // ['value2', 'value3']
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Variadic arguments can also be optional.
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
signature = 'my-command {arg1} {arg2*?}';
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Options
|
|
179
|
+
|
|
180
|
+
Options are defined by `{--optionName}`.
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
signature = 'my-command {--option1} {--option2} {--option3}';
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
By default options are boolean with a default value of `false`.
|
|
187
|
+
You can also change the option type to string by adding `=` to the option definition.
|
|
188
|
+
You can also provide a default value by adding `=value`.
|
|
189
|
+
|
|
190
|
+
If the value is 'true' or 'false', the option will be converted to a boolean.
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
signature = 'my-command {--option1} {--option2=true} {--option3=} {--option4=defaultValue} {--option5=}';
|
|
194
|
+
|
|
195
|
+
handle() {
|
|
196
|
+
this.option('option1'); // by default `false` and can be set to `true` by the user
|
|
197
|
+
this.option('option2'); // by default `true` and can be set to `false` by the user
|
|
198
|
+
this.option('option3'); // by default `null` and can be set to "value" by the user
|
|
199
|
+
this.option('option4'); // by default "defaultValue" and can be set to "value" by the user
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
You can also define a variadic option by adding `*` as option value. (e.g. `{--option2=*}`)
|
|
204
|
+
Variadic options are stored in an array.
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
signature = 'my-command {--option1} {--option2=*}';
|
|
208
|
+
|
|
209
|
+
handle() {
|
|
210
|
+
this.option('option1'); // 'value1'
|
|
211
|
+
this.option('option2'); // ['value2', 'value3'] // or [] if not provided
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Commands I/O
|
|
216
|
+
|
|
217
|
+
### Arguments
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
this.argument('arg1');
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
You can also provide a default value if the argument is optional.
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
this.argument('arg1', 'defaultValue');
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
If you always need a boolean value, you can use the `argumentBoolean` method.
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
this.argumentBoolean('arg1');
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
If you always need a number value, you can use the `argumentNumber` method.
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
this.argumentNumber('arg1');
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
If you always need a array value, you can use the `argumentArray` method.
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
this.argumentArray('arg1');
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Options
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
this.option('option1');
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
You can also provide a default value if the option is optional.
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
this.option('option1', 'defaultValue');
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
If you always need a boolean value, you can use the `optionBoolean` method.
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
this.optionBoolean('option1');
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
If you always need a number value, you can use the `optionNumber` method.
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
this.optionNumber('option1');
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
If you always need a array value, you can use the `optionArray` method.
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
this.optionArray('option1');
|
|
275
|
+
```
|
package/dist/Cli.d.ts
CHANGED
|
@@ -6,12 +6,16 @@ export declare class Cli<C> {
|
|
|
6
6
|
readonly commandRegistry: CommandRegistry;
|
|
7
7
|
private readonly exceptionHandler;
|
|
8
8
|
private readonly ctx?;
|
|
9
|
+
private readonly helpCommand;
|
|
9
10
|
get CommandRegistryClass(): typeof CommandRegistry;
|
|
10
11
|
get HelpCommandClass(): typeof HelpCommand;
|
|
11
12
|
get ExceptionHandlerClass(): typeof ExceptionHandler;
|
|
12
13
|
constructor(ctx?: C);
|
|
13
14
|
setCommandResolver(resolver: (path: string) => Promise<Command>): void;
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
withCommands(...commands: Array<Command | {
|
|
16
|
+
new (): Command;
|
|
17
|
+
} | string>): Promise<void>;
|
|
16
18
|
runCommand(command: string, ...args: any[]): Promise<number>;
|
|
19
|
+
runHelpCommand(): Promise<number>;
|
|
20
|
+
protected registerCommand(command: Command): void;
|
|
17
21
|
}
|
package/dist/Cli.js
CHANGED
|
@@ -11,6 +11,7 @@ class Cli {
|
|
|
11
11
|
commandRegistry;
|
|
12
12
|
exceptionHandler;
|
|
13
13
|
ctx;
|
|
14
|
+
helpCommand;
|
|
14
15
|
get CommandRegistryClass() {
|
|
15
16
|
return CommandRegistry_1.CommandRegistry;
|
|
16
17
|
}
|
|
@@ -24,20 +25,36 @@ class Cli {
|
|
|
24
25
|
this.ctx = ctx;
|
|
25
26
|
this.commandRegistry = new this.CommandRegistryClass();
|
|
26
27
|
this.exceptionHandler = new this.ExceptionHandlerClass();
|
|
27
|
-
this.
|
|
28
|
+
this.helpCommand = new this.HelpCommandClass(this.commandRegistry);
|
|
29
|
+
this.registerCommand(this.helpCommand);
|
|
28
30
|
}
|
|
29
31
|
setCommandResolver(resolver) {
|
|
30
32
|
this.commandRegistry.setCommandResolver(resolver);
|
|
31
33
|
}
|
|
32
|
-
async
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
async withCommands(...commands) {
|
|
35
|
+
for (const command of commands) {
|
|
36
|
+
if (typeof command === 'string') {
|
|
37
|
+
await this.commandRegistry.loadCommandsPath(command);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
if (typeof command === 'function') {
|
|
41
|
+
this.registerCommand(new command());
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
this.registerCommand(command);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
37
48
|
}
|
|
38
49
|
async runCommand(command, ...args) {
|
|
39
50
|
return await this.commandRegistry.runCommand(this.ctx, command, ...args)
|
|
40
51
|
.catch(this.exceptionHandler.handle);
|
|
41
52
|
}
|
|
53
|
+
async runHelpCommand() {
|
|
54
|
+
return await this.runCommand(this.helpCommand.command);
|
|
55
|
+
}
|
|
56
|
+
registerCommand(command) {
|
|
57
|
+
this.commandRegistry.registerCommand(command);
|
|
58
|
+
}
|
|
42
59
|
}
|
|
43
60
|
exports.Cli = Cli;
|
package/dist/Command.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CommandHelper } from "./CommandHelper";
|
|
2
|
-
import { CommandParser } from "./CommandParser";
|
|
2
|
+
import { ArgSignature, CommandParser } from "./CommandParser";
|
|
3
3
|
export type CommandExample = {
|
|
4
4
|
description: string;
|
|
5
5
|
command: string;
|
|
@@ -13,8 +13,10 @@ export declare abstract class Command<C = undefined> extends CommandHelper {
|
|
|
13
13
|
};
|
|
14
14
|
protected commandsExamples: CommandExample[];
|
|
15
15
|
protected parser: CommandParser;
|
|
16
|
-
get command(): string;
|
|
17
16
|
protected abstract handle(): Promise<void | number>;
|
|
17
|
+
private get CommandParserClass();
|
|
18
|
+
protected get defaultOptions(): ArgSignature[];
|
|
19
|
+
get command(): string;
|
|
18
20
|
run(ctx: C, ...args: any[]): Promise<number>;
|
|
19
21
|
protected setOption(name: string, value: any): void;
|
|
20
22
|
protected setArgument(name: string, value: any): void;
|
package/dist/Command.js
CHANGED
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.Command = void 0;
|
|
4
7
|
const CommandHelper_1 = require("./CommandHelper");
|
|
5
8
|
const CommandParser_1 = require("./CommandParser");
|
|
9
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
6
10
|
class Command extends CommandHelper_1.CommandHelper {
|
|
7
11
|
ctx;
|
|
8
12
|
helperDefinitions = {};
|
|
9
13
|
commandsExamples = [];
|
|
10
14
|
parser;
|
|
15
|
+
get CommandParserClass() {
|
|
16
|
+
return CommandParser_1.CommandParser;
|
|
17
|
+
}
|
|
18
|
+
get defaultOptions() {
|
|
19
|
+
return [
|
|
20
|
+
{
|
|
21
|
+
name: 'help',
|
|
22
|
+
optional: true,
|
|
23
|
+
type: 'boolean',
|
|
24
|
+
help: (0, chalk_1.default) `Display help for the given command. When no command is given display help for the {green list} command`,
|
|
25
|
+
alias: ['h']
|
|
26
|
+
}
|
|
27
|
+
];
|
|
28
|
+
}
|
|
11
29
|
get command() {
|
|
12
30
|
if (this.parser) {
|
|
13
31
|
return this.parser.command;
|
|
@@ -16,7 +34,7 @@ class Command extends CommandHelper_1.CommandHelper {
|
|
|
16
34
|
}
|
|
17
35
|
async run(ctx, ...args) {
|
|
18
36
|
this.ctx = ctx;
|
|
19
|
-
this.parser = new
|
|
37
|
+
this.parser = new this.CommandParserClass(this.signature, this.helperDefinitions, this.defaultOptions, ...args);
|
|
20
38
|
if (args.includes('--help') || args.includes('-h')) {
|
|
21
39
|
return this.help.call(this);
|
|
22
40
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const Command_1 = require("./Command");
|
|
4
|
+
const MissingRequiredArgumentValue_1 = require("./errors/MissingRequiredArgumentValue");
|
|
5
|
+
class MockCommand extends Command_1.Command {
|
|
6
|
+
signature = 'mockCommand {argument} {--option}';
|
|
7
|
+
description = 'This is a mock command for testing';
|
|
8
|
+
handle() {
|
|
9
|
+
const opts = this.option('option');
|
|
10
|
+
const arg = this.argument('argument');
|
|
11
|
+
if (opts) {
|
|
12
|
+
return Promise.resolve(11);
|
|
13
|
+
}
|
|
14
|
+
if (arg === 'value') {
|
|
15
|
+
return Promise.resolve(1);
|
|
16
|
+
}
|
|
17
|
+
else if (arg) {
|
|
18
|
+
return Promise.resolve(-1);
|
|
19
|
+
}
|
|
20
|
+
return Promise.resolve(0);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
describe('Command', () => {
|
|
24
|
+
let command;
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
command = new MockCommand();
|
|
27
|
+
});
|
|
28
|
+
it('should have a command', () => {
|
|
29
|
+
expect(command.command).toBe('mockCommand');
|
|
30
|
+
});
|
|
31
|
+
it('should have a signature', () => {
|
|
32
|
+
expect(command.signature).toBe('mockCommand {argument} {--option}');
|
|
33
|
+
});
|
|
34
|
+
it('should have a description', () => {
|
|
35
|
+
expect(command.description).toBe('This is a mock command for testing');
|
|
36
|
+
});
|
|
37
|
+
it('should handle command with argument', async () => {
|
|
38
|
+
const result = await command.run(undefined, 'value');
|
|
39
|
+
expect(result).toBe(1);
|
|
40
|
+
});
|
|
41
|
+
it('should handle command with argument', async () => {
|
|
42
|
+
const result = await command.run(undefined, 'badValue');
|
|
43
|
+
expect(result).toBe(-1);
|
|
44
|
+
});
|
|
45
|
+
it('should throw error if argument is missing', async () => {
|
|
46
|
+
await expect(command.run(undefined)).rejects.toThrowError(MissingRequiredArgumentValue_1.MissingRequiredArgumentValue);
|
|
47
|
+
});
|
|
48
|
+
it('should handle command with option', async () => {
|
|
49
|
+
const result = await command.run(undefined, 'value', '--option');
|
|
50
|
+
expect(result).toBe(11);
|
|
51
|
+
});
|
|
52
|
+
});
|
package/dist/CommandHelper.d.ts
CHANGED
package/dist/CommandHelper.js
CHANGED
|
@@ -8,21 +8,10 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
8
8
|
const lodash_1 = require("lodash");
|
|
9
9
|
const string_1 = require("./lib/string");
|
|
10
10
|
class CommandHelper {
|
|
11
|
-
get defaultOptions() {
|
|
12
|
-
return [
|
|
13
|
-
{
|
|
14
|
-
name: 'help',
|
|
15
|
-
optional: true,
|
|
16
|
-
type: 'boolean',
|
|
17
|
-
help: (0, chalk_1.default) `Display help for the given command. When no command is given display help for the {green list} command`,
|
|
18
|
-
alias: ['h']
|
|
19
|
-
}
|
|
20
|
-
];
|
|
21
|
-
}
|
|
22
11
|
help() {
|
|
23
12
|
const log = console.log;
|
|
24
|
-
const availableArguments = Object.values(this.parser.
|
|
25
|
-
const availableOptions =
|
|
13
|
+
const availableArguments = Object.values(this.parser.getArgumentSignatures());
|
|
14
|
+
const availableOptions = Object.values(this.parser.getOptionSignatures())
|
|
26
15
|
.map((signature) => ({
|
|
27
16
|
...signature,
|
|
28
17
|
optionWithAlias: `--${signature.name}${signature.alias?.map(a => `, -${a}`).join('') ?? ''}`
|
package/dist/CommandParser.d.ts
CHANGED
|
@@ -13,24 +13,31 @@ export declare class CommandParser {
|
|
|
13
13
|
protected readonly helperDefinitions: {
|
|
14
14
|
[key: string]: string;
|
|
15
15
|
};
|
|
16
|
+
protected readonly defaultOptions: ArgSignature[];
|
|
16
17
|
command: string;
|
|
17
18
|
private arguments;
|
|
18
19
|
private options;
|
|
19
20
|
private argumentsSignature;
|
|
20
|
-
private
|
|
21
|
+
private optionSignatures;
|
|
22
|
+
private optionAliases;
|
|
21
23
|
option(name: string): any;
|
|
22
24
|
setOption(name: string, value: any): void;
|
|
25
|
+
optionHelp(name: string): string | undefined;
|
|
23
26
|
argument(name: string): any;
|
|
24
27
|
setArgument(name: string, value: any): void;
|
|
25
|
-
|
|
28
|
+
argumentHelp(name: string): string | undefined;
|
|
29
|
+
getArgumentSignatures(): {
|
|
26
30
|
[argument: string]: ArgSignature;
|
|
27
31
|
};
|
|
28
|
-
|
|
32
|
+
getOptionSignatures(): {
|
|
29
33
|
[option: string]: ArgSignature;
|
|
30
34
|
};
|
|
31
35
|
constructor(signature: string, helperDefinitions: {
|
|
32
36
|
[key: string]: string;
|
|
33
|
-
}, ...args: any[]);
|
|
37
|
+
}, defaultOptions?: ArgSignature[], ...args: any[]);
|
|
38
|
+
private getParamValue;
|
|
39
|
+
private parseArguments;
|
|
40
|
+
private parseOptions;
|
|
34
41
|
private parseSignature;
|
|
35
42
|
private parseParamSignature;
|
|
36
43
|
validate(): void;
|
package/dist/CommandParser.js
CHANGED
|
@@ -6,105 +6,154 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.CommandParser = void 0;
|
|
7
7
|
const minimist_1 = __importDefault(require("minimist"));
|
|
8
8
|
const MissingRequiredArgumentValue_1 = require("./errors/MissingRequiredArgumentValue");
|
|
9
|
+
const MissingSignatureOption_1 = require("./errors/MissingSignatureOption");
|
|
10
|
+
const MissingSignatureArgument_1 = require("./errors/MissingSignatureArgument");
|
|
11
|
+
const InvalidOption_1 = require("./errors/InvalidOption");
|
|
9
12
|
class CommandParser {
|
|
10
13
|
signature;
|
|
11
14
|
helperDefinitions;
|
|
15
|
+
defaultOptions;
|
|
12
16
|
command;
|
|
13
17
|
arguments = {};
|
|
14
18
|
options = {};
|
|
15
19
|
argumentsSignature = {};
|
|
16
|
-
|
|
20
|
+
optionSignatures = {};
|
|
21
|
+
optionAliases = {};
|
|
17
22
|
option(name) {
|
|
18
|
-
if (!this.
|
|
19
|
-
throw new
|
|
20
|
-
}
|
|
21
|
-
const signature = this.optionsSignature[name];
|
|
22
|
-
if (signature.type === 'boolean') {
|
|
23
|
-
if (this.options[name] === 'true' || this.options[name] === '1') {
|
|
24
|
-
return true;
|
|
25
|
-
}
|
|
26
|
-
else if (this.options[name] === 'false' || this.options[name] === '0') {
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
return Boolean(this.options[name]);
|
|
30
|
-
}
|
|
31
|
-
if (signature.type === 'array') {
|
|
32
|
-
if (!this.options[name]) {
|
|
33
|
-
return [];
|
|
34
|
-
}
|
|
35
|
-
return Array.isArray(this.options[name]) ? this.options[name] : [this.options[name]];
|
|
23
|
+
if (!this.optionSignatures[name]) {
|
|
24
|
+
throw new MissingSignatureOption_1.MissingSignatureOption(name, Object.values(this.optionSignatures));
|
|
36
25
|
}
|
|
37
26
|
return this.options[name];
|
|
38
27
|
}
|
|
39
28
|
setOption(name, value) {
|
|
29
|
+
if (!this.optionSignatures[name]) {
|
|
30
|
+
throw new MissingSignatureOption_1.MissingSignatureOption(name, Object.values(this.optionSignatures));
|
|
31
|
+
}
|
|
40
32
|
this.options[name] = value;
|
|
41
33
|
}
|
|
34
|
+
optionHelp(name) {
|
|
35
|
+
const optionSignature = this.optionSignatures[name];
|
|
36
|
+
if (!optionSignature) {
|
|
37
|
+
throw new MissingSignatureOption_1.MissingSignatureOption(name, Object.values(this.optionSignatures));
|
|
38
|
+
}
|
|
39
|
+
return this.optionSignatures[name].help;
|
|
40
|
+
}
|
|
42
41
|
argument(name) {
|
|
42
|
+
if (!this.argumentsSignature[name]) {
|
|
43
|
+
throw new MissingSignatureArgument_1.MissingSignatureArgument(name, Object.values(this.argumentsSignature));
|
|
44
|
+
}
|
|
43
45
|
return this.arguments[name];
|
|
44
46
|
}
|
|
45
47
|
setArgument(name, value) {
|
|
48
|
+
if (!this.argumentsSignature[name]) {
|
|
49
|
+
throw new MissingSignatureArgument_1.MissingSignatureArgument(name, Object.values(this.argumentsSignature));
|
|
50
|
+
}
|
|
46
51
|
this.arguments[name] = value;
|
|
47
52
|
}
|
|
48
|
-
|
|
53
|
+
argumentHelp(name) {
|
|
54
|
+
const argumentSignature = this.argumentsSignature[name];
|
|
55
|
+
if (!argumentSignature) {
|
|
56
|
+
throw new MissingSignatureArgument_1.MissingSignatureArgument(name, Object.values(this.argumentsSignature));
|
|
57
|
+
}
|
|
58
|
+
return this.argumentsSignature[name].help;
|
|
59
|
+
}
|
|
60
|
+
getArgumentSignatures() {
|
|
49
61
|
return this.argumentsSignature;
|
|
50
62
|
}
|
|
51
|
-
|
|
52
|
-
return this.
|
|
63
|
+
getOptionSignatures() {
|
|
64
|
+
return this.optionSignatures;
|
|
53
65
|
}
|
|
54
|
-
constructor(signature, helperDefinitions, ...args) {
|
|
66
|
+
constructor(signature, helperDefinitions, defaultOptions = [], ...args) {
|
|
55
67
|
this.signature = signature;
|
|
56
68
|
this.helperDefinitions = helperDefinitions;
|
|
57
|
-
|
|
69
|
+
this.defaultOptions = defaultOptions;
|
|
70
|
+
const [command, ...signatureParams] = signature.split(/\{(.*?)\}/g).map(param => param.trim()).filter(Boolean);
|
|
58
71
|
const { _: paramValues, ...optionValues } = (0, minimist_1.default)(args);
|
|
72
|
+
if (defaultOptions.length) {
|
|
73
|
+
for (const option of defaultOptions) {
|
|
74
|
+
this.optionSignatures[option.name] = option;
|
|
75
|
+
this.options[option.name] = option.defaultValue;
|
|
76
|
+
if (option.alias) {
|
|
77
|
+
for (const alias of option.alias) {
|
|
78
|
+
this.optionAliases[alias] = option.name;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
59
83
|
this.command = command;
|
|
60
|
-
this.parseSignature(
|
|
84
|
+
this.parseSignature(signatureParams);
|
|
85
|
+
this.parseArguments(paramValues);
|
|
86
|
+
this.parseOptions(optionValues);
|
|
87
|
+
}
|
|
88
|
+
getParamValue(value, signature) {
|
|
89
|
+
if (signature.type === 'boolean') {
|
|
90
|
+
if (value === 'true' || value === '1') {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
else if (value === 'false' || value === '0') {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
return Boolean(value);
|
|
97
|
+
}
|
|
98
|
+
if (signature.type === 'array') {
|
|
99
|
+
if (!value) {
|
|
100
|
+
return [];
|
|
101
|
+
}
|
|
102
|
+
return Array.isArray(value) ? value : [value];
|
|
103
|
+
}
|
|
104
|
+
return value ?? signature.defaultValue;
|
|
105
|
+
}
|
|
106
|
+
parseArguments(paramValues) {
|
|
107
|
+
for (const [argument, value] of Object.entries(this.arguments)) {
|
|
108
|
+
const argSignature = this.argumentsSignature[argument];
|
|
109
|
+
if (argSignature.variadic) {
|
|
110
|
+
this.arguments[argument] = paramValues;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
const paramValue = paramValues.shift();
|
|
114
|
+
this.arguments[argument] = this.getParamValue(paramValue, argSignature);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
61
117
|
}
|
|
62
|
-
|
|
118
|
+
parseOptions(optionValues) {
|
|
119
|
+
for (const [option, value] of Object.entries(optionValues)) {
|
|
120
|
+
const optionAlias = this.optionAliases[option];
|
|
121
|
+
const optionSignature = this.optionSignatures[option] ?? this.optionSignatures[optionAlias];
|
|
122
|
+
if (!optionSignature) {
|
|
123
|
+
throw new InvalidOption_1.InvalidOption(option, Object.values(this.optionSignatures));
|
|
124
|
+
}
|
|
125
|
+
this.options[option] = this.getParamValue(value, optionSignature);
|
|
126
|
+
for (const alias of optionSignature.alias ?? []) {
|
|
127
|
+
if (optionValues[alias]) {
|
|
128
|
+
this.options[optionSignature.name] = optionValues[alias];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
parseSignature(params) {
|
|
63
134
|
for (const paramSignature of params) {
|
|
64
135
|
const param = this.parseParamSignature(paramSignature);
|
|
65
136
|
if (param.isOption) {
|
|
66
|
-
|
|
67
|
-
this.
|
|
68
|
-
this.optionsSignature[param.name] = param;
|
|
137
|
+
this.options[param.name] = param.defaultValue ?? null;
|
|
138
|
+
this.optionSignatures[param.name] = param;
|
|
69
139
|
for (const alias of param.alias ?? []) {
|
|
70
|
-
|
|
71
|
-
this.options[param.name] = optionValues[alias];
|
|
72
|
-
this.optionsSignature[param.name] = param;
|
|
73
|
-
}
|
|
140
|
+
this.optionAliases[alias] = param.name;
|
|
74
141
|
}
|
|
75
142
|
}
|
|
76
143
|
else {
|
|
77
|
-
|
|
78
|
-
const paramValue = paramValues.splice(0, paramValues.length);
|
|
79
|
-
this.arguments[param.name] = paramValue ?? [];
|
|
80
|
-
}
|
|
81
|
-
else {
|
|
82
|
-
const paramValue = paramValues.shift();
|
|
83
|
-
this.arguments[param.name] = paramValue ?? param.defaultValue ?? null;
|
|
84
|
-
}
|
|
144
|
+
this.arguments[param.name] = param.defaultValue ?? null;
|
|
85
145
|
this.argumentsSignature[param.name] = param;
|
|
86
146
|
}
|
|
87
147
|
}
|
|
88
148
|
}
|
|
89
149
|
parseParamSignature(argument) {
|
|
90
|
-
let cleanedArgs = argument;
|
|
91
|
-
let isOptional = false;
|
|
92
|
-
let isVariadic = false;
|
|
93
|
-
if (cleanedArgs.endsWith('?')) {
|
|
94
|
-
cleanedArgs = cleanedArgs.slice(0, -1);
|
|
95
|
-
isOptional = true;
|
|
96
|
-
}
|
|
97
|
-
if (cleanedArgs.endsWith('*')) {
|
|
98
|
-
cleanedArgs = cleanedArgs.slice(0, -1);
|
|
99
|
-
isVariadic = true;
|
|
100
|
-
}
|
|
101
150
|
const arg = {
|
|
102
|
-
name:
|
|
103
|
-
optional:
|
|
104
|
-
type:
|
|
151
|
+
name: argument,
|
|
152
|
+
optional: false,
|
|
153
|
+
type: 'string',
|
|
105
154
|
help: undefined,
|
|
106
|
-
defaultValue:
|
|
107
|
-
variadic:
|
|
155
|
+
defaultValue: null,
|
|
156
|
+
variadic: false,
|
|
108
157
|
isOption: false
|
|
109
158
|
};
|
|
110
159
|
if (arg.name.includes(':')) {
|
|
@@ -149,6 +198,16 @@ class CommandParser {
|
|
|
149
198
|
arg.defaultValue = [];
|
|
150
199
|
arg.type = 'array';
|
|
151
200
|
}
|
|
201
|
+
if (arg.name.endsWith('?')) {
|
|
202
|
+
arg.optional = true;
|
|
203
|
+
arg.name = arg.name.slice(0, -1);
|
|
204
|
+
}
|
|
205
|
+
if (arg.name.endsWith('*')) {
|
|
206
|
+
arg.type = 'array';
|
|
207
|
+
arg.variadic = true;
|
|
208
|
+
arg.defaultValue = [];
|
|
209
|
+
arg.name = arg.name.slice(0, -1);
|
|
210
|
+
}
|
|
152
211
|
arg.help = arg.help ?? this.helperDefinitions[arg.name] ?? this.helperDefinitions[`--${arg.name}`];
|
|
153
212
|
return arg;
|
|
154
213
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const CommandParser_1 = require("./CommandParser");
|
|
4
|
+
const MissingRequiredArgumentValue_1 = require("./errors/MissingRequiredArgumentValue");
|
|
5
|
+
describe('CommandParser', () => {
|
|
6
|
+
let commandParser;
|
|
7
|
+
const parseCommand = (signature, args, helperDefinition = {}) => {
|
|
8
|
+
return new CommandParser_1.CommandParser(signature, helperDefinition, [], ...args);
|
|
9
|
+
};
|
|
10
|
+
it('should parse signature without arguments & options', () => {
|
|
11
|
+
commandParser = parseCommand('test', []);
|
|
12
|
+
expect(commandParser.command).toBe('test');
|
|
13
|
+
});
|
|
14
|
+
describe('Arguments', () => {
|
|
15
|
+
it('should parse signature with arguments', () => {
|
|
16
|
+
commandParser = parseCommand('test {arg1} {arg2}', ['value1', 'value2']);
|
|
17
|
+
expect(commandParser.argument('arg1')).toBe('value1');
|
|
18
|
+
expect(commandParser.argument('arg2')).toBe('value2');
|
|
19
|
+
});
|
|
20
|
+
it('should parse signature with optional arguments', () => {
|
|
21
|
+
commandParser = parseCommand('test {arg1?} {arg2?}', ['value1']);
|
|
22
|
+
expect(commandParser.argument('arg1')).toBe('value1');
|
|
23
|
+
expect(commandParser.argument('arg2')).toBeNull();
|
|
24
|
+
});
|
|
25
|
+
it('should parse signature with optional arguments with default value', () => {
|
|
26
|
+
commandParser = parseCommand('test {arg1?} {arg2=defaultValue1}', ['value1']);
|
|
27
|
+
expect(commandParser.argument('arg1')).toBe('value1');
|
|
28
|
+
expect(commandParser.argument('arg2')).toBe('defaultValue1');
|
|
29
|
+
});
|
|
30
|
+
it('should parse signature with variadic arguments', () => {
|
|
31
|
+
commandParser = parseCommand('test {arg1*}', ['value1', 'value2']);
|
|
32
|
+
expect(commandParser.argument('arg1')).toEqual(['value1', 'value2']);
|
|
33
|
+
});
|
|
34
|
+
it('should parse signature with optional variadic arguments', () => {
|
|
35
|
+
commandParser = parseCommand('test {arg1*?}', ['value1', 'value2']);
|
|
36
|
+
expect(commandParser.argument('arg1')).toEqual(['value1', 'value2']);
|
|
37
|
+
});
|
|
38
|
+
it('should parse signature with optional variadic arguments without value', () => {
|
|
39
|
+
commandParser = parseCommand('test {arg1*?}', []);
|
|
40
|
+
expect(commandParser.argument('arg1')).toEqual([]);
|
|
41
|
+
});
|
|
42
|
+
it('should set argument value', () => {
|
|
43
|
+
commandParser = parseCommand('test {arg1}', ['value1']);
|
|
44
|
+
commandParser.setArgument('arg1', 'newValue');
|
|
45
|
+
expect(commandParser.argument('arg1')).toBe('newValue');
|
|
46
|
+
});
|
|
47
|
+
it('should throw error when argument is missing with setArgument', () => {
|
|
48
|
+
commandParser = parseCommand('test {arg1}', []);
|
|
49
|
+
expect(() => commandParser.setArgument('arg2', 'newValue')).toThrowError(Error);
|
|
50
|
+
});
|
|
51
|
+
it('calling validate method should throw error when argument is missing', () => {
|
|
52
|
+
commandParser = parseCommand('test {arg1}', []);
|
|
53
|
+
expect(() => commandParser.validate()).toThrowError(MissingRequiredArgumentValue_1.MissingRequiredArgumentValue);
|
|
54
|
+
});
|
|
55
|
+
it('calling validate should throw with variadic argument is missing', () => {
|
|
56
|
+
commandParser = parseCommand('test {arg1*}', []);
|
|
57
|
+
expect(() => commandParser.validate()).toThrowError(MissingRequiredArgumentValue_1.MissingRequiredArgumentValue);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
describe('Options', () => {
|
|
61
|
+
it('boolean option should be false when not provided', () => {
|
|
62
|
+
commandParser = parseCommand('test {--option}', []);
|
|
63
|
+
expect(commandParser.option('option')).toBeFalsy();
|
|
64
|
+
});
|
|
65
|
+
it('boolean option should be true when provided', () => {
|
|
66
|
+
commandParser = parseCommand('test {--option}', ['--option']);
|
|
67
|
+
expect(commandParser.option('option')).toBeTruthy();
|
|
68
|
+
});
|
|
69
|
+
it('boolean option should be true when provided with value', () => {
|
|
70
|
+
commandParser = parseCommand('test {--option}', ['--option=true']);
|
|
71
|
+
expect(commandParser.option('option')).toBeTruthy();
|
|
72
|
+
});
|
|
73
|
+
it('boolean option should be false when provided with value', () => {
|
|
74
|
+
commandParser = parseCommand('test {--option}', ['--option=false']);
|
|
75
|
+
expect(commandParser.option('option')).toBeFalsy();
|
|
76
|
+
});
|
|
77
|
+
it('string option should be null when not provided', () => {
|
|
78
|
+
commandParser = parseCommand('test {--option=}', []);
|
|
79
|
+
expect(commandParser.option('option')).toBeNull();
|
|
80
|
+
});
|
|
81
|
+
it('string option should be value when provided', () => {
|
|
82
|
+
commandParser = parseCommand('test {--option=}', ['--option=value']);
|
|
83
|
+
expect(commandParser.option('option')).toBe('value');
|
|
84
|
+
});
|
|
85
|
+
it('string option should take the default value when not provided', () => {
|
|
86
|
+
commandParser = parseCommand('test {--option=default}', []);
|
|
87
|
+
expect(commandParser.option('option')).toBe('default');
|
|
88
|
+
});
|
|
89
|
+
it('string option should take the provided value with default value', () => {
|
|
90
|
+
commandParser = parseCommand('test {--option=default}', ['--option=value']);
|
|
91
|
+
expect(commandParser.option('option')).toBe('value');
|
|
92
|
+
});
|
|
93
|
+
it('array option should be empty when not provided', () => {
|
|
94
|
+
commandParser = parseCommand('test {--option=*}', []);
|
|
95
|
+
expect(commandParser.option('option')).toEqual([]);
|
|
96
|
+
});
|
|
97
|
+
it('array option should be value when provided', () => {
|
|
98
|
+
commandParser = parseCommand('test {--option=*}', ['--option=value1', '--option=value2']);
|
|
99
|
+
expect(commandParser.option('option')).toEqual(['value1', 'value2']);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
describe('Mixed', () => {
|
|
103
|
+
it('should parse signature with arguments and options', () => {
|
|
104
|
+
commandParser = parseCommand('test {arg1} {arg2} {--option}', ['value1', 'value2', '--option']);
|
|
105
|
+
expect(commandParser.argument('arg1')).toBe('value1');
|
|
106
|
+
expect(commandParser.argument('arg2')).toBe('value2');
|
|
107
|
+
expect(commandParser.option('option')).toBeTruthy();
|
|
108
|
+
});
|
|
109
|
+
it('should parse signature with optional arguments and options', () => {
|
|
110
|
+
commandParser = parseCommand('test {arg1?} {arg2?} {--option}', ['value1', '--option']);
|
|
111
|
+
expect(commandParser.argument('arg1')).toBe('value1');
|
|
112
|
+
expect(commandParser.argument('arg2')).toBeNull();
|
|
113
|
+
expect(commandParser.option('option')).toBeTruthy();
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
describe('Helper', () => {
|
|
117
|
+
it('should parse help signature', () => {
|
|
118
|
+
commandParser = parseCommand('test {arg1} {arg2:help 1} {--option : option help 2 }', ['value1', 'value2', '--option']);
|
|
119
|
+
expect(commandParser.argumentHelp('arg1')).toBeUndefined();
|
|
120
|
+
expect(commandParser.argumentHelp('arg2')).toBe('help 1');
|
|
121
|
+
expect(commandParser.optionHelp('option')).toBe('option help 2');
|
|
122
|
+
});
|
|
123
|
+
it('should define help with helperDefinition', () => {
|
|
124
|
+
commandParser = parseCommand('test {arg1} {arg2} {--option} {--option2}', ['value1', 'value2', '--option'], {
|
|
125
|
+
arg1: 'arg1 help',
|
|
126
|
+
arg2: 'arg2 help',
|
|
127
|
+
'--option': 'option help'
|
|
128
|
+
});
|
|
129
|
+
expect(commandParser.argumentHelp('arg1')).toBe('arg1 help');
|
|
130
|
+
expect(commandParser.argumentHelp('arg2')).toBe('arg2 help');
|
|
131
|
+
expect(commandParser.optionHelp('option')).toBe('option help');
|
|
132
|
+
expect(commandParser.optionHelp('option2')).toBeUndefined();
|
|
133
|
+
});
|
|
134
|
+
it('should define help with helperDefinition with default value', () => {
|
|
135
|
+
commandParser = parseCommand('test {arg1:arg1 help} {arg2} {--option=default}', ['value1', 'value2'], {
|
|
136
|
+
arg2: 'arg2 help',
|
|
137
|
+
'--option': 'option help'
|
|
138
|
+
});
|
|
139
|
+
expect(commandParser.argumentHelp('arg1')).toBe('arg1 help');
|
|
140
|
+
expect(commandParser.argumentHelp('arg2')).toBe('arg2 help');
|
|
141
|
+
expect(commandParser.optionHelp('option')).toBe('option help');
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { BobError } from "./BobError";
|
|
2
|
+
import { ArgSignature } from "../CommandParser";
|
|
3
|
+
export declare class InvalidOption extends BobError {
|
|
4
|
+
private option;
|
|
5
|
+
private optionsSignature;
|
|
6
|
+
constructor(option: string, optionsSignature: ArgSignature[]);
|
|
7
|
+
pretty(): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.InvalidOption = void 0;
|
|
7
|
+
const BobError_1 = require("./BobError");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
class InvalidOption extends BobError_1.BobError {
|
|
10
|
+
option;
|
|
11
|
+
optionsSignature;
|
|
12
|
+
constructor(option, optionsSignature) {
|
|
13
|
+
super(`Invalid option ${option} in not recognized`);
|
|
14
|
+
this.option = option;
|
|
15
|
+
this.optionsSignature = optionsSignature;
|
|
16
|
+
}
|
|
17
|
+
pretty() {
|
|
18
|
+
const log = console.log;
|
|
19
|
+
if (this.optionsSignature.length > 0) {
|
|
20
|
+
log((0, chalk_1.default) `\n{yellow Available options}:`);
|
|
21
|
+
for (const option of this.optionsSignature) {
|
|
22
|
+
const type = option.type ? (0, chalk_1.default) `{white (${option.type})}` : '';
|
|
23
|
+
const nameWithAlias = `--${option.name}${option.alias?.map(a => `, -${a}`).join('') ?? ''}`;
|
|
24
|
+
const spaces = ' '.repeat(30 - nameWithAlias.length);
|
|
25
|
+
log((0, chalk_1.default) ` {green ${nameWithAlias}} ${spaces} ${option.help ?? '\b'} ${type}`);
|
|
26
|
+
}
|
|
27
|
+
log('');
|
|
28
|
+
}
|
|
29
|
+
log((0, chalk_1.default) ` {white.bgRed ERROR } Option "{yellow ${this.option}}" is not recognized.`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.InvalidOption = InvalidOption;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { BobError } from "./BobError";
|
|
2
|
+
import { ArgSignature } from "../CommandParser";
|
|
3
|
+
export declare class MissingSignatureArgument extends BobError {
|
|
4
|
+
private argument;
|
|
5
|
+
private argumentSignatures;
|
|
6
|
+
constructor(argument: string, argumentSignatures: ArgSignature[]);
|
|
7
|
+
pretty(): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MissingSignatureArgument = void 0;
|
|
7
|
+
const BobError_1 = require("./BobError");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
class MissingSignatureArgument extends BobError_1.BobError {
|
|
10
|
+
argument;
|
|
11
|
+
argumentSignatures;
|
|
12
|
+
constructor(argument, argumentSignatures) {
|
|
13
|
+
super(`Missing ${argument} in the command signature`);
|
|
14
|
+
this.argument = argument;
|
|
15
|
+
this.argumentSignatures = argumentSignatures;
|
|
16
|
+
}
|
|
17
|
+
pretty() {
|
|
18
|
+
const log = console.log;
|
|
19
|
+
if (this.argumentSignatures.length) {
|
|
20
|
+
log((0, chalk_1.default) `\n{yellow Available arguments}:`);
|
|
21
|
+
for (const argument of this.argumentSignatures) {
|
|
22
|
+
const type = argument.type ? (0, chalk_1.default) `{white (${argument.type})}` : '';
|
|
23
|
+
const spaces = ' '.repeat(20 - argument.name.length);
|
|
24
|
+
log((0, chalk_1.default) ` {green ${argument.name}} ${spaces} ${argument.help ?? '\b'} ${type}`);
|
|
25
|
+
}
|
|
26
|
+
log('');
|
|
27
|
+
}
|
|
28
|
+
log((0, chalk_1.default) ` {white.bgRed ERROR } Argument "{yellow ${this.argument}}" is missing in the signature.`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.MissingSignatureArgument = MissingSignatureArgument;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { BobError } from "./BobError";
|
|
2
|
+
import { ArgSignature } from "../CommandParser";
|
|
3
|
+
export declare class MissingSignatureOption extends BobError {
|
|
4
|
+
private option;
|
|
5
|
+
private optionsSignature;
|
|
6
|
+
constructor(option: string, optionsSignature: ArgSignature[]);
|
|
7
|
+
pretty(): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MissingSignatureOption = void 0;
|
|
7
|
+
const BobError_1 = require("./BobError");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
class MissingSignatureOption extends BobError_1.BobError {
|
|
10
|
+
option;
|
|
11
|
+
optionsSignature;
|
|
12
|
+
constructor(option, optionsSignature) {
|
|
13
|
+
super(`Missing ${option} in the command signature`);
|
|
14
|
+
this.option = option;
|
|
15
|
+
this.optionsSignature = optionsSignature;
|
|
16
|
+
}
|
|
17
|
+
pretty() {
|
|
18
|
+
const log = console.log;
|
|
19
|
+
if (this.optionsSignature.length) {
|
|
20
|
+
log((0, chalk_1.default) `{yellow Available options}:`);
|
|
21
|
+
for (const option of this.optionsSignature) {
|
|
22
|
+
const type = option.type ? (0, chalk_1.default) `{white (${option.type})}` : '';
|
|
23
|
+
const spaces = ' '.repeat(20 - option.name.length);
|
|
24
|
+
log((0, chalk_1.default) ` {green ${option.name}} ${spaces} ${option.help ?? '\b'} ${type}`);
|
|
25
|
+
}
|
|
26
|
+
log('');
|
|
27
|
+
}
|
|
28
|
+
log((0, chalk_1.default) ` {white.bgRed ERROR } Option "{yellow ${this.option}}" is missing in the signature.`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.MissingSignatureOption = MissingSignatureOption;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bob-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"description": "BOB Core",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -8,18 +8,22 @@
|
|
|
8
8
|
"/dist"
|
|
9
9
|
],
|
|
10
10
|
"scripts": {
|
|
11
|
-
"start": "node -r @swc-node/register
|
|
11
|
+
"start": "node -r @swc-node/register debug/main.ts",
|
|
12
12
|
"build": "tsc",
|
|
13
|
-
"prepare": "npm run build"
|
|
13
|
+
"prepare": "npm run build",
|
|
14
|
+
"test": "jest"
|
|
14
15
|
},
|
|
15
16
|
"author": "Léo Hubert",
|
|
16
17
|
"license": "ISC",
|
|
17
18
|
"devDependencies": {
|
|
18
19
|
"@swc-node/register": "^1.9.2",
|
|
20
|
+
"@types/jest": "^29.5.12",
|
|
19
21
|
"@types/lodash": "^4.17.5",
|
|
20
22
|
"@types/minimist": "^1.2.5",
|
|
21
23
|
"@types/node": "^20.14.5",
|
|
22
24
|
"@types/string-similarity": "^4.0.2",
|
|
25
|
+
"jest": "^29.7.0",
|
|
26
|
+
"ts-jest": "^29.1.5",
|
|
23
27
|
"typescript": "^5.4.5"
|
|
24
28
|
},
|
|
25
29
|
"dependencies": {
|