@navios/commander 1.0.0-alpha.2 → 1.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/CHANGELOG.md +67 -0
- package/README.md +42 -18
- package/dist/src/commander.factory.d.mts +84 -10
- package/dist/src/commander.factory.d.mts.map +1 -1
- package/dist/src/commands/help.command.d.mts +18 -0
- package/dist/src/commands/help.command.d.mts.map +1 -0
- package/dist/src/commands/index.d.mts +2 -0
- package/dist/src/commands/index.d.mts.map +1 -0
- package/dist/src/decorators/cli-module.decorator.d.mts +29 -4
- package/dist/src/decorators/cli-module.decorator.d.mts.map +1 -1
- package/dist/src/decorators/command.decorator.d.mts +6 -1
- package/dist/src/decorators/command.decorator.d.mts.map +1 -1
- package/dist/src/define-environment.d.mts +31 -0
- package/dist/src/define-environment.d.mts.map +1 -0
- package/dist/src/index.d.mts +2 -1
- package/dist/src/index.d.mts.map +1 -1
- package/dist/src/interfaces/abstract-cli-adapter.interface.d.mts +53 -0
- package/dist/src/interfaces/abstract-cli-adapter.interface.d.mts.map +1 -0
- package/dist/src/interfaces/commander-execution-context.interface.d.mts +1 -1
- package/dist/src/interfaces/environment.interface.d.mts +30 -0
- package/dist/src/interfaces/environment.interface.d.mts.map +1 -0
- package/dist/src/interfaces/index.d.mts +2 -0
- package/dist/src/interfaces/index.d.mts.map +1 -1
- package/dist/src/metadata/command-entry.metadata.d.mts +31 -0
- package/dist/src/metadata/command-entry.metadata.d.mts.map +1 -0
- package/dist/src/metadata/command.metadata.d.mts +6 -1
- package/dist/src/metadata/command.metadata.d.mts.map +1 -1
- package/dist/src/metadata/index.d.mts +1 -1
- package/dist/src/metadata/index.d.mts.map +1 -1
- package/dist/src/services/cli-parser.service.d.mts +2 -12
- package/dist/src/services/cli-parser.service.d.mts.map +1 -1
- package/dist/src/services/command-registry.service.d.mts +89 -0
- package/dist/src/services/command-registry.service.d.mts.map +1 -0
- package/dist/src/services/commander-adapter.service.d.mts +56 -0
- package/dist/src/services/commander-adapter.service.d.mts.map +1 -0
- package/dist/src/services/index.d.mts +2 -1
- package/dist/src/services/index.d.mts.map +1 -1
- package/dist/src/tokens/execution-context.token.d.mts +1 -1
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/lib/index.cjs +536 -8513
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +422 -298
- package/lib/index.d.cts.map +1 -1
- package/lib/index.d.mts +422 -298
- package/lib/index.d.mts.map +1 -1
- package/lib/index.mjs +502 -8284
- package/lib/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/commander.factory.e2e.spec.mts +258 -68
- package/src/commander.factory.mts +109 -17
- package/src/commands/help.command.mts +37 -0
- package/src/commands/index.mts +1 -0
- package/src/decorators/cli-module.decorator.mts +58 -20
- package/src/decorators/command.decorator.mts +7 -1
- package/src/define-environment.mts +39 -0
- package/src/index.mts +2 -1
- package/src/interfaces/abstract-cli-adapter.interface.mts +52 -0
- package/src/interfaces/commander-execution-context.interface.mts +1 -1
- package/src/interfaces/environment.interface.mts +34 -0
- package/src/interfaces/index.mts +2 -0
- package/src/metadata/command-entry.metadata.mts +41 -0
- package/src/metadata/command.metadata.mts +7 -0
- package/src/metadata/index.mts +1 -1
- package/src/services/cli-parser.service.mts +14 -28
- package/src/services/command-registry.service.mts +217 -0
- package/src/services/commander-adapter.service.mts +209 -0
- package/src/services/index.mts +2 -1
- package/src/tokens/execution-context.token.mts +1 -1
- package/tsconfig.json +1 -1
- package/src/commander.application.mts +0 -303
- package/src/metadata/cli-module.metadata.mts +0 -100
- package/src/services/module-loader.service.mts +0 -231
|
@@ -1,13 +1,78 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
ClassTypeWithInstance,
|
|
3
|
+
LogLevel,
|
|
4
|
+
NaviosApplication,
|
|
5
|
+
NaviosModule,
|
|
6
|
+
} from '@navios/core'
|
|
2
7
|
|
|
3
|
-
import {
|
|
8
|
+
import { ConsoleLogger, NaviosFactory } from '@navios/core'
|
|
4
9
|
|
|
5
|
-
import type {
|
|
10
|
+
import type { CliEnvironment } from './interfaces/environment.interface.mjs'
|
|
6
11
|
|
|
7
|
-
import {
|
|
12
|
+
import { defineCliEnvironment } from './define-environment.mjs'
|
|
8
13
|
|
|
9
14
|
/**
|
|
10
|
-
*
|
|
15
|
+
* Logger display options for CLI applications.
|
|
16
|
+
* All options default to false for cleaner CLI output.
|
|
17
|
+
*
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
export interface CommanderLoggerOptions {
|
|
21
|
+
/**
|
|
22
|
+
* Enabled log levels.
|
|
23
|
+
* @default ['log', 'error', 'warn', 'debug', 'verbose', 'fatal']
|
|
24
|
+
*/
|
|
25
|
+
logLevels?: LogLevel[]
|
|
26
|
+
/**
|
|
27
|
+
* If true, will print the process ID in the log message.
|
|
28
|
+
* @default false
|
|
29
|
+
*/
|
|
30
|
+
showPid?: boolean
|
|
31
|
+
/**
|
|
32
|
+
* If true, will print the log level in the log message.
|
|
33
|
+
* @default true
|
|
34
|
+
*/
|
|
35
|
+
showLogLevel?: boolean
|
|
36
|
+
/**
|
|
37
|
+
* If true, will print the prefix/app name in the log message.
|
|
38
|
+
* @default false
|
|
39
|
+
*/
|
|
40
|
+
showPrefix?: boolean
|
|
41
|
+
/**
|
|
42
|
+
* If true, will print the context in the log message.
|
|
43
|
+
* @default true
|
|
44
|
+
*/
|
|
45
|
+
showContext?: boolean
|
|
46
|
+
/**
|
|
47
|
+
* If true, will print the absolute timestamp in the log message.
|
|
48
|
+
* @default false
|
|
49
|
+
*/
|
|
50
|
+
showTimestamp?: boolean
|
|
51
|
+
/**
|
|
52
|
+
* If enabled, will print timestamp difference between current and previous log message.
|
|
53
|
+
* @default false
|
|
54
|
+
*/
|
|
55
|
+
showTimeDiff?: boolean
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Configuration options for CommanderFactory.
|
|
60
|
+
*
|
|
61
|
+
* @public
|
|
62
|
+
*/
|
|
63
|
+
export interface CommanderFactoryOptions {
|
|
64
|
+
/**
|
|
65
|
+
* Logger display options. These override the default CLI-friendly logger settings.
|
|
66
|
+
*/
|
|
67
|
+
logger?: CommanderLoggerOptions
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Factory class for creating CLI applications.
|
|
72
|
+
*
|
|
73
|
+
* This is a convenience wrapper around `NaviosFactory.create()` that
|
|
74
|
+
* configures everything needed for CLI usage. It sets up the CLI adapter
|
|
75
|
+
* and returns a typed `NaviosApplication<CliEnvironment>`.
|
|
11
76
|
*
|
|
12
77
|
* @example
|
|
13
78
|
* ```typescript
|
|
@@ -17,32 +82,59 @@ import { CommanderApplication } from './commander.application.mjs'
|
|
|
17
82
|
* async function bootstrap() {
|
|
18
83
|
* const app = await CommanderFactory.create(AppModule)
|
|
19
84
|
* await app.init()
|
|
20
|
-
*
|
|
85
|
+
*
|
|
86
|
+
* const adapter = app.getAdapter()
|
|
87
|
+
* await adapter.run(process.argv)
|
|
88
|
+
*
|
|
21
89
|
* await app.close()
|
|
22
90
|
* }
|
|
23
91
|
* ```
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* // Alternative: use NaviosFactory directly
|
|
96
|
+
* import { NaviosFactory } from '@navios/core'
|
|
97
|
+
* import { defineCliEnvironment, type CliEnvironment } from '@navios/commander'
|
|
98
|
+
*
|
|
99
|
+
* const app = await NaviosFactory.create<CliEnvironment>(AppModule, {
|
|
100
|
+
* adapter: defineCliEnvironment(),
|
|
101
|
+
* })
|
|
102
|
+
* ```
|
|
24
103
|
*/
|
|
25
104
|
export class CommanderFactory {
|
|
26
105
|
/**
|
|
27
|
-
* Creates a new
|
|
106
|
+
* Creates a new CLI application instance configured with the provided module.
|
|
28
107
|
*
|
|
29
|
-
* @param appModule - The root CLI module class
|
|
30
|
-
* @param options - Optional configuration options for the application
|
|
31
|
-
* @returns A promise that resolves to a configured
|
|
108
|
+
* @param appModule - The root CLI module class decorated with `@CliModule`
|
|
109
|
+
* @param options - Optional configuration options for the CLI application
|
|
110
|
+
* @returns A promise that resolves to a configured NaviosApplication instance
|
|
32
111
|
*
|
|
33
112
|
* @example
|
|
34
113
|
* ```typescript
|
|
35
114
|
* const app = await CommanderFactory.create(AppModule)
|
|
36
115
|
* await app.init()
|
|
116
|
+
*
|
|
117
|
+
* const adapter = app.getAdapter()
|
|
118
|
+
* await adapter.run(process.argv)
|
|
37
119
|
* ```
|
|
38
120
|
*/
|
|
39
|
-
static async create(
|
|
40
|
-
appModule: ClassTypeWithInstance<
|
|
41
|
-
options:
|
|
42
|
-
) {
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
121
|
+
static async create<TModule extends NaviosModule = NaviosModule>(
|
|
122
|
+
appModule: ClassTypeWithInstance<TModule>,
|
|
123
|
+
options: CommanderFactoryOptions = {},
|
|
124
|
+
): Promise<NaviosApplication<CliEnvironment>> {
|
|
125
|
+
const app = await NaviosFactory.create<CliEnvironment>(appModule, {
|
|
126
|
+
adapter: defineCliEnvironment(),
|
|
127
|
+
logger: ConsoleLogger.create({
|
|
128
|
+
logLevels: options.logger?.logLevels,
|
|
129
|
+
showTimeDiff: options.logger?.showTimeDiff ?? false,
|
|
130
|
+
showPid: options.logger?.showPid ?? false,
|
|
131
|
+
showLogLevel: options.logger?.showLogLevel ?? true,
|
|
132
|
+
showPrefix: options.logger?.showPrefix ?? false,
|
|
133
|
+
showContext: options.logger?.showContext ?? true,
|
|
134
|
+
showTimestamp: options.logger?.showTimestamp ?? false,
|
|
135
|
+
}),
|
|
136
|
+
})
|
|
137
|
+
|
|
46
138
|
return app
|
|
47
139
|
}
|
|
48
140
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { inject, Logger } from '@navios/core'
|
|
2
|
+
|
|
3
|
+
import { z } from 'zod'
|
|
4
|
+
|
|
5
|
+
import type { CommandHandler } from '../interfaces/command-handler.interface.mjs'
|
|
6
|
+
|
|
7
|
+
import { Command } from '../decorators/command.decorator.mjs'
|
|
8
|
+
import { CommandRegistryService } from '../services/command-registry.service.mjs'
|
|
9
|
+
|
|
10
|
+
const helpOptionsSchema = z.object({
|
|
11
|
+
command: z.string().optional(),
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
type HelpOptions = z.infer<typeof helpOptionsSchema>
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Built-in help command that lists all available commands or shows help for a specific command.
|
|
18
|
+
*
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
@Command({
|
|
22
|
+
path: 'help',
|
|
23
|
+
description: 'Show available commands or help for a specific command',
|
|
24
|
+
optionsSchema: helpOptionsSchema,
|
|
25
|
+
})
|
|
26
|
+
export class HelpCommand implements CommandHandler<HelpOptions> {
|
|
27
|
+
private logger = inject(Logger, { context: 'Commander' })
|
|
28
|
+
private commandRegistry = inject(CommandRegistryService)
|
|
29
|
+
|
|
30
|
+
async execute(options: HelpOptions): Promise<void> {
|
|
31
|
+
if (options.command) {
|
|
32
|
+
this.logger.log(this.commandRegistry.formatCommandHelp(options.command))
|
|
33
|
+
} else {
|
|
34
|
+
this.logger.log(this.commandRegistry.formatCommandList())
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './help.command.mjs'
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { ClassType, Registry } from '@navios/core'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { Module, getModuleMetadata, getModuleCustomEntry } from '@navios/core'
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
CommandEntryKey,
|
|
7
|
+
type CommandEntryValue,
|
|
8
|
+
} from '../metadata/command-entry.metadata.mjs'
|
|
6
9
|
|
|
7
10
|
/**
|
|
8
11
|
* Options for the `@CliModule` decorator.
|
|
@@ -16,10 +19,20 @@ export interface CliModuleOptions {
|
|
|
16
19
|
*/
|
|
17
20
|
commands?: ClassType[] | Set<ClassType>
|
|
18
21
|
/**
|
|
19
|
-
* Array or Set of
|
|
20
|
-
*
|
|
22
|
+
* Array or Set of controller classes for HTTP endpoints.
|
|
23
|
+
* Allows mixing HTTP and CLI functionality in the same module.
|
|
24
|
+
*/
|
|
25
|
+
controllers?: ClassType[] | Set<ClassType>
|
|
26
|
+
/**
|
|
27
|
+
* Array or Set of other modules to import.
|
|
28
|
+
* Imported modules' commands and controllers will be available.
|
|
21
29
|
*/
|
|
22
30
|
imports?: ClassType[] | Set<ClassType>
|
|
31
|
+
/**
|
|
32
|
+
* Guards to apply to all controllers in this module.
|
|
33
|
+
* Guards are executed in reverse order (last guard first).
|
|
34
|
+
*/
|
|
35
|
+
guards?: ClassType[] | Set<ClassType>
|
|
23
36
|
/**
|
|
24
37
|
* Service override classes to import for side effects.
|
|
25
38
|
* These classes are imported to ensure their @Injectable decorators execute,
|
|
@@ -42,7 +55,11 @@ export interface CliModuleOptions {
|
|
|
42
55
|
/**
|
|
43
56
|
* Decorator that marks a class as a CLI module.
|
|
44
57
|
*
|
|
45
|
-
*
|
|
58
|
+
* This decorator extends the standard @Module decorator, adding support for
|
|
59
|
+
* CLI commands while maintaining full compatibility with HTTP controllers.
|
|
60
|
+
* Modules organize commands and can import other modules to compose larger
|
|
61
|
+
* CLI applications.
|
|
62
|
+
*
|
|
46
63
|
* The module can optionally implement `NaviosModule` interface for lifecycle hooks.
|
|
47
64
|
*
|
|
48
65
|
* @param options - Configuration options for the module
|
|
@@ -60,17 +77,32 @@ export interface CliModuleOptions {
|
|
|
60
77
|
* })
|
|
61
78
|
* export class AppModule {}
|
|
62
79
|
* ```
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* // Mixed HTTP and CLI module
|
|
84
|
+
* @CliModule({
|
|
85
|
+
* controllers: [HealthController],
|
|
86
|
+
* commands: [MigrateCommand],
|
|
87
|
+
* imports: [DatabaseModule],
|
|
88
|
+
* })
|
|
89
|
+
* export class AppModule {}
|
|
90
|
+
* ```
|
|
63
91
|
*/
|
|
64
92
|
export function CliModule(
|
|
65
93
|
{
|
|
66
94
|
commands = [],
|
|
95
|
+
controllers = [],
|
|
67
96
|
imports = [],
|
|
97
|
+
guards = [],
|
|
68
98
|
overrides = [],
|
|
69
99
|
priority,
|
|
70
100
|
registry,
|
|
71
101
|
}: CliModuleOptions = {
|
|
72
102
|
commands: [],
|
|
103
|
+
controllers: [],
|
|
73
104
|
imports: [],
|
|
105
|
+
guards: [],
|
|
74
106
|
overrides: [],
|
|
75
107
|
},
|
|
76
108
|
) {
|
|
@@ -80,24 +112,30 @@ export function CliModule(
|
|
|
80
112
|
'[Navios Commander] @CliModule decorator can only be used on classes.',
|
|
81
113
|
)
|
|
82
114
|
}
|
|
83
|
-
// Register the module in the service locator
|
|
84
|
-
const token = InjectionToken.create(target)
|
|
85
|
-
const moduleMetadata = getCliModuleMetadata(target, context)
|
|
86
|
-
for (const command of commands) {
|
|
87
|
-
moduleMetadata.commands.add(command)
|
|
88
|
-
}
|
|
89
|
-
for (const importedModule of imports) {
|
|
90
|
-
moduleMetadata.imports.add(importedModule)
|
|
91
|
-
}
|
|
92
|
-
for (const override of overrides) {
|
|
93
|
-
moduleMetadata.overrides.add(override)
|
|
94
|
-
}
|
|
95
115
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
116
|
+
// Apply standard @Module decorator first
|
|
117
|
+
const result = Module({
|
|
118
|
+
controllers,
|
|
119
|
+
imports,
|
|
120
|
+
guards,
|
|
121
|
+
overrides,
|
|
99
122
|
priority,
|
|
100
123
|
registry,
|
|
101
124
|
})(target, context)
|
|
125
|
+
|
|
126
|
+
// Get the module metadata that @Module just created
|
|
127
|
+
const metadata = getModuleMetadata(target, context)
|
|
128
|
+
|
|
129
|
+
// Store commands in customEntries
|
|
130
|
+
const commandSet = getModuleCustomEntry<CommandEntryValue>(
|
|
131
|
+
metadata,
|
|
132
|
+
CommandEntryKey,
|
|
133
|
+
() => new Set(),
|
|
134
|
+
)
|
|
135
|
+
for (const command of commands) {
|
|
136
|
+
commandSet.add(command)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return result
|
|
102
140
|
}
|
|
103
141
|
}
|
|
@@ -16,6 +16,11 @@ export interface CommandOptions {
|
|
|
16
16
|
* Can be a single word (e.g., 'greet') or multi-word with colons (e.g., 'user:create', 'db:migrate').
|
|
17
17
|
*/
|
|
18
18
|
path: string
|
|
19
|
+
/**
|
|
20
|
+
* Optional description of the command for help text.
|
|
21
|
+
* Displayed when users run `help` or `--help`.
|
|
22
|
+
*/
|
|
23
|
+
description?: string
|
|
19
24
|
/**
|
|
20
25
|
* Optional Zod schema for validating command options.
|
|
21
26
|
* If provided, options will be validated and parsed according to this schema.
|
|
@@ -65,6 +70,7 @@ export interface CommandOptions {
|
|
|
65
70
|
*/
|
|
66
71
|
export function Command({
|
|
67
72
|
path,
|
|
73
|
+
description,
|
|
68
74
|
optionsSchema,
|
|
69
75
|
priority,
|
|
70
76
|
registry,
|
|
@@ -77,7 +83,7 @@ export function Command({
|
|
|
77
83
|
}
|
|
78
84
|
const token = InjectionToken.create(target)
|
|
79
85
|
if (context.metadata) {
|
|
80
|
-
getCommandMetadata(target, context, path, optionsSchema)
|
|
86
|
+
getCommandMetadata(target, context, path, description, optionsSchema)
|
|
81
87
|
}
|
|
82
88
|
return Injectable({
|
|
83
89
|
token,
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { AnyInjectableType, InjectionToken } from '@navios/core'
|
|
2
|
+
|
|
3
|
+
import { AdapterToken } from '@navios/core'
|
|
4
|
+
|
|
5
|
+
import { CommanderAdapterService } from './services/commander-adapter.service.mjs'
|
|
6
|
+
import { CommandRegistryService } from './services/command-registry.service.mjs'
|
|
7
|
+
import { CliParserService } from './services/cli-parser.service.mjs'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Defines the CLI environment configuration for use with NaviosFactory.
|
|
11
|
+
*
|
|
12
|
+
* This function returns the token mappings needed to configure a CLI application.
|
|
13
|
+
* Use it with `NaviosFactory.create()` to create a CLI application.
|
|
14
|
+
*
|
|
15
|
+
* @returns Environment configuration with token mappings
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import { NaviosFactory } from '@navios/core'
|
|
20
|
+
* import { defineCliEnvironment, type CliEnvironment } from '@navios/commander'
|
|
21
|
+
*
|
|
22
|
+
* const app = await NaviosFactory.create<CliEnvironment>(AppModule, {
|
|
23
|
+
* adapter: defineCliEnvironment(),
|
|
24
|
+
* })
|
|
25
|
+
* await app.init()
|
|
26
|
+
*
|
|
27
|
+
* const adapter = app.getAdapter() as AbstractCliAdapterInterface
|
|
28
|
+
* await adapter.run(process.argv)
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export function defineCliEnvironment() {
|
|
32
|
+
const tokens = new Map<InjectionToken<any, undefined>, AnyInjectableType>([
|
|
33
|
+
[AdapterToken, CommanderAdapterService],
|
|
34
|
+
])
|
|
35
|
+
return { tokens }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Re-export services for direct access if needed
|
|
39
|
+
export { CommanderAdapterService, CommandRegistryService, CliParserService }
|
package/src/index.mts
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
export * from '@navios/core'
|
|
3
3
|
|
|
4
4
|
// Export commander-specific exports
|
|
5
|
-
export * from './
|
|
5
|
+
export * from './commands/index.mjs'
|
|
6
6
|
export * from './commander.factory.mjs'
|
|
7
7
|
export * from './decorators/index.mjs'
|
|
8
|
+
export * from './define-environment.mjs'
|
|
8
9
|
export * from './interfaces/index.mjs'
|
|
9
10
|
export * from './metadata/index.mjs'
|
|
10
11
|
export * from './services/index.mjs'
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { AbstractAdapterInterface } from '@navios/core'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Interface for CLI adapters.
|
|
5
|
+
* Extends the base adapter interface with CLI-specific methods.
|
|
6
|
+
*
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export interface AbstractCliAdapterInterface extends AbstractAdapterInterface {
|
|
10
|
+
/**
|
|
11
|
+
* Run the CLI application with the given arguments.
|
|
12
|
+
* Parses arguments and executes the matching command.
|
|
13
|
+
*
|
|
14
|
+
* @param argv - Command-line arguments array (defaults to `process.argv`)
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const adapter = app.getAdapter() as AbstractCliAdapterInterface
|
|
19
|
+
* await adapter.run(process.argv)
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
run(argv?: string[]): Promise<void>
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Execute a command programmatically with the provided options.
|
|
26
|
+
*
|
|
27
|
+
* @param path - The command path (e.g., 'greet', 'user:create')
|
|
28
|
+
* @param options - The command options object
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* await adapter.executeCommand('user:create', {
|
|
33
|
+
* name: 'John',
|
|
34
|
+
* email: 'john@example.com',
|
|
35
|
+
* })
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
executeCommand(path: string, options: Record<string, unknown>): Promise<void>
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get all registered command paths and their class references.
|
|
42
|
+
*
|
|
43
|
+
* @returns Array of objects containing path and class
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* const commands = adapter.getAllCommands()
|
|
48
|
+
* commands.forEach(({ path }) => console.log(path))
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
getAllCommands(): Array<{ path: string; class: unknown }>
|
|
52
|
+
}
|
|
@@ -8,7 +8,7 @@ import type { CommandMetadata } from '../metadata/command.metadata.mjs'
|
|
|
8
8
|
*
|
|
9
9
|
* @example
|
|
10
10
|
* ```typescript
|
|
11
|
-
* import { inject, Injectable } from '@navios/
|
|
11
|
+
* import { inject, Injectable } from '@navios/core'
|
|
12
12
|
* import { CommandExecutionContext } from '@navios/commander'
|
|
13
13
|
*
|
|
14
14
|
* @Injectable()
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { AdapterEnvironment } from '@navios/core'
|
|
2
|
+
|
|
3
|
+
import type { AbstractCliAdapterInterface } from './abstract-cli-adapter.interface.mjs'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Options for configuring the CLI adapter.
|
|
7
|
+
*
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
11
|
+
export interface CliAdapterOptions {
|
|
12
|
+
// Reserved for future options
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Environment type definition for CLI adapters.
|
|
17
|
+
* Used with NaviosFactory.create<CliEnvironment>() for type-safe CLI applications.
|
|
18
|
+
*
|
|
19
|
+
* @public
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* import { NaviosFactory } from '@navios/core'
|
|
24
|
+
* import { defineCliEnvironment, type CliEnvironment } from '@navios/commander'
|
|
25
|
+
*
|
|
26
|
+
* const app = await NaviosFactory.create<CliEnvironment>(AppModule, {
|
|
27
|
+
* adapter: defineCliEnvironment(),
|
|
28
|
+
* })
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export interface CliEnvironment extends AdapterEnvironment {
|
|
32
|
+
options: CliAdapterOptions
|
|
33
|
+
adapter: AbstractCliAdapterInterface
|
|
34
|
+
}
|
package/src/interfaces/index.mts
CHANGED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { ClassType } from '@navios/core'
|
|
2
|
+
|
|
3
|
+
import { extractModuleMetadata } from '@navios/core'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Symbol key for storing commands in ModuleMetadata.customEntries.
|
|
7
|
+
* Used by @CliModule to store command classes.
|
|
8
|
+
*
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
export const CommandEntryKey = Symbol('CommandEntryKey')
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Type for the command entry value stored in customEntries.
|
|
15
|
+
*
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
export type CommandEntryValue = Set<ClassType>
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Extracts commands from a module's metadata.
|
|
22
|
+
* Returns empty set if no commands are defined.
|
|
23
|
+
*
|
|
24
|
+
* @param moduleClass - The module class decorated with @CliModule or @Module
|
|
25
|
+
* @returns Set of command classes registered in the module
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const commands = extractModuleCommands(AppModule)
|
|
30
|
+
* for (const command of commands) {
|
|
31
|
+
* console.log(command.name)
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export function extractModuleCommands(moduleClass: ClassType): Set<ClassType> {
|
|
36
|
+
const metadata = extractModuleMetadata(moduleClass)
|
|
37
|
+
return (
|
|
38
|
+
(metadata.customEntries.get(CommandEntryKey) as CommandEntryValue) ??
|
|
39
|
+
new Set()
|
|
40
|
+
)
|
|
41
|
+
}
|
|
@@ -17,6 +17,10 @@ export interface CommandMetadata {
|
|
|
17
17
|
* The command path (e.g., 'greet', 'user:create').
|
|
18
18
|
*/
|
|
19
19
|
path: string
|
|
20
|
+
/**
|
|
21
|
+
* Optional description of the command for help text.
|
|
22
|
+
*/
|
|
23
|
+
description?: string
|
|
20
24
|
/**
|
|
21
25
|
* Optional Zod schema for validating command options.
|
|
22
26
|
*/
|
|
@@ -34,6 +38,7 @@ export interface CommandMetadata {
|
|
|
34
38
|
* @param target - The command class
|
|
35
39
|
* @param context - The decorator context
|
|
36
40
|
* @param path - The command path
|
|
41
|
+
* @param description - Optional description for help text
|
|
37
42
|
* @param optionsSchema - Optional Zod schema
|
|
38
43
|
* @returns The command metadata
|
|
39
44
|
*/
|
|
@@ -41,6 +46,7 @@ export function getCommandMetadata(
|
|
|
41
46
|
target: ClassType,
|
|
42
47
|
context: ClassDecoratorContext,
|
|
43
48
|
path: string,
|
|
49
|
+
description?: string,
|
|
44
50
|
optionsSchema?: ZodObject,
|
|
45
51
|
): CommandMetadata {
|
|
46
52
|
if (context.metadata) {
|
|
@@ -52,6 +58,7 @@ export function getCommandMetadata(
|
|
|
52
58
|
} else {
|
|
53
59
|
const newMetadata: CommandMetadata = {
|
|
54
60
|
path,
|
|
61
|
+
description,
|
|
55
62
|
optionsSchema,
|
|
56
63
|
customAttributes: new Map<string | symbol, any>(),
|
|
57
64
|
}
|
package/src/metadata/index.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export * from './command.metadata.mjs'
|
|
2
|
-
export * from './
|
|
2
|
+
export * from './command-entry.metadata.mjs'
|
|
@@ -286,20 +286,20 @@ export class CliParserService {
|
|
|
286
286
|
|
|
287
287
|
/**
|
|
288
288
|
* Checks if a Zod schema represents a boolean type
|
|
289
|
-
* Unwraps ZodOptional and ZodDefault
|
|
289
|
+
* Unwraps ZodOptional and ZodDefault using Zod v4 API
|
|
290
290
|
*/
|
|
291
291
|
private isSchemaBoolean(schema: ZodType): boolean {
|
|
292
292
|
try {
|
|
293
293
|
let currentSchema = schema
|
|
294
|
-
|
|
294
|
+
let typeName = currentSchema.def.type
|
|
295
295
|
|
|
296
|
-
// Unwrap ZodOptional and ZodDefault
|
|
297
|
-
|
|
298
|
-
currentSchema = (currentSchema as any)?.
|
|
296
|
+
// Unwrap ZodOptional and ZodDefault using Zod v4's def.innerType
|
|
297
|
+
while (typeName === 'optional' || typeName === 'default') {
|
|
298
|
+
currentSchema = (currentSchema as any)?.def?.innerType || currentSchema
|
|
299
|
+
typeName = currentSchema.def.type
|
|
299
300
|
}
|
|
300
301
|
|
|
301
|
-
|
|
302
|
-
return innerTypeName === 'boolean'
|
|
302
|
+
return typeName === 'boolean'
|
|
303
303
|
} catch {
|
|
304
304
|
return false
|
|
305
305
|
}
|
|
@@ -307,36 +307,22 @@ export class CliParserService {
|
|
|
307
307
|
|
|
308
308
|
/**
|
|
309
309
|
* Checks if a Zod schema represents an array type
|
|
310
|
-
* Unwraps ZodOptional and ZodDefault
|
|
310
|
+
* Unwraps ZodOptional and ZodDefault using Zod v4 API
|
|
311
311
|
*/
|
|
312
312
|
private isSchemaArray(schema: ZodType): boolean {
|
|
313
313
|
try {
|
|
314
314
|
let currentSchema = schema
|
|
315
|
-
|
|
315
|
+
let typeName = currentSchema.def.type
|
|
316
316
|
|
|
317
|
-
// Unwrap ZodOptional and ZodDefault
|
|
318
|
-
|
|
319
|
-
currentSchema = (currentSchema as any)?.
|
|
317
|
+
// Unwrap ZodOptional and ZodDefault using Zod v4's def.innerType
|
|
318
|
+
while (typeName === 'optional' || typeName === 'default') {
|
|
319
|
+
currentSchema = (currentSchema as any)?.def?.innerType || currentSchema
|
|
320
|
+
typeName = currentSchema.def.type
|
|
320
321
|
}
|
|
321
322
|
|
|
322
|
-
|
|
323
|
-
return innerTypeName === 'array'
|
|
323
|
+
return typeName === 'array'
|
|
324
324
|
} catch {
|
|
325
325
|
return false
|
|
326
326
|
}
|
|
327
327
|
}
|
|
328
|
-
|
|
329
|
-
/**
|
|
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
|
|
334
|
-
*/
|
|
335
|
-
formatCommandList(commands: Array<{ path: string; class: any }>): string {
|
|
336
|
-
const lines = ['Available commands:', '']
|
|
337
|
-
for (const { path } of commands) {
|
|
338
|
-
lines.push(` ${path}`)
|
|
339
|
-
}
|
|
340
|
-
return lines.join('\n')
|
|
341
|
-
}
|
|
342
328
|
}
|