@travetto/cli 7.0.0-rc.4 → 7.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 CHANGED
@@ -59,7 +59,7 @@ This module also has a tight integration with the [VSCode plugin](https://market
59
59
  At it's heart, a cli command is the contract defined by what flags, and what arguments the command supports. Within the framework this requires three criteria to be met:
60
60
  * The file must be located in the `support/` folder, and have a name that matches `cli.*.ts`
61
61
  * The file must be a class that has a main method
62
- * The class must use the [@CliCommand](https://github.com/travetto/travetto/tree/main/module/cli/src/registry/decorator.ts#L85) decorator
62
+ * The class must use the [@CliCommand](https://github.com/travetto/travetto/tree/main/module/cli/src/registry/decorator.ts#L98) decorator
63
63
 
64
64
  **Code: Basic Command**
65
65
  ```typescript
@@ -94,7 +94,7 @@ Examples of mappings:
94
94
  The pattern is that underscores(_) translate to colons (:), and the `cli.` prefix, and `.ts` suffix are dropped.
95
95
 
96
96
  ## Binding Flags
97
- [@CliCommand](https://github.com/travetto/travetto/tree/main/module/cli/src/registry/decorator.ts#L85) is a wrapper for [@Schema](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/schema.ts#L19), and so every class that uses the [@CliCommand](https://github.com/travetto/travetto/tree/main/module/cli/src/registry/decorator.ts#L85) decorator is now a full [@Schema](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/schema.ts#L19) class. The fields of the class represent the flags that are available to the command.
97
+ [@CliCommand](https://github.com/travetto/travetto/tree/main/module/cli/src/registry/decorator.ts#L98) is a wrapper for [@Schema](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/schema.ts#L19), and so every class that uses the [@CliCommand](https://github.com/travetto/travetto/tree/main/module/cli/src/registry/decorator.ts#L98) decorator is now a full [@Schema](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/schema.ts#L19) class. The fields of the class represent the flags that are available to the command.
98
98
 
99
99
  **Code: Basic Command with Flag**
100
100
  ```typescript
@@ -131,7 +131,7 @@ $ trv basic:flag --loud
131
131
  HELLO
132
132
  ```
133
133
 
134
- The [@CliCommand](https://github.com/travetto/travetto/tree/main/module/cli/src/registry/decorator.ts#L85) supports the following data types for flags:
134
+ The [@CliCommand](https://github.com/travetto/travetto/tree/main/module/cli/src/registry/decorator.ts#L98) supports the following data types for flags:
135
135
  * Boolean values
136
136
  * Number values. The [@Integer](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/input.ts#L166), [@Float](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/input.ts#L173), [@Precision](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/input.ts#L159), [@Min](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/input.ts#L93) and [@Max](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/input.ts#L104) decorators help provide additional validation.
137
137
  * String values. [@MinLength](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/input.ts#L93), [@MaxLength](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/input.ts#L104), [@Match](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/input.ts#L84) and [@Enum](https://github.com/travetto/travetto/tree/main/module/schema/src/decorator/input.ts#L58) provide additional constraints
@@ -213,9 +213,9 @@ export class BasicCommand {
213
213
 
214
214
  **Terminal: Basic Command**
215
215
  ```bash
216
- $ trv basic:arglist -h
216
+ $ trv basic:arg-list -h
217
217
 
218
- Usage: basic:arglist [options] <volumes...:number>
218
+ Usage: basic:arg-list [options] <volumes...:number>
219
219
 
220
220
  Options:
221
221
  -r, --reverse
@@ -224,19 +224,19 @@ Options:
224
224
 
225
225
  **Terminal: Basic Arg List**
226
226
  ```bash
227
- $ trv basic:arglist 10 5 3 9 8 1
227
+ $ trv basic:arg-list 10 5 3 9 8 1
228
228
 
229
229
  1 3 5 8 9 10
230
230
  ```
231
231
 
232
232
  **Terminal: Basic Arg List with Invalid Number**
233
233
  ```bash
234
- $ trv basic:arglist 10 5 3 9 20 1
234
+ $ trv basic:arg-list 10 5 3 9 20 1
235
235
 
236
236
  Execution failed:
237
237
  * Argument volumes[4] is greater than (10)
238
238
 
239
- Usage: basic:arglist [options] <volumes...:number>
239
+ Usage: basic:arg-list [options] <volumes...:number>
240
240
 
241
241
  Options:
242
242
  -r, --reverse
@@ -245,7 +245,7 @@ Options:
245
245
 
246
246
  **Terminal: Basic Arg List with Reverse**
247
247
  ```bash
248
- $ trv basic:arglist -r 10 5 3 9 8 1
248
+ $ trv basic:arg-list -r 10 5 3 9 8 1
249
249
 
250
250
  10 9 8 5 3 1
251
251
  ```
@@ -390,7 +390,7 @@ npx trv call:db --host localhost --port 3306 --username app --password <custom>
390
390
  ```
391
391
 
392
392
  ## VSCode Integration
393
- By default, cli commands do not expose themselves to the VSCode extension, as the majority of them are not intended for that sort of operation. [Web API](https://github.com/travetto/travetto/tree/main/module/web#readme "Declarative support for creating Web Applications") does expose a cli target `web:http` that will show up, to help run/debug a web application. Any command can mark itself as being a run target, and will be eligible for running from within the [VSCode plugin](https://marketplace.visualstudio.com/items?itemName=arcsine.travetto-plugin). This is achieved by setting the `runTarget` field on the [@CliCommand](https://github.com/travetto/travetto/tree/main/module/cli/src/registry/decorator.ts#L85) decorator. This means the target will be visible within the editor tooling.
393
+ By default, cli commands do not expose themselves to the VSCode extension, as the majority of them are not intended for that sort of operation. [Web API](https://github.com/travetto/travetto/tree/main/module/web#readme "Declarative support for creating Web Applications") does expose a cli target `web:http` that will show up, to help run/debug a web application. Any command can mark itself as being a run target, and will be eligible for running from within the [VSCode plugin](https://marketplace.visualstudio.com/items?itemName=arcsine.travetto-plugin). This is achieved by setting the `runTarget` field on the [@CliCommand](https://github.com/travetto/travetto/tree/main/module/cli/src/registry/decorator.ts#L98) decorator. This means the target will be visible within the editor tooling.
394
394
 
395
395
  **Code: Simple Run Target**
396
396
  ```typescript
@@ -472,7 +472,7 @@ import type { WebHttpServer } from '../src/types.ts';
472
472
  /**
473
473
  * Run a web server
474
474
  */
475
- @CliCommand({ runTarget: true, with: { debugIpc: true, restartForDev: true, module: true, env: true } })
475
+ @CliCommand({ runTarget: true, with: { debugIpc: 'optional', restartOnChange: true, module: true, env: true } })
476
476
  export class WebHttpCommand implements CliCommandShape {
477
477
 
478
478
  /** Port to run on */
@@ -502,7 +502,7 @@ export class WebHttpCommand implements CliCommandShape {
502
502
  }
503
503
  ```
504
504
 
505
- 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.
505
+ 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#L12) `name` defined in the [Runtime](https://github.com/travetto/travetto/tree/main/module/runtime#readme "Runtime for travetto applications.") module.
506
506
 
507
507
  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.
508
508
 
@@ -550,13 +550,13 @@ Options:
550
550
  Available Services
551
551
  --------------------
552
552
  * dynamodb@3.1.0
553
- * elasticsearch@9.2.1
553
+ * elasticsearch@9.2.3
554
554
  * firestore@latest
555
555
  * mongodb@8.2
556
556
  * mysql@9.5
557
557
  * postgresql@18.1
558
558
  * redis@8.4
559
- * s3@4.10.0
559
+ * s3@4.11.0
560
560
  ```
561
561
 
562
562
  A sample of all services available to the entire framework:
@@ -568,13 +568,13 @@ $ trv service status
568
568
  Service Version Status
569
569
  -------------------------------------------------
570
570
  dynamodb 3.1.0 Running 93af422e793a
571
- elasticsearch 9.2.1 Running ed76ee063d13
571
+ elasticsearch 9.2.3 Running ed76ee063d13
572
572
  firestore latest Running feec2e5e95b4
573
573
  mongodb 8.2 Running 5513eba6734e
574
574
  mysql 9.5 Running 307bc66d442a
575
575
  postgresql 18.1 Running e78291e71040
576
576
  redis 8.4 Running 77ba279b4e30
577
- s3 4.10.0 Running fdacfc55b9e3
577
+ s3 4.11.0 Running fdacfc55b9e3
578
578
  ```
579
579
 
580
580
  ### Defining new Services
package/bin/trv.js CHANGED
@@ -1,7 +1,4 @@
1
1
  #!/usr/bin/env node
2
-
3
- globalThis.__entry_point__ = __filename;
4
-
5
2
  // @ts-check
6
- require('@travetto/compiler/bin/entry.common.js')
7
- .load(operations => operations.exec('@travetto/cli/support/entry.trv.js'));
3
+ import { load } from '@travetto/compiler/bin/entry.common.js';
4
+ load(operations => operations.exec('@travetto/cli/support/entry.trv.js'));
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@travetto/cli",
3
- "version": "7.0.0-rc.4",
3
+ "version": "7.0.0",
4
+ "type": "module",
4
5
  "description": "CLI infrastructure for Travetto framework",
5
6
  "keywords": [
6
7
  "cli",
@@ -28,8 +29,8 @@
28
29
  "directory": "module/cli"
29
30
  },
30
31
  "dependencies": {
31
- "@travetto/schema": "^7.0.0-rc.4",
32
- "@travetto/terminal": "^7.0.0-rc.4"
32
+ "@travetto/schema": "^7.0.0",
33
+ "@travetto/terminal": "^7.0.0"
33
34
  },
34
35
  "travetto": {
35
36
  "displayName": "Command Line Interface",
@@ -1,4 +1,4 @@
1
- import { Class, ClassInstance, Env, Runtime, RuntimeIndex, describeFunction, getClass } from '@travetto/runtime';
1
+ import { Class, ClassInstance, Env, Runtime, RuntimeIndex, TypedObject, castTo, describeFunction, getClass } from '@travetto/runtime';
2
2
  import { SchemaFieldConfig, SchemaRegistryIndex, ValidationError } from '@travetto/schema';
3
3
 
4
4
  import { CliCommandShape } from '../types.ts';
@@ -18,19 +18,23 @@ type CliCommandConfigOptions = {
18
18
  /** Module to run for */
19
19
  module?: boolean;
20
20
  /** Should debug invocation trigger via ipc */
21
- debugIpc?: boolean;
22
- /** Should restart on code change */
23
- restartForDev?: boolean;
21
+ debugIpc?: boolean | 'optional';
22
+ /** Should restart on source change */
23
+ restartOnChange?: boolean | 'optional';
24
24
  };
25
25
  };
26
26
 
27
- const FIELD_CONFIG: {
28
- name: keyof Exclude<CliCommandConfigOptions['with'], undefined>;
27
+ type WithConfig = Required<Exclude<CliCommandConfigOptions['with'], undefined>>;
28
+ type WithHandler<K extends keyof WithConfig> = (config?: WithConfig[K]) => ({
29
+ name: K;
29
30
  field: Partial<SchemaFieldConfig>;
30
- run: (cmd: Cmd) => (Promise<unknown> | unknown);
31
- }[] =
32
- [
33
- {
31
+ run?: (cmd: Cmd) => (Promise<unknown> | unknown);
32
+ } | undefined)
33
+
34
+ const FIELD_CONFIG: { [K in keyof WithConfig]: WithHandler<K> } = {
35
+ env: (config) => {
36
+ if (!config) return;
37
+ return {
34
38
  name: 'env',
35
39
  run: cmd => Env.TRV_ENV.set(cmd.env || Runtime.env),
36
40
  field: {
@@ -39,10 +43,12 @@ const FIELD_CONFIG: {
39
43
  description: 'Application environment',
40
44
  required: { active: false },
41
45
  },
42
- },
43
- {
46
+ }
47
+ },
48
+ module: (config) => {
49
+ if (!config) return;
50
+ return {
44
51
  name: 'module',
45
- run: (): void => { },
46
52
  field: {
47
53
  type: String,
48
54
  aliases: ['-m', CliParseUtil.toEnvField(Env.TRV_MODULE.key)],
@@ -50,36 +56,43 @@ const FIELD_CONFIG: {
50
56
  specifiers: ['module'],
51
57
  required: { active: Runtime.monoRoot },
52
58
  },
53
- },
54
- {
59
+ }
60
+ },
61
+ debugIpc: (config) => {
62
+ if (!config) return;
63
+ return {
55
64
  name: 'debugIpc',
56
- run: cmd => CliUtil.debugIfIpc(cmd).then((executed) => executed && process.exit(0)),
65
+ run: cmd => CliUtil.runWithDebugIpc(cmd).then((executed) => executed && process.exit(0)),
57
66
  field: {
58
67
  type: Boolean,
59
- aliases: ['-di'],
68
+ aliases: ['-di', CliParseUtil.toEnvField(Env.TRV_DEBUG_IPC.key)],
60
69
  description: 'Should debug invocation trigger via ipc',
61
- default: true,
70
+ default: config !== 'optional',
62
71
  required: { active: false },
63
72
  },
64
- },
65
- {
66
- name: 'restartForDev',
67
- run: cmd => CliUtil.runWithRestartOnCodeChanges(cmd),
73
+ };
74
+ },
75
+ restartOnChange: (config) => {
76
+ if (!config) return;
77
+ return {
78
+ name: 'restartOnChange',
79
+ run: cmd => CliUtil.runWithRestartOnChange(cmd),
68
80
  field: {
69
81
  type: Boolean,
70
- aliases: ['-cr'],
82
+ aliases: ['-rc', CliParseUtil.toEnvField(Env.TRV_RESTART_ON_CHANGE.key)],
71
83
  description: 'Should the invocation automatically restart on source changes',
72
- default: Runtime.envType === 'development',
84
+ default: config !== 'optional' && Runtime.envType === 'development',
73
85
  required: { active: false },
74
86
  },
75
- }
76
- ];
87
+ };
88
+ }
89
+ };
77
90
 
78
91
  /**
79
92
  * Decorator to register a CLI command
80
93
  *
81
94
  * @augments `@travetto/schema:Schema`
82
- * @example main
95
+ * @example method:main
83
96
  * @kind decorator
84
97
  */
85
98
  export function CliCommand(config: CliCommandConfigOptions = {}) {
@@ -91,13 +104,13 @@ export function CliCommand(config: CliCommandConfigOptions = {}) {
91
104
  return;
92
105
  }
93
106
 
94
- const VALID_FIELDS = FIELD_CONFIG.filter(field => !!config.with?.[field.name]);
107
+ const VALID_FIELDS = TypedObject.keys(FIELD_CONFIG).map((name) => FIELD_CONFIG[name](castTo(config.with?.[name]))).filter(x => !!x);
95
108
 
96
109
  CliCommandRegistryIndex.getForRegister(target).register({
97
110
  runTarget: config.runTarget,
98
111
  preMain: async (cmd: Cmd) => {
99
112
  for (const field of VALID_FIELDS) {
100
- await field.run(cmd);
113
+ await field.run?.(cmd);
101
114
  }
102
115
  }
103
116
  });
@@ -105,7 +118,8 @@ export function CliCommand(config: CliCommandConfigOptions = {}) {
105
118
  const commandModule = description.module;
106
119
 
107
120
  for (const { name, field: { type, ...field } } of VALID_FIELDS) {
108
- adapter.registerField(name, field, { type });
121
+ adapter.registerField(name, { type }, field);
122
+ Object.defineProperty(target.prototype, name, { value: field.default, writable: true });
109
123
  }
110
124
 
111
125
  const runtimeModule = config.runtimeModule ?? (config.with?.module ? 'current' : undefined);
@@ -80,7 +80,6 @@ export class CliCommandRegistryIndex implements RegistryIndex {
80
80
  const uninitialized = filtered
81
81
  .filter(cls => !this.store.finalized(cls));
82
82
 
83
-
84
83
  // Initialize any uninitialized commands
85
84
  if (uninitialized.length) {
86
85
  // Ensure processed
package/src/trv.d.ts CHANGED
@@ -8,8 +8,12 @@ declare module '@travetto/runtime' {
8
8
  */
9
9
  TRV_CLI_IPC: string;
10
10
  /**
11
- * Determines (assuming the operation supports it), that restart behavior can trigger
11
+ * Overrides behavior for allowing restart on changes
12
12
  */
13
- TRV_CAN_RESTART: boolean;
13
+ TRV_RESTART_ON_CHANGE: boolean;
14
+ /**
15
+ * Overrides behavior for triggering debug session via IPC
16
+ */
17
+ TRV_DEBUG_IPC: boolean;
14
18
  }
15
19
  }
package/src/types.ts CHANGED
@@ -90,7 +90,7 @@ export type CliCommandShapeFields = {
90
90
  /**
91
91
  * Should the invocation run with auto-restart on source changes
92
92
  */
93
- restartForDev?: boolean;
93
+ restartOnChange?: boolean;
94
94
  /**
95
95
  * The module to run the command from
96
96
  */
package/src/util.ts CHANGED
@@ -37,9 +37,8 @@ export class CliUtil {
37
37
  /**
38
38
  * Run a command as restartable, linking into self
39
39
  */
40
- static async runWithRestartOnCodeChanges<T extends CliCommandShapeFields & CliCommandShape>(cmd: T, config?: RunWithRestartOptions): Promise<boolean> {
41
-
42
- if (Env.TRV_CAN_RESTART.isFalse || cmd.restartForDev !== true) {
40
+ static async runWithRestartOnChange<T extends CliCommandShapeFields & CliCommandShape>(cmd: T, config?: RunWithRestartOptions): Promise<boolean> {
41
+ if (cmd.restartOnChange !== true) {
43
42
  process.on('message', event => isCodeRestart(event) && process.exit(event.code));
44
43
  return false;
45
44
  }
@@ -48,7 +47,7 @@ export class CliUtil {
48
47
  let exhaustedRestarts = false;
49
48
  let subProcess: ChildProcess | undefined;
50
49
 
51
- const env = { ...process.env, ...Env.TRV_CAN_RESTART.export(false) };
50
+ const env = { ...process.env, ...Env.TRV_RESTART_ON_CHANGE.export(false) };
52
51
  const maxRetries = config?.maxRetriesPerMinute ?? 5;
53
52
  const relayInterrupt = config?.relayInterrupt ?? true;
54
53
  const restarts: number[] = [];
@@ -92,7 +91,6 @@ export class CliUtil {
92
91
  restarts.push(Date.now());
93
92
  }
94
93
 
95
-
96
94
  if (exhaustedRestarts) {
97
95
  console.error(`Bailing, due to ${maxRetries} restarts in under 10s`);
98
96
  }
@@ -104,8 +102,8 @@ export class CliUtil {
104
102
  /**
105
103
  * Dispatch IPC payload
106
104
  */
107
- static async triggerIpc<T extends CliCommandShape>(action: 'run', cmd: T): Promise<boolean> {
108
- if (!Env.TRV_CLI_IPC.isSet) {
105
+ static async runWithDebugIpc<T extends CliCommandShapeFields & CliCommandShape>(cmd: T): Promise<boolean> {
106
+ if (cmd.debugIpc !== true || !Env.TRV_CLI_IPC.isSet) {
109
107
  return false;
110
108
  }
111
109
 
@@ -117,7 +115,7 @@ export class CliUtil {
117
115
 
118
116
  const env: Record<string, string> = {};
119
117
  const request = {
120
- type: `@travetto/cli:${action}`,
118
+ type: `@travetto/cli:run`,
121
119
  data: {
122
120
  name: cmd._cfg!.name,
123
121
  env,
@@ -134,13 +132,6 @@ export class CliUtil {
134
132
  return sent.ok;
135
133
  }
136
134
 
137
- /**
138
- * Debug if IPC available
139
- */
140
- static async debugIfIpc<T extends CliCommandShapeFields & CliCommandShape>(cmd: T): Promise<boolean> {
141
- return cmd.debugIpc === true && this.triggerIpc('run', cmd);
142
- }
143
-
144
135
  /**
145
136
  * Write data to channel and ensure its flushed before continuing
146
137
  */
@@ -7,7 +7,6 @@ import { CliCommandRegistryIndex } from '../src/registry/registry-index.ts';
7
7
  import { CliUtil } from '../src/util.ts';
8
8
  import { CliSchemaExportUtil } from '../src/schema-export.ts';
9
9
 
10
-
11
10
  /**
12
11
  * Generates the schema for all CLI operations
13
12
  */