@navios/commander 0.5.2 → 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.
Files changed (66) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +24 -13
  3. package/dist/src/commander.application.d.mts +124 -6
  4. package/dist/src/commander.application.d.mts.map +1 -1
  5. package/dist/src/commander.factory.d.mts +31 -3
  6. package/dist/src/commander.factory.d.mts.map +1 -1
  7. package/dist/src/decorators/cli-module.decorator.d.mts +36 -1
  8. package/dist/src/decorators/cli-module.decorator.d.mts.map +1 -1
  9. package/dist/src/decorators/command.decorator.d.mts +44 -1
  10. package/dist/src/decorators/command.decorator.d.mts.map +1 -1
  11. package/dist/src/index.d.mts +1 -1
  12. package/dist/src/index.d.mts.map +1 -1
  13. package/dist/src/interfaces/command-handler.interface.d.mts +33 -0
  14. package/dist/src/interfaces/command-handler.interface.d.mts.map +1 -1
  15. package/dist/src/interfaces/commander-execution-context.interface.d.mts +43 -0
  16. package/dist/src/interfaces/commander-execution-context.interface.d.mts.map +1 -1
  17. package/dist/src/interfaces/index.d.mts +0 -1
  18. package/dist/src/interfaces/index.d.mts.map +1 -1
  19. package/dist/src/interfaces/module.interface.d.mts +1 -4
  20. package/dist/src/interfaces/module.interface.d.mts.map +1 -1
  21. package/dist/src/metadata/cli-module.metadata.d.mts +46 -1
  22. package/dist/src/metadata/cli-module.metadata.d.mts.map +1 -1
  23. package/dist/src/metadata/command.metadata.d.mts +48 -1
  24. package/dist/src/metadata/command.metadata.d.mts.map +1 -1
  25. package/dist/src/services/cli-parser.service.d.mts +32 -1
  26. package/dist/src/services/cli-parser.service.d.mts.map +1 -1
  27. package/dist/src/services/module-loader.service.d.mts +44 -5
  28. package/dist/src/services/module-loader.service.d.mts.map +1 -1
  29. package/dist/src/tokens/execution-context.token.d.mts +25 -3
  30. package/dist/src/tokens/execution-context.token.d.mts.map +1 -1
  31. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  32. package/dist/tsconfig.tsbuildinfo +1 -1
  33. package/dist/tsdown.config.d.mts +3 -0
  34. package/dist/tsdown.config.d.mts.map +1 -0
  35. package/lib/index.cjs +7721 -0
  36. package/lib/index.cjs.map +1 -0
  37. package/lib/index.d.cts +670 -0
  38. package/lib/index.d.cts.map +1 -0
  39. package/lib/index.d.mts +670 -101
  40. package/lib/index.d.mts.map +1 -0
  41. package/lib/index.mjs +7509 -598
  42. package/lib/index.mjs.map +1 -1
  43. package/package.json +5 -5
  44. package/project.json +2 -2
  45. package/src/commander.application.mts +138 -18
  46. package/src/commander.factory.mts +32 -4
  47. package/src/decorators/cli-module.decorator.mts +37 -2
  48. package/src/decorators/command.decorator.mts +45 -2
  49. package/src/index.mts +4 -1
  50. package/src/interfaces/command-handler.interface.mts +33 -0
  51. package/src/interfaces/commander-execution-context.interface.mts +43 -0
  52. package/src/interfaces/index.mts +0 -1
  53. package/src/metadata/cli-module.metadata.mts +48 -7
  54. package/src/metadata/command.metadata.mts +48 -1
  55. package/src/services/__tests__/cli-parser.service.spec.mts +15 -11
  56. package/src/services/cli-parser.service.mts +35 -3
  57. package/src/services/module-loader.service.mts +45 -6
  58. package/src/tokens/execution-context.token.mts +29 -5
  59. package/tsdown.config.mts +33 -0
  60. package/lib/_tsup-dts-rollup.d.mts +0 -489
  61. package/lib/_tsup-dts-rollup.d.ts +0 -489
  62. package/lib/index.d.ts +0 -101
  63. package/lib/index.js +0 -642
  64. package/lib/index.js.map +0 -1
  65. package/src/interfaces/module.interface.mts +0 -4
  66. package/tsup.config.mts +0 -12
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@navios/commander",
3
- "version": "0.5.2",
3
+ "version": "0.7.0",
4
4
  "author": {
5
5
  "name": "Oleksandr Hanzha",
6
6
  "email": "alex@granted.name"
@@ -30,11 +30,11 @@
30
30
  }
