@navios/commander 0.5.1 → 0.7.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/CHANGELOG.md +32 -0
- package/README.md +56 -8
- package/dist/src/commander.application.d.mts +124 -6
- package/dist/src/commander.application.d.mts.map +1 -1
- package/dist/src/commander.factory.d.mts +31 -3
- package/dist/src/commander.factory.d.mts.map +1 -1
- package/dist/src/decorators/cli-module.decorator.d.mts +36 -1
- package/dist/src/decorators/cli-module.decorator.d.mts.map +1 -1
- package/dist/src/decorators/command.decorator.d.mts +44 -1
- package/dist/src/decorators/command.decorator.d.mts.map +1 -1
- package/dist/src/index.d.mts +2 -1
- package/dist/src/index.d.mts.map +1 -1
- package/dist/src/interfaces/command-handler.interface.d.mts +33 -0
- package/dist/src/interfaces/command-handler.interface.d.mts.map +1 -1
- package/dist/src/interfaces/commander-execution-context.interface.d.mts +54 -0
- package/dist/src/interfaces/commander-execution-context.interface.d.mts.map +1 -0
- package/dist/src/interfaces/index.d.mts +1 -1
- package/dist/src/interfaces/index.d.mts.map +1 -1
- package/dist/src/interfaces/module.interface.d.mts +1 -4
- package/dist/src/interfaces/module.interface.d.mts.map +1 -1
- package/dist/src/metadata/cli-module.metadata.d.mts +46 -1
- package/dist/src/metadata/cli-module.metadata.d.mts.map +1 -1
- package/dist/src/metadata/command.metadata.d.mts +48 -1
- package/dist/src/metadata/command.metadata.d.mts.map +1 -1
- package/dist/src/services/cli-parser.service.d.mts +32 -1
- package/dist/src/services/cli-parser.service.d.mts.map +1 -1
- package/dist/src/services/module-loader.service.d.mts +44 -5
- package/dist/src/services/module-loader.service.d.mts.map +1 -1
- package/dist/src/tokens/execution-context.token.d.mts +27 -0
- package/dist/src/tokens/execution-context.token.d.mts.map +1 -0
- package/dist/src/tokens/index.d.mts +2 -0
- package/dist/src/tokens/index.d.mts.map +1 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/tsdown.config.d.mts +3 -0
- package/dist/tsdown.config.d.mts.map +1 -0
- package/lib/index.cjs +7721 -0
- package/lib/index.cjs.map +1 -0
- package/lib/index.d.cts +670 -0
- package/lib/index.d.cts.map +1 -0
- package/lib/index.d.mts +670 -98
- package/lib/index.d.mts.map +1 -0
- package/lib/index.mjs +7511 -565
- package/lib/index.mjs.map +1 -1
- package/package.json +5 -5
- package/project.json +2 -2
- package/src/commander.application.mts +161 -17
- package/src/commander.factory.mts +32 -4
- package/src/decorators/cli-module.decorator.mts +37 -2
- package/src/decorators/command.decorator.mts +45 -2
- package/src/index.mts +5 -1
- package/src/interfaces/command-handler.interface.mts +33 -0
- package/src/interfaces/commander-execution-context.interface.mts +64 -0
- package/src/interfaces/index.mts +1 -1
- package/src/metadata/cli-module.metadata.mts +48 -7
- package/src/metadata/command.metadata.mts +48 -1
- package/src/services/__tests__/cli-parser.service.spec.mts +15 -11
- package/src/services/cli-parser.service.mts +35 -3
- package/src/services/module-loader.service.mts +45 -6
- package/src/tokens/execution-context.token.mts +34 -0
- package/src/tokens/index.mts +1 -0
- package/tsdown.config.mts +33 -0
- package/lib/_tsup-dts-rollup.d.mts +0 -466
- package/lib/_tsup-dts-rollup.d.ts +0 -466
- package/lib/index.d.ts +0 -98
- package/lib/index.js +0 -604
- package/lib/index.js.map +0 -1
- package/src/interfaces/module.interface.mts +0 -4
- package/tsup.config.mts +0 -12
|
@@ -1,14 +1,42 @@
|
|
|
1
|
-
import type { ClassType } from '@navios/
|
|
1
|
+
import type { ClassType } from '@navios/core'
|
|
2
2
|
import type { ZodObject } from 'zod'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @internal
|
|
6
|
+
* Symbol key used to store command metadata on classes.
|
|
7
|
+
*/
|
|
4
8
|
export const CommandMetadataKey = Symbol('CommandMetadataKey')
|
|
5
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Metadata associated with a command.
|
|
12
|
+
*
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
6
15
|
export interface CommandMetadata {
|
|
16
|
+
/**
|
|
17
|
+
* The command path (e.g., 'greet', 'user:create').
|
|
18
|
+
*/
|
|
7
19
|
path: string
|
|
20
|
+
/**
|
|
21
|
+
* Optional Zod schema for validating command options.
|
|
22
|
+
*/
|
|
8
23
|
optionsSchema?: ZodObject
|
|
24
|
+
/**
|
|
25
|
+
* Map of custom attributes that can be attached to the command.
|
|
26
|
+
*/
|
|
9
27
|
customAttributes: Map<string | symbol, any>
|
|
10
28
|
}
|
|
11
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Gets or creates command metadata for a class.
|
|
32
|
+
*
|
|
33
|
+
* @internal
|
|
34
|
+
* @param target - The command class
|
|
35
|
+
* @param context - The decorator context
|
|
36
|
+
* @param path - The command path
|
|
37
|
+
* @param optionsSchema - Optional Zod schema
|
|
38
|
+
* @returns The command metadata
|
|
39
|
+
*/
|
|
12
40
|
export function getCommandMetadata(
|
|
13
41
|
target: ClassType,
|
|
14
42
|
context: ClassDecoratorContext,
|
|
@@ -36,6 +64,19 @@ export function getCommandMetadata(
|
|
|
36
64
|
throw new Error('[Navios Commander] Wrong environment.')
|
|
37
65
|
}
|
|
38
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Extracts command metadata from a class.
|
|
69
|
+
*
|
|
70
|
+
* @param target - The command class
|
|
71
|
+
* @returns The command metadata
|
|
72
|
+
* @throws {Error} If the class is not decorated with @Command
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* const metadata = extractCommandMetadata(GreetCommand)
|
|
77
|
+
* console.log(metadata.path) // 'greet'
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
39
80
|
export function extractCommandMetadata(target: ClassType): CommandMetadata {
|
|
40
81
|
// @ts-expect-error We add a custom metadata key to the target
|
|
41
82
|
const metadata = target[CommandMetadataKey] as CommandMetadata | undefined
|
|
@@ -47,6 +88,12 @@ export function extractCommandMetadata(target: ClassType): CommandMetadata {
|
|
|
47
88
|
return metadata
|
|
48
89
|
}
|
|
49
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Checks if a class has command metadata.
|
|
93
|
+
*
|
|
94
|
+
* @param target - The class to check
|
|
95
|
+
* @returns `true` if the class is decorated with @Command, `false` otherwise
|
|
96
|
+
*/
|
|
50
97
|
export function hasCommandMetadata(target: ClassType): boolean {
|
|
51
98
|
// @ts-expect-error We add a custom metadata key to the target
|
|
52
99
|
const metadata = target[CommandMetadataKey] as CommandMetadata | undefined
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Container } from '@navios/
|
|
1
|
+
import { Container } from '@navios/core'
|
|
2
2
|
|
|
3
3
|
import { beforeEach, describe, expect, it } from 'vitest'
|
|
4
4
|
import { z } from 'zod'
|
|
@@ -434,14 +434,7 @@ describe('CliParserService', () => {
|
|
|
434
434
|
})
|
|
435
435
|
|
|
436
436
|
const result = parser.parse(
|
|
437
|
-
[
|
|
438
|
-
'node',
|
|
439
|
-
'script.js',
|
|
440
|
-
'test',
|
|
441
|
-
'--tags=foo',
|
|
442
|
-
'--tags=bar',
|
|
443
|
-
'--tags=baz',
|
|
444
|
-
],
|
|
437
|
+
['node', 'script.js', 'test', '--tags=foo', '--tags=bar', '--tags=baz'],
|
|
445
438
|
schema,
|
|
446
439
|
)
|
|
447
440
|
|
|
@@ -600,12 +593,23 @@ describe('CliParserService', () => {
|
|
|
600
593
|
})
|
|
601
594
|
|
|
602
595
|
const result = parser.parse(
|
|
603
|
-
[
|
|
596
|
+
[
|
|
597
|
+
'node',
|
|
598
|
+
'script.js',
|
|
599
|
+
'test',
|
|
600
|
+
'--items',
|
|
601
|
+
'[1,2,3]',
|
|
602
|
+
'--items',
|
|
603
|
+
'["a","b"]',
|
|
604
|
+
],
|
|
604
605
|
schema,
|
|
605
606
|
)
|
|
606
607
|
|
|
607
608
|
expect(result.options).toEqual({
|
|
608
|
-
items: [
|
|
609
|
+
items: [
|
|
610
|
+
[1, 2, 3],
|
|
611
|
+
['a', 'b'],
|
|
612
|
+
],
|
|
609
613
|
})
|
|
610
614
|
})
|
|
611
615
|
|
|
@@ -1,13 +1,41 @@
|
|
|
1
1
|
import type { ZodObject, ZodType } from 'zod'
|
|
2
2
|
|
|
3
|
-
import { Injectable } from '@navios/
|
|
3
|
+
import { Injectable } from '@navios/core'
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Result of parsing command-line arguments.
|
|
7
|
+
*
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
5
10
|
export interface ParsedCliArgs {
|
|
11
|
+
/**
|
|
12
|
+
* The command path (e.g., 'greet', 'user:create').
|
|
13
|
+
* Multi-word commands are joined with spaces.
|
|
14
|
+
*/
|
|
6
15
|
command: string
|
|
16
|
+
/**
|
|
17
|
+
* Parsed options as key-value pairs.
|
|
18
|
+
* Keys are converted from kebab-case to camelCase.
|
|
19
|
+
*/
|
|
7
20
|
options: Record<string, any>
|
|
21
|
+
/**
|
|
22
|
+
* Positional arguments that don't match any option flags.
|
|
23
|
+
*/
|
|
8
24
|
positionals: string[]
|
|
9
25
|
}
|
|
10
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Service for parsing command-line arguments.
|
|
29
|
+
*
|
|
30
|
+
* Handles parsing of various CLI argument formats including:
|
|
31
|
+
* - Long options: `--key value` or `--key=value`
|
|
32
|
+
* - Short options: `-k value` or `-abc` (multiple flags)
|
|
33
|
+
* - Boolean flags
|
|
34
|
+
* - Array options
|
|
35
|
+
* - Positional arguments
|
|
36
|
+
*
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
11
39
|
@Injectable()
|
|
12
40
|
export class CliParserService {
|
|
13
41
|
/**
|
|
@@ -63,7 +91,8 @@ export class CliParserService {
|
|
|
63
91
|
const optionName = key.slice(0, equalIndex)
|
|
64
92
|
const optionValue = key.slice(equalIndex + 1)
|
|
65
93
|
const camelCaseKey = this.camelCase(optionName)
|
|
66
|
-
const isArray =
|
|
94
|
+
const isArray =
|
|
95
|
+
arrayFields.has(camelCaseKey) || arrayFields.has(optionName)
|
|
67
96
|
|
|
68
97
|
if (isArray) {
|
|
69
98
|
// For array fields, accumulate values
|
|
@@ -298,7 +327,10 @@ export class CliParserService {
|
|
|
298
327
|
}
|
|
299
328
|
|
|
300
329
|
/**
|
|
301
|
-
* Formats help text
|
|
330
|
+
* Formats help text listing all available commands.
|
|
331
|
+
*
|
|
332
|
+
* @param commands - Array of command objects with path and class
|
|
333
|
+
* @returns Formatted string listing all commands
|
|
302
334
|
*/
|
|
303
335
|
formatCommandList(commands: Array<{ path: string; class: any }>): string {
|
|
304
336
|
const lines = ['Available commands:', '']
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { ClassTypeWithInstance } from '@navios/
|
|
1
|
+
import type { ClassTypeWithInstance, NaviosModule } from '@navios/core'
|
|
2
2
|
|
|
3
|
-
import { Container, inject, Injectable } from '@navios/
|
|
3
|
+
import { Container, inject, Injectable } from '@navios/core'
|
|
4
4
|
|
|
5
|
-
import type { CommandHandler
|
|
5
|
+
import type { CommandHandler } from '../interfaces/index.mjs'
|
|
6
6
|
import type { CliModuleMetadata, CommandMetadata } from '../metadata/index.mjs'
|
|
7
7
|
|
|
8
8
|
import {
|
|
@@ -10,20 +10,46 @@ import {
|
|
|
10
10
|
extractCommandMetadata,
|
|
11
11
|
} from '../metadata/index.mjs'
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Command class with its associated metadata.
|
|
15
|
+
*
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
13
18
|
export interface CommandWithMetadata {
|
|
19
|
+
/**
|
|
20
|
+
* The command class constructor.
|
|
21
|
+
*/
|
|
14
22
|
class: ClassTypeWithInstance<CommandHandler>
|
|
23
|
+
/**
|
|
24
|
+
* The command metadata including path and options schema.
|
|
25
|
+
*/
|
|
15
26
|
metadata: CommandMetadata
|
|
16
27
|
}
|
|
17
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Service for loading and managing CLI modules and commands.
|
|
31
|
+
*
|
|
32
|
+
* Handles module traversal, command registration, and metadata collection.
|
|
33
|
+
* This service is used internally by CommanderApplication.
|
|
34
|
+
*
|
|
35
|
+
* @public
|
|
36
|
+
*/
|
|
18
37
|
@Injectable()
|
|
19
|
-
export class
|
|
38
|
+
export class CliModuleLoaderService {
|
|
20
39
|
protected container = inject(Container)
|
|
21
40
|
private modulesMetadata: Map<string, CliModuleMetadata> = new Map()
|
|
22
41
|
private loadedModules: Map<string, any> = new Map()
|
|
23
42
|
private commandsMetadata: Map<string, CommandWithMetadata> = new Map()
|
|
24
43
|
private initialized = false
|
|
25
44
|
|
|
26
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Loads all modules starting from the root app module.
|
|
47
|
+
*
|
|
48
|
+
* Traverses the module tree, loads imported modules, and collects command metadata.
|
|
49
|
+
*
|
|
50
|
+
* @param appModule - The root CLI module
|
|
51
|
+
*/
|
|
52
|
+
async loadModules(appModule: ClassTypeWithInstance<NaviosModule>) {
|
|
27
53
|
if (this.initialized) {
|
|
28
54
|
return
|
|
29
55
|
}
|
|
@@ -32,7 +58,7 @@ export class ModuleLoaderService {
|
|
|
32
58
|
}
|
|
33
59
|
|
|
34
60
|
private async traverseModules(
|
|
35
|
-
module: ClassTypeWithInstance<
|
|
61
|
+
module: ClassTypeWithInstance<NaviosModule>,
|
|
36
62
|
parentMetadata?: CliModuleMetadata,
|
|
37
63
|
) {
|
|
38
64
|
const metadata = extractCliModuleMetadata(module)
|
|
@@ -80,10 +106,20 @@ export class ModuleLoaderService {
|
|
|
80
106
|
}
|
|
81
107
|
}
|
|
82
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Gets all loaded module metadata.
|
|
111
|
+
*
|
|
112
|
+
* @returns Map of module names to their metadata
|
|
113
|
+
*/
|
|
83
114
|
getAllModules(): Map<string, CliModuleMetadata> {
|
|
84
115
|
return this.modulesMetadata
|
|
85
116
|
}
|
|
86
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Gets all command classes indexed by command class name.
|
|
120
|
+
*
|
|
121
|
+
* @returns Map of command class names to command classes
|
|
122
|
+
*/
|
|
87
123
|
getAllCommands(): Map<string, ClassTypeWithInstance<any>> {
|
|
88
124
|
const commands = new Map<string, ClassTypeWithInstance<any>>()
|
|
89
125
|
for (const metadata of this.modulesMetadata.values()) {
|
|
@@ -111,6 +147,9 @@ export class ModuleLoaderService {
|
|
|
111
147
|
return this.commandsMetadata.get(path)
|
|
112
148
|
}
|
|
113
149
|
|
|
150
|
+
/**
|
|
151
|
+
* Disposes of all loaded modules and commands, clearing internal state.
|
|
152
|
+
*/
|
|
114
153
|
dispose() {
|
|
115
154
|
this.modulesMetadata.clear()
|
|
116
155
|
this.loadedModules.clear()
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { InjectionToken } from '@navios/core'
|
|
2
|
+
|
|
3
|
+
import type { CommanderExecutionContext } from '../interfaces/index.mjs'
|
|
4
|
+
|
|
5
|
+
const CommandExecutionContextInjectionToken =
|
|
6
|
+
'CommanderExecutionContextInjectionToken'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Injection token for accessing the current command execution context.
|
|
10
|
+
*
|
|
11
|
+
* Use this token with `inject()` to access the `CommanderExecutionContext` in services
|
|
12
|
+
* that need information about the currently executing command.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { inject, Injectable } from '@navios/di'
|
|
17
|
+
* import { CommandExecutionContext } from '@navios/commander'
|
|
18
|
+
*
|
|
19
|
+
* @Injectable()
|
|
20
|
+
* class MyService {
|
|
21
|
+
* private ctx = inject(CommandExecutionContext)
|
|
22
|
+
*
|
|
23
|
+
* doSomething() {
|
|
24
|
+
* const commandPath = this.ctx.getCommandPath()
|
|
25
|
+
* const options = this.ctx.getOptions()
|
|
26
|
+
* // Use context information...
|
|
27
|
+
* }
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export const CommandExecutionContext =
|
|
32
|
+
InjectionToken.create<CommanderExecutionContext>(
|
|
33
|
+
CommandExecutionContextInjectionToken,
|
|
34
|
+
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './execution-context.token.mjs'
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { withFilter } from 'rolldown/filter'
|
|
2
|
+
import { defineConfig } from 'tsdown'
|
|
3
|
+
import swc from 'unplugin-swc'
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
entry: ['src/index.mts'],
|
|
7
|
+
outDir: 'lib',
|
|
8
|
+
format: ['esm', 'cjs'],
|
|
9
|
+
clean: true,
|
|
10
|
+
treeshake: true,
|
|
11
|
+
sourcemap: true,
|
|
12
|
+
platform: 'node',
|
|
13
|
+
dts: true,
|
|
14
|
+
target: 'es2022',
|
|
15
|
+
plugins: [
|
|
16
|
+
withFilter(
|
|
17
|
+
swc.rolldown({
|
|
18
|
+
jsc: {
|
|
19
|
+
target: 'es2022',
|
|
20
|
+
parser: {
|
|
21
|
+
syntax: 'typescript',
|
|
22
|
+
decorators: true,
|
|
23
|
+
},
|
|
24
|
+
transform: {
|
|
25
|
+
decoratorVersion: '2022-03',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
}),
|
|
29
|
+
// Only run this transform if the file contains a decorator.
|
|
30
|
+
{ transform: { code: '@' } },
|
|
31
|
+
),
|
|
32
|
+
],
|
|
33
|
+
})
|