@travetto/cli 8.0.0-alpha.20 → 8.0.0-alpha.22
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 +58 -36
- package/package.json +3 -3
- package/src/help.ts +89 -34
- package/src/registry/decorator.ts +2 -2
- package/src/schema-export.ts +1 -1
- package/support/cli.cli_schema.ts +4 -1
- package/support/cli.main.ts +4 -1
- package/support/cli.service.ts +4 -1
package/README.md
CHANGED
|
@@ -22,34 +22,38 @@ $ trv --help
|
|
|
22
22
|
Usage: [options] [command]
|
|
23
23
|
|
|
24
24
|
Commands:
|
|
25
|
-
doc
|
|
26
|
-
doc:angular
|
|
27
|
-
doc:mapping
|
|
28
|
-
email:compile
|
|
29
|
-
email:editor
|
|
30
|
-
email:test
|
|
31
|
-
eslint
|
|
32
|
-
eslint:register
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
25
|
+
doc Generate documentation outputs from a module `DOC.tsx` entry file.
|
|
26
|
+
doc:angular Generate documentation into the angular webapp under related/travetto.github.io
|
|
27
|
+
doc:mapping Generate module mapping for
|
|
28
|
+
email:compile Compile all email templates into generated runtime artifacts.
|
|
29
|
+
email:editor Start the email template editor service for interactive preview and testing.
|
|
30
|
+
email:test Render and send a template file to a target recipient for quick validation.
|
|
31
|
+
eslint Run ESLint for the workspace or changed files.
|
|
32
|
+
eslint:register Generate the workspace ESLint configuration entry file.
|
|
33
|
+
llm:support:execute Execute llm-support operations with dry-run by default.
|
|
34
|
+
llm:support:mcp Minimal MCP stdio server for llm-support tools.
|
|
35
|
+
llm:support:plan Build plan-first execution details for llm-support operations.
|
|
36
|
+
llm:support:recommend Recommend llm-support bundles, workflows, and operations.
|
|
37
|
+
llm:support:status Show llm-support execution coverage status.
|
|
38
|
+
model:export Export model definitions for a selected provider and model set.
|
|
39
|
+
model:install Install or update model definitions for a selected provider.
|
|
40
|
+
openapi:client Generate API clients from an OpenAPI specification using the generator image.
|
|
41
|
+
openapi:spec Generate the OpenAPI specification for the selected module.
|
|
42
|
+
pack Build a standard module package artifact.
|
|
43
|
+
pack:docker Build container-ready artifacts and optionally publish Docker images.
|
|
44
|
+
pack:lambda Build an AWS Lambda-ready zip package using the pack pipeline.
|
|
45
|
+
pack:zip Build a deployable zip artifact using the standard pack pipeline.
|
|
46
|
+
repo:exec Execute a shell command across workspace modules.
|
|
47
|
+
repo:list List workspace modules and their relationships.
|
|
48
|
+
repo:publish Publish unpublished workspace modules to the package registry.
|
|
49
|
+
repo:version Bump workspace module versions and optionally commit/tag release metadata.
|
|
50
|
+
repo:version-sync Synchronize package versions and dependency ranges across the monorepo.
|
|
51
|
+
run:double Doubles a number
|
|
52
|
+
service Manage development services (start/stop/restart/status) across the workspace.
|
|
53
|
+
test Execute the test framework for targeted files, suites, or methods.
|
|
54
|
+
test:watch Start the test watcher for continuous test execution.
|
|
55
|
+
web:http Start the configured web HTTP server for a module.
|
|
56
|
+
web:rpc-client Generate web-rpc client artifacts from a specified provider or leveraging local config.
|
|
53
57
|
```
|
|
54
58
|
|
|
55
59
|
This listing is from the [Travetto](https://travetto.dev) monorepo, and represents the majority of tools that can be invoked from the command line.
|
|
@@ -259,7 +263,7 @@ import { CliCommand } from '@travetto/cli';
|
|
|
259
263
|
import { Max, Min } from '@travetto/schema';
|
|
260
264
|
|
|
261
265
|
/**
|
|
262
|
-
*
|
|
266
|
+
* Example command with a custom argument
|
|
263
267
|
*/
|
|
264
268
|
@CliCommand()
|
|
265
269
|
export class CustomCommand {
|
|
@@ -283,6 +287,8 @@ $ trv custom:arg --help
|
|
|
283
287
|
|
|
284
288
|
Usage: custom:arg [options] [volume:number]
|
|
285
289
|
|
|
290
|
+
Example command with a custom argument
|
|
291
|
+
|
|
286
292
|
Options:
|
|
287
293
|
-m, --message <string> The message to send back to the user (default: "hello")
|
|
288
294
|
--help display help for command
|
|
@@ -311,7 +317,7 @@ import { CliCommand } from '@travetto/cli';
|
|
|
311
317
|
import { Max, Min } from '@travetto/schema';
|
|
312
318
|
|
|
313
319
|
/**
|
|
314
|
-
*
|
|
320
|
+
* Example of a command with a custom environment variable argument
|
|
315
321
|
*/
|
|
316
322
|
@CliCommand()
|
|
317
323
|
export class CustomCommand {
|
|
@@ -334,6 +340,8 @@ $ trv custom:env-arg --help
|
|
|
334
340
|
|
|
335
341
|
Usage: custom:env-arg [options] [volume:number]
|
|
336
342
|
|
|
343
|
+
Example of a command with a custom environment variable argument
|
|
344
|
+
|
|
337
345
|
Options:
|
|
338
346
|
-t, --text <string> The message to send back to the user (default: "hello")
|
|
339
347
|
--help display help for command
|
|
@@ -442,7 +450,12 @@ import { Registry } from '@travetto/registry';
|
|
|
442
450
|
import type { WebHttpServer } from '../src/types.ts';
|
|
443
451
|
|
|
444
452
|
/**
|
|
445
|
-
*
|
|
453
|
+
* Start the configured web HTTP server for a module.
|
|
454
|
+
*
|
|
455
|
+
* Initializes registry and server bindings, supports restart-aware development
|
|
456
|
+
* flags, and can attempt to clear conflicting port owners in local workflows.
|
|
457
|
+
*
|
|
458
|
+
* @example trv web:http -m <MODULE> -p 3000
|
|
446
459
|
*/
|
|
447
460
|
@CliCommand()
|
|
448
461
|
export class WebHttpCommand implements CliCommandShape {
|
|
@@ -551,12 +564,17 @@ A simple example of the validation can be found in the `doc` command:
|
|
|
551
564
|
## CLI - service
|
|
552
565
|
The module provides the ability to start/stop/restart services as [docker](https://www.docker.com/community-edition) containers. This is meant to be used for development purposes, to minimize the effort of getting an application up and running. Services can be targeted individually or handled as a group.
|
|
553
566
|
|
|
554
|
-
**Terminal:
|
|
567
|
+
**Terminal: Help for service**
|
|
555
568
|
```bash
|
|
556
569
|
$ trv service --help
|
|
557
570
|
|
|
558
571
|
Usage: service [options] <action:restart|start|status|stop> [services...:string]
|
|
559
572
|
|
|
573
|
+
Manage development services (start/stop/restart/status) across the workspace.
|
|
574
|
+
|
|
575
|
+
Services are discovered from registered descriptors and executed with streamed
|
|
576
|
+
terminal feedback, including optional quiet mode.
|
|
577
|
+
|
|
560
578
|
Options:
|
|
561
579
|
-q, --quiet (default: false)
|
|
562
580
|
--help display help for command
|
|
@@ -566,7 +584,7 @@ Available Services
|
|
|
566
584
|
* dynamodb@3.3.0
|
|
567
585
|
* elasticsearch@9.2.8
|
|
568
586
|
* firestore@latest
|
|
569
|
-
* mongodb@8.
|
|
587
|
+
* mongodb@8.3
|
|
570
588
|
* mysql@9.6
|
|
571
589
|
* postgresql@18.3
|
|
572
590
|
* redis@8.4
|
|
@@ -584,7 +602,7 @@ Service Version Status
|
|
|
584
602
|
dynamodb 3.3.0 Running 93af422e793a
|
|
585
603
|
elasticsearch 9.2.8 Running ed76ee063d13
|
|
586
604
|
firestore latest Running feec2e5e95b4
|
|
587
|
-
mongodb 8.
|
|
605
|
+
mongodb 8.3 Running 5513eba6734e
|
|
588
606
|
mysql 9.6 Running 307bc66d442a
|
|
589
607
|
postgresql 18.3 Running e78291e71040
|
|
590
608
|
redis 8.4 Running 77ba279b4e30
|
|
@@ -598,12 +616,16 @@ The services are defined as plain typescript files within the framework and can
|
|
|
598
616
|
```typescript
|
|
599
617
|
import type { ServiceDescriptor } from '@travetto/cli';
|
|
600
618
|
|
|
601
|
-
const version = process.env.MONGO_VERSION || '8.
|
|
619
|
+
const version = process.env.MONGO_VERSION || '8.3';
|
|
602
620
|
|
|
603
621
|
export const service: ServiceDescriptor = {
|
|
604
622
|
name: 'mongodb',
|
|
605
623
|
version,
|
|
606
624
|
port: 27017,
|
|
607
|
-
image: `mongo:${version}
|
|
625
|
+
image: `mongo:${version}`,
|
|
626
|
+
env: {
|
|
627
|
+
// Temp until mongo image fixes orbstack issue
|
|
628
|
+
GLIBC_TUNABLES: 'glibc.pthread.rseq=1'
|
|
629
|
+
}
|
|
608
630
|
};
|
|
609
631
|
```
|
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.22",
|
|
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.17",
|
|
33
|
+
"@travetto/terminal": "^8.0.0-alpha.16"
|
|
34
34
|
},
|
|
35
35
|
"travetto": {
|
|
36
36
|
"displayName": "Command Line Interface",
|
package/src/help.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import util from 'node:util';
|
|
2
2
|
|
|
3
|
-
import { castKey, getClass, JSONUtil, Runtime } from '@travetto/runtime';
|
|
3
|
+
import { castKey, CodecUtil, getClass, JSONUtil, Runtime } from '@travetto/runtime';
|
|
4
4
|
import { SchemaRegistryIndex, ValidationResultError } from '@travetto/schema';
|
|
5
5
|
|
|
6
6
|
import { cliTpl } from './color.ts';
|
|
@@ -33,38 +33,43 @@ const COMMAND_TO_MODULE = Object.fromEntries(Object.entries(MODULE_TO_COMMAND).f
|
|
|
33
33
|
*/
|
|
34
34
|
export class HelpUtil {
|
|
35
35
|
|
|
36
|
-
/**
|
|
37
|
-
static
|
|
38
|
-
const module = COMMAND_TO_MODULE[command];
|
|
39
|
-
if (module) {
|
|
40
|
-
return cliTpl`
|
|
41
|
-
${{ title: 'Missing Package' }}\n${'-'.repeat(20)}\nTo use ${{ input: command }} please run:\n
|
|
42
|
-
${{ identifier: Runtime.getInstallCommand(module) }}
|
|
43
|
-
`;
|
|
44
|
-
} else {
|
|
45
|
-
return cliTpl`${{ subtitle: 'Unknown command' }}: ${{ input: command }}`;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Render command-specific help
|
|
51
|
-
* @param command
|
|
52
|
-
*/
|
|
53
|
-
static async renderCommandHelp(command: CliCommandShape): Promise<string> {
|
|
36
|
+
/** Get usage help for a command */
|
|
37
|
+
static getUsageMessage(command: CliCommandShape): string[] {
|
|
54
38
|
const schema = SchemaRegistryIndex.getConfig(getClass(command));
|
|
55
39
|
const { name: commandName } = CliCommandRegistryIndex.get(getClass(command));
|
|
56
|
-
const args = schema.methods.main?.parameters ?? [];
|
|
57
40
|
|
|
58
|
-
const usage
|
|
59
|
-
|
|
60
|
-
|
|
41
|
+
const usage: string[] = [];
|
|
42
|
+
|
|
43
|
+
usage.push(
|
|
44
|
+
cliTpl`${{ title: 'Usage:' }} ${{ param: commandName }} ${{ input: '[options]' }}`
|
|
45
|
+
);
|
|
61
46
|
|
|
62
47
|
// Ensure finalized
|
|
63
|
-
for (const field of
|
|
48
|
+
for (const field of schema.methods.main?.parameters ?? []) {
|
|
64
49
|
const type = field.type === String && field.enum && field.enum?.values.length <= 7 ? field.enum?.values?.join('|') : field.type.name.toLowerCase();
|
|
65
50
|
const arg = `${field.name}${field.array ? '...' : ''}:${type}`;
|
|
66
51
|
usage.push(cliTpl`${{ input: field.required?.active !== false ? `<${arg}>` : `[${arg}]` }}`);
|
|
67
52
|
}
|
|
53
|
+
usage.push('');
|
|
54
|
+
return usage;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Get description help for a command */
|
|
58
|
+
static getDescriptionMessage(command: CliCommandShape): string[] {
|
|
59
|
+
const schema = SchemaRegistryIndex.getConfig(getClass(command));
|
|
60
|
+
const description: string[] = [];
|
|
61
|
+
|
|
62
|
+
if (schema.description) {
|
|
63
|
+
description.push(cliTpl`${{ title: 'Description:' }}`, ...schema.description.split('\n').map(line => ` ${line}`), '');
|
|
64
|
+
}
|
|
65
|
+
return description;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Get options help for a command */
|
|
69
|
+
static getOptionsMessage(command: CliCommandShape): string[] {
|
|
70
|
+
const schema = SchemaRegistryIndex.getConfig(getClass(command));
|
|
71
|
+
const params: string[] = [];
|
|
72
|
+
const descriptions: string[] = [];
|
|
68
73
|
|
|
69
74
|
for (const field of Object.values(schema.fields)) {
|
|
70
75
|
const key = castKey<CliCommandShape>(field.name);
|
|
@@ -106,20 +111,68 @@ ${{ identifier: Runtime.getInstallCommand(module) }}
|
|
|
106
111
|
const paramWidth = Math.max(...paramWidths);
|
|
107
112
|
const descWidth = Math.max(...descWidths);
|
|
108
113
|
|
|
114
|
+
const options: string[] = [
|
|
115
|
+
cliTpl`${{ title: 'Options:' }}`,
|
|
116
|
+
...params.map((_, i) =>
|
|
117
|
+
` ${params[i]}${' '.repeat((paramWidth - paramWidths[i]))} ${descriptions[i].padEnd(descWidth)}${' '.repeat((descWidth - descWidths[i]))}`
|
|
118
|
+
),
|
|
119
|
+
''
|
|
120
|
+
];
|
|
121
|
+
return options;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Get extended help for a command */
|
|
125
|
+
static async getExtendedHelpMessage(command: CliCommandShape): Promise<string[]> {
|
|
109
126
|
const extendedHelpText = await (command.help?.() ?? []);
|
|
110
127
|
if (extendedHelpText.length && extendedHelpText.at(-1) !== '') {
|
|
111
128
|
extendedHelpText.push('');
|
|
112
129
|
}
|
|
130
|
+
return extendedHelpText;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Get examples for a command */
|
|
134
|
+
static getExamplesMessage(command: CliCommandShape): string[] {
|
|
135
|
+
const schema = SchemaRegistryIndex.getConfig(getClass(command));
|
|
136
|
+
const examples: string[] = [];
|
|
137
|
+
if (schema.examples) {
|
|
138
|
+
examples.push(cliTpl`${{ title: 'Examples:' }}`);
|
|
139
|
+
for (const example of schema.examples) {
|
|
140
|
+
for (const line of example.split('\n')) {
|
|
141
|
+
examples.push(
|
|
142
|
+
line.trim().startsWith('>') ?
|
|
143
|
+
cliTpl` ${{ input: line.substring(line.indexOf('> ') + 2).trim() }}` :
|
|
144
|
+
cliTpl` ${{ subtitle: line.trim() }}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
examples.push('');
|
|
148
|
+
}
|
|
149
|
+
return examples;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Render the unknown command message */
|
|
153
|
+
static renderUnknownCommandMessage(command: string): string {
|
|
154
|
+
const module = COMMAND_TO_MODULE[command];
|
|
155
|
+
if (module) {
|
|
156
|
+
return cliTpl`
|
|
157
|
+
${{ title: 'Missing Package' }}\n${'-'.repeat(20)}\nTo use ${{ input: command }} please run:\n
|
|
158
|
+
${{ identifier: Runtime.getInstallCommand(module) }}
|
|
159
|
+
`;
|
|
160
|
+
} else {
|
|
161
|
+
return cliTpl`${{ subtitle: 'Unknown command' }}: ${{ input: command }}`;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
113
164
|
|
|
165
|
+
/**
|
|
166
|
+
* Render command-specific help
|
|
167
|
+
* @param command
|
|
168
|
+
*/
|
|
169
|
+
static async renderCommandHelp(command: CliCommandShape): Promise<string> {
|
|
114
170
|
return [
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
...
|
|
119
|
-
|
|
120
|
-
),
|
|
121
|
-
'',
|
|
122
|
-
...extendedHelpText
|
|
171
|
+
...this.getUsageMessage(command),
|
|
172
|
+
...this.getDescriptionMessage(command),
|
|
173
|
+
...this.getOptionsMessage(command),
|
|
174
|
+
...await this.getExtendedHelpMessage(command),
|
|
175
|
+
...this.getExamplesMessage(command)
|
|
123
176
|
].map(line => line.trimEnd()).join('\n');
|
|
124
177
|
}
|
|
125
178
|
|
|
@@ -136,11 +189,13 @@ ${{ identifier: Runtime.getInstallCommand(module) }}
|
|
|
136
189
|
for (const { command: cmd, schema } of resolved) {
|
|
137
190
|
try {
|
|
138
191
|
if (schema && !schema.private) {
|
|
139
|
-
|
|
192
|
+
const description = CodecUtil.readFirstLine(schema.description, '');
|
|
193
|
+
rows.push(cliTpl` ${{ param: cmd.padEnd(maxWidth, ' ') }} ${{ title: description }}`);
|
|
140
194
|
}
|
|
141
195
|
} catch (error) {
|
|
142
196
|
if (error instanceof Error) {
|
|
143
|
-
|
|
197
|
+
const failure = CodecUtil.readFirstLine(error.message);
|
|
198
|
+
rows.push(cliTpl` ${{ param: cmd.padEnd(maxWidth, ' ') }} ${{ failure }}`);
|
|
144
199
|
} else {
|
|
145
200
|
throw error;
|
|
146
201
|
}
|
|
@@ -84,7 +84,7 @@ export function CliModuleFlag(config: CliFlagOptions & { scope?: 'current' | 'co
|
|
|
84
84
|
...CliParseUtil.buildAliases(config, Env.TRV_MODULE.key),
|
|
85
85
|
description: 'Module to run for',
|
|
86
86
|
specifiers: ['module'],
|
|
87
|
-
required: { active: Runtime.monoRoot },
|
|
87
|
+
required: { active: Runtime.monoRoot && config.scope !== 'command' },
|
|
88
88
|
});
|
|
89
89
|
|
|
90
90
|
SchemaRegistryIndex.getForRegister(cls).register({
|
|
@@ -147,7 +147,7 @@ export function CliDebugIpcFlag(config: CliFlagOptions = {}) {
|
|
|
147
147
|
const cls = getClass(instance);
|
|
148
148
|
SchemaRegistryIndex.getForRegister(cls).registerField(property, {
|
|
149
149
|
...CliParseUtil.buildAliases(config, Env.TRV_DEBUG_IPC.key),
|
|
150
|
-
description: 'Should the invocation
|
|
150
|
+
description: 'Should the invocation support debugging via IPC (e.g. from VSCode)'
|
|
151
151
|
});
|
|
152
152
|
|
|
153
153
|
CliCommandRegistryIndex.getForRegister(cls).register({ runTarget: true });
|
package/src/schema-export.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { castTo, type Class, describeFunction } from '@travetto/runtime';
|
|
2
2
|
import { type SchemaInputConfig, SchemaRegistryIndex } from '@travetto/schema';
|
|
3
3
|
|
|
4
|
-
import { CliCommandRegistryIndex } from '
|
|
4
|
+
import { CliCommandRegistryIndex } from './registry/registry-index.ts';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* CLI Command argument/flag shape
|
|
@@ -25,7 +25,10 @@ async function nameValidator(names?: string[]): Promise<ValidationError | undefi
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
28
|
+
* Exports machine-readable command metadata for automation and tooling.
|
|
29
|
+
*
|
|
30
|
+
* Used by editor integrations to discover runnable commands and inputs.
|
|
31
|
+
* Used by guidance workflows to validate command signatures.
|
|
29
32
|
*/
|
|
30
33
|
@CliCommand()
|
|
31
34
|
@IsPrivate()
|
package/support/cli.main.ts
CHANGED
|
@@ -11,7 +11,10 @@ async function validateMain(fileOrImport: string): Promise<ValidationError | und
|
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
14
|
+
* Execute a module `main()` entrypoint directly.
|
|
15
|
+
*
|
|
16
|
+
* This internal command resolves an import/source target, invokes its exported
|
|
17
|
+
* `main` function, and forwards unknown CLI args to that function.
|
|
15
18
|
*/
|
|
16
19
|
@CliCommand()
|
|
17
20
|
@IsPrivate()
|
package/support/cli.service.ts
CHANGED
|
@@ -16,7 +16,10 @@ async function validateService(_: ServiceAction, services: string[]): Promise<Va
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
19
|
+
* Manage development services (start/stop/restart/status) across the workspace.
|
|
20
|
+
*
|
|
21
|
+
* Services are discovered from registered descriptors and executed with streamed
|
|
22
|
+
* terminal feedback, including optional quiet mode.
|
|
20
23
|
*/
|
|
21
24
|
@CliCommand()
|
|
22
25
|
export class CliServiceCommand implements CliCommandShape {
|