31
31
  },
32
32
  "devDependencies": {
33
- "tsx": "^4.20.5",
34
- "typescript": "^5.9.2",
35
- "zod": "^4.1.8"
33
+ "tsx": "^4.21.0",
34
+ "typescript": "^5.9.3",
35
+ "zod": "^4.1.13"
36
36
  },
37
37
  "dependencies": {
38
- "@navios/di": "^0.4.2"
38
+ "@navios/di": "^0.6.0"
39
39
  }
40
40
  }
package/project.json CHANGED
@@ -38,11 +38,11 @@
38
38
  },
39
39
  "build": {
40
40
  "executor": "nx:run-commands",
41
- "inputs": ["projectSources", "{projectRoot}/tsup.config.mts"],
41
+ "inputs": ["projectSources", "{projectRoot}/tsdown.config.mts"],
42
42
  "outputs": ["{projectRoot}/lib"],
43
43
  "dependsOn": ["check", "test:ci", "lint"],
44
44
  "options": {
45
- "command": "tsup",
45
+ "command": "tsdown",
46
46
  "cwd": "packages/commander"
47
47
  }
48
48
  },
@@ -1,38 +1,94 @@
1
- import type { ClassTypeWithInstance, InjectionToken } from '@navios/di'
1
+ import type {
2
+ ClassTypeWithInstance,
3
+ InjectionToken,
4
+ NaviosModule,
5
+ } from '@navios/core'
2
6
 
3
- import { Container, inject, Injectable } from '@navios/di'
7
+ import { Container, inject, Injectable } from '@navios/core'
4
8
 
5
- import type { CommandHandler, Module } from './interfaces/index.mjs'
9
+ import type { CommandHandler } from './interfaces/index.mjs'
6
10
 
7
11
  import { CommanderExecutionContext } from './interfaces/index.mjs'
8
- import { CliParserService, ModuleLoaderService } from './services/index.mjs'
9
- import { ExecutionContext } from './tokens/index.mjs'
10
-
12
+ import { CliModuleLoaderService, CliParserService } from './services/index.mjs'
13
+ import { CommandExecutionContext } from './tokens/index.mjs'
14
+
15
+ /**
16
+ * Configuration options for CommanderApplication.
17
+ *
18
+ * @public
19
+ */
11
20
  export interface CommanderApplicationOptions {}
12
21
 
22
+ /**
23
+ * Main application class for managing CLI command execution.
24
+ *
25
+ * This class handles module loading, command registration, and command execution.
26
+ * It provides both programmatic and CLI-based command execution capabilities.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * const app = await CommanderFactory.create(AppModule)
31
+ * await app.init()
32
+ * await app.run(process.argv)
33
+ * ```
34
+ */
13
35
  @Injectable()
