bob-core 2.0.0-beta.8 → 2.0.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 +338 -173
- package/dist/cjs/package-Blqq-jZJ.cjs +1 -0
- package/dist/cjs/src/Cli.d.ts +10 -11
- package/dist/cjs/src/Command.d.ts +13 -18
- package/dist/cjs/src/CommandIO.d.ts +5 -2
- package/dist/cjs/src/CommandParser.d.ts +13 -5
- package/dist/cjs/src/CommandRegistry.d.ts +13 -6
- package/dist/cjs/src/CommandSignatureParser.d.ts +5 -4
- package/dist/cjs/src/CommandWithSignature.d.ts +3 -3
- package/dist/cjs/src/ExceptionHandler.d.ts +1 -1
- package/dist/cjs/src/Logger.d.ts +1 -1
- package/dist/cjs/src/StringSimilarity.d.ts +26 -0
- package/dist/cjs/src/commands/HelpCommand.d.ts +1 -1
- package/dist/cjs/src/contracts/CommandOption.d.ts +3 -3
- package/dist/cjs/src/errors/BadCommandOption.d.ts +2 -1
- package/dist/cjs/src/errors/BadCommandParameter.d.ts +2 -1
- package/dist/cjs/src/errors/CommandNotFoundError.d.ts +2 -1
- package/dist/cjs/src/errors/InvalidOption.d.ts +2 -1
- package/dist/cjs/src/errors/MissingRequiredArgumentValue.d.ts +2 -1
- package/dist/cjs/src/errors/MissingRequiredOptionValue.d.ts +2 -1
- package/dist/cjs/src/index.d.ts +1 -0
- package/dist/cjs/src/index.js +17 -0
- package/dist/cjs/src/lib/types.d.ts +4 -2
- package/dist/cjs/src/options/HelpOption.d.ts +1 -1
- package/dist/esm/package-DbMvpGfM.js +33 -0
- package/dist/esm/src/Cli.d.ts +10 -11
- package/dist/esm/src/Command.d.ts +13 -18
- package/dist/esm/src/CommandIO.d.ts +5 -2
- package/dist/esm/src/CommandParser.d.ts +13 -5
- package/dist/esm/src/CommandRegistry.d.ts +13 -6
- package/dist/esm/src/CommandSignatureParser.d.ts +5 -4
- package/dist/esm/src/CommandWithSignature.d.ts +3 -3
- package/dist/esm/src/ExceptionHandler.d.ts +1 -1
- package/dist/esm/src/Logger.d.ts +1 -1
- package/dist/esm/src/StringSimilarity.d.ts +26 -0
- package/dist/esm/src/commands/HelpCommand.d.ts +1 -1
- package/dist/esm/src/contracts/CommandOption.d.ts +3 -3
- package/dist/esm/src/errors/BadCommandOption.d.ts +2 -1
- package/dist/esm/src/errors/BadCommandParameter.d.ts +2 -1
- package/dist/esm/src/errors/CommandNotFoundError.d.ts +2 -1
- package/dist/esm/src/errors/InvalidOption.d.ts +2 -1
- package/dist/esm/src/errors/MissingRequiredArgumentValue.d.ts +2 -1
- package/dist/esm/src/errors/MissingRequiredOptionValue.d.ts +2 -1
- package/dist/esm/src/index.d.ts +1 -0
- package/dist/esm/src/index.js +1029 -0
- package/dist/esm/src/lib/types.d.ts +4 -2
- package/dist/esm/src/options/HelpOption.d.ts +1 -1
- package/package.json +27 -20
- package/dist/cjs/index.d.ts +0 -2
- package/dist/cjs/index.js +0 -9
- package/dist/cjs/package-BaL-l6OV.cjs +0 -1
- package/dist/cjs/src/testFixtures.d.ts +0 -11
- package/dist/esm/index.d.ts +0 -2
- package/dist/esm/index.js +0 -971
- package/dist/esm/package-ODN3iB6L.js +0 -31
- package/dist/esm/src/testFixtures.d.ts +0 -11
package/README.md
CHANGED
|
@@ -1,275 +1,440 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
```
|
|
4
|
+
____ ____ ____
|
|
5
|
+
| __ ) / __ \| __ )
|
|
6
|
+
| _ \| | | | _ \
|
|
7
|
+
| |_) | | | | |_) |
|
|
8
|
+
|____/ \____/|____/
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
# BOB Core
|
|
12
|
+
|
|
13
|
+
**Your Bash Operation Buddy** 💪
|
|
14
|
+
|
|
15
|
+
*Build powerful TypeScript CLIs with type-safe commands and beautiful interactive prompts*
|
|
16
|
+
|
|
17
|
+
[](https://www.npmjs.com/package/bob-core)
|
|
18
|
+
[](https://opensource.org/licenses/ISC)
|
|
19
|
+
[](https://www.typescriptlang.org/)
|
|
4
20
|
|
|
5
|
-
|
|
21
|
+
[Features](#features) • [Installation](#installation) • [Quick Start](#quick-start) • [Documentation](#documentation) • [Examples](#examples)
|
|
6
22
|
|
|
7
|
-
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
✨ **Type-Safe Commands** - Full TypeScript support with type inference for arguments and options
|
|
30
|
+
🎯 **Declarative API** - Define commands with simple schemas or string signatures
|
|
31
|
+
💬 **Interactive Prompts** - Built-in support for confirmations, selections, inputs, and more
|
|
32
|
+
🎨 **Beautiful Help** - Automatically generated, well-formatted help documentation
|
|
33
|
+
🔍 **Smart Suggestions** - Fuzzy matching suggests similar commands when you make typos
|
|
34
|
+
📦 **Zero Config** - Works out of the box with sensible defaults
|
|
35
|
+
🚀 **Dual Module Support** - Both CommonJS and ESM supported
|
|
36
|
+
⚡️ **Fast & Lightweight** - Minimal dependencies, maximum performance
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
8
41
|
|
|
9
42
|
```bash
|
|
10
43
|
npm install bob-core
|
|
11
44
|
```
|
|
12
45
|
|
|
13
|
-
|
|
46
|
+
```bash
|
|
47
|
+
yarn add bob-core
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pnpm add bob-core
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Quick Start
|
|
57
|
+
|
|
58
|
+
### Create your CLI
|
|
14
59
|
|
|
15
60
|
```typescript
|
|
16
|
-
|
|
61
|
+
// cli.ts
|
|
62
|
+
import { Cli } from 'bob-core';
|
|
17
63
|
|
|
18
|
-
const cli = new
|
|
64
|
+
const cli = new Cli({
|
|
65
|
+
name: 'my-cli',
|
|
66
|
+
version: '1.0.0'
|
|
67
|
+
});
|
|
19
68
|
|
|
20
69
|
await cli.withCommands('./commands');
|
|
21
70
|
|
|
22
|
-
cli.
|
|
71
|
+
const exitCode = await cli.runCommand(process.argv[2], ...process.argv.slice(3));
|
|
72
|
+
process.exit(exitCode);
|
|
23
73
|
```
|
|
24
74
|
|
|
25
|
-
Create a
|
|
75
|
+
### Create a Command
|
|
26
76
|
|
|
27
|
-
|
|
28
|
-
import { LegacyCommand } from 'bob-core';
|
|
29
|
-
|
|
30
|
-
export default class MyCommand extends LegacyCommand {
|
|
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
|
-
}
|
|
77
|
+
**Modern Schema-Based (Recommended):**
|
|
43
78
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
79
|
+
```typescript
|
|
80
|
+
// commands/greet.ts
|
|
81
|
+
import { Command } from 'bob-core';
|
|
82
|
+
|
|
83
|
+
export default new Command('greet', {
|
|
84
|
+
description: 'Greet a user',
|
|
85
|
+
arguments: {
|
|
86
|
+
name: 'string'
|
|
87
|
+
},
|
|
88
|
+
options: {
|
|
89
|
+
enthusiastic: {
|
|
90
|
+
type: 'boolean',
|
|
91
|
+
alias: ['e'],
|
|
92
|
+
default: false,
|
|
93
|
+
description: 'Add enthusiasm!'
|
|
94
|
+
}
|
|
60
95
|
}
|
|
61
|
-
}
|
|
96
|
+
}).handler((ctx, { arguments: args, options }) => {
|
|
97
|
+
const greeting = `Hello, ${args.name}${options.enthusiastic ? '!' : '.'}`;
|
|
98
|
+
console.log(greeting);
|
|
99
|
+
});
|
|
62
100
|
```
|
|
63
101
|
|
|
64
|
-
|
|
102
|
+
**Modern Class-Based:**
|
|
65
103
|
|
|
66
|
-
|
|
104
|
+
```typescript
|
|
105
|
+
// commands/greet.ts
|
|
106
|
+
import { Command, CommandHandlerOptions, OptionsSchema } from 'bob-core';
|
|
107
|
+
|
|
108
|
+
const GreetOptions = {
|
|
109
|
+
enthusiastic: {
|
|
110
|
+
type: 'boolean',
|
|
111
|
+
alias: ['e'],
|
|
112
|
+
default: false,
|
|
113
|
+
description: 'Add enthusiasm!'
|
|
114
|
+
}
|
|
115
|
+
} satisfies OptionsSchema;
|
|
116
|
+
type GreetOptions = typeof GreetOptions;
|
|
117
|
+
|
|
118
|
+
const GreetArguments = {
|
|
119
|
+
name: 'string'
|
|
120
|
+
} satisfies OptionsSchema;
|
|
121
|
+
type GreetArguments = typeof GreetArguments;
|
|
122
|
+
|
|
123
|
+
export default class GreetCommand extends Command<any, GreetOptions, GreetArguments> {
|
|
124
|
+
constructor() {
|
|
125
|
+
super('greet', {
|
|
126
|
+
description: 'Greet a user',
|
|
127
|
+
options: GreetOptions,
|
|
128
|
+
arguments: GreetArguments
|
|
129
|
+
});
|
|
130
|
+
}
|
|
67
131
|
|
|
68
|
-
|
|
69
|
-
|
|
132
|
+
handle(ctx: any, opts: CommandHandlerOptions<GreetOptions, GreetArguments>) {
|
|
133
|
+
const greeting = `Hello, ${opts.arguments.name}${opts.options.enthusiastic ? '!' : '.'}`;
|
|
134
|
+
console.log(greeting);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
70
137
|
```
|
|
71
138
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
```bash
|
|
75
|
-
Bob CLI x.x.x 💪
|
|
139
|
+
**Signature-Based:**
|
|
76
140
|
|
|
77
|
-
|
|
78
|
-
|
|
141
|
+
```typescript
|
|
142
|
+
// commands/greet.ts
|
|
143
|
+
import { CommandWithSignature } from 'bob-core';
|
|
79
144
|
|
|
80
|
-
|
|
145
|
+
export default class GreetCommand extends CommandWithSignature {
|
|
146
|
+
signature = 'greet {name} {--enthusiastic|-e}';
|
|
147
|
+
description = 'Greet a user';
|
|
81
148
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
sub sub command description
|
|
86
|
-
sub:sub sub:sub command description
|
|
149
|
+
protected async handle() {
|
|
150
|
+
const name = this.argument<string>('name');
|
|
151
|
+
const enthusiastic = this.option<boolean>('enthusiastic');
|
|
87
152
|
|
|
153
|
+
const greeting = `Hello, ${name}${enthusiastic ? '!' : '.'}`;
|
|
154
|
+
console.log(greeting);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
88
157
|
```
|
|
89
158
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
You can also display the help of a specific command.
|
|
159
|
+
### Run It
|
|
93
160
|
|
|
94
161
|
```bash
|
|
95
|
-
node cli.js
|
|
96
|
-
|
|
162
|
+
$ node cli.js greet John
|
|
163
|
+
Hello, John.
|
|
97
164
|
|
|
98
|
-
|
|
165
|
+
$ node cli.js greet Jane --enthusiastic
|
|
166
|
+
Hello, Jane!
|
|
167
|
+
|
|
168
|
+
$ node cli.js help greet
|
|
99
169
|
Description:
|
|
100
|
-
|
|
170
|
+
Greet a user
|
|
101
171
|
|
|
102
172
|
Usage:
|
|
103
|
-
|
|
173
|
+
greet <name> [options]
|
|
104
174
|
|
|
105
175
|
Arguments:
|
|
106
|
-
|
|
107
|
-
test test description [default: null]
|
|
108
|
-
test2 [default: []] (variadic)
|
|
176
|
+
name (string)
|
|
109
177
|
|
|
110
178
|
Options:
|
|
111
|
-
--
|
|
112
|
-
--
|
|
113
|
-
|
|
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)
|
|
179
|
+
--enthusiastic, -e Add enthusiasm! (boolean) [default: false]
|
|
180
|
+
--help, -h Display help for the given command
|
|
181
|
+
```
|
|
116
182
|
|
|
117
|
-
|
|
118
|
-
Example description 1
|
|
183
|
+
---
|
|
119
184
|
|
|
120
|
-
|
|
185
|
+
## Interactive Prompts
|
|
121
186
|
|
|
122
|
-
|
|
187
|
+
Build beautiful interactive CLIs with built-in prompts:
|
|
123
188
|
|
|
124
|
-
|
|
125
|
-
|
|
189
|
+
```typescript
|
|
190
|
+
import { Command, CommandHandlerOptions, OptionsSchema } from 'bob-core';
|
|
191
|
+
|
|
192
|
+
export default class SetupCommand extends Command<any, OptionsSchema, OptionsSchema> {
|
|
193
|
+
constructor() {
|
|
194
|
+
super('setup', {
|
|
195
|
+
description: 'Interactive project setup'
|
|
196
|
+
});
|
|
197
|
+
}
|
|
126
198
|
|
|
127
|
-
|
|
199
|
+
async handle(ctx: any, opts: CommandHandlerOptions<OptionsSchema, OptionsSchema>) {
|
|
200
|
+
// Text input
|
|
201
|
+
const name = await this.io.askForInput('Project name:');
|
|
202
|
+
|
|
203
|
+
// Confirmation
|
|
204
|
+
const useTypeScript = await this.io.askForConfirmation('Use TypeScript?', true);
|
|
205
|
+
|
|
206
|
+
// Selection
|
|
207
|
+
const framework = await this.io.askForSelect('Framework:', [
|
|
208
|
+
{ title: 'React', value: 'react' },
|
|
209
|
+
{ title: 'Vue', value: 'vue' },
|
|
210
|
+
{ title: 'Svelte', value: 'svelte' }
|
|
211
|
+
]);
|
|
212
|
+
|
|
213
|
+
// Multi-select
|
|
214
|
+
const features = await this.io.askForSelect(
|
|
215
|
+
'Features:',
|
|
216
|
+
['ESLint', 'Prettier', 'Testing'],
|
|
217
|
+
{ type: 'multiselect' }
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
// Spinner/loader
|
|
221
|
+
using loader = this.io.newLoader('Creating project...');
|
|
222
|
+
await createProject({ name, framework, features });
|
|
223
|
+
loader.stop();
|
|
224
|
+
|
|
225
|
+
this.io.info('✅ Project created!');
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
```
|
|
128
229
|
|
|
230
|
+
---
|
|
129
231
|
|
|
130
|
-
##
|
|
232
|
+
## Context Injection
|
|
131
233
|
|
|
132
|
-
|
|
234
|
+
Pass shared dependencies and configuration to your commands:
|
|
133
235
|
|
|
134
|
-
Example:
|
|
135
236
|
```typescript
|
|
136
|
-
|
|
137
|
-
|
|
237
|
+
interface AppContext {
|
|
238
|
+
config: Config;
|
|
239
|
+
database: Database;
|
|
240
|
+
logger: Logger;
|
|
241
|
+
}
|
|
138
242
|
|
|
139
|
-
|
|
243
|
+
const context: AppContext = {
|
|
244
|
+
config: loadConfig(),
|
|
245
|
+
database: new Database(),
|
|
246
|
+
logger: new Logger()
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
const cli = new Cli<AppContext>({
|
|
250
|
+
ctx: context,
|
|
251
|
+
name: 'my-app',
|
|
252
|
+
version: '1.0.0'
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// Access context in commands
|
|
256
|
+
export default new Command<AppContext>('users:list', {
|
|
257
|
+
description: 'List users'
|
|
258
|
+
}).handler(async (ctx) => {
|
|
259
|
+
const users = await ctx.database.getUsers();
|
|
260
|
+
users.forEach(user => console.log(user.name));
|
|
261
|
+
});
|
|
262
|
+
```
|
|
140
263
|
|
|
141
|
-
|
|
142
|
-
In the following example, the command defines three **required** arguments `arg1`, `arg2` and `arg3`.
|
|
264
|
+
---
|
|
143
265
|
|
|
144
|
-
|
|
145
|
-
signature = 'my-command {arg1} {arg2} {arg3}';
|
|
146
|
-
```
|
|
266
|
+
## Documentation
|
|
147
267
|
|
|
148
|
-
|
|
268
|
+
📚 **[Getting Started](./docs/getting-started.md)** - Installation and first CLI
|
|
269
|
+
🔨 **[Creating Commands](./docs/creating-commands.md)** - Schema-based and signature-based approaches
|
|
270
|
+
⚙️ **[Arguments & Options](./docs/arguments-and-options.md)** - Type-safe parameters
|
|
271
|
+
💬 **[Interactive Prompts](./docs/interactive-prompts.md)** - Build interactive CLIs
|
|
272
|
+
🚀 **[Advanced Topics](./docs/advanced.md)** - Context, resolvers, error handling
|
|
273
|
+
❓ **[Help System](./docs/help-system.md)** - Customize help output
|
|
274
|
+
📖 **[API Reference](./docs/api-reference.md)** - Complete API documentation
|
|
275
|
+
💡 **[Examples](./docs/examples.md)** - Real-world examples
|
|
149
276
|
|
|
150
|
-
|
|
151
|
-
signature = 'my-command {arg1} {arg2?} {arg3=defaultValue}';
|
|
277
|
+
---
|
|
152
278
|
|
|
153
|
-
|
|
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
|
-
```
|
|
279
|
+
## Examples
|
|
159
280
|
|
|
160
|
-
|
|
161
|
-
Variadic arguments are stored in an array.
|
|
281
|
+
### Type-Safe Arguments
|
|
162
282
|
|
|
163
283
|
```typescript
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
284
|
+
export default new Command('deploy', {
|
|
285
|
+
arguments: {
|
|
286
|
+
environment: 'string', // Required
|
|
287
|
+
region: { // Optional with default
|
|
288
|
+
type: 'string',
|
|
289
|
+
default: 'us-east-1',
|
|
290
|
+
required: false
|
|
169
291
|
}
|
|
292
|
+
}
|
|
293
|
+
}).handler((ctx, { arguments: args }) => {
|
|
294
|
+
// args.environment is string
|
|
295
|
+
// args.region is string | null
|
|
296
|
+
});
|
|
170
297
|
```
|
|
171
298
|
|
|
172
|
-
Variadic
|
|
299
|
+
### Variadic Arguments
|
|
173
300
|
|
|
174
301
|
```typescript
|
|
175
|
-
|
|
302
|
+
export default new Command('delete', {
|
|
303
|
+
arguments: {
|
|
304
|
+
files: ['string'] // Array of strings
|
|
305
|
+
}
|
|
306
|
+
}).handler((ctx, { arguments: args }) => {
|
|
307
|
+
// args.files is string[]
|
|
308
|
+
args.files.forEach(file => deleteFile(file));
|
|
309
|
+
});
|
|
176
310
|
```
|
|
177
311
|
|
|
178
|
-
### Options
|
|
179
|
-
|
|
180
|
-
Options are defined by `{--optionName}`.
|
|
312
|
+
### Options with Aliases
|
|
181
313
|
|
|
182
314
|
```typescript
|
|
183
|
-
|
|
184
|
-
|
|
315
|
+
export default new Command('serve', {
|
|
316
|
+
options: {
|
|
317
|
+
port: {
|
|
318
|
+
type: 'number',
|
|
319
|
+
alias: ['p'],
|
|
320
|
+
default: 3000
|
|
321
|
+
},
|
|
322
|
+
verbose: {
|
|
323
|
+
type: 'boolean',
|
|
324
|
+
alias: ['v', 'V'],
|
|
325
|
+
default: false
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
});
|
|
185
329
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
330
|
+
// Usage: serve --port=8080 -v
|
|
331
|
+
// Usage: serve -p 8080 --verbose
|
|
332
|
+
```
|
|
189
333
|
|
|
190
|
-
|
|
334
|
+
### Pre-Handlers for Validation
|
|
191
335
|
|
|
192
336
|
```typescript
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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
|
|
337
|
+
export default new Command('deploy')
|
|
338
|
+
.preHandler(async (ctx) => {
|
|
339
|
+
if (!ctx.isAuthenticated) {
|
|
340
|
+
console.error('Not authenticated');
|
|
341
|
+
return 1; // Stop execution
|
|
200
342
|
}
|
|
343
|
+
})
|
|
344
|
+
.handler(async (ctx) => {
|
|
345
|
+
// Only runs if authenticated
|
|
346
|
+
});
|
|
201
347
|
```
|
|
202
348
|
|
|
203
|
-
|
|
204
|
-
Variadic options are stored in an array.
|
|
349
|
+
### Command Groups
|
|
205
350
|
|
|
206
351
|
```typescript
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
352
|
+
// commands/db/migrate.ts
|
|
353
|
+
export default new Command('db:migrate', {
|
|
354
|
+
description: 'Run migrations',
|
|
355
|
+
group: 'Database'
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
// commands/db/seed.ts
|
|
359
|
+
export default new Command('db:seed', {
|
|
360
|
+
description: 'Seed database',
|
|
361
|
+
group: 'Database'
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
// Displayed as:
|
|
365
|
+
// Database:
|
|
366
|
+
// db:migrate Run migrations
|
|
367
|
+
// db:seed Seed database
|
|
213
368
|
```
|
|
214
369
|
|
|
215
|
-
|
|
370
|
+
---
|
|
216
371
|
|
|
217
|
-
|
|
372
|
+
## Why BOB Core?
|
|
218
373
|
|
|
219
|
-
|
|
220
|
-
this.argument('arg1');
|
|
221
|
-
```
|
|
374
|
+
BOB Core makes CLI development in TypeScript a breeze:
|
|
222
375
|
|
|
223
|
-
|
|
376
|
+
- **No Boilerplate** - Define commands declaratively, not imperatively
|
|
377
|
+
- **Type Safety** - Catch errors at compile time, not runtime
|
|
378
|
+
- **Great DX** - Intelligent auto-complete, clear error messages
|
|
379
|
+
- **User Friendly** - Beautiful help, smart suggestions, interactive prompts
|
|
380
|
+
- **Flexible** - Multiple command styles, extend anything
|
|
381
|
+
- **Well Tested** - Comprehensive test suite with Vitest
|
|
224
382
|
|
|
225
|
-
|
|
226
|
-
this.argument('arg1', 'defaultValue');
|
|
227
|
-
```
|
|
383
|
+
---
|
|
228
384
|
|
|
229
|
-
|
|
385
|
+
## Supported Types
|
|
230
386
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
387
|
+
| Type | Description | Example |
|
|
388
|
+
|------|-------------|---------|
|
|
389
|
+
| `'string'` | Text value | `'hello'` |
|
|
390
|
+
| `'number'` | Numeric value | `42` |
|
|
391
|
+
| `'boolean'` | True/false | `true` |
|
|
392
|
+
| `['string']` | String array | `['a', 'b']` |
|
|
393
|
+
| `['number']` | Number array | `[1, 2, 3]` |
|
|
234
394
|
|
|
235
|
-
|
|
395
|
+
**Note:** The `secret` flag is not a type but a property of OptionDefinition.
|
|
236
396
|
|
|
237
|
-
|
|
238
|
-
this.argumentNumber('arg1');
|
|
239
|
-
```
|
|
397
|
+
### Secret/Masked Input
|
|
240
398
|
|
|
241
|
-
|
|
399
|
+
For sensitive input like passwords, use the `secret: true` flag in the option definition:
|
|
242
400
|
|
|
243
401
|
```typescript
|
|
244
|
-
|
|
402
|
+
options: {
|
|
403
|
+
password: {
|
|
404
|
+
type: 'string', // Type is still 'string'
|
|
405
|
+
secret: true, // Flag to mask input in interactive prompts
|
|
406
|
+
required: true,
|
|
407
|
+
description: 'User password'
|
|
408
|
+
}
|
|
409
|
+
}
|
|
245
410
|
```
|
|
246
411
|
|
|
247
|
-
|
|
412
|
+
The `secret` flag masks the input when prompting interactively, making it perfect for passwords and API keys.
|
|
248
413
|
|
|
249
|
-
|
|
250
|
-
this.option('option1');
|
|
251
|
-
```
|
|
414
|
+
---
|
|
252
415
|
|
|
253
|
-
|
|
416
|
+
## Contributing
|
|
254
417
|
|
|
255
|
-
|
|
256
|
-
this.option('option1', 'defaultValue');
|
|
257
|
-
```
|
|
418
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
258
419
|
|
|
259
|
-
|
|
420
|
+
1. Fork the repository
|
|
421
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
422
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
423
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
424
|
+
5. Open a Pull Request
|
|
260
425
|
|
|
261
|
-
|
|
262
|
-
this.optionBoolean('option1');
|
|
263
|
-
```
|
|
426
|
+
---
|
|
264
427
|
|
|
265
|
-
|
|
428
|
+
## License
|
|
266
429
|
|
|
267
|
-
|
|
268
|
-
this.optionNumber('option1');
|
|
269
|
-
```
|
|
430
|
+
[ISC](LICENSE) © Léo Hubert
|
|
270
431
|
|
|
271
|
-
|
|
432
|
+
---
|
|
272
433
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
434
|
+
<div align="center">
|
|
435
|
+
|
|
436
|
+
**[⬆ back to top](#bob-core)**
|
|
437
|
+
|
|
438
|
+
Made with ❤️ by developers, for developers
|
|
439
|
+
|
|
440
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e="bob-core",t="2.0.0",s="BOB Core",i="module",n="./dist/cjs/src/index.js",r="./dist/esm/src/index.js",c="./dist/esm/src/index.d.ts",o=["dist"],d={".":{import:{types:"./dist/esm/src/index.d.ts",default:"./dist/esm/src/index.js"},require:{types:"./dist/cjs/src/index.d.ts",default:"./dist/cjs/src/index.js"}}},p={start:"node -r @swc-node/register debug/main.ts",build:"rimraf ./dist && vite build",typecheck:"tsc --noEmit",prepack:"npm run build",test:"vitest run",lint:"eslint .","lint:fix":"eslint . --fix"},l="Léo Hubert",m="ISC",a={"@eslint/js":"^9.37.0","@faker-js/faker":"^10.0.0","@swc-node/register":"^1.11.1","@trivago/prettier-plugin-sort-imports":"^5.2.2","@types/minimist":"^1.2.5","@types/node":"^20.14.5","@types/prompts":"^2.4.9","@types/string-similarity":"^4.0.2","@vitest/coverage-v8":"^3.2.4",eslint:"^9.37.0","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.4",prettier:"^3.6.2",rimraf:"^6.0.1",tsx:"^4.20.6",typescript:"^5.9.3","typescript-eslint":"^8.46.0",vite:"^7.2.7","vite-plugin-dts":"^4.5.4",vitest:"^3.2.4"},u={chalk:"^4.1.2",minimist:"^1.2.8",prompts:"^2.4.2"},y={name:e,version:t,description:s,type:i,main:n,module:r,types:c,files:o,exports:d,scripts:p,author:l,license:m,devDependencies:a,dependencies:u};exports.author=l;exports.default=y;exports.dependencies=u;exports.description=s;exports.devDependencies=a;exports.exports=d;exports.files=o;exports.license=m;exports.main=n;exports.module=r;exports.name=e;exports.scripts=p;exports.type=i;exports.types=c;exports.version=t;
|
package/dist/cjs/src/Cli.d.ts
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
import { CommandRegistry, CommandResolver, FileImporter } from './CommandRegistry.js';
|
|
2
|
-
import { default as HelpCommand, HelpCommandOptions } from './commands/HelpCommand.js';
|
|
3
|
-
import { ExceptionHandler } from './ExceptionHandler.js';
|
|
4
1
|
import { Command } from './Command.js';
|
|
2
|
+
import { CommandRegistry, CommandRegistryOptions, CommandResolver, FileImporter } from './CommandRegistry.js';
|
|
3
|
+
import { ExceptionHandler } from './ExceptionHandler.js';
|
|
5
4
|
import { Logger } from './Logger.js';
|
|
6
|
-
|
|
5
|
+
import { default as HelpCommand, HelpCommandOptions } from './commands/HelpCommand.js';
|
|
6
|
+
import { ContextDefinition, OptionsSchema } from './lib/types.js';
|
|
7
|
+
export type CliOptions<C extends ContextDefinition = ContextDefinition> = {
|
|
7
8
|
ctx?: C;
|
|
8
9
|
name?: string;
|
|
9
10
|
version?: string;
|
|
10
11
|
logger?: Logger;
|
|
11
12
|
};
|
|
12
|
-
export declare class Cli<C =
|
|
13
|
+
export declare class Cli<C extends ContextDefinition = ContextDefinition> {
|
|
13
14
|
private readonly ctx?;
|
|
14
15
|
private readonly logger;
|
|
15
16
|
readonly commandRegistry: CommandRegistry;
|
|
16
17
|
private readonly exceptionHandler;
|
|
17
18
|
private readonly helpCommand;
|
|
18
|
-
protected newCommandRegistry(opts:
|
|
19
|
-
logger: Logger;
|
|
20
|
-
}): CommandRegistry;
|
|
19
|
+
protected newCommandRegistry(opts: CommandRegistryOptions): CommandRegistry;
|
|
21
20
|
protected newHelpCommand(opts: HelpCommandOptions): HelpCommand;
|
|
22
21
|
protected newExceptionHandler(opts: {
|
|
23
22
|
logger: Logger;
|
|
@@ -25,10 +24,10 @@ export declare class Cli<C = any> {
|
|
|
25
24
|
constructor(opts?: CliOptions<C>);
|
|
26
25
|
withCommandResolver(resolver: CommandResolver): this;
|
|
27
26
|
withFileImporter(importer: FileImporter): this;
|
|
28
|
-
withCommands(...commands: Array<Command<C,
|
|
27
|
+
withCommands(...commands: Array<Command<C, OptionsSchema, OptionsSchema> | {
|
|
29
28
|
new (): Command<C>;
|
|
30
29
|
} | string>): Promise<void>;
|
|
31
|
-
runCommand(command: string | Command | undefined, ...args:
|
|
30
|
+
runCommand(command: string | Command | undefined, ...args: string[]): Promise<number>;
|
|
32
31
|
runHelpCommand(): Promise<number>;
|
|
33
|
-
protected registerCommand(command: Command<C>): void;
|
|
32
|
+
protected registerCommand(command: Command<C, OptionsSchema, OptionsSchema>): void;
|
|
34
33
|
}
|