@navios/commander 1.5.1 → 1.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 (52) hide show
  1. package/.turbo/turbo-build.log +48 -49
  2. package/.turbo/turbo-check.log +0 -2
  3. package/.turbo/turbo-lint.log +2 -3
  4. package/.turbo/turbo-test$colon$ci.log +109 -117
  5. package/.turbo/turbo-test.log +107 -0
  6. package/CHANGELOG.md +21 -0
  7. package/dist/src/interfaces/command-handler.interface.d.mts +7 -3
  8. package/dist/src/interfaces/command-handler.interface.d.mts.map +1 -1
  9. package/dist/src/interfaces/commander-execution-context.interface.d.mts +11 -1
  10. package/dist/src/interfaces/commander-execution-context.interface.d.mts.map +1 -1
  11. package/dist/src/services/cli-parser.service.d.mts +42 -0
  12. package/dist/src/services/cli-parser.service.d.mts.map +1 -1
  13. package/dist/src/services/command-registry.service.d.mts +5 -0
  14. package/dist/src/services/command-registry.service.d.mts.map +1 -1
  15. package/dist/src/services/commander-adapter.service.d.mts +5 -1
  16. package/dist/src/services/commander-adapter.service.d.mts.map +1 -1
  17. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  18. package/dist/tsconfig.tsbuildinfo +1 -1
  19. package/lib/{cli-module.decorator-BzsOEMPH.d.cts → cli-module.decorator-BV3vVKlR.d.cts} +8 -4
  20. package/lib/cli-module.decorator-BV3vVKlR.d.cts.map +1 -0
  21. package/lib/{cli-module.decorator-CCV_elPP.d.mts → cli-module.decorator-DDlgpTgI.d.mts} +19 -5
  22. package/lib/cli-module.decorator-DDlgpTgI.d.mts.map +1 -0
  23. package/lib/{help-command.token-XHx3WkoD.mjs → help-command.token-ChAUjOyV.mjs} +27 -2
  24. package/lib/help-command.token-ChAUjOyV.mjs.map +1 -0
  25. package/lib/{help-command.token-DamE31Aw.cjs → help-command.token-mlwEyWij.cjs} +27 -2
  26. package/lib/help-command.token-mlwEyWij.cjs.map +1 -0
  27. package/lib/{help.command-Bynoll_7.mjs → help.command-CzQymUFY.mjs} +2 -2
  28. package/lib/{help.command-Bynoll_7.mjs.map → help.command-CzQymUFY.mjs.map} +1 -1
  29. package/lib/{help.command-DvKmMpB7.cjs → help.command-knivRhJz.cjs} +2 -2
  30. package/lib/{help.command-DvKmMpB7.cjs.map → help.command-knivRhJz.cjs.map} +1 -1
  31. package/lib/index.cjs +127 -12
  32. package/lib/index.cjs.map +1 -1
  33. package/lib/index.d.cts +60 -3
  34. package/lib/index.d.cts.map +1 -1
  35. package/lib/index.d.mts +49 -2
  36. package/lib/index.d.mts.map +1 -1
  37. package/lib/index.mjs +127 -12
  38. package/lib/index.mjs.map +1 -1
  39. package/lib/legacy-compat/index.d.cts +1 -1
  40. package/lib/legacy-compat/index.d.mts +1 -1
  41. package/package.json +2 -2
  42. package/src/__tests__/commander.factory.e2e.spec.mts +105 -13
  43. package/src/interfaces/command-handler.interface.mts +7 -3
  44. package/src/interfaces/commander-execution-context.interface.mts +13 -0
  45. package/src/services/__tests__/cli-parser.service.spec.mts +294 -0
  46. package/src/services/cli-parser.service.mts +196 -31
  47. package/src/services/command-registry.service.mts +51 -0
  48. package/src/services/commander-adapter.service.mts +13 -4
  49. package/lib/cli-module.decorator-BzsOEMPH.d.cts.map +0 -1
  50. package/lib/cli-module.decorator-CCV_elPP.d.mts.map +0 -1
  51. package/lib/help-command.token-DamE31Aw.cjs.map +0 -1
  52. package/lib/help-command.token-XHx3WkoD.mjs.map +0 -1
