@travetto/cli 6.0.0-rc.3 → 6.0.1

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
@@ -50,6 +50,7 @@ Commands:
50
50
  test:watch Invoke the test watcher
51
51
  web:http Run a web server
52
52
  web:rpc-client Generate the web-rpc client
53
+ web:server Run a web server
53
54
  ```
54
55
 
55
56
  This listing is from the [Travetto](https://travetto.dev) monorepo, and represents the majority of tools that can be invoked from the command line.
@@ -390,7 +391,7 @@ npx trv call:db --host localhost --port 3306 --username app --password <custom>
390
391
  ```
391
392
 
392
393
  ## 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 api for Web Applications with support for the dependency injection.") 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/decorators.ts#L84) decorator. This means the target will be visible within the editor tooling.
394
+ 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/decorators.ts#L84) decorator. This means the target will be visible within the editor tooling.
394
395
 
395
396
  **Code: Simple Run Target**
396
397
  ```typescript
@@ -458,11 +459,11 @@ export interface CliCommandShape<T extends unknown[] = unknown[]> {
458
459
  ```
459
460
 
460
461
  ### Dependency Injection
461
- If the goal is to run a more complex application, which may include depending on [Dependency Injection](https://github.com/travetto/travetto/tree/main/module/di#readme "Dependency registration/management and injection support."), we can take a look at [Web API](https://github.com/travetto/travetto/tree/main/module/web#readme "Declarative api for Web Applications with support for the dependency injection.")'s target:
462
+ If the goal is to run a more complex application, which may include depending on [Dependency Injection](https://github.com/travetto/travetto/tree/main/module/di#readme "Dependency registration/management and injection support."), we can take a look at [Web API](https://github.com/travetto/travetto/tree/main/module/web#readme "Declarative support for creating Web Applications")'s target:
462
463
 
463
464
  **Code: Simple Run Target**
464
465
  ```typescript
465
- import { Runtime, ShutdownManager, toConcrete } from '@travetto/runtime';
466
+ import { Runtime, toConcrete, Util } from '@travetto/runtime';
466
467
  import { DependencyRegistry } from '@travetto/di';
467
468
  import { CliCommand, CliCommandShape } from '@travetto/cli';
468
469
  import { NetUtil } from '@travetto/web';
@@ -492,18 +493,13 @@ export class WebHttpCommand implements CliCommandShape {
492
493
  await RootRegistry.init();
493
494
  const instance = await DependencyRegistry.getInstance(toConcrete<WebHttpServer>());
494
495
 
495
- let res;
496
- try {
497
- res = await instance.serve();
498
- } catch (err) {
499
- if (NetUtil.isPortUsedError(err) && !Runtime.production && this.killConflict) {
500
- await NetUtil.freePort(err.port);
501
- res = await instance.serve();
502
- }
503
- throw err;
504
- }
505
- ShutdownManager.onGracefulShutdown(res.kill, this);
506
- return res.wait;
496
+ const handle = await Util.acquireWithRetry(
497
+ () => instance.serve(),
498
+ NetUtil.freePortOnConflict,
499
+ this.killConflict && !Runtime.production ? 5 : 1
500
+ );
501
+
502
+ await handle.complete;
507
503
  }
508
504
  }
509
505
  ```
@@ -555,14 +551,14 @@ Options:
555
551
 
556
552
  Available Services
557
553
  --------------------
558
- * dynamodb@2.5.3
554
+ * dynamodb@2.6.1
559
555
  * elasticsearch@8.17.0
560
556
  * firestore@latest
561
557
  * mongodb@8.0
562
- * mysql@9.1
563
- * postgresql@17.2
564
- * redis@7.4
565
- * s3@3.12.0
558
+ * mysql@9.3
559
+ * postgresql@17.5
560
+ * redis@8.0
561
+ * s3@4.2.0
566
562
  ```
567
563
 
568
564
  A sample of all services available to the entire framework:
@@ -573,14 +569,14 @@ $ trv service status
573
569
 
574
570
  Service Version Status
575
571
  -------------------------------------------------
576
- dynamodb 2.5.3 Running 93af422e793a
572
+ dynamodb 2.6.1 Running 93af422e793a
577
573
  elasticsearch 8.17.0 Running ed76ee063d13
578
574
  firestore latest Running feec2e5e95b4
579
575
  mongodb 8.0 Running 5513eba6734e
580
- mysql 9.1 Running 307bc66d442a
581
- postgresql 17.2 Running e78291e71040
582
- redis 7.4 Running 77ba279b4e30
583
- s3 3.12.0 Running fdacfc55b9e3
576
+ mysql 9.3 Running 307bc66d442a
577
+ postgresql 17.5 Running e78291e71040
578
+ redis 8.0 Running 77ba279b4e30
579
+ s3 4.2.0 Running fdacfc55b9e3
584
580
  ```
585
581
 
586
582
  ### Defining new Services
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/cli",
3
- "version": "6.0.0-rc.3",
3
+ "version": "6.0.1",
4
4
  "description": "CLI infrastructure for Travetto framework",
5
5
  "keywords": [
6
6
  "cli",
@@ -28,8 +28,8 @@
28
28
  "directory": "module/cli"
29
29
  },
30
30
  "dependencies": {
31
- "@travetto/schema": "^6.0.0-rc.2",
32
- "@travetto/terminal": "^6.0.0-rc.2"
31
+ "@travetto/schema": "^6.0.1",
32
+ "@travetto/terminal": "^6.0.1"
33
33
  },
34
34
  "travetto": {
35
35
  "displayName": "Command Line Interface",
package/src/decorators.ts CHANGED
@@ -80,6 +80,7 @@ const FIELD_CONFIG: {
80
80
  * Decorator to register a CLI command
81
81
  * @augments `@travetto/schema:Schema`
82
82
  * @augments `@travetto/cli:CliCommand`
83
+ * @schemaMethods `main`
83
84
  */
84
85
  export function CliCommand(cfg: CliCommandConfigOptions = {}) {
85
86
  return function <T extends CliCommandShape>(target: Class<T>): void {
package/src/error.ts CHANGED
@@ -6,14 +6,13 @@ import { CliValidationError, CliCommandShape } from './types.ts';
6
6
 
7
7
  const COMMAND_PACKAGE = [
8
8
  [/^test(:watch)?$/, 'test', false],
9
- [/^service$/, 'command', true],
10
- [/^lint(:register)?$/, 'eslint', true],
9
+ [/^lint(:register)?$/, 'eslint', false],
11
10
  [/^model:(install|export)$/, 'model', true],
12
11
  [/^openapi:(spec|client)$/, 'openapi', true],
13
12
  [/^email:(compile|editor)$/, 'email-compiler', false],
14
13
  [/^pack(:zip|:docker)?$/, 'pack', false],
15
- [/^web:http$/, 'web-http-server', false],
16
- [/^web:rpc-client$/, 'web-rpc', false],
14
+ [/^web:(http|server)$/, 'web-http-server', true],
15
+ [/^web:rpc-client$/, 'web-rpc', true],
17
16
  ] as const;
18
17
 
19
18
  /**
package/src/execute.ts CHANGED
@@ -75,7 +75,7 @@ export class ExecutionManager {
75
75
  } catch (err) {
76
76
  await this.#onError(err);
77
77
  } finally {
78
- await ShutdownManager.gracefulShutdown();
78
+ await ShutdownManager.gracefulShutdown('@travetto/cli:execute');
79
79
  }
80
80
  }
81
81
  }
package/src/help.ts CHANGED
@@ -76,7 +76,7 @@ export class HelpUtil {
76
76
  const descWidth = Math.max(...descWidths);
77
77
 
78
78
  const helpText = await (command.help?.() ?? []);
79
- if (helpText.length && helpText[helpText.length - 1] !== '') {
79
+ if (helpText.length && helpText.at(-1) !== '') {
80
80
  helpText.push('');
81
81
  }
82
82
 
package/src/schema.ts CHANGED
@@ -46,16 +46,11 @@ const fieldToInput = (x: FieldConfig): CliCommandInput => ({
46
46
  */
47
47
  export class CliCommandSchemaUtil {
48
48
 
49
- static #schemas = new Map<Class, CliCommandSchema>();
50
-
51
49
  /**
52
50
  * Get schema for a given command
53
51
  */
54
52
  static async getSchema(src: Class | CliCommandShape): Promise<CliCommandSchema> {
55
53
  const cls = 'main' in src ? CliCommandRegistry.getClass(src) : src;
56
- if (this.#schemas.has(cls)) {
57
- return this.#schemas.get(cls)!;
58
- }
59
54
 
60
55
  // Ensure finalized
61
56
  const parent = SchemaRegistry.getParentClass(cls);
@@ -112,7 +107,7 @@ export class CliCommandSchemaUtil {
112
107
  title: fullSchema.title ?? cls.name,
113
108
  description: fullSchema.description ?? ''
114
109
  };
115
- this.#schemas.set(cls, cfg);
110
+
116
111
  return cfg;
117
112
  }
118
113
 
package/src/service.ts CHANGED
@@ -68,7 +68,7 @@ export class ServiceRunner {
68
68
  }
69
69
 
70
70
  async #hasImage(): Promise<boolean> {
71
- const result = await ExecUtil.getResult(spawn('docker', ['image', 'inspect', this.svc.image], { shell: false }), { catch: true });
71
+ const result = await ExecUtil.getResult(spawn('docker', ['image', 'inspect', this.svc.image]), { catch: true });
72
72
  return result.valid;
73
73
  }
74
74
 
@@ -96,15 +96,15 @@ export class ServiceRunner {
96
96
  await fs.mkdir(item, { recursive: true });
97
97
  }
98
98
 
99
- return (await ExecUtil.getResult(spawn('docker', args, { shell: false, stdio: [0, 'pipe', 2] }))).stdout;
99
+ return (await ExecUtil.getResult(spawn('docker', args, { stdio: [0, 'pipe', 2] }))).stdout;
100
100
  }
101
101
 
102
102
  async #getContainerId(): Promise<string | undefined> {
103
- return (await ExecUtil.getResult(spawn('docker', ['ps', '-q', '--filter', `label=trv-${this.svc.name}`], { shell: false }))).stdout.trim();
103
+ return (await ExecUtil.getResult(spawn('docker', ['ps', '-q', '--filter', `label=trv-${this.svc.name}`]))).stdout.trim();
104
104
  }
105
105
 
106
106
  async #killContainer(cid: string): Promise<void> {
107
- await ExecUtil.getResult(spawn('docker', ['kill', cid], { shell: false }));
107
+ await ExecUtil.getResult(spawn('docker', ['kill', cid]));
108
108
  }
109
109
 
110
110
  async * action(op: ServiceAction): AsyncIterable<['success' | 'failure' | 'message', string]> {
@@ -1,53 +0,0 @@
1
- import ts from 'typescript';
2
-
3
- import { TransformerState, DecoratorMeta, AfterClass } from '@travetto/transformer';
4
- import { SchemaTransformUtil } from '@travetto/schema/support/transformer/util.ts';
5
-
6
- /**
7
- * Converts classes with `@CliCommand` to `@Schema` and maps the main method
8
- */
9
- export class CliCommandTransformer {
10
-
11
- /**
12
- * On presence of `@CliCommand`
13
- */
14
- @AfterClass('CliCommand')
15
- static registerMainMethod(state: TransformerState, node: ts.ClassDeclaration, dm?: DecoratorMeta): typeof node {
16
- const dec = dm?.dec;
17
-
18
- if (!dec || !ts.isCallExpression(dec.expression)) { // If not valid
19
- return node;
20
- }
21
-
22
- // Find runnable method
23
- const mainMethod = node.members
24
- .find((x): x is ts.MethodDeclaration =>
25
- ts.isMethodDeclaration(x) && x.name!.getText() === 'main'
26
- );
27
-
28
- if (!mainMethod) {
29
- return node;
30
- }
31
-
32
- const members = node.members.map(x => ts.isMethodDeclaration(x) && x === mainMethod ?
33
- state.factory.updateMethodDeclaration(
34
- x,
35
- x.modifiers,
36
- x.asteriskToken,
37
- x.name,
38
- x.questionToken,
39
- x.typeParameters,
40
- x.parameters.map(y => SchemaTransformUtil.computeField(state, y)),
41
- x.type,
42
- x.body
43
- ) : x);
44
-
45
- return state.factory.updateClassDeclaration(node,
46
- node.modifiers,
47
- node.name,
48
- node.typeParameters,
49
- node.heritageClauses,
50
- members
51
- );
52
- }
53
- }