14
36
  export class CommanderApplication {
15
- private moduleLoader = inject(ModuleLoaderService)
37
+ private moduleLoader = inject(CliModuleLoaderService)
16
38
  private cliParser = inject(CliParserService)
17
39
  protected container = inject(Container)
18
40
 
19
- private appModule: ClassTypeWithInstance<Module> | null = null
41
+ private appModule: ClassTypeWithInstance<NaviosModule> | null = null
20
42
  private options: CommanderApplicationOptions = {}
21
43
 
44
+ /**
45
+ * Indicates whether the application has been initialized.
46
+ * Set to `true` after `init()` is called successfully.
47
+ */
22
48
  isInitialized = false
23
49
 
50
+ /**
51
+ * @internal
52
+ * Sets up the application with the provided module and options.
53
+ * This is called automatically by CommanderFactory.create().
54
+ */
24
55
  async setup(
25
- appModule: ClassTypeWithInstance<Module>,
56
+ appModule: ClassTypeWithInstance<NaviosModule>,
26
57
  options: CommanderApplicationOptions = {},
27
58
  ) {
28
59
  this.appModule = appModule
29
60
  this.options = options
30
61
  }
31
62
 
63
+ /**
64
+ * Gets the dependency injection container used by this application.
65
+ *
66
+ * @returns The Container instance
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * const container = app.getContainer()
71
+ * const service = await container.get(MyService)
72
+ * ```
73
+ */
32
74
  getContainer() {
33
75
  return this.container
34
76
  }
35
77
 
78
+ /**
79
+ * Initializes the application by loading all modules and registering commands.
80
+ *
81
+ * This method must be called before executing commands or running the CLI.
82
+ * It traverses the module tree, loads all imported modules, and collects command metadata.
83
+ *
84
+ * @throws {Error} If the app module is not set (setup() was not called)
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * const app = await CommanderFactory.create(AppModule)
89
+ * await app.init() // Must be called before run() or executeCommand()
90
+ * ```
91
+ */
36
92
  async init() {
37
93
  if (!this.appModule) {
38
94
  throw new Error(
@@ -43,6 +99,27 @@ export class CommanderApplication {
43
99
  this.isInitialized = true
44
100
  }
45
101
 
102
+ /**
103
+ * Executes a command programmatically with the provided options.
104
+ *
105
+ * This method is useful for testing, automation, or programmatic workflows.
106
+ * The options will be validated against the command's Zod schema if one is provided.
107
+ *
108
+ * @param commandPath - The command path (e.g., 'greet', 'user:create')
109
+ * @param options - The command options object (will be validated if schema exists)
110
+ * @throws {Error} If the application is not initialized
111
+ * @throws {Error} If the command is not found
112
+ * @throws {Error} If the command does not implement the execute method
113
+ * @throws {ZodError} If options validation fails
114
+ *
115
+ * @example
116
+ * ```typescript
117
+ * await app.executeCommand('greet', {
118
+ * name: 'World',
119
+ * greeting: 'Hi'
120
+ * })
121
+ * ```
122
+ */
46
123
  async executeCommand(commandPath: string, options: any = {}) {
47
124
  if (!this.isInitialized) {
48
125
  throw new Error(
@@ -76,15 +153,12 @@ export class CommanderApplication {
76
153
  const requestId = `cmd-${Date.now()}-${Math.random().toString(36).substring(7)}`
77
154
 
78
155
  // Begin request context and add ExecutionContext
79
- const requestContext = this.container.beginRequest(requestId)
80
- requestContext.addInstance(ExecutionContext, executionContext)
156
+ const scopeContainer = this.container.beginRequest(requestId)
157
+ scopeContainer.addInstance(CommandExecutionContext, executionContext)
81
158
 
82
159
  try {
83
- // Set current request context
84
- this.container.setCurrentRequestContext(requestId)
85
-
86
160
  // Get command instance and execute
87
- const commandInstance = await this.container.get<CommandHandler>(
161
+ const commandInstance = await scopeContainer.get<CommandHandler>(
88
162
  commandClass as unknown as InjectionToken<CommandHandler>,
89
163
  )
90
164
 
@@ -97,10 +171,23 @@ export class CommanderApplication {
97
171
  await commandInstance.execute(validatedOptions)
98
172
  } finally {
99
173
  // Clean up request context
100
- await this.container.endRequest(requestId)
174
+ await scopeContainer.endRequest()
101
175
  }
102
176
  }
103
177
 
178
+ /**
179
+ * Gets all registered commands with their paths and class references.
180
+ *
181
+ * @returns An array of objects containing the command path and class
182
+ *
183
+ * @example
184
+ * ```typescript
185
+ * const commands = app.getAllCommands()
186
+ * commands.forEach(({ path }) => {
187
+ * console.log(`Available: ${path}`)
188
+ * })
189
+ * ```
190
+ */
104
191
  getAllCommands() {
105
192
  // Use pre-collected command metadata from module loading
106
193
  const commandsMap = this.moduleLoader.getAllCommandsWithMetadata()
@@ -120,8 +207,26 @@ export class CommanderApplication {
120
207
  }
121
208
 
122
209
  /**
123
- * Runs the CLI application by parsing process.argv and executing the command
124
- * @param argv - Command-line arguments (defaults to process.argv)
210
+ * Runs the CLI application by parsing command-line arguments and executing the appropriate command.
211
+ *
212
+ * This is the main entry point for CLI usage. It parses `argv`, validates options,
213
+ * and executes the matching command. Supports help command (`help`, `--help`, `-h`)
214
+ * which displays all available commands.
215
+ *
216
+ * @param argv - Command-line arguments array (defaults to `process.argv`)
217
+ * @throws {Error} If the application is not initialized
218
+ * @throws {Error} If no command is provided
219
+ * @throws {Error} If the command is not found
220
+ * @throws {ZodError} If options validation fails
221
+ *
222
+ * @example
223
+ * ```typescript
224
+ * // Parse and execute from process.argv
225
+ * await app.run()
226
+ *
227
+ * // Or provide custom arguments
228
+ * await app.run(['node', 'cli.js', 'greet', '--name', 'World'])
229
+ * ```
125
230
  */
126
231
  async run(argv: string[] = process.argv) {
127
232
  if (!this.isInitialized) {
@@ -171,12 +276,27 @@ export class CommanderApplication {
171
276
  }
172
277
  }
173
278
 
279
+ /**
280
+ * @internal
281
+ * Disposes of resources used by the application.
282
+ */
174
283
  async dispose() {
175
284
  if (this.moduleLoader) {
176
285
  this.moduleLoader.dispose()
177
286
  }
178
287
  }
179
288
 
289
+ /**
290
+ * Closes the application and cleans up resources.
291
+ *
292
+ * This should be called when the application is no longer needed to free up resources.
293
+ *
294
+ * @example
295
+ * ```typescript
296
+ * await app.run(process.argv)
297
+ * await app.close()
298
+ * ```
299
+ */
180
300
  async close() {
181
301
  await this.dispose()
182
302
  }
@@ -1,15 +1,43 @@
1
- import type { ClassTypeWithInstance } from '@navios/di'
1
+ import type { ClassTypeWithInstance, NaviosModule } from '@navios/core'
2
2
 
3
- import { Container } from '@navios/di'
3
+ import { Container } from '@navios/core'
4
4
 
5
5
  import type { CommanderApplicationOptions } from './commander.application.mjs'
6
- import type { Module } from './interfaces/index.mjs'
7
6
 
8
7
  import { CommanderApplication } from './commander.application.mjs'
9
8
 
9
+ /**
10
+ * Factory class for creating and configuring CLI applications.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { CommanderFactory } from '@navios/commander'
15
+ * import { AppModule } from './app.module'
16
+ *
17
+ * async function bootstrap() {
18
+ * const app = await CommanderFactory.create(AppModule)
19
+ * await app.init()
20
+ * await app.run(process.argv)
21
+ * await app.close()
22
+ * }
23
+ * ```
24
+ */
10
25
  export class CommanderFactory {
26
+ /**
27
+ * Creates a new CommanderApplication instance and configures it with the provided module.
28
+ *
29
+ * @param appModule - The root CLI module class that contains commands and/or imports other modules
30
+ * @param options - Optional configuration options for the application
31
+ * @returns A promise that resolves to a configured CommanderApplication instance
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * const app = await CommanderFactory.create(AppModule)
36
+ * await app.init()
37
+ * ```
38
+ */
11
39
  static async create(
12
- appModule: ClassTypeWithInstance<Module>,
40
+ appModule: ClassTypeWithInstance<NaviosModule>,
13
41
  options: CommanderApplicationOptions = {},
14
42
  ) {
15
43
  const container = new Container()
@@ -1,14 +1,49 @@
1
- import type { ClassType } from '@navios/di'
1
+ import type { ClassType } from '@navios/core'
2
2
 
3
- import { Injectable, InjectableScope, InjectionToken } from '@navios/di'
3
+ import { Injectable, InjectableScope, InjectionToken } from '@navios/core'
4
4
 
5
5
  import { getCliModuleMetadata } from '../metadata/index.mjs'
6
6
 
7
+ /**
8
+ * Options for the `@CliModule` decorator.
9
+ *
10
+ * @public
11
+ */
7
12
  export interface CliModuleOptions {
13
+ /**
14
+ * Array or Set of command classes to register in this module.
15
+ * Commands must be decorated with `@Command`.
16
+ */
8
17
  commands?: ClassType[] | Set<ClassType>
18
+ /**
19
+ * Array or Set of other CLI modules to import.
20
+ * Imported modules' commands will be available in this module.
21
+ */
9
22
  imports?: ClassType[] | Set<ClassType>
10
23
  }
11
24
 
25
+ /**
26
+ * Decorator that marks a class as a CLI module.
27
+ *
28
+ * Modules organize commands and can import other modules to compose larger CLI applications.
29
+ * The module can optionally implement `NaviosModule` interface for lifecycle hooks.
30
+ *
31
+ * @param options - Configuration options for the module
32
+ * @returns A class decorator function
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * import { CliModule } from '@navios/commander'
37
+ * import { GreetCommand } from './greet.command'
38
+ * import { UserModule } from './user.module'
39
+ *
40
+ * @CliModule({
41
+ * commands: [GreetCommand],
42
+ * imports: [UserModule]
43
+ * })
44
+ * export class AppModule {}
45
+ * ```
46
+ */
12
47
  export function CliModule(
13
48
  { commands = [], imports = [] }: CliModuleOptions = {
14
49
  commands: [],
@@ -1,15 +1,58 @@
1
- import type { ClassType } from '@navios/di'
1
+ import type { ClassType } from '@navios/core'
2
2
  import type { ZodObject } from 'zod'
3
3
 
4
- import { Injectable, InjectableScope, InjectionToken } from '@navios/di'
4
+ import { Injectable, InjectableScope, InjectionToken } from '@navios/core'
5
5
 
6
6
  import { getCommandMetadata } from '../metadata/index.mjs'
7
7
 
8
+ /**
9
+ * Options for the `@Command` decorator.
10
+ *
11
+ * @public
12
+ */
8
13
  export interface CommandOptions {
14
+ /**
15
+ * The command path that users will invoke from the CLI.
16
+ * Can be a single word (e.g., 'greet') or multi-word with colons (e.g., 'user:create', 'db:migrate').
17
+ */
9
18
  path: string
19
+ /**
20
+ * Optional Zod schema for validating command options.
21
+ * If provided, options will be validated and parsed according to this schema.
22
+ */
10
23
  optionsSchema?: ZodObject
11
24
  }
12
25
 
26
+ /**
27
+ * Decorator that marks a class as a CLI command.
28
+ *
29
+ * The decorated class must implement the `CommandHandler` interface with an `execute` method.
30
+ * The command will be automatically registered when its module is loaded.
31
+ *
32
+ * @param options - Configuration options for the command
33
+ * @returns A class decorator function
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * import { Command, CommandHandler } from '@navios/commander'
38
+ * import { z } from 'zod'
39
+ *
40
+ * const optionsSchema = z.object({
41
+ * name: z.string(),
42
+ * greeting: z.string().optional().default('Hello')
43
+ * })
44
+ *
45
+ * @Command({
46
+ * path: 'greet',
47
+ * optionsSchema: optionsSchema
48
+ * })
49
+ * export class GreetCommand implements CommandHandler<z.infer<typeof optionsSchema>> {
50
+ * async execute(options) {
51
+ * console.log(`${options.greeting}, ${options.name}!`)
52
+ * }
53
+ * }
54
+ * ```
55
+ */
13
56
  export function Command({ path, optionsSchema }: CommandOptions) {
14
57
  return function (target: ClassType, context: ClassDecoratorContext) {
15
58
  if (context.kind !== 'class') {
package/src/index.mts CHANGED
@@ -1,4 +1,7 @@
1
- export * from '@navios/di'
1
+ // Re-export DI types and values that users might need
2
+ export * from '@navios/core'
3
+
4
+ // Export commander-specific exports
2
5
  export * from './commander.application.mjs'
3
6
  export * from './commander.factory.mjs'
4
7
  export * from './decorators/index.mjs'
@@ -1,3 +1,36 @@
1
+ /**
2
+ * Interface that all command classes must implement.
3
+ *
4
+ * Commands decorated with `@Command` must implement this interface.
5
+ * The `execute` method is called when the command is invoked.
6
+ *
7
+ * @template TOptions - The type of options that the command accepts
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { Command, CommandHandler } from '@navios/commander'
12
+ * import { z } from 'zod'
13
+ *
14
+ * const optionsSchema = z.object({
15
+ * name: z.string()
16
+ * })
17
+ *
18
+ * type Options = z.infer<typeof optionsSchema>
19
+ *
20
+ * @Command({ path: 'greet', optionsSchema })
21
+ * export class GreetCommand implements CommandHandler<Options> {
22
+ * async execute(options: Options) {
23
+ * console.log(`Hello, ${options.name}!`)
24
+ * }
25
+ * }
26
+ * ```
27
+ */
1
28
  export interface CommandHandler<TOptions = any> {
29
+ /**
30
+ * Executes the command with the provided options.
31
+ *
32
+ * @param options - The validated command options (validated against the command's schema if provided)
33
+ * @returns A promise or void
34
+ */
2
35
  execute(options: TOptions): void | Promise<void>
3
36
  }
@@ -1,20 +1,63 @@
1
1
  import type { CommandMetadata } from '../metadata/command.metadata.mjs'
2
2
 
3
+ /**
4
+ * Execution context for a command execution.
5
+ *
6
+ * Provides access to command metadata, path, and validated options during command execution.
7
+ * This context is automatically injected and available via the `CommandExecutionContext` token.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { inject, Injectable } from '@navios/di'
12
+ * import { CommandExecutionContext } from '@navios/commander'
13
+ *
14
+ * @Injectable()
15
+ * class CommandLogger {
16
+ * private ctx = inject(CommandExecutionContext)
17
+ *
18
+ * log() {
19
+ * console.log('Command:', this.ctx.getCommandPath())
20
+ * console.log('Options:', this.ctx.getOptions())
21
+ * }
22
+ * }
23
+ * ```
24
+ */
3
25
  export class CommanderExecutionContext {
26
+ /**
27
+ * @internal
28
+ * Creates a new execution context.
29
+ */
4
30
  constructor(
5
31
  private readonly command: CommandMetadata,
6
32
  private readonly commandPath: string,
7
33
  private readonly options: any,
8
34
  ) {}
9
35
 
36
+ /**
37
+ * Gets the command metadata.
38
+ *
39
+ * @returns The command metadata including path and options schema
40
+ */
10
41
  getCommand(): CommandMetadata {
11
42
  return this.command
12
43
  }
13
44
 
45
+ /**
46
+ * Gets the command path that was invoked.
47
+ *
48
+ * @returns The command path (e.g., 'greet', 'user:create')
49
+ */
14
50
  getCommandPath(): string {
15
51
  return this.commandPath
16
52
  }
17
53
 
54
+ /**
55
+ * Gets the validated command options.
56
+ *
57
+ * Options are validated against the command's Zod schema if one was provided.
58
+ *
59
+ * @returns The validated options object
60
+ */
18
61
  getOptions(): any {
19
62
  return this.options
20
63
  }
@@ -1,3 +1,2 @@
1
- export * from './module.interface.mjs'
2
1
  export * from './command-handler.interface.mjs'
3
2
  export * from './commander-execution-context.interface.mjs'
@@ -1,13 +1,39 @@
1
- import type { ClassType } from '@navios/di'
1
+ import type { ClassType } from '@navios/core'
2
2
 
3
+ /**
4
+ * @internal
5
+ * Symbol key used to store CLI module metadata on classes.
6
+ */
3
7
  export const CliModuleMetadataKey = Symbol('CliModuleMetadataKey')
4
8
 
9
+ /**
10
+ * Metadata associated with a CLI module.
11
+ *
12
+ * @public
13
+ */
5
14
  export interface CliModuleMetadata {
15
+ /**
16
+ * Set of command classes registered in this module.
17
+ */
6
18
  commands: Set<ClassType>
19
+ /**
20
+ * Set of other modules imported by this module.
21
+ */
7
22
  imports: Set<ClassType>
23
+ /**
24
+ * Map of custom attributes that can be attached to the module.
25
+ */
8
26
  customAttributes: Map<string | symbol, any>
9
27
  }
10
28
 
29
+ /**
30
+ * Gets or creates CLI module metadata for a class.
31
+ *
32
+ * @internal
33
+ * @param target - The module class
34
+ * @param context - The decorator context
35
+ * @returns The module metadata
36
+ */
11
37
  export function getCliModuleMetadata(
12
38
  target: ClassType,
13
39
  context: ClassDecoratorContext,
@@ -33,13 +59,22 @@ export function getCliModuleMetadata(
33
59
  throw new Error('[Navios Commander] Wrong environment.')
34
60
  }
35
61
 
36
- export function extractCliModuleMetadata(
37
- target: ClassType,
38
- ): CliModuleMetadata {
62
+ /**
63
+ * Extracts CLI module metadata from a class.
64
+ *
65
+ * @param target - The module class
66
+ * @returns The module metadata
67
+ * @throws {Error} If the class is not decorated with @CliModule
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * const metadata = extractCliModuleMetadata(AppModule)
72
+ * console.log(metadata.commands.size) // Number of commands
73
+ * ```
74
+ */
75
+ export function extractCliModuleMetadata(target: ClassType): CliModuleMetadata {
39
76
  // @ts-expect-error We add a custom metadata key to the target
40
- const metadata = target[CliModuleMetadataKey] as
41
- | CliModuleMetadata
42
- | undefined
77
+ const metadata = target[CliModuleMetadataKey] as CliModuleMetadata | undefined
43
78
  if (!metadata) {
44
79
  throw new Error(
45
80
  `[Navios Commander] Module metadata not found for ${target.name}. Make sure to use @CliModule decorator.`,
@@ -48,6 +83,12 @@ export function extractCliModuleMetadata(
48
83
  return metadata
49
84
  }
50
85
 
86
+ /**
87
+ * Checks if a class has CLI module metadata.
88
+ *
89
+ * @param target - The class to check
90
+ * @returns `true` if the class is decorated with @CliModule, `false` otherwise
91
+ */
51
92
  export function hasCliModuleMetadata(target: ClassType): boolean {
52
93
  // @ts-expect-error We add a custom metadata key to the target
53
94
  return !!target[CliModuleMetadataKey]