@@ -16,6 +16,7 @@ export interface ParsedCliArgs {
16
16
  /**
17
17
  * Parsed options as key-value pairs.
18
18
  * Keys are converted from kebab-case to camelCase.
19
+ * Supports object notation (e.g., --obj.field=value creates { obj: { field: value } }).
19
20
  */
20
21
  options: Record<string, any>
21
22
  /**
@@ -33,6 +34,8 @@ export interface ParsedCliArgs {
33
34
  * - Boolean flags
34
35
  * - Array options
35
36
  * - Positional arguments
37
+ * - Object notation: `--obj.field=value` or `--obj.nested.field value`
38
+ * Creates nested objects automatically (e.g., { obj: { field: value } })
36
39
  *
37
40
  * @public
38
41
  */
@@ -81,52 +84,103 @@ export class CliParserService {
81
84
 
82
85
  if (arg.startsWith('--')) {
83
86
  // Long option format: --key=value or --key value
87
+ // Also supports object notation: --obj.field=value or --obj.field value
84
88
  const key = arg.slice(2)
85
89
  const equalIndex = key.indexOf('=')
86
90
 
87
91
  if (equalIndex !== -1) {
88
- // Format: --key=value
92
+ // Format: --key=value or --obj.field=value
89
93
  const optionName = key.slice(0, equalIndex)
90
94
  const optionValue = key.slice(equalIndex + 1)
91
- const camelCaseKey = this.camelCase(optionName)
92
- const isArray = arrayFields.has(camelCaseKey) || arrayFields.has(optionName)
93
95
 
94
- if (isArray) {
95
- // For array fields, accumulate values
96
- if (!options[camelCaseKey]) {
97
- options[camelCaseKey] = []
96
+ if (this.isObjectNotation(optionName)) {
97
+ // Object notation: --obj.field=value
98
+ const processedPath = this.processObjectNotationKey(optionName)
99
+ const isArray = optionsSchema ? this.isNestedArray(optionsSchema, processedPath) : false
100
+
101
+ if (isArray) {
102
+ const existingValue = this.getNestedProperty(options, processedPath)
103
+ if (!Array.isArray(existingValue)) {
104
+ this.setNestedProperty(options, processedPath, [])
105
+ }
106
+ this.getNestedProperty(options, processedPath).push(this.parseValue(optionValue))
107
+ } else {
108
+ this.setNestedProperty(options, processedPath, this.parseValue(optionValue))
98
109
  }
99
- options[camelCaseKey].push(this.parseValue(optionValue))
100
110
  } else {
101
- options[camelCaseKey] = this.parseValue(optionValue)
111
+ // Flat option: --key=value
112
+ const camelCaseKey = this.camelCase(optionName)
113
+ const isArray = arrayFields.has(camelCaseKey) || arrayFields.has(optionName)
114
+
115
+ if (isArray) {
116
+ // For array fields, accumulate values
117
+ if (!options[camelCaseKey]) {
118
+ options[camelCaseKey] = []
119
+ }
120
+ options[camelCaseKey].push(this.parseValue(optionValue))
121
+ } else {
122
+ options[camelCaseKey] = this.parseValue(optionValue)
123
+ }
102
124
  }
103
125
  i++
104
126
  } else {
105
127
  // Format: --key value or --boolean-flag
106
- const camelCaseKey = this.camelCase(key)
107
- const isBoolean = booleanFields.has(camelCaseKey) || booleanFields.has(key)
108
- const isArray = arrayFields.has(camelCaseKey) || arrayFields.has(key)
109
- const nextArg = args[i + 1]
110
-
111
- if (isBoolean) {
112
- // Known boolean flag from schema
113
- options[camelCaseKey] = true
114
- i++
115
- } else if (isArray && nextArg && !nextArg.startsWith('-')) {
116
- // Known array field from schema - accumulate values
117
- if (!options[camelCaseKey]) {
118
- options[camelCaseKey] = []
128
+ // Also supports: --obj.field value or --obj.boolean-flag
129
+
130
+ if (this.isObjectNotation(key)) {
131
+ // Object notation: --obj.field value or --obj.flag
132
+ const processedPath = this.processObjectNotationKey(key)
133
+ const isBoolean = optionsSchema
134
+ ? this.isNestedBoolean(optionsSchema, processedPath)
135
+ : false
136
+ const isArray = optionsSchema ? this.isNestedArray(optionsSchema, processedPath) : false
137
+ const nextArg = args[i + 1]
138
+
139
+ if (isBoolean) {
140
+ this.setNestedProperty(options, processedPath, true)
141
+ i++
142
+ } else if (isArray && nextArg && !nextArg.startsWith('-')) {
143
+ const existingValue = this.getNestedProperty(options, processedPath)
144
+ if (!Array.isArray(existingValue)) {
145
+ this.setNestedProperty(options, processedPath, [])
146
+ }
147
+ this.getNestedProperty(options, processedPath).push(this.parseValue(nextArg))
148
+ i += 2
149
+ } else if (nextArg && !nextArg.startsWith('-')) {
150
+ this.setNestedProperty(options, processedPath, this.parseValue(nextArg))
151
+ i += 2
152
+ } else {
153
+ // Assume boolean flag
154
+ this.setNestedProperty(options, processedPath, true)
155
+ i++
119
156
  }
120
- options[camelCaseKey].push(this.parseValue(nextArg))
121
- i += 2
122
- } else if (nextArg && !nextArg.startsWith('-')) {
123
- // Has a value
124
- options[camelCaseKey] = this.parseValue(nextArg)
125
- i += 2
126
157
  } else {
127
- // Assume boolean flag
128
- options[camelCaseKey] = true
129
- i++
158
+ // Flat option: --key value or --flag
159
+ const camelCaseKey = this.camelCase(key)
160
+ const isBoolean = booleanFields.has(camelCaseKey) || booleanFields.has(key)
161
+ const isArray = arrayFields.has(camelCaseKey) || arrayFields.has(key)
162
+ const nextArg = args[i + 1]
163
+
164
+ if (isBoolean) {
165
+ // Known boolean flag from schema
166
+ options[camelCaseKey] = true
167
+ i++
168
+ } else if (isArray && nextArg && !nextArg.startsWith('-')) {
169
+ // Known array field from schema - accumulate values
170
+ if (!options[camelCaseKey]) {
171
+ options[camelCaseKey] = []
172
+ }
173
+ options[camelCaseKey].push(this.parseValue(nextArg))
174
+ i += 2
175
+ } else if (nextArg && !nextArg.startsWith('-')) {
176
+ // Has a value
177
+ options[camelCaseKey] = this.parseValue(nextArg)
178
+ i += 2
179
+ } else {
180
+ // Assume boolean flag
181
+ options[camelCaseKey] = true
182
+ i++
183
+ }
130
184
  }
131
185
  }
132
186
  } else if (arg.startsWith('-') && arg.length > 1 && arg !== '-') {
@@ -321,4 +375,115 @@ export class CliParserService {
321
375
  return false
322
376
  }
323
377
  }
378
+
379
+ /**
380
+ * Sets a nested property on an object using dot notation path.
381
+ * Creates intermediate objects as needed.
382
+ *
383
+ * @example
384
+ * setNestedProperty({}, 'a.b.c', 'value') // { a: { b: { c: 'value' } } }
385
+ */
386
+ private setNestedProperty(obj: Record<string, any>, path: string, value: any): void {
387
+ const parts = path.split('.')
388
+ let current = obj
389
+
390
+ for (let i = 0; i < parts.length - 1; i++) {
391
+ const part = parts[i]
392
+ if (!(part in current) || typeof current[part] !== 'object' || current[part] === null) {
393
+ current[part] = {}
394
+ }
395
+ current = current[part]
396
+ }
397
+
398
+ current[parts[parts.length - 1]] = value
399
+ }
400
+
401
+ /**
402
+ * Gets a nested property from an object using dot notation path.
403
+ * Returns undefined if path doesn't exist.
404
+ */
405
+ private getNestedProperty(obj: Record<string, any>, path: string): any {
406
+ const parts = path.split('.')
407
+ let current = obj
408
+
409
+ for (const part of parts) {
410
+ if (current === undefined || current === null || typeof current !== 'object') {
411
+ return undefined
412
+ }
413
+ current = current[part]
414
+ }
415
+
416
+ return current
417
+ }
418
+
419
+ /**
420
+ * Checks if an option key contains dot notation (object notation).
421
+ * Returns true for keys like "obj.field" or "deep.nested.value".
422
+ */
423
+ private isObjectNotation(key: string): boolean {
424
+ return key.includes('.')
425
+ }
426
+
427
+ /**
428
+ * Processes an option key that may contain object notation.
429
+ * Converts each segment from kebab-case to camelCase.
430
+ *
431
+ * @example
432
+ * processObjectNotationKey('my-obj.field-name') // 'myObj.fieldName'
433
+ */
434
+ private processObjectNotationKey(key: string): string {
435
+ return key
436
+ .split('.')
437
+ .map((segment) => this.camelCase(segment))
438
+ .join('.')
439
+ }
440
+
441
+ /**
442
+ * Gets the nested schema for a given dot-notation path.
443
+ * Returns undefined if the path doesn't lead to a valid schema.
444
+ */
445
+ private getNestedSchema(schema: z.ZodObject, path: string): z.ZodType | undefined {
446
+ try {
447
+ const parts = path.split('.')
448
+ let currentSchema: any = schema
449
+
450
+ for (const part of parts) {
451
+ // Unwrap optional/default wrappers
452
+ while (currentSchema?.def?.type === 'optional' || currentSchema?.def?.type === 'default') {
453
+ currentSchema = currentSchema.def.innerType
454
+ }
455
+
456
+ if (currentSchema?.def?.type !== 'object') {
457
+ return undefined
458
+ }
459
+
460
+ const shape = currentSchema.def.shape
461
+ if (!shape || !(part in shape)) {
462
+ return undefined
463
+ }
464
+
465
+ currentSchema = shape[part]
466
+ }
467
+
468
+ return currentSchema
469
+ } catch {
470
+ return undefined
471
+ }
472
+ }
473
+
474
+ /**
475
+ * Checks if a nested path represents a boolean field in the schema.
476
+ */
477
+ private isNestedBoolean(schema: z.ZodObject, path: string): boolean {
478
+ const nestedSchema = this.getNestedSchema(schema, path)
479
+ return nestedSchema ? this.isSchemaBoolean(nestedSchema) : false
480
+ }
481
+
482
+ /**
483
+ * Checks if a nested path represents an array field in the schema.
484
+ */
485
+ private isNestedArray(schema: z.ZodObject, path: string): boolean {
486
+ const nestedSchema = this.getNestedSchema(schema, path)
487
+ return nestedSchema ? this.isSchemaArray(nestedSchema) : false
488
+ }
324
489
  }
@@ -133,6 +133,9 @@ export class CommandRegistryService {
133
133
  const optionFlag = `--${kebabKey}`
134
134
  const fieldType = this.getSchemaTypeName(fieldSchema as any)
135
135
  lines.push(` ${optionFlag.padEnd(20)} ${fieldType}`)
136
+
137
+ // Check for nested object fields and display them with dot notation
138
+ this.formatNestedObjectOptions(fieldSchema as any, kebabKey, lines, ' ')
136
139
  }
137
140
  }
138
141
  } catch {
@@ -143,6 +146,54 @@ export class CommandRegistryService {
143
146
  return lines.join('\n')
144
147
  }
145
148
 
149
+ /**
150
+ * Recursively formats nested object options for help display.
151
+ * Shows nested fields with dot notation (e.g., --config.port)
152
+ */
153
+ private formatNestedObjectOptions(
154
+ schema: any,
155
+ parentPath: string,
156
+ lines: string[],
157
+ indent: string,
158
+ ): void {
159
+ try {
160
+ let currentSchema = schema
161
+ let typeName = currentSchema?.def?.type
162
+
163
+ // Unwrap optional/default wrappers
164
+ while (typeName === 'optional' || typeName === 'default') {
165
+ currentSchema = currentSchema?.def?.innerType
166
+ typeName = currentSchema?.def?.type
167
+ }
168
+
169
+ if (typeName !== 'object') {
170
+ return
171
+ }
172
+
173
+ const shape = currentSchema?.def?.shape
174
+ if (!shape || typeof shape !== 'object') {
175
+ return
176
+ }
177
+
178
+ for (const [key, fieldSchema] of Object.entries(shape)) {
179
+ const kebabKey = key.replace(/([A-Z])/g, '-$1').toLowerCase()
180
+ const optionFlag = `--${parentPath}.${kebabKey}`
181
+ const fieldType = this.getSchemaTypeName(fieldSchema as any)
182
+ lines.push(`${indent}${optionFlag.padEnd(20 - indent.length + 2)} ${fieldType}`)
183
+
184
+ // Recurse for deeper nesting
185
+ this.formatNestedObjectOptions(
186
+ fieldSchema as any,
187
+ `${parentPath}.${kebabKey}`,
188
+ lines,
189
+ indent + ' ',
190
+ )
191
+ }
192
+ } catch {
193
+ // Silently fail if schema introspection fails
194
+ }
195
+ }
196
+
146
197
  /**
147
198
  * Gets a human-readable type name from a zod/v4 schema.
148
199
  */
@@ -130,7 +130,7 @@ export class CommanderAdapterService implements AbstractCliAdapterInterface {
130
130
  ? this.cliParser.parse(argv, command.metadata.optionsSchema)
131
131
  : preliminaryParse
132
132
 
133
- await this.executeCommand(parsed.command, parsed.options)
133
+ await this.executeCommand(parsed.command, parsed.options, parsed.positionals)
134
134
  } catch (error) {
135
135
  if (error instanceof Error) {
136
136
  this.logger.error(`Error: ${error.message}`)
@@ -146,7 +146,11 @@ export class CommanderAdapterService implements AbstractCliAdapterInterface {
146
146
  /**
147
147
  * Execute a command programmatically with the provided options.
148
148
  */
149
- async executeCommand(path: string, options: Record<string, unknown> = {}): Promise<void> {
149
+ async executeCommand(
150
+ path: string,
151
+ options: Record<string, unknown> = {},
152
+ positionals: string[] = [],
153
+ ): Promise<void> {
150
154
  const command = this.commandRegistry.getByPath(path)
151
155
  if (!command) {
152
156
  throw new Error(`[Navios Commander] Command not found: ${path}`)
@@ -161,7 +165,12 @@ export class CommanderAdapterService implements AbstractCliAdapterInterface {
161
165
  }
162
166
 
163
167
  // Create execution context
164
- const executionContext = new CommanderExecutionContext(metadata, path, validatedOptions)
168
+ const executionContext = new CommanderExecutionContext(
169
+ metadata,
170
+ path,
171
+ validatedOptions,
172
+ positionals,
173
+ )
165
174
 
166
175
  // Begin request scope
167
176
  const requestId = `cmd-${Date.now()}-${Math.random().toString(36).substring(7)}`
@@ -177,7 +186,7 @@ export class CommanderAdapterService implements AbstractCliAdapterInterface {
177
186
  throw new Error(`Command ${path} does not implement execute method`)
178
187
  }
179
188
 
180
- await commandInstance.execute(validatedOptions)
189
+ await commandInstance.execute(validatedOptions, positionals)
181
190
  } finally {
182
191
  await scopeContainer.endRequest()
183
192
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli-module.decorator-BzsOEMPH.d.cts","names":["CommandHandler","TOptions","Promise","InjectionToken","ClassType","ClassTypeWithInstance","Registry","z","CommandHandler","CommandOptions","ZodObject","Command","path","description","token","optionsSchema","priority","registry","ClassDecoratorContext","ClassType","Registry","CliModuleOptions","Set","CliModule","commands","controllers","imports","guards","overrides","priority","registry","ClassDecoratorContext"],"sources":["../src/interfaces/command-handler.interface.d.mts","../src/decorators/command.decorator.d.mts","../src/decorators/cli-module.decorator.d.mts"],"sourcesContent":["/**\n * Interface that all command classes must implement.\n *\n * Commands decorated with `@Command` must implement this interface.\n * The `execute` method is called when the command is invoked.\n *\n * @template TOptions - The type of options that the command accepts\n *\n * @example\n * ```typescript\n * import { Command, CommandHandler } from '@navios/commander'\n * import { z } from 'zod/v4'\n *\n * const optionsSchema = z.object({\n * name: z.string()\n * })\n *\n * type Options = z.infer<typeof optionsSchema>\n *\n * @Command({ path: 'greet', optionsSchema })\n * export class GreetCommand implements CommandHandler<Options> {\n * async execute(options: Options) {\n * console.log(`Hello, ${options.name}!`)\n * }\n * }\n * ```\n */\nexport interface CommandHandler<TOptions = any> {\n /**\n * Executes the command with the provided options.\n *\n * @param options - The validated command options (validated against the command's schema if provided)\n * @returns A promise or void\n */\n execute(options: TOptions): void | Promise<void>\n}\n//# sourceMappingURL=command-handler.interface.d.mts.map\n","import { InjectionToken } from '@navios/core'\n\nimport type { ClassType, ClassTypeWithInstance, Registry } from '@navios/core'\nimport type { z } from 'zod/v4'\n\nimport type { CommandHandler } from '../interfaces/index.mjs'\n/**\n * Options for the `@Command` decorator.\n *\n * @public\n */\nexport interface CommandOptions {\n /**\n * The token to use for the command.\n * If provided, the command will be registered with this token.\n */\n token?: InjectionToken<ClassTypeWithInstance<CommandHandler<any>>>\n /**\n * The command path that users will invoke from the CLI.\n * Can be a single word (e.g., 'greet') or multi-word with colons (e.g., 'user:create', 'db:migrate').\n */\n path: string\n /**\n * Optional description of the command for help text.\n * Displayed when users run `help` or `--help`.\n */\n description?: string\n /**\n * Optional zod/v4 schema for validating command options.\n * If provided, options will be validated and parsed according to this schema.\n */\n optionsSchema?: z.ZodObject\n /**\n * Priority level for the command.\n * Higher priority commands will be loaded first.\n */\n priority?: number\n /**\n * Registry to use for the command.\n * Registry is used to store the command and its options schema.\n */\n registry?: Registry\n}\n/**\n * Decorator that marks a class as a CLI command.\n *\n * The decorated class must implement the `CommandHandler` interface with an `execute` method.\n * The command will be automatically registered when its module is loaded.\n *\n * @param options - Configuration options for the command\n * @returns A class decorator function\n *\n * @example\n * ```typescript\n * import { Command, CommandHandler } from '@navios/commander'\n * import { z } from 'zod/v4'\n *\n * const optionsSchema = z.object({\n * name: z.string(),\n * greeting: z.string().optional().default('Hello')\n * })\n *\n * @Command({\n * path: 'greet',\n * optionsSchema: optionsSchema\n * })\n * export class GreetCommand implements CommandHandler<z.infer<typeof optionsSchema>> {\n * async execute(options) {\n * console.log(`${options.greeting}, ${options.name}!`)\n * }\n * }\n * ```\n */\nexport declare function Command({\n path,\n description,\n token,\n optionsSchema,\n priority,\n registry,\n}: CommandOptions): (\n target: ClassType,\n context: ClassDecoratorContext<abstract new (...args: any) => any>,\n) => any\n//# sourceMappingURL=command.decorator.d.mts.map\n","import type { ClassType, Registry } from '@navios/core'\n/**\n * Options for the `@CliModule` decorator.\n *\n * @public\n */\nexport interface CliModuleOptions {\n /**\n * Array or Set of command classes to register in this module.\n * Commands must be decorated with `@Command`.\n */\n commands?: ClassType[] | Set<ClassType>\n /**\n * Array or Set of controller classes for HTTP endpoints.\n * Allows mixing HTTP and CLI functionality in the same module.\n */\n controllers?: ClassType[] | Set<ClassType>\n /**\n * Array or Set of other modules to import.\n * Imported modules' commands and controllers will be available.\n */\n imports?: ClassType[] | Set<ClassType>\n /**\n * Guards to apply to all controllers in this module.\n * Guards are executed in reverse order (last guard first).\n */\n guards?: ClassType[] | Set<ClassType>\n /**\n * Service override classes to import for side effects.\n * These classes are imported to ensure their @Injectable decorators execute,\n * allowing them to register with the DI system. Overrides should use the same\n * InjectionToken as the original service with a higher priority.\n */\n overrides?: ClassType[] | Set<ClassType>\n /**\n * Priority level for the module.\n * Higher priority modules will be loaded first.\n */\n priority?: number\n /**\n * Registry to use for the module.\n * Registry is used to store the module and its commands.\n */\n registry?: Registry\n}\n/**\n * Decorator that marks a class as a CLI module.\n *\n * This decorator extends the standard @Module decorator, adding support for\n * CLI commands while maintaining full compatibility with HTTP controllers.\n * Modules organize commands and can import other modules to compose larger\n * CLI applications.\n *\n * The module can optionally implement `NaviosModule` interface for lifecycle hooks.\n *\n * @param options - Configuration options for the module\n * @returns A class decorator function\n *\n * @example\n * ```typescript\n * import { CliModule } from '@navios/commander'\n * import { GreetCommand } from './greet.command'\n * import { UserModule } from './user.module'\n *\n * @CliModule({\n * commands: [GreetCommand],\n * imports: [UserModule]\n * })\n * export class AppModule {}\n * ```\n *\n * @example\n * ```typescript\n * // Mixed HTTP and CLI module\n * @CliModule({\n * controllers: [HealthController],\n * commands: [MigrateCommand],\n * imports: [DatabaseModule],\n * })\n * export class AppModule {}\n * ```\n */\nexport declare function CliModule({\n commands,\n controllers,\n imports,\n guards,\n overrides,\n priority,\n registry,\n}?: CliModuleOptions): (\n target: ClassType,\n context: ClassDecoratorContext<abstract new (...args: any) => any>,\n) => ClassType\n//# sourceMappingURL=cli-module.decorator.d.mts.map\n"],"mappings":";;;;;;;;;AA2BA;;;;AChBA;;;;;;;AA8DA;;;;;;;;;;;;UD9CiBA;;AErBjB;;;;;EAUkCmB,OAAAA,CAAAA,OAAAA,EFkBflB,QElBekB,CAAAA,EAAAA,IAAAA,GFkBGjB,OElBHiB,CAAAA,IAAAA,CAAAA;;;;;;ADLlC;;;AAKUhB,UALOM,cAAAA,CAKPN;EAeQI;;;AA0ClB;EACEK,KAAAA,CAAAA,EA1DQT,cA0DRS,CA1DuBP,qBA0DvBO,CA1D6CJ,cA0D7CI,CAAAA,GAAAA,CAAAA,CAAAA,CAAAA;EACAC;;;;EAIAI,IAAAA,EAAAA,MAAAA;EACCR;;;;;;;AC1EH;;EAK+BU,aAAAA,CAAAA,EDoBbZ,CAAAA,CAAEG,SCpBWS;EAAJG;;;;EAUfH,QAAAA,CAAAA,EAAAA,MAAAA;EAAkBA;;;;EAKLG,QAAAA,CAAAA,EDeZhB,QCfYgB;;;;;;AAwDzB;;;;;;;;;;;;;;;;;;;;;;;;;;iBDTwBX,OAAAA;;;;;;;GAOrBF,0BACOL,oBACCc;;;;;;ADvDX;;UErBiBG,gBAAAA;;ADKjB;;;EAKUlB,QAAAA,CAAAA,ECLGgB,SDKHhB,EAAAA,GCLiBmB,GDKjBnB,CCLqBgB,SDKrBhB,CAAAA;EAeQI;;;AA0ClB;EACEK,WAAAA,CAAAA,EC1DcO,SD0DdP,EAAAA,GC1D4BU,GD0D5BV,CC1DgCO,SD0DhCP,CAAAA;EACAC;;;;EAIAI,OAAAA,CAAAA,EC1DUE,SD0DVF,EAAAA,GC1DwBK,GD0DxBL,CC1D4BE,SD0D5BF,CAAAA;EACCR;;;;WCtDQU,cAAcG,IAAIH;;;AApB7B;;;;EAUgBA,SAAAA,CAAAA,EAiBFA,SAjBEA,EAAAA,GAiBYG,GAjBZH,CAiBgBA,SAjBhBA,CAAAA;EAAkBA;;;;EAKRG,QAAAA,CAAAA,EAAAA,MAAAA;EAKfH;;;;EAOqBA,QAAAA,CAAAA,EAUnBC,QAVmBD;;;;AAiDhC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAwBI,SAAAA;;;;;;;;IAQpBF,4BACMF,oBACCY,8DACNZ"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli-module.decorator-CCV_elPP.d.mts","names":["CommandHandler","TOptions","Promise","AbstractAdapterInterface","AbstractCliAdapterInterface","Promise","Record","Array","AdapterEnvironment","AbstractCliAdapterInterface","CliAdapterOptions","CliEnvironment","ClassType","z","CommandMetadataKey","CommandMetadata","ZodObject","Map","getCommandMetadata","ClassDecoratorContext","extractCommandMetadata","hasCommandMetadata","CommandMetadata","CommanderExecutionContext","InjectionToken","ClassType","ClassTypeWithInstance","Registry","z","CommandHandler","CommandOptions","ZodObject","Command","path","description","token","optionsSchema","priority","registry","ClassDecoratorContext","ClassType","Registry","CliModuleOptions","Set","CliModule","commands","controllers","imports","guards","overrides","priority","registry","ClassDecoratorContext"],"sources":["../src/interfaces/command-handler.interface.d.mts","../src/interfaces/abstract-cli-adapter.interface.d.mts","../src/interfaces/environment.interface.d.mts","../src/metadata/command.metadata.d.mts","../src/interfaces/commander-execution-context.interface.d.mts","../src/decorators/command.decorator.d.mts","../src/decorators/cli-module.decorator.d.mts"],"sourcesContent":["/**\n * Interface that all command classes must implement.\n *\n * Commands decorated with `@Command` must implement this interface.\n * The `execute` method is called when the command is invoked.\n *\n * @template TOptions - The type of options that the command accepts\n *\n * @example\n * ```typescript\n * import { Command, CommandHandler } from '@navios/commander'\n * import { z } from 'zod/v4'\n *\n * const optionsSchema = z.object({\n * name: z.string()\n * })\n *\n * type Options = z.infer<typeof optionsSchema>\n *\n * @Command({ path: 'greet', optionsSchema })\n * export class GreetCommand implements CommandHandler<Options> {\n * async execute(options: Options) {\n * console.log(`Hello, ${options.name}!`)\n * }\n * }\n * ```\n */\nexport interface CommandHandler<TOptions = any> {\n /**\n * Executes the command with the provided options.\n *\n * @param options - The validated command options (validated against the command's schema if provided)\n * @returns A promise or void\n */\n execute(options: TOptions): void | Promise<void>\n}\n//# sourceMappingURL=command-handler.interface.d.mts.map\n","import type { AbstractAdapterInterface } from '@navios/core'\n/**\n * Interface for CLI adapters.\n * Extends the base adapter interface with CLI-specific methods.\n *\n * @public\n */\nexport interface AbstractCliAdapterInterface extends AbstractAdapterInterface {\n /**\n * Run the CLI application with the given arguments.\n * Parses arguments and executes the matching command.\n *\n * @param argv - Command-line arguments array (defaults to `process.argv`)\n *\n * @example\n * ```typescript\n * const adapter = app.getAdapter() as AbstractCliAdapterInterface\n * await adapter.run(process.argv)\n * ```\n */\n run(argv?: string[]): Promise<void>\n /**\n * Execute a command programmatically with the provided options.\n *\n * @param path - The command path (e.g., 'greet', 'user:create')\n * @param options - The command options object\n *\n * @example\n * ```typescript\n * await adapter.executeCommand('user:create', {\n * name: 'John',\n * email: 'john@example.com',\n * })\n * ```\n */\n executeCommand(path: string, options: Record<string, unknown>): Promise<void>\n /**\n * Get all registered command paths and their class references.\n *\n * @returns Array of objects containing path and class\n *\n * @example\n * ```typescript\n * const commands = adapter.getAllCommands()\n * commands.forEach(({ path }) => console.log(path))\n * ```\n */\n getAllCommands(): Array<{\n path: string\n class: unknown\n }>\n}\n//# sourceMappingURL=abstract-cli-adapter.interface.d.mts.map\n","import type { AdapterEnvironment } from '@navios/core'\n\nimport type { AbstractCliAdapterInterface } from './abstract-cli-adapter.interface.mjs'\n/**\n * Options for configuring the CLI adapter.\n *\n * @public\n */\nexport interface CliAdapterOptions {}\n/**\n * Environment type definition for CLI adapters.\n * Used with NaviosFactory.create<CliEnvironment>() for type-safe CLI applications.\n *\n * @public\n *\n * @example\n * ```typescript\n * import { NaviosFactory } from '@navios/core'\n * import { defineCliEnvironment, type CliEnvironment } from '@navios/commander'\n *\n * const app = await NaviosFactory.create<CliEnvironment>(AppModule, {\n * adapter: defineCliEnvironment(),\n * })\n * ```\n */\nexport interface CliEnvironment extends AdapterEnvironment {\n options: CliAdapterOptions\n adapter: AbstractCliAdapterInterface\n}\n//# sourceMappingURL=environment.interface.d.mts.map\n","import type { ClassType } from '@navios/core'\nimport type { z } from 'zod/v4'\n/**\n * @internal\n * Symbol key used to store command metadata on classes.\n */\nexport declare const CommandMetadataKey: unique symbol\n/**\n * Metadata associated with a command.\n *\n * @public\n */\nexport interface CommandMetadata {\n /**\n * The command path (e.g., 'greet', 'user:create').\n */\n path: string\n /**\n * Optional description of the command for help text.\n */\n description?: string\n /**\n * Optional zod/v4 schema for validating command options.\n */\n optionsSchema?: z.ZodObject\n /**\n * Map of custom attributes that can be attached to the command.\n */\n customAttributes: Map<string | symbol, any>\n}\n/**\n * Gets or creates command metadata for a class.\n *\n * @internal\n * @param target - The command class\n * @param context - The decorator context\n * @param path - The command path\n * @param description - Optional description for help text\n * @param optionsSchema - Optional zod/v4 schema\n * @returns The command metadata\n */\nexport declare function getCommandMetadata(\n target: ClassType,\n context: ClassDecoratorContext,\n path: string,\n description?: string,\n optionsSchema?: z.ZodObject,\n): CommandMetadata\n/**\n * Extracts command metadata from a class.\n *\n * @param target - The command class\n * @returns The command metadata\n * @throws {Error} If the class is not decorated with @Command\n *\n * @example\n * ```typescript\n * const metadata = extractCommandMetadata(GreetCommand)\n * console.log(metadata.path) // 'greet'\n * ```\n */\nexport declare function extractCommandMetadata(target: ClassType): CommandMetadata\n/**\n * Checks if a class has command metadata.\n *\n * @param target - The class to check\n * @returns `true` if the class is decorated with @Command, `false` otherwise\n */\nexport declare function hasCommandMetadata(target: ClassType): boolean\n//# sourceMappingURL=command.metadata.d.mts.map\n","import type { CommandMetadata } from '../metadata/command.metadata.mjs'\n/**\n * Execution context for a command execution.\n *\n * Provides access to command metadata, path, and validated options during command execution.\n * This context is automatically injected and available via the `CommandExecutionContext` token.\n *\n * @example\n * ```typescript\n * import { inject, Injectable } from '@navios/core'\n * import { CommandExecutionContext } from '@navios/commander'\n *\n * @Injectable()\n * class CommandLogger {\n * private ctx = inject(CommandExecutionContext)\n *\n * log() {\n * console.log('Command:', this.ctx.getCommandPath())\n * console.log('Options:', this.ctx.getOptions())\n * }\n * }\n * ```\n */\nexport declare class CommanderExecutionContext {\n private readonly command\n private readonly commandPath\n private readonly options\n /**\n * @internal\n * Creates a new execution context.\n */\n constructor(command: CommandMetadata, commandPath: string, options: any)\n /**\n * Gets the command metadata.\n *\n * @returns The command metadata including path and options schema\n */\n getCommand(): CommandMetadata\n /**\n * Gets the command path that was invoked.\n *\n * @returns The command path (e.g., 'greet', 'user:create')\n */\n getCommandPath(): string\n /**\n * Gets the validated command options.\n *\n * Options are validated against the command's zod/v4 schema if one was provided.\n *\n * @returns The validated options object\n */\n getOptions(): any\n}\n//# sourceMappingURL=commander-execution-context.interface.d.mts.map\n","import { InjectionToken } from '@navios/core'\n\nimport type { ClassType, ClassTypeWithInstance, Registry } from '@navios/core'\nimport type { z } from 'zod/v4'\n\nimport type { CommandHandler } from '../interfaces/index.mjs'\n/**\n * Options for the `@Command` decorator.\n *\n * @public\n */\nexport interface CommandOptions {\n /**\n * The token to use for the command.\n * If provided, the command will be registered with this token.\n */\n token?: InjectionToken<ClassTypeWithInstance<CommandHandler<any>>>\n /**\n * The command path that users will invoke from the CLI.\n * Can be a single word (e.g., 'greet') or multi-word with colons (e.g., 'user:create', 'db:migrate').\n */\n path: string\n /**\n * Optional description of the command for help text.\n * Displayed when users run `help` or `--help`.\n */\n description?: string\n /**\n * Optional zod/v4 schema for validating command options.\n * If provided, options will be validated and parsed according to this schema.\n */\n optionsSchema?: z.ZodObject\n /**\n * Priority level for the command.\n * Higher priority commands will be loaded first.\n */\n priority?: number\n /**\n * Registry to use for the command.\n * Registry is used to store the command and its options schema.\n */\n registry?: Registry\n}\n/**\n * Decorator that marks a class as a CLI command.\n *\n * The decorated class must implement the `CommandHandler` interface with an `execute` method.\n * The command will be automatically registered when its module is loaded.\n *\n * @param options - Configuration options for the command\n * @returns A class decorator function\n *\n * @example\n * ```typescript\n * import { Command, CommandHandler } from '@navios/commander'\n * import { z } from 'zod/v4'\n *\n * const optionsSchema = z.object({\n * name: z.string(),\n * greeting: z.string().optional().default('Hello')\n * })\n *\n * @Command({\n * path: 'greet',\n * optionsSchema: optionsSchema\n * })\n * export class GreetCommand implements CommandHandler<z.infer<typeof optionsSchema>> {\n * async execute(options) {\n * console.log(`${options.greeting}, ${options.name}!`)\n * }\n * }\n * ```\n */\nexport declare function Command({\n path,\n description,\n token,\n optionsSchema,\n priority,\n registry,\n}: CommandOptions): (\n target: ClassType,\n context: ClassDecoratorContext<abstract new (...args: any) => any>,\n) => any\n//# sourceMappingURL=command.decorator.d.mts.map\n","import type { ClassType, Registry } from '@navios/core'\n/**\n * Options for the `@CliModule` decorator.\n *\n * @public\n */\nexport interface CliModuleOptions {\n /**\n * Array or Set of command classes to register in this module.\n * Commands must be decorated with `@Command`.\n */\n commands?: ClassType[] | Set<ClassType>\n /**\n * Array or Set of controller classes for HTTP endpoints.\n * Allows mixing HTTP and CLI functionality in the same module.\n */\n controllers?: ClassType[] | Set<ClassType>\n /**\n * Array or Set of other modules to import.\n * Imported modules' commands and controllers will be available.\n */\n imports?: ClassType[] | Set<ClassType>\n /**\n * Guards to apply to all controllers in this module.\n * Guards are executed in reverse order (last guard first).\n */\n guards?: ClassType[] | Set<ClassType>\n /**\n * Service override classes to import for side effects.\n * These classes are imported to ensure their @Injectable decorators execute,\n * allowing them to register with the DI system. Overrides should use the same\n * InjectionToken as the original service with a higher priority.\n */\n overrides?: ClassType[] | Set<ClassType>\n /**\n * Priority level for the module.\n * Higher priority modules will be loaded first.\n */\n priority?: number\n /**\n * Registry to use for the module.\n * Registry is used to store the module and its commands.\n */\n registry?: Registry\n}\n/**\n * Decorator that marks a class as a CLI module.\n *\n * This decorator extends the standard @Module decorator, adding support for\n * CLI commands while maintaining full compatibility with HTTP controllers.\n * Modules organize commands and can import other modules to compose larger\n * CLI applications.\n *\n * The module can optionally implement `NaviosModule` interface for lifecycle hooks.\n *\n * @param options - Configuration options for the module\n * @returns A class decorator function\n *\n * @example\n * ```typescript\n * import { CliModule } from '@navios/commander'\n * import { GreetCommand } from './greet.command'\n * import { UserModule } from './user.module'\n *\n * @CliModule({\n * commands: [GreetCommand],\n * imports: [UserModule]\n * })\n * export class AppModule {}\n * ```\n *\n * @example\n * ```typescript\n * // Mixed HTTP and CLI module\n * @CliModule({\n * controllers: [HealthController],\n * commands: [MigrateCommand],\n * imports: [DatabaseModule],\n * })\n * export class AppModule {}\n * ```\n */\nexport declare function CliModule({\n commands,\n controllers,\n imports,\n guards,\n overrides,\n priority,\n registry,\n}?: CliModuleOptions): (\n target: ClassType,\n context: ClassDecoratorContext<abstract new (...args: any) => any>,\n) => ClassType\n//# sourceMappingURL=cli-module.decorator.d.mts.map\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"help-command.token-DamE31Aw.cjs","names":["Injectable","CommandRegistryService","commands","Map","register","path","command","has","Error","set","getByPath","get","getAll","getAllAsArray","result","class","cls","push","formatCommandList","lines","metadata","description","padEnd","join","formatCommandHelp","commandPath","optionsSchema","shape","def","key","fieldSchema","Object","entries","kebabKey","replace","toLowerCase","optionFlag","fieldType","getSchemaTypeName","schema","currentSchema","typeName","type","isOptional","defaultValue","innerType","undefined","JSON","stringify","getSchemaMeta","directMeta","meta","clear","InjectionToken","HelpCommandToken","create"],"sources":["../src/services/command-registry.service.mts","../src/tokens/help-command.token.mts"],"sourcesContent":["import { Injectable } from '@navios/core'\n\nimport type { ClassType } from '@navios/core'\n\nimport type { CommandMetadata } from '../metadata/index.mjs'\n\n/**\n * Represents a registered command with its metadata and module information.\n *\n * @public\n */\nexport interface RegisteredCommand {\n /**\n * The command class\n */\n class: ClassType\n /**\n * The command metadata from @Command decorator\n */\n metadata: CommandMetadata\n /**\n * Name of the module this command belongs to\n */\n moduleName: string\n}\n\n/**\n * Service for registering and looking up CLI commands.\n * Used internally by the CLI adapter to manage discovered commands.\n *\n * @public\n */\n@Injectable()\nexport class CommandRegistryService {\n private commands = new Map<string, RegisteredCommand>()\n\n /**\n * Register a command with its metadata.\n *\n * @param path - The command path (e.g., 'greet', 'user:create')\n * @param command - The registered command data\n * @throws Error if a command with the same path is already registered\n */\n register(path: string, command: RegisteredCommand): void {\n if (this.commands.has(path)) {\n throw new Error(`[Navios Commander] Duplicate command path: ${path}`)\n }\n this.commands.set(path, command)\n }\n\n /**\n * Get a command by its path.\n *\n * @param path - The command path\n * @returns The registered command or undefined if not found\n */\n getByPath(path: string): RegisteredCommand | undefined {\n return this.commands.get(path)\n }\n\n /**\n * Get all registered commands.\n *\n * @returns Map of path to registered command\n */\n getAll(): Map<string, RegisteredCommand> {\n return new Map(this.commands)\n }\n\n /**\n * Get all registered commands as an array of path and class pairs.\n * Useful for listing available commands.\n *\n * @returns Array of objects containing path and class\n */\n getAllAsArray(): Array<{ path: string; class: ClassType }> {\n const result: Array<{ path: string; class: ClassType }> = []\n for (const [path, { class: cls }] of this.commands) {\n result.push({ path, class: cls })\n }\n return result\n }\n\n /**\n * Formats help text listing all available commands with descriptions.\n *\n * @returns Formatted string listing all commands\n */\n formatCommandList(): string {\n const lines = ['Available commands:', '']\n for (const [path, { metadata }] of this.commands) {\n const description = metadata.description\n if (description) {\n lines.push(` ${path.padEnd(20)} ${description}`)\n } else {\n lines.push(` ${path}`)\n }\n }\n return lines.join('\\n')\n }\n\n /**\n * Formats help text for a specific command.\n *\n * @param commandPath - The command path to show help for\n * @returns Formatted string with command help\n */\n formatCommandHelp(commandPath: string): string {\n const command = this.commands.get(commandPath)\n if (!command) {\n return `Unknown command: ${commandPath}\\n\\n${this.formatCommandList()}`\n }\n\n const { metadata } = command\n const lines: string[] = []\n\n lines.push(`Usage: ${metadata.path} [options]`)\n lines.push('')\n\n if (metadata.description) {\n lines.push(metadata.description)\n lines.push('')\n }\n\n // Extract options from schema if available\n if (metadata.optionsSchema) {\n lines.push('Options:')\n try {\n const shape = metadata.optionsSchema.def.shape\n if (shape && typeof shape === 'object') {\n for (const [key, fieldSchema] of Object.entries(shape)) {\n const kebabKey = key.replace(/([A-Z])/g, '-$1').toLowerCase()\n const optionFlag = `--${kebabKey}`\n const fieldType = this.getSchemaTypeName(fieldSchema as any)\n lines.push(` ${optionFlag.padEnd(20)} ${fieldType}`)\n }\n }\n } catch {\n // Schema introspection failed, skip options\n }\n }\n\n return lines.join('\\n')\n }\n\n /**\n * Gets a human-readable type name from a zod/v4 schema.\n */\n private getSchemaTypeName(schema: any): string {\n try {\n let currentSchema = schema\n let typeName = currentSchema?.def?.type\n let isOptional = false\n let defaultValue: any\n\n // Unwrap optional/default wrappers\n while (typeName === 'optional' || typeName === 'default') {\n if (typeName === 'optional') {\n isOptional = true\n }\n if (typeName === 'default') {\n isOptional = true\n defaultValue = currentSchema?.def?.defaultValue?.()\n }\n currentSchema = currentSchema?.def?.innerType\n typeName = currentSchema?.def?.type\n }\n\n let result = `<${typeName || 'unknown'}>`\n if (defaultValue !== undefined) {\n result += ` (default: ${JSON.stringify(defaultValue)})`\n } else if (isOptional) {\n result += ' (optional)'\n }\n\n // Get description from meta() if available\n const description = this.getSchemaMeta(schema)?.description\n if (description) {\n result += ` - ${description}`\n }\n\n return result\n } catch {\n return '<unknown>'\n }\n }\n\n /**\n * Gets metadata from a zod/v4 schema, traversing innerType if needed.\n * zod/v4 v4 stores meta at the outermost layer when .meta() is called last,\n * or in innerType when .meta() is called before .optional()/.default().\n */\n private getSchemaMeta(schema: any): Record<string, unknown> | undefined {\n try {\n // First check direct meta (when .meta() is called last in chain)\n const directMeta = schema.meta?.()\n if (directMeta) return directMeta\n\n // Check innerType for wrapped schemas (optional, default, etc.)\n const innerType = schema.def?.innerType\n if (innerType) {\n return this.getSchemaMeta(innerType)\n }\n\n return undefined\n } catch {\n return undefined\n }\n }\n\n /**\n * Clear all registered commands.\n */\n clear(): void {\n this.commands.clear()\n }\n}\n","import { InjectionToken } from '@navios/core'\n\nimport type { HelpCommand } from '../overrides/help.command.mjs'\n\nexport const HelpCommandToken = InjectionToken.create<HelpCommand>('HelpCommand')\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"help-command.token-XHx3WkoD.mjs","names":["Injectable","CommandRegistryService","commands","Map","register","path","command","has","Error","set","getByPath","get","getAll","getAllAsArray","result","class","cls","push","formatCommandList","lines","metadata","description","padEnd","join","formatCommandHelp","commandPath","optionsSchema","shape","def","key","fieldSchema","Object","entries","kebabKey","replace","toLowerCase","optionFlag","fieldType","getSchemaTypeName","schema","currentSchema","typeName","type","isOptional","defaultValue","innerType","undefined","JSON","stringify","getSchemaMeta","directMeta","meta","clear","InjectionToken","HelpCommandToken","create"],"sources":["../src/services/command-registry.service.mts","../src/tokens/help-command.token.mts"],"sourcesContent":["import { Injectable } from '@navios/core'\n\nimport type { ClassType } from '@navios/core'\n\nimport type { CommandMetadata } from '../metadata/index.mjs'\n\n/**\n * Represents a registered command with its metadata and module information.\n *\n * @public\n */\nexport interface RegisteredCommand {\n /**\n * The command class\n */\n class: ClassType\n /**\n * The command metadata from @Command decorator\n */\n metadata: CommandMetadata\n /**\n * Name of the module this command belongs to\n */\n moduleName: string\n}\n\n/**\n * Service for registering and looking up CLI commands.\n * Used internally by the CLI adapter to manage discovered commands.\n *\n * @public\n */\n@Injectable()\nexport class CommandRegistryService {\n private commands = new Map<string, RegisteredCommand>()\n\n /**\n * Register a command with its metadata.\n *\n * @param path - The command path (e.g., 'greet', 'user:create')\n * @param command - The registered command data\n * @throws Error if a command with the same path is already registered\n */\n register(path: string, command: RegisteredCommand): void {\n if (this.commands.has(path)) {\n throw new Error(`[Navios Commander] Duplicate command path: ${path}`)\n }\n this.commands.set(path, command)\n }\n\n /**\n * Get a command by its path.\n *\n * @param path - The command path\n * @returns The registered command or undefined if not found\n */\n getByPath(path: string): RegisteredCommand | undefined {\n return this.commands.get(path)\n }\n\n /**\n * Get all registered commands.\n *\n * @returns Map of path to registered command\n */\n getAll(): Map<string, RegisteredCommand> {\n return new Map(this.commands)\n }\n\n /**\n * Get all registered commands as an array of path and class pairs.\n * Useful for listing available commands.\n *\n * @returns Array of objects containing path and class\n */\n getAllAsArray(): Array<{ path: string; class: ClassType }> {\n const result: Array<{ path: string; class: ClassType }> = []\n for (const [path, { class: cls }] of this.commands) {\n result.push({ path, class: cls })\n }\n return result\n }\n\n /**\n * Formats help text listing all available commands with descriptions.\n *\n * @returns Formatted string listing all commands\n */\n formatCommandList(): string {\n const lines = ['Available commands:', '']\n for (const [path, { metadata }] of this.commands) {\n const description = metadata.description\n if (description) {\n lines.push(` ${path.padEnd(20)} ${description}`)\n } else {\n lines.push(` ${path}`)\n }\n }\n return lines.join('\\n')\n }\n\n /**\n * Formats help text for a specific command.\n *\n * @param commandPath - The command path to show help for\n * @returns Formatted string with command help\n */\n formatCommandHelp(commandPath: string): string {\n const command = this.commands.get(commandPath)\n if (!command) {\n return `Unknown command: ${commandPath}\\n\\n${this.formatCommandList()}`\n }\n\n const { metadata } = command\n const lines: string[] = []\n\n lines.push(`Usage: ${metadata.path} [options]`)\n lines.push('')\n\n if (metadata.description) {\n lines.push(metadata.description)\n lines.push('')\n }\n\n // Extract options from schema if available\n if (metadata.optionsSchema) {\n lines.push('Options:')\n try {\n const shape = metadata.optionsSchema.def.shape\n if (shape && typeof shape === 'object') {\n for (const [key, fieldSchema] of Object.entries(shape)) {\n const kebabKey = key.replace(/([A-Z])/g, '-$1').toLowerCase()\n const optionFlag = `--${kebabKey}`\n const fieldType = this.getSchemaTypeName(fieldSchema as any)\n lines.push(` ${optionFlag.padEnd(20)} ${fieldType}`)\n }\n }\n } catch {\n // Schema introspection failed, skip options\n }\n }\n\n return lines.join('\\n')\n }\n\n /**\n * Gets a human-readable type name from a zod/v4 schema.\n */\n private getSchemaTypeName(schema: any): string {\n try {\n let currentSchema = schema\n let typeName = currentSchema?.def?.type\n let isOptional = false\n let defaultValue: any\n\n // Unwrap optional/default wrappers\n while (typeName === 'optional' || typeName === 'default') {\n if (typeName === 'optional') {\n isOptional = true\n }\n if (typeName === 'default') {\n isOptional = true\n defaultValue = currentSchema?.def?.defaultValue?.()\n }\n currentSchema = currentSchema?.def?.innerType\n typeName = currentSchema?.def?.type\n }\n\n let result = `<${typeName || 'unknown'}>`\n if (defaultValue !== undefined) {\n result += ` (default: ${JSON.stringify(defaultValue)})`\n } else if (isOptional) {\n result += ' (optional)'\n }\n\n // Get description from meta() if available\n const description = this.getSchemaMeta(schema)?.description\n if (description) {\n result += ` - ${description}`\n }\n\n return result\n } catch {\n return '<unknown>'\n }\n }\n\n /**\n * Gets metadata from a zod/v4 schema, traversing innerType if needed.\n * zod/v4 v4 stores meta at the outermost layer when .meta() is called last,\n * or in innerType when .meta() is called before .optional()/.default().\n */\n private getSchemaMeta(schema: any): Record<string, unknown> | undefined {\n try {\n // First check direct meta (when .meta() is called last in chain)\n const directMeta = schema.meta?.()\n if (directMeta) return directMeta\n\n // Check innerType for wrapped schemas (optional, default, etc.)\n const innerType = schema.def?.innerType\n if (innerType) {\n return this.getSchemaMeta(innerType)\n }\n\n return undefined\n } catch {\n return undefined\n }\n }\n\n /**\n * Clear all registered commands.\n */\n clear(): void {\n this.commands.clear()\n }\n}\n","import { InjectionToken } from '@navios/core'\n\nimport type { HelpCommand } from '../overrides/help.command.mjs'\n\nexport const HelpCommandToken = InjectionToken.create<HelpCommand>('HelpCommand')\n"],"mappings":"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"}