@noravel/command 1.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.
Files changed (82) hide show
  1. package/LICENSE +9 -0
  2. package/README.md +569 -0
  3. package/dist/Command.d.ts +27 -0
  4. package/dist/Command.js +86 -0
  5. package/dist/Contracts/Command.d.ts +10 -0
  6. package/dist/Contracts/Command.js +2 -0
  7. package/dist/Contracts/CommandDefinition.d.ts +7 -0
  8. package/dist/Contracts/CommandDefinition.js +2 -0
  9. package/dist/Contracts/InputArgument.d.ts +12 -0
  10. package/dist/Contracts/InputArgument.js +9 -0
  11. package/dist/Contracts/InputOption.d.ts +15 -0
  12. package/dist/Contracts/InputOption.js +10 -0
  13. package/dist/Detector.d.ts +4 -0
  14. package/dist/Detector.js +73 -0
  15. package/dist/Executor.d.ts +4 -0
  16. package/dist/Executor.js +9 -0
  17. package/dist/Inputs/InputArgument.d.ts +13 -0
  18. package/dist/Inputs/InputArgument.js +39 -0
  19. package/dist/Inputs/InputDefinition.d.ts +11 -0
  20. package/dist/Inputs/InputDefinition.js +25 -0
  21. package/dist/Inputs/InputOption.d.ts +18 -0
  22. package/dist/Inputs/InputOption.js +84 -0
  23. package/dist/Inputs/Prompt.d.ts +5 -0
  24. package/dist/Inputs/Prompt.js +178 -0
  25. package/dist/Kernel.d.ts +15 -0
  26. package/dist/Kernel.js +88 -0
  27. package/dist/MakerCommand.d.ts +27 -0
  28. package/dist/MakerCommand.js +68 -0
  29. package/dist/Outputs/Helper.d.ts +7 -0
  30. package/dist/Outputs/Helper.js +61 -0
  31. package/dist/Outputs/OutputColor.d.ts +18 -0
  32. package/dist/Outputs/OutputColor.js +53 -0
  33. package/dist/Outputs/OutputMessage.d.ts +11 -0
  34. package/dist/Outputs/OutputMessage.js +70 -0
  35. package/dist/Outputs/ProgressBar/ProgressBar.d.ts +22 -0
  36. package/dist/Outputs/ProgressBar/ProgressBar.js +98 -0
  37. package/dist/Outputs/ProgressBar/StatusBar.d.ts +11 -0
  38. package/dist/Outputs/ProgressBar/StatusBar.js +10 -0
  39. package/dist/Outputs/ProgressBar/StatusBarFactory.d.ts +5 -0
  40. package/dist/Outputs/ProgressBar/StatusBarFactory.js +20 -0
  41. package/dist/Outputs/ProgressBar/StatusBarNormal.d.ts +6 -0
  42. package/dist/Outputs/ProgressBar/StatusBarNormal.js +19 -0
  43. package/dist/Outputs/ProgressBar/StatusBarVerbose.d.ts +6 -0
  44. package/dist/Outputs/ProgressBar/StatusBarVerbose.js +20 -0
  45. package/dist/Outputs/ProgressBar.d.ts +22 -0
  46. package/dist/Outputs/ProgressBar.js +123 -0
  47. package/dist/Parser.d.ts +9 -0
  48. package/dist/Parser.js +79 -0
  49. package/dist/index.d.ts +5 -0
  50. package/dist/index.js +14 -0
  51. package/dist/src/Command.d.ts +23 -0
  52. package/dist/src/Command.js +61 -0
  53. package/dist/src/Contracts/Command.d.ts +9 -0
  54. package/dist/src/Contracts/Command.js +2 -0
  55. package/dist/src/Contracts/InputArgument.d.ts +11 -0
  56. package/dist/src/Contracts/InputArgument.js +9 -0
  57. package/dist/src/Contracts/InputOption.d.ts +12 -0
  58. package/dist/src/Contracts/InputOption.js +10 -0
  59. package/dist/src/Detector.d.ts +4 -0
  60. package/dist/src/Detector.js +50 -0
  61. package/dist/src/Inputs/InputArgument.d.ts +12 -0
  62. package/dist/src/Inputs/InputArgument.js +36 -0
  63. package/dist/src/Inputs/InputDefinition.d.ts +11 -0
  64. package/dist/src/Inputs/InputDefinition.js +25 -0
  65. package/dist/src/Inputs/InputOption.d.ts +18 -0
  66. package/dist/src/Inputs/InputOption.js +84 -0
  67. package/dist/src/Kernel.d.ts +15 -0
  68. package/dist/src/Kernel.js +87 -0
  69. package/dist/src/MakerCommand.d.ts +27 -0
  70. package/dist/src/MakerCommand.js +68 -0
  71. package/dist/src/Outputs/Helper.d.ts +7 -0
  72. package/dist/src/Outputs/Helper.js +61 -0
  73. package/dist/src/Outputs/OutputColor.d.ts +18 -0
  74. package/dist/src/Outputs/OutputColor.js +53 -0
  75. package/dist/src/Outputs/OutputMessage.d.ts +11 -0
  76. package/dist/src/Outputs/OutputMessage.js +144 -0
  77. package/dist/src/Parser.d.ts +9 -0
  78. package/dist/src/Parser.js +79 -0
  79. package/dist/src/index.d.ts +4 -0
  80. package/dist/src/index.js +12 -0
  81. package/dist/tsconfig.tsbuildinfo +1 -0
  82. package/package.json +35 -0
