@travetto/cli 7.0.7 → 7.1.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 +3 -3
- package/bin/trv.js +1 -1
- package/package.json +3 -3
- package/src/error.ts +2 -2
- package/src/execute.ts +1 -1
- package/src/registry/decorator.ts +10 -10
- package/src/registry/registry-index.ts +1 -1
- package/src/trv.d.ts +2 -2
- package/src/types.ts +2 -2
- package/src/util.ts +30 -23
package/README.md
CHANGED
|
@@ -472,14 +472,14 @@ import type { WebHttpServer } from '../src/types.ts';
|
|
|
472
472
|
/**
|
|
473
473
|
* Run a web server
|
|
474
474
|
*/
|
|
475
|
-
@CliCommand({ runTarget: true, with: { debugIpc: 'optional', restartOnChange: true, module: true,
|
|
475
|
+
@CliCommand({ runTarget: true, with: { debugIpc: 'optional', restartOnChange: true, module: true, profiles: true } })
|
|
476
476
|
export class WebHttpCommand implements CliCommandShape {
|
|
477
477
|
|
|
478
478
|
/** Port to run on */
|
|
479
479
|
port?: number;
|
|
480
480
|
|
|
481
481
|
/** Kill conflicting port owner */
|
|
482
|
-
killConflict?: boolean = Runtime.
|
|
482
|
+
killConflict?: boolean = Runtime.localDevelopment;
|
|
483
483
|
|
|
484
484
|
preMain(): void {
|
|
485
485
|
if (this.port) {
|
|
@@ -506,7 +506,7 @@ export class WebHttpCommand implements CliCommandShape {
|
|
|
506
506
|
}
|
|
507
507
|
```
|
|
508
508
|
|
|
509
|
-
As noted in the example above, `fields` is specified in this execution, with support for `module`, and `env`. These env flag is directly tied to the [Runtime](https://github.com/travetto/travetto/tree/main/module/runtime/src/context.ts#
|
|
509
|
+
As noted in the example above, `fields` is specified in this execution, with support for `module`, and `env`. These env flag is directly tied to the [Runtime](https://github.com/travetto/travetto/tree/main/module/runtime/src/context.ts#L13) `name` defined in the [Runtime](https://github.com/travetto/travetto/tree/main/module/runtime#readme "Runtime for travetto applications.") module.
|
|
510
510
|
|
|
511
511
|
The `module` field is slightly more complex, but is geared towards supporting commands within a monorepo context. This flag ensures that a module is specified if running from the root of the monorepo, and that the module provided is real, and can run the desired command. When running from an explicit module folder in the monorepo, the module flag is ignored.
|
|
512
512
|
|
package/bin/trv.js
CHANGED
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
// @ts-check
|
|
3
3
|
import '@travetto/compiler/bin/hook.js';
|
|
4
4
|
const { invoke } = await import('@travetto/compiler/support/invoke.ts');
|
|
5
|
-
invoke('exec', ['@travetto/cli/support/entry.trv.js', ...process.argv.slice(2)]);
|
|
5
|
+
await invoke('exec', ['@travetto/cli/support/entry.trv.js', ...process.argv.slice(2)]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/cli",
|
|
3
|
-
"version": "7.0
|
|
3
|
+
"version": "7.1.0",
|
|
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": "^7.0
|
|
33
|
-
"@travetto/terminal": "^7.0
|
|
32
|
+
"@travetto/schema": "^7.1.0",
|
|
33
|
+
"@travetto/terminal": "^7.1.0"
|
|
34
34
|
},
|
|
35
35
|
"travetto": {
|
|
36
36
|
"displayName": "Command Line Interface",
|
package/src/error.ts
CHANGED
|
@@ -23,8 +23,8 @@ export class CliUnknownCommandError extends Error {
|
|
|
23
23
|
#getMissingCommandHelp(cmd: string): string | undefined {
|
|
24
24
|
const matchedConfig = COMMAND_PACKAGE.find(([regex]) => regex.test(cmd));
|
|
25
25
|
if (matchedConfig) {
|
|
26
|
-
const [, pkg,
|
|
27
|
-
const install = PackageUtil.getInstallCommand(Runtime, `@travetto/${pkg}`,
|
|
26
|
+
const [, pkg, production] = matchedConfig;
|
|
27
|
+
const install = PackageUtil.getInstallCommand(Runtime, `@travetto/${pkg}`, production);
|
|
28
28
|
return cliTpl`
|
|
29
29
|
${{ title: 'Missing Package' }}\n${'-'.repeat(20)}\nTo use ${{ input: cmd }} please run:\n
|
|
30
30
|
${{ identifier: install }}
|
package/src/execute.ts
CHANGED
|
@@ -7,14 +7,14 @@ import { CliModuleUtil } from '../module.ts';
|
|
|
7
7
|
import { CliParseUtil } from '../parse.ts';
|
|
8
8
|
import { CliUtil } from '../util.ts';
|
|
9
9
|
|
|
10
|
-
type Cmd = CliCommandShape & {
|
|
10
|
+
type Cmd = CliCommandShape & { profiles?: string[] };
|
|
11
11
|
|
|
12
12
|
type CliCommandConfigOptions = {
|
|
13
13
|
runTarget?: boolean;
|
|
14
14
|
runtimeModule?: 'current' | 'command';
|
|
15
15
|
with?: {
|
|
16
16
|
/** Application environment */
|
|
17
|
-
|
|
17
|
+
profiles?: boolean;
|
|
18
18
|
/** Module to run for */
|
|
19
19
|
module?: boolean;
|
|
20
20
|
/** Should debug invocation trigger via ipc */
|
|
@@ -32,15 +32,15 @@ type WithHandler<K extends keyof WithConfig> = (config?: WithConfig[K]) => ({
|
|
|
32
32
|
} | undefined);
|
|
33
33
|
|
|
34
34
|
const FIELD_CONFIG: { [K in keyof WithConfig]: WithHandler<K> } = {
|
|
35
|
-
|
|
35
|
+
profiles: (config) => {
|
|
36
36
|
if (!config) { return; }
|
|
37
37
|
return {
|
|
38
|
-
name: '
|
|
39
|
-
run: cmd => Env.
|
|
38
|
+
name: 'profiles',
|
|
39
|
+
run: cmd => cmd.profiles && Env.TRV_PROFILES.set([...cmd.profiles, ...(Env.TRV_PROFILES.list ?? [])]),
|
|
40
40
|
field: {
|
|
41
41
|
type: String,
|
|
42
|
-
aliases: ['
|
|
43
|
-
description: 'Application
|
|
42
|
+
aliases: ['--profile', '--profiles', CliParseUtil.toEnvField(Env.TRV_PROFILES.key)],
|
|
43
|
+
description: 'Application profiles',
|
|
44
44
|
required: { active: false },
|
|
45
45
|
},
|
|
46
46
|
};
|
|
@@ -62,7 +62,7 @@ const FIELD_CONFIG: { [K in keyof WithConfig]: WithHandler<K> } = {
|
|
|
62
62
|
if (!config) { return; }
|
|
63
63
|
return {
|
|
64
64
|
name: 'debugIpc',
|
|
65
|
-
run: cmd => CliUtil.runWithDebugIpc(cmd)
|
|
65
|
+
run: cmd => CliUtil.runWithDebugIpc(cmd),
|
|
66
66
|
field: {
|
|
67
67
|
type: Boolean,
|
|
68
68
|
aliases: ['-di', CliParseUtil.toEnvField(Env.TRV_DEBUG_IPC.key)],
|
|
@@ -79,9 +79,9 @@ const FIELD_CONFIG: { [K in keyof WithConfig]: WithHandler<K> } = {
|
|
|
79
79
|
run: cmd => CliUtil.runWithRestartOnChange(cmd),
|
|
80
80
|
field: {
|
|
81
81
|
type: Boolean,
|
|
82
|
-
aliases: ['-rc'
|
|
82
|
+
aliases: ['-rc'],
|
|
83
83
|
description: 'Should the invocation automatically restart on source changes',
|
|
84
|
-
default: config !== 'optional' && Runtime.
|
|
84
|
+
default: config !== 'optional' && Runtime.localDevelopment,
|
|
85
85
|
required: { active: false },
|
|
86
86
|
},
|
|
87
87
|
};
|
|
@@ -41,7 +41,7 @@ export class CliCommandRegistryIndex implements RegistryIndex {
|
|
|
41
41
|
if (!this.#fileMapping) {
|
|
42
42
|
const all = new Map<string, string>();
|
|
43
43
|
for (const entry of RuntimeIndex.find({
|
|
44
|
-
module: module => !Runtime.production || module.
|
|
44
|
+
module: module => !Runtime.production || module.production,
|
|
45
45
|
folder: folder => folder === 'support',
|
|
46
46
|
file: file => file.role === 'std' && CLI_FILE_REGEX.test(file.sourceFile)
|
|
47
47
|
})) {
|
package/src/trv.d.ts
CHANGED
|
@@ -8,9 +8,9 @@ declare module '@travetto/runtime' {
|
|
|
8
8
|
*/
|
|
9
9
|
TRV_CLI_IPC: string;
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* Signals to the child they are the restart target
|
|
12
12
|
*/
|
|
13
|
-
|
|
13
|
+
TRV_RESTART_TARGET: boolean;
|
|
14
14
|
/**
|
|
15
15
|
* Overrides behavior for triggering debug session via IPC
|
|
16
16
|
*/
|
package/src/types.ts
CHANGED
|
@@ -80,9 +80,9 @@ export interface CliCommandShape<T extends unknown[] = unknown[]> {
|
|
|
80
80
|
*/
|
|
81
81
|
export type CliCommandShapeFields = {
|
|
82
82
|
/**
|
|
83
|
-
*
|
|
83
|
+
* Profiles to run the application under
|
|
84
84
|
*/
|
|
85
|
-
|
|
85
|
+
profiles?: string[];
|
|
86
86
|
/**
|
|
87
87
|
* Should the cli invocation trigger a debug session, via IPC
|
|
88
88
|
*/
|
package/src/util.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { spawn, type ChildProcess } from 'node:child_process';
|
|
2
2
|
|
|
3
|
-
import { Env, ExecUtil, Runtime, ShutdownManager, Util, WatchUtil } from '@travetto/runtime';
|
|
3
|
+
import { AppError, Env, ExecUtil, Runtime, ShutdownManager, Util, WatchUtil } from '@travetto/runtime';
|
|
4
4
|
|
|
5
5
|
import type { CliCommandShape, CliCommandShapeFields } from './types.ts';
|
|
6
6
|
|
|
@@ -28,53 +28,57 @@ export class CliUtil {
|
|
|
28
28
|
/**
|
|
29
29
|
* Run a command as restartable, linking into self
|
|
30
30
|
*/
|
|
31
|
-
static async runWithRestartOnChange<T extends CliCommandShapeFields>(cmd: T): Promise<
|
|
32
|
-
if (
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
static async runWithRestartOnChange<T extends CliCommandShapeFields>(cmd: T): Promise<void> {
|
|
32
|
+
if (Env.TRV_RESTART_TARGET.isTrue) {
|
|
33
|
+
Env.TRV_RESTART_TARGET.clear();
|
|
34
|
+
WatchUtil.listenForSignals();
|
|
35
|
+
return;
|
|
36
|
+
} else if (cmd.restartOnChange !== true) {
|
|
37
|
+
return; // Not restarting, run normal
|
|
35
38
|
}
|
|
36
39
|
|
|
37
|
-
|
|
38
|
-
void WatchUtil.watchCompilerEvents('file', () => WatchUtil.triggerRestartSignal(subProcess));
|
|
40
|
+
ShutdownManager.disableInterrupt();
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
let child: ChildProcess | undefined;
|
|
43
|
+
void WatchUtil.watchCompilerEvents('file', () => child && WatchUtil.triggerSignal(child, 'WATCH_RESTART'));
|
|
44
|
+
process.on('SIGINT', () => child && WatchUtil.triggerSignal(child, 'WATCH_SHUTDOWN'));
|
|
41
45
|
|
|
42
|
-
const
|
|
43
|
-
console.error(`[cli-restart] ${msg}`, { pid: process.pid, ...extra });
|
|
44
|
-
};
|
|
46
|
+
const env = { ...process.env, ...Env.TRV_RESTART_TARGET.export(true) };
|
|
45
47
|
|
|
46
48
|
await WatchUtil.runWithRetry(
|
|
47
49
|
async () => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
);
|
|
50
|
+
child = spawn(process.argv0, process.argv.slice(1), { env, stdio: ['pipe', 1, 2, 'ipc'] });
|
|
51
|
+
const { code } = await ExecUtil.deferToSubprocess(child);
|
|
51
52
|
return WatchUtil.exitCodeToResult(code);
|
|
52
53
|
},
|
|
53
54
|
{
|
|
54
55
|
maxRetries: 5,
|
|
55
56
|
onRetry: async (state, config) => {
|
|
56
57
|
const duration = WatchUtil.computeRestartDelay(state, config);
|
|
57
|
-
|
|
58
|
+
console.error(
|
|
59
|
+
'[cli-restart] Restarting subprocess due to change...',
|
|
60
|
+
{ waiting: duration, iteration: state.iteration, errorIterations: state.errorIterations || undefined }
|
|
61
|
+
);
|
|
58
62
|
await Util.nonBlockingTimeout(duration);
|
|
59
63
|
},
|
|
60
|
-
}
|
|
64
|
+
}
|
|
65
|
+
);
|
|
61
66
|
|
|
62
|
-
await ShutdownManager.
|
|
63
|
-
process.exit();
|
|
67
|
+
await ShutdownManager.shutdown();
|
|
64
68
|
}
|
|
65
69
|
|
|
66
70
|
/**
|
|
67
71
|
* Dispatch IPC payload
|
|
68
72
|
*/
|
|
69
|
-
static async runWithDebugIpc<T extends CliCommandShapeFields & CliCommandShape>(cmd: T): Promise<
|
|
73
|
+
static async runWithDebugIpc<T extends CliCommandShapeFields & CliCommandShape>(cmd: T): Promise<void> {
|
|
70
74
|
if (cmd.debugIpc !== true || !Env.TRV_CLI_IPC.isSet) {
|
|
71
|
-
return
|
|
75
|
+
return; // Not debugging, run normal
|
|
72
76
|
}
|
|
73
77
|
|
|
74
78
|
const info = await fetch(Env.TRV_CLI_IPC.value!).catch(() => ({ ok: false }));
|
|
75
79
|
|
|
76
|
-
if (!info.ok) {
|
|
77
|
-
return
|
|
80
|
+
if (!info.ok) {
|
|
81
|
+
return; // Server not running, run normal
|
|
78
82
|
}
|
|
79
83
|
|
|
80
84
|
const env: Record<string, string> = {};
|
|
@@ -91,7 +95,10 @@ export class CliUtil {
|
|
|
91
95
|
|
|
92
96
|
Object.entries(process.env).forEach(([key, value]) => validEnv(key) && (env[key] = value!));
|
|
93
97
|
const sent = await fetch(Env.TRV_CLI_IPC.value!, { method: 'POST', body: JSON.stringify(request) });
|
|
94
|
-
|
|
98
|
+
|
|
99
|
+
if (!sent.ok) {
|
|
100
|
+
throw new AppError(`IPC Request failed: ${sent.status} ${await sent.text()}`);
|
|
101
|
+
}
|
|
95
102
|
}
|
|
96
103
|
|
|
97
104
|
/**
|