@travetto/cli 8.0.0-alpha.10 → 8.0.0-alpha.11
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 +15 -15
- package/bin/trv.js +1 -1
- package/package.json +3 -3
- package/src/help.ts +41 -41
- package/src/parse.ts +3 -4
- package/src/registry/registry-adapter.ts +1 -13
- package/src/types.ts +2 -0
package/README.md
CHANGED
|
@@ -75,12 +75,12 @@ export class BasicCommand {
|
|
|
75
75
|
|
|
76
76
|
**Terminal: Basic Command Help**
|
|
77
77
|
```bash
|
|
78
|
-
$ trv basic
|
|
78
|
+
$ trv basic --help
|
|
79
79
|
|
|
80
80
|
Usage: basic [options]
|
|
81
81
|
|
|
82
82
|
Options:
|
|
83
|
-
|
|
83
|
+
--help display help for command
|
|
84
84
|
```
|
|
85
85
|
|
|
86
86
|
## Command Naming
|
|
@@ -113,13 +113,13 @@ export class BasicCommand {
|
|
|
113
113
|
|
|
114
114
|
**Terminal: Basic Command with Flag Help**
|
|
115
115
|
```bash
|
|
116
|
-
$ trv basic:flag
|
|
116
|
+
$ trv basic:flag --help
|
|
117
117
|
|
|
118
118
|
Usage: basic:flag [options]
|
|
119
119
|
|
|
120
120
|
Options:
|
|
121
121
|
-l, --loud
|
|
122
|
-
|
|
122
|
+
--help display help for command
|
|
123
123
|
```
|
|
124
124
|
|
|
125
125
|
As you can see the command now has the support of a basic boolean flag to determine if the response should be loud or not. The default value here is undefined/false, and so is an opt-in experience.
|
|
@@ -158,12 +158,12 @@ export class BasicCommand {
|
|
|
158
158
|
|
|
159
159
|
**Terminal: Basic Command**
|
|
160
160
|
```bash
|
|
161
|
-
$ trv basic:arg
|
|
161
|
+
$ trv basic:arg --help
|
|
162
162
|
|
|
163
163
|
Usage: basic:arg [options] [volume:number]
|
|
164
164
|
|
|
165
165
|
Options:
|
|
166
|
-
|
|
166
|
+
--help display help for command
|
|
167
167
|
```
|
|
168
168
|
|
|
169
169
|
**Terminal: Basic Command with Invalid Loud Arg**
|
|
@@ -176,7 +176,7 @@ Execution failed:
|
|
|
176
176
|
Usage: basic:arg [options] [volume:number]
|
|
177
177
|
|
|
178
178
|
Options:
|
|
179
|
-
|
|
179
|
+
--help display help for command
|
|
180
180
|
```
|
|
181
181
|
|
|
182
182
|
**Terminal: Basic Command with Loud Arg > 7**
|
|
@@ -213,13 +213,13 @@ export class BasicCommand {
|
|
|
213
213
|
|
|
214
214
|
**Terminal: Basic Command**
|
|
215
215
|
```bash
|
|
216
|
-
$ trv basic:arg-list
|
|
216
|
+
$ trv basic:arg-list --help
|
|
217
217
|
|
|
218
218
|
Usage: basic:arg-list [options] <volumes...:number>
|
|
219
219
|
|
|
220
220
|
Options:
|
|
221
221
|
-r, --reverse
|
|
222
|
-
|
|
222
|
+
--help display help for command
|
|
223
223
|
```
|
|
224
224
|
|
|
225
225
|
**Terminal: Basic Arg List**
|
|
@@ -240,7 +240,7 @@ Usage: basic:arg-list [options] <volumes...:number>
|
|
|
240
240
|
|
|
241
241
|
Options:
|
|
242
242
|
-r, --reverse
|
|
243
|
-
|
|
243
|
+
--help display help for command
|
|
244
244
|
```
|
|
245
245
|
|
|
246
246
|
**Terminal: Basic Arg List with Reverse**
|
|
@@ -279,13 +279,13 @@ export class CustomCommand {
|
|
|
279
279
|
|
|
280
280
|
**Terminal: Custom Command Help**
|
|
281
281
|
```bash
|
|
282
|
-
$ trv custom:arg
|
|
282
|
+
$ trv custom:arg --help
|
|
283
283
|
|
|
284
284
|
Usage: custom:arg [options] [volume:number]
|
|
285
285
|
|
|
286
286
|
Options:
|
|
287
287
|
-m, --message <string> The message to send back to the user (default: "hello")
|
|
288
|
-
|
|
288
|
+
--help display help for command
|
|
289
289
|
```
|
|
290
290
|
|
|
291
291
|
**Terminal: Custom Command Help with overridden Text**
|
|
@@ -330,13 +330,13 @@ export class CustomCommand {
|
|
|
330
330
|
|
|
331
331
|
**Terminal: Custom Command Help**
|
|
332
332
|
```bash
|
|
333
|
-
$ trv custom:env-arg
|
|
333
|
+
$ trv custom:env-arg --help
|
|
334
334
|
|
|
335
335
|
Usage: custom:env-arg [options] [volume:number]
|
|
336
336
|
|
|
337
337
|
Options:
|
|
338
338
|
-t, --text <string> The message to send back to the user (default: "hello")
|
|
339
|
-
|
|
339
|
+
--help display help for command
|
|
340
340
|
```
|
|
341
341
|
|
|
342
342
|
**Terminal: Custom Command Help with default Text**
|
|
@@ -559,7 +559,7 @@ Usage: service [options] <action:restart|start|status|stop> [services...:string]
|
|
|
559
559
|
|
|
560
560
|
Options:
|
|
561
561
|
-q, --quiet (default: false)
|
|
562
|
-
|
|
562
|
+
--help display help for command
|
|
563
563
|
|
|
564
564
|
Available Services
|
|
565
565
|
--------------------
|
package/bin/trv.js
CHANGED
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
import '@travetto/runtime/support/patch.js';
|
|
4
4
|
import '@travetto/compiler/bin/hook.js';
|
|
5
5
|
const { invoke } = await import('@travetto/compiler/support/invoke.ts');
|
|
6
|
-
await invoke('exec',
|
|
6
|
+
await invoke('exec', '@travetto/cli/support/entry.trv.ts', ...process.argv.slice(2));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/cli",
|
|
3
|
-
"version": "8.0.0-alpha.
|
|
3
|
+
"version": "8.0.0-alpha.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI infrastructure for Travetto framework",
|
|
6
6
|
"keywords": [
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"directory": "module/cli"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@travetto/schema": "^8.0.0-alpha.
|
|
33
|
-
"@travetto/terminal": "^8.0.0-alpha.
|
|
32
|
+
"@travetto/schema": "^8.0.0-alpha.6",
|
|
33
|
+
"@travetto/terminal": "^8.0.0-alpha.6"
|
|
34
34
|
},
|
|
35
35
|
"travetto": {
|
|
36
36
|
"displayName": "Command Line Interface",
|
package/src/help.ts
CHANGED
|
@@ -4,32 +4,29 @@ import { castKey, getClass, JSONUtil, Runtime } from '@travetto/runtime';
|
|
|
4
4
|
import { SchemaRegistryIndex, ValidationResultError } from '@travetto/schema';
|
|
5
5
|
|
|
6
6
|
import { cliTpl } from './color.ts';
|
|
7
|
-
import type
|
|
7
|
+
import { HELP_FLAG, type CliCommandShape } from './types.ts';
|
|
8
8
|
import { CliCommandRegistryIndex, UNKNOWN_COMMAND } from './registry/registry-index.ts';
|
|
9
9
|
import { CliSchemaExportUtil } from './schema-export.ts';
|
|
10
10
|
|
|
11
|
-
const validationSourceMap: Record<string, string> = {
|
|
12
|
-
arg: 'Argument',
|
|
13
|
-
flag: 'Flag'
|
|
14
|
-
};
|
|
11
|
+
const validationSourceMap: Record<string, string> = { arg: 'Argument', flag: 'Flag' };
|
|
15
12
|
|
|
16
13
|
const ifDefined = <T>(value: T | null | '' | undefined): T | undefined =>
|
|
17
14
|
(value === null || value === '' || value === undefined) ? undefined : value;
|
|
18
15
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
]);
|
|
16
|
+
const MODULE_TO_COMMAND = {
|
|
17
|
+
'@travetto/doc': ['doc'],
|
|
18
|
+
'@travetto/email-compiler': ['email:compile', 'email:test', 'email:editor'],
|
|
19
|
+
'@travetto/eslint': ['eslint', 'eslint:register', 'lint', 'lint:register'],
|
|
20
|
+
'@travetto/model': ['model:install', 'model:export'],
|
|
21
|
+
'@travetto/openapi': ['openapi:spec', 'openapi:client'],
|
|
22
|
+
'@travetto/pack': ['pack', 'pack:zip', 'pack:docker'],
|
|
23
|
+
'@travetto/repo': ['repo:publish', 'repo:version', 'repo:exec', 'repo:list'],
|
|
24
|
+
'@travetto/test': ['test', 'test:watch', 'test:direct'],
|
|
25
|
+
'@travetto/web-http': ['web:http'],
|
|
26
|
+
'@travetto/web-rpc': ['web:rpc-client'],
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const COMMAND_TO_MODULE = Object.fromEntries(Object.entries(MODULE_TO_COMMAND).flatMap(([k, v]) => v.map(sv => [sv, k])));
|
|
33
30
|
|
|
34
31
|
/**
|
|
35
32
|
* Utilities for showing help
|
|
@@ -37,15 +34,15 @@ const INSTALL_COMMANDS = new Map<string, string>([
|
|
|
37
34
|
export class HelpUtil {
|
|
38
35
|
|
|
39
36
|
/** Render the unknown command message */
|
|
40
|
-
static renderUnknownCommandMessage(
|
|
41
|
-
const
|
|
42
|
-
if (
|
|
37
|
+
static renderUnknownCommandMessage(command: string): string {
|
|
38
|
+
const module = COMMAND_TO_MODULE[command];
|
|
39
|
+
if (module) {
|
|
43
40
|
return cliTpl`
|
|
44
|
-
${{ title: 'Missing Package' }}\n${'-'.repeat(20)}\nTo use ${{ input:
|
|
45
|
-
${{ identifier:
|
|
41
|
+
${{ title: 'Missing Package' }}\n${'-'.repeat(20)}\nTo use ${{ input: command }} please run:\n
|
|
42
|
+
${{ identifier: Runtime.getInstallCommand(module) }}
|
|
46
43
|
`;
|
|
47
44
|
} else {
|
|
48
|
-
return cliTpl`${{ subtitle: 'Unknown command' }}: ${{ input:
|
|
45
|
+
return cliTpl`${{ subtitle: 'Unknown command' }}: ${{ input: command }}`;
|
|
49
46
|
}
|
|
50
47
|
}
|
|
51
48
|
|
|
@@ -58,25 +55,24 @@ ${{ identifier: install }}
|
|
|
58
55
|
const { name: commandName } = CliCommandRegistryIndex.get(getClass(command));
|
|
59
56
|
const args = schema.methods.main?.parameters ?? [];
|
|
60
57
|
|
|
61
|
-
|
|
58
|
+
const usage = [cliTpl`${{ title: 'Usage:' }} ${{ param: commandName }} ${{ input: '[options]' }}`,];
|
|
59
|
+
const params: string[] = [];
|
|
60
|
+
const descriptions: string[] = [];
|
|
62
61
|
|
|
63
|
-
|
|
62
|
+
// Ensure finalized
|
|
64
63
|
for (const field of args) {
|
|
65
64
|
const type = field.type === String && field.enum && field.enum?.values.length <= 7 ? field.enum?.values?.join('|') : field.type.name.toLowerCase();
|
|
66
65
|
const arg = `${field.name}${field.array ? '...' : ''}:${type}`;
|
|
67
66
|
usage.push(cliTpl`${{ input: field.required?.active !== false ? `<${arg}>` : `[${arg}]` }}`);
|
|
68
67
|
}
|
|
69
68
|
|
|
70
|
-
const params: string[] = [];
|
|
71
|
-
const descriptions: string[] = [];
|
|
72
|
-
|
|
73
69
|
for (const field of Object.values(schema.fields)) {
|
|
74
70
|
const key = castKey<CliCommandShape>(field.name);
|
|
75
71
|
const defaultValue = ifDefined(command[key]) ?? ifDefined(field.default);
|
|
76
72
|
const aliases = (field.aliases ?? [])
|
|
77
73
|
.filter(flag => flag.startsWith('-'))
|
|
78
74
|
.filter(flag =>
|
|
79
|
-
(field.type !== Boolean) || (
|
|
75
|
+
(field.type !== Boolean) || (defaultValue !== true ? !flag.startsWith('--no-') : flag.startsWith('--'))
|
|
80
76
|
);
|
|
81
77
|
let type: string | undefined;
|
|
82
78
|
|
|
@@ -86,29 +82,33 @@ ${{ identifier: install }}
|
|
|
86
82
|
({ type } = CliSchemaExportUtil.baseInputType(field));
|
|
87
83
|
}
|
|
88
84
|
|
|
89
|
-
const
|
|
85
|
+
const parameter = [
|
|
90
86
|
cliTpl`${{ param: aliases.join(', ') }}`,
|
|
91
87
|
...(type ? [cliTpl`${{ type: `<${type}>` }}`] : []),
|
|
92
88
|
];
|
|
93
89
|
|
|
94
|
-
params.push(
|
|
95
|
-
const
|
|
90
|
+
params.push(parameter.join(' '));
|
|
91
|
+
const parts = [cliTpl`${{ title: field.description }}`];
|
|
96
92
|
|
|
97
|
-
if (
|
|
98
|
-
|
|
93
|
+
if (defaultValue !== undefined) {
|
|
94
|
+
parts.push(cliTpl`(default: ${{ input: JSONUtil.toUTF8(defaultValue) }})`);
|
|
99
95
|
}
|
|
100
|
-
descriptions.push(
|
|
96
|
+
descriptions.push(parts.join(' '));
|
|
101
97
|
}
|
|
102
98
|
|
|
99
|
+
params.push(cliTpl`${{ param: HELP_FLAG }}`);
|
|
100
|
+
descriptions.push('display help for command');
|
|
101
|
+
|
|
102
|
+
|
|
103
103
|
const paramWidths = params.map(item => util.stripVTControlCharacters(item).length);
|
|
104
104
|
const descWidths = descriptions.map(item => util.stripVTControlCharacters(item).length);
|
|
105
105
|
|
|
106
106
|
const paramWidth = Math.max(...paramWidths);
|
|
107
107
|
const descWidth = Math.max(...descWidths);
|
|
108
108
|
|
|
109
|
-
const
|
|
110
|
-
if (
|
|
111
|
-
|
|
109
|
+
const extendedHelpText = await (command.help?.() ?? []);
|
|
110
|
+
if (extendedHelpText.length && extendedHelpText.at(-1) !== '') {
|
|
111
|
+
extendedHelpText.push('');
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
return [
|
|
@@ -119,7 +119,7 @@ ${{ identifier: install }}
|
|
|
119
119
|
` ${params[i]}${' '.repeat((paramWidth - paramWidths[i]))} ${descriptions[i].padEnd(descWidth)}${' '.repeat((descWidth - descWidths[i]))}`
|
|
120
120
|
),
|
|
121
121
|
'',
|
|
122
|
-
...
|
|
122
|
+
...extendedHelpText
|
|
123
123
|
].map(line => line.trimEnd()).join('\n');
|
|
124
124
|
}
|
|
125
125
|
|
package/src/parse.ts
CHANGED
|
@@ -4,13 +4,12 @@ import path from 'node:path';
|
|
|
4
4
|
import { Runtime } from '@travetto/runtime';
|
|
5
5
|
import type { SchemaClassConfig, SchemaFieldConfig, SchemaInputConfig } from '@travetto/schema';
|
|
6
6
|
|
|
7
|
-
import type
|
|
7
|
+
import { HELP_FLAG, type ParsedState } from './types.ts';
|
|
8
8
|
|
|
9
9
|
type ParsedInput = ParsedState['all'][number];
|
|
10
10
|
|
|
11
11
|
const RAW_SEPARATOR = '--';
|
|
12
12
|
const VALID_FLAG = /^-{1,2}[a-z]/i;
|
|
13
|
-
const HELP_FLAG = /^(-h|--help)$/;
|
|
14
13
|
const LONG_FLAG_WITH_EQ = /^--[a-z][^= ]+=\S+/i;
|
|
15
14
|
const CONFIG_PREFIX = '+=';
|
|
16
15
|
const SPACE = new Set([32, 7, 13, 10]);
|
|
@@ -124,9 +123,9 @@ export class CliParseUtil {
|
|
|
124
123
|
const max = out.includes(RAW_SEPARATOR) ? out.indexOf(RAW_SEPARATOR) : out.length;
|
|
125
124
|
const valid = out.slice(0, max);
|
|
126
125
|
const cmd = valid.length > 0 && !valid[0].startsWith('-') ? valid[0] : undefined;
|
|
127
|
-
const
|
|
126
|
+
const help = valid.includes(HELP_FLAG);
|
|
128
127
|
const args = out.slice(cmd ? 1 : 0);
|
|
129
|
-
const result = { cmd, args, help
|
|
128
|
+
const result = { cmd, args, help };
|
|
130
129
|
return result;
|
|
131
130
|
}
|
|
132
131
|
|
|
@@ -29,22 +29,10 @@ export class CliCommandRegistryAdapter implements RegistryAdapter<CliCommandConf
|
|
|
29
29
|
this.#cls = cls;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
// TODO: handle when aliases overlap/conflict
|
|
32
33
|
finalize(parent?: CliCommandConfig): void {
|
|
33
34
|
// Add help command
|
|
34
35
|
const schema = SchemaRegistryIndex.getConfig(this.#cls);
|
|
35
|
-
|
|
36
|
-
// Add help to every command
|
|
37
|
-
(schema.fields ??= {}).help = {
|
|
38
|
-
type: Boolean,
|
|
39
|
-
name: 'help',
|
|
40
|
-
class: this.#cls,
|
|
41
|
-
description: 'display help for command',
|
|
42
|
-
required: { active: false },
|
|
43
|
-
default: false,
|
|
44
|
-
access: 'readonly',
|
|
45
|
-
aliases: ['-h', '--help']
|
|
46
|
-
};
|
|
47
|
-
|
|
48
36
|
const used = new Set(Object.values(schema.fields)
|
|
49
37
|
.flatMap(field => field.aliases ?? [])
|
|
50
38
|
.filter(alias => !alias.startsWith(ENV_PREFIX))
|
package/src/types.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Any, Class } from '@travetto/runtime';
|
|
2
2
|
|
|
3
|
+
export const HELP_FLAG = '--help';
|
|
4
|
+
|
|
3
5
|
type OrProm<T> = T | Promise<T>;
|
|
4
6
|
type ParsedFlag = { type: 'flag', input: string, array?: boolean, fieldName: string, value?: unknown };
|
|
5
7
|
type ParsedArg = { type: 'arg', input: string, array?: boolean, index: number };
|