package/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024, Trịnh Trần Phương Nam
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,569 @@
1
+ # Noravel Command
2
+
3
+ # Installation
4
+
5
+ ```bash
6
+ npm install @noravel/command
7
+ ```
8
+
9
+ # Content
10
+
11
+ - [Create handler](#create-handler)
12
+ - [Create command](#create-command)
13
+ - [Define input expectations](#define-input-expectations)
14
+ - [Arguments](#arguments)
15
+ - [Options](#options)
16
+ - [Options with values](#options-with-values)
17
+ - [Option shortcuts](#option-shortcuts)
18
+ - [Input arrays](#input-arrays)
19
+ - [Option arrays](#option-arrays)
20
+ - [Input descriptions](#input-descriptions)
21
+ - [Command I/O](#command-io)
22
+ - [Create a maker command](#create-a-maker-command)
23
+ - [Help command](#help-command)
24
+ - [Programmatically executing commands](#programmatically-executing-commands)
25
+
26
+ ## Create handler
27
+
28
+ Create a handler file in your project.
29
+
30
+ ```bash
31
+ touch noravel
32
+ ```
33
+
34
+ Open a `noravel` file and add the following code:
35
+
36
+ ```js
37
+ #!/usr/bin/env node
38
+
39
+ import { Kernel } from '@noravel/command';
40
+
41
+ const kernel = new Kernel(process.argv);
42
+ kernel.run();
43
+ ```
44
+
45
+ ## Create command
46
+
47
+ Create a command file in your project.
48
+
49
+ ```bash
50
+ touch Commands/Greeting.js
51
+ ```
52
+
53
+ Open a `Commands/Greeting.js` file and add the following code:
54
+
55
+ ```js
56
+ import { Command } from '@noravel/command';
57
+
58
+ class Greeting extends Command {
59
+ signature = 'greeting';
60
+ description = 'Sending greetings to someone';
61
+
62
+ async handle() {
63
+ console.log('Hello World');
64
+ }
65
+ }
66
+
67
+ export default Greeting;
68
+ ```
69
+
70
+ Make sure your command class exists the `handle` method. Then you can register your command in the `noravel` file.
71
+
72
+ ```js
73
+ #!/usr/bin/env node
74
+
75
+ import { Kernel } from '@noravel/command';
76
+ import Greeting from './Commands/Greeting.js';
77
+
78
+ const kernel = new Kernel(process.argv);
79
+ kernel.register([
80
+ Greeting,
81
+ ]).run();
82
+ ```
83
+
84
+ Now, you can run your command like this:
85
+
86
+ ```bash
87
+ ./noravel greeting
88
+ ```
89
+
90
+ ## Defining input expectations
91
+
92
+ When writing console commands, it is common to gather input from the user through arguments or options.
93
+ Noravel Command makes it very convenient to define the input you expect from the user using the `signature` property on your commands.
94
+ The signature property allows you to define the name, arguments, and options for the command in a single, expressive.
95
+
96
+ ### Arguments
97
+
98
+ All user supplied arguments and options are wrapped in curly braces. In the following example, the command defines one required argument: `user:`
99
+
100
+ ```js
101
+ signature = 'greeting {user}';
102
+ ```
103
+
104
+ You may also make arguments optional or define default values for arguments:
105
+
106
+ ```js
107
+ // Optional argument
108
+ signature = 'greeting {user?}';
109
+
110
+ // Optional argument with default value
111
+ signature = 'greeting {user=Nam}';
112
+ ```
113
+
114
+ ### Options
115
+
116
+ Options, like arguments, are another form of user input.
117
+ Options are prefixed by two hyphens (`--`) when they are provided via the command line.
118
+ There are two types of options: those that receive a value and those that don't.
119
+ Options that don't receive a value serve as a boolean "switch".
120
+ Let's take a look at an example of this type of option:
121
+
122
+ ```js
123
+ signature = 'greeting {--verbose}';
124
+ ```
125
+
126
+ In this example, the `--verbose` switch may be specified when calling your command.
127
+ If the `--verbose` switch is passed, the value of the option will be `true`. Otherwise, the value will be `false`:
128
+
129
+ ```bash
130
+ ./noravel greeting --verbose
131
+ ```
132
+
133
+ #### Options with values
134
+
135
+ Next, let's take a look at an option that expects a value. If the user must specify a value for an option, you should suffix the option name with a `=` sign:
136
+
137
+ ```js
138
+ signature = 'greeting {--verbose=}';
139
+ ```
140
+
141
+ In this example, the user may pass a value for the option like so. If the option is not specified when invoking the command, its value will be `undefined`:
142
+
143
+ ```bash
144
+ ./noravel greeting --verbose=Default
145
+ ```
146
+
147
+ You may assign default values to options by specifying the default value after the option name. If no option value is passed by the user, the default value will be used:
148
+
149
+ ```js
150
+ signature = 'greeting {--verbose=Default}';
151
+ ```
152
+
153
+ #### Option shortcuts
154
+
155
+ To assign a shortcut when defining an option, you may specify it before the option name and use the `|` character as a delimiter to separate the shortcut from the full option name:
156
+
157
+ ```js
158
+ signature = 'greeting {--v|verbose=}';
159
+ ```
160
+
161
+ When invoking the command on your terminal, option shortcuts should be prefixed with a single hyphen and no `=` character should be included when specifying a value for the option:
162
+
163
+ ```bash
164
+ ./noravel greeting -vDefault
165
+ ```
166
+
167
+ ### Input arrays
168
+
169
+ If you would like to define arguments or options to expect multiple input values, you may use the `*` character.
170
+ First, let's take a look at an example that specifies such an argument:
171
+
172
+ ```js
173
+ signature = 'greeting {user*}';
174
+ ```
175
+
176
+ When running this command, the user arguments may be passed in order to the command line.
177
+ For example, the following command will set the value of user to an array with 1 and 2 as its values:
178
+
179
+ ```bash
180
+ ./noravel greeting user1 user2
181
+ ```
182
+
183
+ This `*` character can be combined with an optional argument definition to allow zero or more instances of an argument:
184
+
185
+ ```js
186
+ signature = 'greeting {user?*}';
187
+ ```
188
+
189
+ ### Option arrays
190
+
191
+ When defining an option that expects multiple input values,
192
+ each option value passed to the command should be prefixed with the option name:
193
+
194
+ ```js
195
+ signature = 'greeting {--tag=*}';
196
+ ```
197
+
198
+ Such a command may be invoked by passing multiple `--tag` arguments:
199
+
200
+ ```bash
201
+ ./noravel greeting --tag=tag1 --tag=tag2
202
+ ```
203
+
204
+ ### Input descriptions
205
+
206
+ You may assign descriptions to input arguments and options by separating the argument name from the description using a colon.
207
+ If you need a little extra room to define your command, feel free to spread the definition across multiple lines:
208
+
209
+ ```js
210
+ signature = `greeting {name : The name of the person to greet}
211
+ {--v|verbose : Increase the verbosity of messages}
212
+ {--tag=* : Tags to apply to the greeting}`;
213
+ ```
214
+
215
+ **Note**: If your command contains required arguments, the user will receive a thrown error when they are not provided.
216
+
217
+ ## Command I/O
218
+
219
+ ### Retrieving Input
220
+
221
+ While your command is executing, you will likely need to access the values for the arguments and options accepted by your command. To do so, you may use the `getArgument` and `getOption` methods. If an argument or option does not exist, `undefined` will be returned:
222
+
223
+ ```js
224
+ async handle() {
225
+ const name = this.getArgument('name');
226
+ const verbose = this.getOption('verbose');
227
+ }
228
+ ```
229
+
230
+ If you need to retrieve all of the arguments as an `array`, call the `getArgument` method without any parameters:
231
+
232
+ ```js
233
+ async handle() {
234
+ const arguments = this.getArgument();
235
+ }
236
+ ```
237
+
238
+ Options may be retrieved just as easily as arguments using the option method. To retrieve all of the options as an array, call the `getOption` method without any parameters:
239
+
240
+ ```js
241
+ async handle() {
242
+ const options = this.getOption();
243
+ }
244
+ ```
245
+
246
+ ### Prompting for input
247
+
248
+ In addition to displaying output, you may also ask the user to provide input during the execution of your command. The `ask` method will prompt the user with the given question, accept their input, and then return the user's input back to your command:
249
+
250
+ ```js
251
+ async handle() {
252
+ const name = this.prompt.ask('What is your name?');
253
+ }
254
+ ```
255
+
256
+ The `secret` method is similar to `ask`, but the user's input will not be visible to them as they type in the console. This method is useful when asking for sensitive information such as passwords:
257
+
258
+ ```js
259
+ async handle() {
260
+ const password = this.prompt.secret('What is your password?');
261
+ }
262
+ ```
263
+
264
+ **Multiple choice questions**
265
+
266
+ If you need to give the user a predefined set of choices when asking a question, you may use the choice method.
267
+ You may set the array index of the default value to be returned if no option is chosen by passing the index as the third argument to the method:
268
+
269
+ ```js
270
+ async handle() {
271
+ const choice = this.prompt.choice('What is your favorite color?', ['red', 'green', 'blue'], defaultIndex);
272
+ }
273
+ ```
274
+
275
+ In addition, the `choice` method accepts optional fourth argument for determining whether multiple selections are permitted:
276
+
277
+ ```js
278
+ const choices = this.prompt.choice('What is your favorite color?', ['red', 'green', 'blue'], defaultIndex, true);
279
+ ```
280
+
281
+ ### Writing Output
282
+
283
+ To send output to the console, you may use the `line`, `info`, `comment`, `success`, `warning`, and `error` methods. Each of these methods will use appropriate ANSI colors for their purpose. For example, let's display some general information to the user.
284
+
285
+ ```js
286
+ async handle() {
287
+ this.output.info('This is an info message');
288
+ this.output.success('This is a success message');
289
+ this.output.warning('This is a warning message');
290
+ this.output.error('This is an error message');
291
+ this.output.comment('This is a comment message');
292
+ }
293
+ ```
294
+
295
+ **Table**
296
+
297
+ The `table` method makes it easy to correctly format multiple rows / columns of data. All you need to do is provide the column names and the data for the table and Noravel Command will automatically calculate the appropriate width and height of the table for you:
298
+
299
+ ```js
300
+ async handle() {
301
+ this.output.table(
302
+ ['id', 'name', 'email', 'date of birth'],
303
+ [
304
+ [1, 'John Doe', 'johndoe@example.com', '2000-01-01'],
305
+ [2, 'Jane Doe', 'janedoe@example.com', '1999-01-01'],
306
+ [3, 'James Doe', 'jamesdoe@example.com', '2010-01-01'],
307
+ [4, 'John Smith', 'johnsmith@example.com', '2000-11-01'],
308
+ [5, 'Jane Smith', 'janesmith@example.com', '2000-01-21'],
309
+ [6, 'James Smith', 'jamessmith@example.com', '2001-01-01'],
310
+ ]
311
+ );
312
+ }
313
+ ```
314
+
315
+ #### Progress Bars
316
+
317
+ For long running tasks, it can be helpful to show a progress bar that informs users how complete the task is.
318
+ First, define the total number of steps the process will iterate through.
319
+ Then, advance the progress bar after processing each item.
320
+
321
+ ```js
322
+ async handle() {
323
+ const bar = this.output.createProgressBar(100);
324
+ bar.start();
325
+ for (let i = 0; i < units; i++) {
326
+ // Do some work...
327
+ bar.advance();
328
+ }
329
+ bar.finish();
330
+ }
331
+ ```
332
+
333
+ **Progress Bar Methods**
334
+
335
+ The progress bar provides several methods to control its behavior:
336
+
337
+ ```js
338
+ async handle() {
339
+ const bar = this.output.createProgressBar(100);
340
+
341
+ // Start the progress bar with an optional message
342
+ bar.start('Processing items...');
343
+
344
+ // Advance the progress by one step
345
+ bar.advance();
346
+
347
+ // Set a different total after creation
348
+ bar.setTotal(150);
349
+
350
+ // Get the current total
351
+ const total = bar.getTotal();
352
+
353
+ // Set the progress bar size (in characters)
354
+ bar.setSize(50);
355
+
356
+ // Get the current size
357
+ const size = bar.getSize();
358
+
359
+ // Finish the progress bar with an optional message
360
+ bar.finish('Processing completed!');
361
+ }
362
+ ```
363
+
364
+ **Progress Bar Formats**
365
+
366
+ The progress bar supports three different display formats:
367
+
368
+ ```js
369
+ async handle() {
370
+ const bar = this.output.createProgressBar(100);
371
+
372
+ // Normal format (default): [=====> ] 50.0% 50/100
373
+ bar.setFormat('normal');
374
+
375
+ // Verbose format: [=====>] 50.0% 50/100 remaining: 25.0s. elapsed: 12.5s.
376
+ bar.setFormat('verbose');
377
+
378
+ // Minimal format: Progress: 50.0%
379
+ bar.setFormat('minimal');
380
+
381
+ bar.start();
382
+ for (let i = 0; i < 100; i++) {
383
+ bar.advance();
384
+ }
385
+ bar.finish();
386
+ }
387
+ ```
388
+
389
+ **Progress Bar Styles**
390
+
391
+ You can choose between different progress bar styles:
392
+
393
+ ```js
394
+ async handle() {
395
+ const bar = this.output.createProgressBar(100);
396
+
397
+ // Arrow style (default): [=====>-----]
398
+ bar.useArrowProgress();
399
+
400
+ // Shape style: [#####_____]
401
+ bar.useShapeProgress();
402
+
403
+ // Block style: [█████░░░░░]
404
+ bar.useBlockProgress();
405
+
406
+ bar.start();
407
+ for (let i = 0; i < 100; i++) {
408
+ bar.advance();
409
+ }
410
+ bar.finish();
411
+ }
412
+ ```
413
+
414
+ **Constructor Options**
415
+
416
+ When creating a progress bar, you can specify custom options:
417
+
418
+ ```js
419
+ async handle() {
420
+ // Create progress bar with custom size (in characters)
421
+ const bar = this.output.createProgressBar(100, 80);
422
+
423
+ // Create progress bar that uses full terminal width
424
+ const fullBar = this.output.createProgressBar(100, null);
425
+
426
+ bar.start();
427
+ for (let i = 0; i < 100; i++) {
428
+ bar.advance();
429
+ }
430
+ bar.finish();
431
+ }
432
+ ```
433
+
434
+
435
+
436
+ ## Create a maker command
437
+
438
+ Create a command file in your project.
439
+
440
+ ```bash
441
+ touch Commands/ControllerMaker.js
442
+ ```
443
+
444
+ Open a `Commands/ControllerMaker.js` file and add the following code:
445
+
446
+ ```js
447
+ import { MakerCommand } from '@noravel/command';
448
+
449
+ class ControllerMaker extends MakerCommand {
450
+ signature = `make:controller
451
+ {name : The name of the controller}
452
+ {--m|model= : Generate a resource controller for the given model}
453
+ {--f|force : Create the class even if the controller already exists}`;
454
+ description = 'Create a new controller class';
455
+
456
+ async handle() {
457
+ console.log('Creating controller...');
458
+ }
459
+ }
460
+
461
+ export default ControllerMaker;
462
+ ```
463
+
464
+ Now let register the command in the `noravel` file:
465
+
466
+ ```js
467
+ #!/usr/bin/env node
468
+
469
+ import { Kernel } from '@noravel/command';
470
+ import Greeting from './Commands/Greeting.js';
471
+ import ControllerMaker from './Commands/ControllerMaker.js';
472
+
473
+ const kernel = new Kernel(process.argv);
474
+ kernel.register([
475
+ Greeting,
476
+ ControllerMaker,
477
+ ]).run();
478
+ ```
479
+
480
+ Let's look at the methods available in the `MakerCommand` class:
481
+
482
+ ```ts
483
+ class MakerCommand {
484
+ // Returns the base path of the project
485
+ public basePath(dirPath?: string): string;
486
+
487
+ // Returns the filename; if the user hasn't entered it, it will wait for user input
488
+ public async fileName(question?: string = 'What should the file be named?'): Promise<string>;
489
+
490
+ // Creates a file with the given name and path
491
+ public makeFile(fileName: string, dirPath: string): void;
492
+
493
+ // Returns the message that the file already exists
494
+ protected fileAlreadyExists(filePath: string): string;
495
+
496
+ // Returns the message that the file created successfully
497
+ protected fileCreatedSuccessfully(filePath: string): string;
498
+
499
+ // Returns the contents of a file that will be written to the file being created
500
+ protected contentFile(fileName: string): string;
501
+ }
502
+ ```
503
+
504
+ ## Help command
505
+
506
+ Check the available commands:
507
+
508
+ ```bash
509
+ ./noravel --help
510
+ ```
511
+
512
+ Output:
513
+
514
+ ```
515
+ Usage:
516
+ command [arguments] [--options]
517
+
518
+ Available commands:
519
+ greeting Sending greetings to someone
520
+ make:controller Create a new controller class
521
+
522
+ Options:
523
+ -h, --help Show this help message
524
+ -v, --version Display the version of Noravel Command
525
+ ```
526
+
527
+ You can also view a description of a specific command by:
528
+
529
+ ```bash
530
+ ./noravel make:controller --help
531
+ ```
532
+
533
+ Output:
534
+
535
+ ```
536
+ Description:
537
+ Create a new controller class
538
+
539
+ Usage:
540
+ make:controller [options] [--] <name>
541
+
542
+ Arguments:
543
+ name The name of the controller
544
+
545
+ Options:
546
+ -m, --model Generate a resource controller for the given model
547
+ -f, --force Create the class even if the controller already exists
548
+ -h, --help Display help for the given command
549
+ -v, --version Display the version of Noravel Command
550
+ ```
551
+
552
+ ## Programmatically executing commands
553
+
554
+ Sometimes you may wish to execute your command outside of the CLI.
555
+ For example, you may wish to execute your command from a route or controller.
556
+ You may use the `call` method on the `Executor` to accomplish this.
557
+ The `call` method accepts either the command's class name as its first argument, and an array of command parameters as the second argument.
558
+
559
+ ```js
560
+ import Executor from './Executor.js';
561
+ import Greeting from './Commands/Greeting.js';
562
+
563
+ await Executor.call(Greeting, [
564
+ 'John Doe',
565
+ '--verbose',
566
+ '--tag=foo',
567
+ '--tag=bar',
568
+ ]);
569
+ ```
@@ -0,0 +1,27 @@
1
+ import CommandContract from './Contracts/Command';
2
+ import InputDefinition from './Inputs/InputDefinition';
3
+ import Prompt from './Inputs/Prompt';
4
+ import OutputMessage from './Outputs/OutputMessage';
5
+ export default abstract class Command implements CommandContract {
6
+ argv: string[];
7
+ protected signature: string;
8
+ protected name: string;
9
+ protected description: string;
10
+ protected definition: InputDefinition;
11
+ protected inputs: {
12
+ arguments: Record<string, unknown>;
13
+ options: Record<string, unknown>;
14
+ };
15
+ protected output: OutputMessage;
16
+ protected prompt: Prompt;
17
+ constructor(argv: string[]);
18
+ bootstrap(): this;
19
+ detect(): this;
20
+ getName(): string;
21
+ getDescription(): string;
22
+ getArgument(name?: string): unknown;
23
+ getOption(name?: string): unknown;
24
+ showHelp(): void;
25
+ exec(command: string): Promise<unknown>;
26
+ abstract handle(): void;
27
+ }
@@ -0,0 +1,86 @@
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
+ const node_child_process_1 = require("node:child_process");
7
+ const Parser_1 = __importDefault(require("./Parser"));
8
+ const Detector_1 = __importDefault(require("./Detector"));
9
+ const InputDefinition_1 = __importDefault(require("./Inputs/InputDefinition"));
10
+ const Prompt_1 = __importDefault(require("./Inputs/Prompt"));
11
+ const OutputMessage_1 = __importDefault(require("./Outputs/OutputMessage"));
12
+ const Helper_1 = __importDefault(require("./Outputs/Helper"));
13
+ class Command {
14
+ argv;
15
+ signature = '';
16
+ name = '';
17
+ description = '';
18
+ definition;
19
+ inputs = {
20
+ arguments: {},
21
+ options: {},
22
+ };
23
+ output;
24
+ prompt;
25
+ constructor(argv) {
26
+ this.argv = argv;
27
+ this.definition = new InputDefinition_1.default();
28
+ this.output = new OutputMessage_1.default();
29
+ this.prompt = new Prompt_1.default();
30
+ }
31
+ bootstrap() {
32
+ this.signature = this.signature + ' {--h|help : Display help for the given command} {--v|version : Display the version of Noravel Command}';
33
+ const [name, argumentDefinition, optionDefinition] = Parser_1.default.parse(this.signature);
34
+ this.name = name;
35
+ this.definition.setArguments(argumentDefinition);
36
+ this.definition.setOptions(optionDefinition);
37
+ return this;
38
+ }
39
+ detect() {
40
+ const [_arguments, _options] = Detector_1.default.detect(this.argv.slice(1), this.definition);
41
+ this.inputs.arguments = _arguments;
42
+ this.inputs.options = _options;
43
+ return this;
44
+ }
45
+ getName() {
46
+ return this.name;
47
+ }
48
+ getDescription() {
49
+ return this.description;
50
+ }
51
+ getArgument(name) {
52
+ if (!name) {
53
+ return Object.values(this.inputs.arguments);
54
+ }
55
+ return this.inputs.arguments[name];
56
+ }
57
+ getOption(name) {
58
+ if (!name) {
59
+ return Object.values(this.inputs.options);
60
+ }
61
+ return this.inputs.options[name];
62
+ }
63
+ showHelp() {
64
+ const helper = new Helper_1.default();
65
+ helper.showHelp(this.name, this.description, this.definition);
66
+ }
67
+ async exec(command) {
68
+ return new Promise((resolve, reject) => {
69
+ (0, node_child_process_1.exec)(command, (error, stdout, stderr) => {
70
+ if (error) {
71
+ this.output.error(error.message);
72
+ reject(error);
73
+ return;
74
+ }
75
+ if (stderr) {
76
+ this.output.error(stderr);
77
+ reject(new Error(stderr));
78
+ return;
79
+ }
80
+ this.output.info(stdout);
81
+ resolve(stdout);
82
+ });
83
+ });
84
+ }
85
+ }
86
+ exports.default = Command;
@@ -0,0 +1,10 @@
1
+ export default interface Command {
2
+ bootstrap(): this;
3
+ detect(): this;
4
+ getName(): string;
5
+ getDescription(): string;
6
+ getArgument(name?: string): unknown;
7
+ getOption(name?: string): unknown;
8
+ showHelp(): void;
9
+ handle(): void;
10
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });