@navios/commander 1.0.0 → 1.2.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 (76) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +22 -0
  3. package/dist/src/commander.factory.d.mts +59 -0
  4. package/dist/src/commander.factory.d.mts.map +1 -1
  5. package/dist/src/commands/help.command.d.mts.map +1 -1
  6. package/dist/src/decorators/command.decorator.d.mts +9 -2
  7. package/dist/src/decorators/command.decorator.d.mts.map +1 -1
  8. package/dist/src/legacy-compat/decorators/cli-module.decorator.d.mts +26 -0
  9. package/dist/src/legacy-compat/decorators/cli-module.decorator.d.mts.map +1 -0
  10. package/dist/src/legacy-compat/decorators/command.decorator.d.mts +34 -0
  11. package/dist/src/legacy-compat/decorators/command.decorator.d.mts.map +1 -0
  12. package/dist/src/legacy-compat/decorators/index.d.mts +3 -0
  13. package/dist/src/legacy-compat/decorators/index.d.mts.map +1 -0
  14. package/dist/src/legacy-compat/index.d.mts +28 -0
  15. package/dist/src/legacy-compat/index.d.mts.map +1 -0
  16. package/dist/src/overrides/help.command.d.mts +18 -0
  17. package/dist/src/overrides/help.command.d.mts.map +1 -0
  18. package/dist/src/tokens/help-command.token.d.mts +4 -0
  19. package/dist/src/tokens/help-command.token.d.mts.map +1 -0
  20. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  21. package/dist/tsconfig.tsbuildinfo +1 -1
  22. package/lib/cli-module.decorator-CkP22084.cjs +71 -0
  23. package/lib/cli-module.decorator-CkP22084.cjs.map +1 -0
  24. package/lib/cli-module.decorator-DGuGfpex.d.mts +411 -0
  25. package/lib/cli-module.decorator-DGuGfpex.d.mts.map +1 -0
  26. package/lib/cli-module.decorator-DVl8009Q.d.cts +213 -0
  27. package/lib/cli-module.decorator-DVl8009Q.d.cts.map +1 -0
  28. package/lib/cli-module.decorator-UGbtkRYc.mjs +66 -0
  29. package/lib/cli-module.decorator-UGbtkRYc.mjs.map +1 -0
  30. package/lib/command.decorator-DVLSAqYZ.mjs +135 -0
  31. package/lib/command.decorator-DVLSAqYZ.mjs.map +1 -0
  32. package/lib/command.decorator-UrNJmQN0.cjs +176 -0
  33. package/lib/command.decorator-UrNJmQN0.cjs.map +1 -0
  34. package/lib/help-command.token-C0Kgj60o.mjs +427 -0
  35. package/lib/help-command.token-C0Kgj60o.mjs.map +1 -0
  36. package/lib/help-command.token-CMWYI6em.cjs +438 -0
  37. package/lib/help-command.token-CMWYI6em.cjs.map +1 -0
  38. package/lib/help.command-DQyv6ali.cjs +317 -0
  39. package/lib/help.command-DQyv6ali.cjs.map +1 -0
  40. package/lib/help.command-dtZbhq0w.mjs +318 -0
  41. package/lib/help.command-dtZbhq0w.mjs.map +1 -0
  42. package/lib/index.cjs +45 -627
  43. package/lib/index.cjs.map +1 -1
  44. package/lib/index.d.cts +139 -281
  45. package/lib/index.d.cts.map +1 -1
  46. package/lib/index.d.mts +62 -402
  47. package/lib/index.d.mts.map +1 -1
  48. package/lib/index.mjs +30 -612
  49. package/lib/index.mjs.map +1 -1
  50. package/lib/legacy-compat/index.cjs +108 -0
  51. package/lib/legacy-compat/index.cjs.map +1 -0
  52. package/lib/legacy-compat/index.d.cts +63 -0
  53. package/lib/legacy-compat/index.d.cts.map +1 -0
  54. package/lib/legacy-compat/index.d.mts +63 -0
  55. package/lib/legacy-compat/index.d.mts.map +1 -0
  56. package/lib/legacy-compat/index.mjs +101 -0
  57. package/lib/legacy-compat/index.mjs.map +1 -0
  58. package/package.json +20 -3
  59. package/src/commander.factory.mts +107 -8
  60. package/src/commands/help.command.mts +4 -3
  61. package/src/decorators/command.decorator.mts +17 -8
  62. package/src/legacy-compat/decorators/cli-module.decorator.mts +46 -0
  63. package/src/legacy-compat/decorators/command.decorator.mts +46 -0
  64. package/src/legacy-compat/decorators/index.mts +2 -0
  65. package/src/legacy-compat/index.mts +31 -0
  66. package/src/overrides/help.command.mts +40 -0
  67. package/src/tokens/help-command.token.mts +5 -0
  68. package/tsconfig.json +0 -3
  69. package/tsconfig.spec.json +1 -1
  70. package/tsdown.config.mts +1 -1
  71. package/dist/src/commander.application.d.mts +0 -147
  72. package/dist/src/commander.application.d.mts.map +0 -1
  73. package/dist/src/metadata/cli-module.metadata.d.mts +0 -60
  74. package/dist/src/metadata/cli-module.metadata.d.mts.map +0 -1
  75. package/dist/src/services/module-loader.service.d.mts +0 -74
  76. package/dist/src/services/module-loader.service.d.mts.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["createClassContext","Command","OriginalCommand","options","target","context","originalDecorator","createClassContext","CliModule","OriginalCliModule","options","commands","controllers","imports","guards","overrides","target","context","originalDecorator"],"sources":["../../../../node_modules/@navios/di/lib/legacy-compat/index.mjs","../../src/legacy-compat/decorators/command.decorator.mts","../../src/legacy-compat/decorators/cli-module.decorator.mts"],"sourcesContent":["import { t as Injectable$1 } from \"../injectable.decorator-CyPrBzBN.mjs\";\nimport { t as Factory$1 } from \"../factory.decorator-_IPWcwQn.mjs\";\n\n//#region src/legacy-compat/context-compat.mts\n/**\n* Compatibility layer for converting legacy decorator signatures to Stage 3 format.\n*\n* This module provides utilities to create mock Stage 3 decorator contexts\n* from legacy decorator arguments, and manages metadata storage using WeakMap.\n*/ const classMetadataMap = /* @__PURE__ */ new WeakMap();\n/**\n* Gets the constructor from a prototype (for method decorators).\n*/ function getConstructor(prototype) {\n\tif (!prototype || typeof prototype !== \"object\") return null;\n\tconst constructor = prototype.constructor;\n\tif (constructor && typeof constructor === \"function\") return constructor;\n\treturn null;\n}\n/**\n* Creates a mock ClassDecoratorContext for legacy class decorators.\n* @internal\n*/ function createClassContext(target) {\n\tif (!classMetadataMap.has(target)) classMetadataMap.set(target, {});\n\tconst metadata = classMetadataMap.get(target);\n\treturn {\n\t\tkind: \"class\",\n\t\tname: target.name,\n\t\tmetadata,\n\t\taddInitializer() {}\n\t};\n}\n/**\n* Creates a mock ClassMethodDecoratorContext for legacy method decorators.\n*\n* Note: Method decorators need to share metadata with the class context\n* because endpoint metadata is stored at the class level.\n* @internal\n*/ function createMethodContext(target, propertyKey, descriptor) {\n\tconst constructor = getConstructor(target);\n\tif (!constructor) throw new Error(\"[Navios] Could not determine class constructor from method decorator target.\");\n\tif (!classMetadataMap.has(constructor)) classMetadataMap.set(constructor, {});\n\treturn {\n\t\tkind: \"method\",\n\t\tname: propertyKey,\n\t\tmetadata: classMetadataMap.get(constructor),\n\t\tstatic: false,\n\t\tprivate: false,\n\t\taccess: {\n\t\t\thas: () => true,\n\t\t\tget: () => descriptor.value,\n\t\t\tset: () => {}\n\t\t},\n\t\taddInitializer() {}\n\t};\n}\n\n//#endregion\n//#region src/legacy-compat/injectable.decorator.mts\n/**\n* Legacy-compatible Injectable decorator.\n*\n* Works with TypeScript experimental decorators (legacy API).\n*\n* @param options - Injectable configuration options\n* @returns A class decorator compatible with legacy decorator API\n*\n* @example\n* ```typescript\n* @Injectable()\n* export class UserService {\n* getUser(id: string) {\n* return { id, name: 'John' }\n* }\n* }\n* ```\n*/ function Injectable(options = {}) {\n\treturn function(target) {\n\t\tconst context = createClassContext(target);\n\t\treturn (Object.keys(options).length === 0 ? Injectable$1() : Injectable$1(options))(target, context);\n\t};\n}\n\n//#endregion\n//#region src/legacy-compat/factory.decorator.mts\n/**\n* Legacy-compatible Factory decorator.\n*\n* Works with TypeScript experimental decorators (legacy API).\n*\n* @param options - Factory configuration options\n* @returns A class decorator compatible with legacy decorator API\n*\n* @example\n* ```typescript\n* @Factory()\n* export class DatabaseConnectionFactory {\n* create() {\n* return { host: 'localhost', port: 5432 }\n* }\n* }\n* ```\n*/ function Factory(options = {}) {\n\treturn function(target) {\n\t\tconst context = createClassContext(target);\n\t\treturn (Object.keys(options).length === 0 ? Factory$1() : Factory$1(options))(target, context);\n\t};\n}\n\n//#endregion\nexport { Factory, Injectable, createClassContext, createMethodContext };\n//# sourceMappingURL=index.mjs.map","import type { ClassType } from '@navios/core'\nimport { createClassContext } from '@navios/di/legacy-compat'\n\nimport {\n Command as OriginalCommand,\n type CommandOptions,\n} from '../../decorators/command.decorator.mjs'\n\nexport type { CommandOptions }\n\n/**\n * Legacy-compatible Command decorator.\n *\n * Works with TypeScript experimental decorators (legacy API).\n *\n * @param options - Command configuration options\n * @returns A class decorator compatible with legacy decorator API\n *\n * @example\n * ```typescript\n * import { Command, CommandHandler } from '@navios/commander/legacy-compat'\n * import { z } from 'zod'\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 function Command(options: CommandOptions) {\n return function (target: ClassType) {\n const context = createClassContext(target)\n const originalDecorator = OriginalCommand(options)\n return originalDecorator(target, context)\n }\n}\n","import type { ClassType } from '@navios/core'\nimport { createClassContext } from '@navios/di/legacy-compat'\n\nimport {\n CliModule as OriginalCliModule,\n type CliModuleOptions,\n} from '../../decorators/cli-module.decorator.mjs'\n\nexport type { CliModuleOptions }\n\n/**\n * Legacy-compatible CliModule decorator.\n *\n * Works with TypeScript experimental decorators (legacy API).\n *\n * @param options - CLI module configuration options\n * @returns A class decorator compatible with legacy decorator API\n *\n * @example\n * ```typescript\n * import { CliModule } from '@navios/commander/legacy-compat'\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 */\nexport function CliModule(\n options: CliModuleOptions = {\n commands: [],\n controllers: [],\n imports: [],\n guards: [],\n overrides: [],\n },\n) {\n return function (target: ClassType) {\n const context = createClassContext(target)\n const originalDecorator = OriginalCliModule(options)\n return originalDecorator(target, context)\n }\n}\n"],"x_google_ignoreList":[0],"mappings":";;;;;;;;;;;GASG,MAAM,mCAAmC,IAAI,SAAS;;;;GAYtD,SAAS,mBAAmB,QAAQ;AACtC,KAAI,CAAC,iBAAiB,IAAI,OAAO,CAAE,kBAAiB,IAAI,QAAQ,EAAE,CAAC;CACnE,MAAM,WAAW,iBAAiB,IAAI,OAAO;AAC7C,QAAO;EACN,MAAM;EACN,MAAM,OAAO;EACb;EACA,iBAAiB;EACjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GCUF,SAAgBC,QAAQE,SAAuB;AAC7C,QAAO,SAAUC,QAAiB;EAChC,MAAMC,UAAUL,mBAAmBI,OAAAA;AAEnC,SAD0BF,UAAgBC,QAAAA,CACjBC,QAAQC,QAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GCZrC,SAAgBG,UACdE,UAA4B;CAC1BC,UAAU,EAAE;CACZC,aAAa,EAAE;CACfC,SAAS,EAAE;CACXC,QAAQ,EAAE;CACVC,WAAW,EAAE;CACd,EAAA;AAED,QAAO,SAAUC,QAAiB;EAChC,MAAMC,UAAUV,mBAAmBS,OAAAA;AAEnC,SAD0BP,YAAkBC,QAAAA,CACnBM,QAAQC,QAAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@navios/commander",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "author": {
5
5
  "name": "Oleksandr Hanzha",
6
6
  "email": "alex@granted.name"
@@ -8,12 +8,18 @@
8
8
  "repository": {
9
9
  "directory": "packages/commander",
10
10
  "type": "git",
11
- "url": "https://github.com/Arilas/navios.git"
11
+ "url": "https://github.com/navios-org/commander.git"
12
12
  },
13
13
  "license": "MIT",
14
14
  "peerDependencies": {
15
+ "@navios/commander-tui": "^1.0.0",
15
16
  "zod": "^4.0.0"
16
17
  },
18
+ "peerDependenciesMeta": {
19
+ "@navios/commander-tui": {
20
+ "optional": true
21
+ }
22
+ },
17
23
  "typings": "./lib/index.d.mts",
18
24
  "main": "./lib/index.cjs",
19
25
  "module": "./lib/index.mjs",
@@ -27,12 +33,23 @@
27
33
  "types": "./lib/index.d.cts",
28
34
  "default": "./lib/index.cjs"
29
35
  }
36
+ },
37
+ "./legacy-compat": {
38
+ "import": {
39
+ "types": "./lib/legacy-compat/index.d.mts",
40
+ "default": "./lib/legacy-compat/index.mjs"
41
+ },
42
+ "require": {
43
+ "types": "./lib/legacy-compat/index.d.cts",
44
+ "default": "./lib/legacy-compat/index.cjs"
45
+ }
30
46
  }
31
47
  },
32
48
  "devDependencies": {
49
+ "@navios/builder": "^1.0.0",
33
50
  "tsx": "^4.21.0",
34
51
  "typescript": "^5.9.3",
35
- "zod": "^4.2.1"
52
+ "zod": "^4.3.5"
36
53
  },
37
54
  "dependencies": {
38
55
  "@navios/core": "^1.0.0"
@@ -1,16 +1,11 @@
1
- import type {
2
- ClassTypeWithInstance,
3
- LogLevel,
4
- NaviosApplication,
5
- NaviosModule,
6
- } from '@navios/core'
7
-
8
1
  import { ConsoleLogger, NaviosFactory } from '@navios/core'
9
2
 
10
- import type { CliEnvironment } from './interfaces/environment.interface.mjs'
3
+ import type { ClassTypeWithInstance, LogLevel, NaviosApplication, NaviosModule } from '@navios/core'
11
4
 
12
5
  import { defineCliEnvironment } from './define-environment.mjs'
13
6
 
7
+ import type { CliEnvironment } from './interfaces/environment.interface.mjs'
8
+
14
9
  /**
15
10
  * Logger display options for CLI applications.
16
11
  * All options default to false for cleaner CLI output.
@@ -55,16 +50,76 @@ export interface CommanderLoggerOptions {
55
50
  showTimeDiff?: boolean
56
51
  }
57
52
 
53
+ /**
54
+ * TUI-specific options for terminal UI mode.
55
+ * Only used when enableTUI is true.
56
+ *
57
+ * @public
58
+ */
59
+ export interface CommanderTuiOptions {
60
+ /**
61
+ * Exit on Ctrl+C.
62
+ * @default true
63
+ */
64
+ exitOnCtrlC?: boolean
65
+ /**
66
+ * Sidebar width in columns.
67
+ */
68
+ sidebarWidth?: number
69
+ /**
70
+ * Sidebar position.
71
+ */
72
+ sidebarPosition?: 'left' | 'right'
73
+ /**
74
+ * Sidebar header title.
75
+ */
76
+ sidebarTitle?: string
77
+ /**
78
+ * Auto close after all screens complete successfully.
79
+ * Set to true for default delay (5000ms), or specify delay in milliseconds.
80
+ */
81
+ autoClose?: boolean | number
82
+ /**
83
+ * Theme preset name ('dark', 'light', 'high-contrast') or custom theme object.
84
+ */
85
+ theme?: string | Record<string, unknown>
86
+ /**
87
+ * Enable mouse support.
88
+ * @default false
89
+ */
90
+ useMouse?: boolean
91
+ /**
92
+ * Hide the default console logger screen from the sidebar.
93
+ * @default false
94
+ */
95
+ hideDefaultScreen?: boolean
96
+ }
97
+
58
98
  /**
59
99
  * Configuration options for CommanderFactory.
60
100
  *
61
101
  * @public
62
102
  */
63
103
  export interface CommanderFactoryOptions {
104
+ /**
105
+ * Enabled log levels.
106
+ * @default ['log', 'error', 'warn', 'debug', 'verbose', 'fatal']
107
+ */
108
+ logLevels?: LogLevel[]
64
109
  /**
65
110
  * Logger display options. These override the default CLI-friendly logger settings.
111
+ * Ignored when enableTUI is true.
66
112
  */
67
113
  logger?: CommanderLoggerOptions
114
+ /**
115
+ * Enable TUI mode with @navios/commander-tui.
116
+ * Requires @navios/commander-tui to be installed.
117
+ */
118
+ enableTUI?: boolean
119
+ /**
120
+ * TUI-specific options. Only used when enableTUI is true.
121
+ */
122
+ tuiOptions?: CommanderTuiOptions
68
123
  }
69
124
 
70
125
  /**
@@ -122,6 +177,50 @@ export class CommanderFactory {
122
177
  appModule: ClassTypeWithInstance<TModule>,
123
178
  options: CommanderFactoryOptions = {},
124
179
  ): Promise<NaviosApplication<CliEnvironment>> {
180
+ if (options.enableTUI) {
181
+ // Dynamic import to keep commander-tui as optional peer dependency
182
+ let tuiModule: typeof import('@navios/commander-tui')
183
+ try {
184
+ tuiModule = await import('@navios/commander-tui')
185
+ } catch {
186
+ throw new Error(
187
+ 'TUI mode requires @navios/commander-tui package. ' +
188
+ 'Install it with: npm install @navios/commander-tui',
189
+ )
190
+ }
191
+
192
+ const { overrideConsoleLogger, ScreenManager } = tuiModule
193
+
194
+ // Override the ConsoleLogger service to use the ScreenLogger service instead of the default ConsoleLogger service.
195
+ overrideConsoleLogger(options.tuiOptions?.hideDefaultScreen ?? false)
196
+
197
+ if (options.tuiOptions?.hideDefaultScreen) {
198
+ // Import the help command override to ensure it is registered
199
+ await import('./overrides/help.command.mjs')
200
+ }
201
+ // Create app without custom logger - TUI override handles it
202
+ const app = await NaviosFactory.create<CliEnvironment>(appModule, {
203
+ adapter: defineCliEnvironment(),
204
+ logger: options.logLevels,
205
+ })
206
+
207
+ // Get screen manager and bind TUI before returning
208
+ const screenManager = await app.get(ScreenManager)
209
+ await screenManager.bind({
210
+ exitOnCtrlC: options.tuiOptions?.exitOnCtrlC,
211
+ sidebarWidth: options.tuiOptions?.sidebarWidth,
212
+ sidebarPosition: options.tuiOptions?.sidebarPosition,
213
+ sidebarTitle: options.tuiOptions?.sidebarTitle,
214
+ autoClose: options.tuiOptions?.autoClose,
215
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
216
+ theme: options.tuiOptions?.theme as any,
217
+ useMouse: options.tuiOptions?.useMouse,
218
+ })
219
+
220
+ return app
221
+ }
222
+
223
+ // Standard (non-TUI) mode - existing behavior unchanged
125
224
  const app = await NaviosFactory.create<CliEnvironment>(appModule, {
126
225
  adapter: defineCliEnvironment(),
127
226
  logger: ConsoleLogger.create({
@@ -1,11 +1,11 @@
1
1
  import { inject, Logger } from '@navios/core'
2
-
3
2
  import { z } from 'zod'
4
3
 
5
- import type { CommandHandler } from '../interfaces/command-handler.interface.mjs'
6
-
7
4
  import { Command } from '../decorators/command.decorator.mjs'
8
5
  import { CommandRegistryService } from '../services/command-registry.service.mjs'
6
+ import { HelpCommandToken } from '../tokens/help-command.token.mjs'
7
+
8
+ import type { CommandHandler } from '../interfaces/command-handler.interface.mjs'
9
9
 
10
10
  const helpOptionsSchema = z.object({
11
11
  command: z.string().optional(),
@@ -19,6 +19,7 @@ type HelpOptions = z.infer<typeof helpOptionsSchema>
19
19
  * @public
20
20
  */
21
21
  @Command({
22
+ token: HelpCommandToken,
22
23
  path: 'help',
23
24
  description: 'Show available commands or help for a specific command',
24
25
  optionsSchema: helpOptionsSchema,
@@ -1,16 +1,23 @@
1
- import type { ClassType, Registry } from '@navios/core'
2
- import type { ZodObject } from 'zod'
3
-
4
1
  import { Injectable, InjectableScope, InjectionToken } from '@navios/core'
5
2
 
3
+ import type { ClassType, ClassTypeWithInstance, Registry } from '@navios/core'
4
+ import type { ZodObject } from 'zod'
5
+
6
6
  import { getCommandMetadata } from '../metadata/index.mjs'
7
7
 
8
+ import type { CommandHandler } from '../interfaces/index.mjs'
9
+
8
10
  /**
9
11
  * Options for the `@Command` decorator.
10
12
  *
11
13
  * @public
12
14
  */
13
15
  export interface CommandOptions {
16
+ /**
17
+ * The token to use for the command.
18
+ * If provided, the command will be registered with this token.
19
+ */
20
+ token?: InjectionToken<ClassTypeWithInstance<CommandHandler<any>>>
14
21
  /**
15
22
  * The command path that users will invoke from the CLI.
16
23
  * Can be a single word (e.g., 'greet') or multi-word with colons (e.g., 'user:create', 'db:migrate').
@@ -71,22 +78,24 @@ export interface CommandOptions {
71
78
  export function Command({
72
79
  path,
73
80
  description,
81
+ token,
74
82
  optionsSchema,
75
83
  priority,
76
84
  registry,
77
85
  }: CommandOptions) {
78
86
  return function (target: ClassType, context: ClassDecoratorContext) {
79
87
  if (context.kind !== 'class') {
80
- throw new Error(
81
- '[Navios Commander] @Command decorator can only be used on classes.',
82
- )
88
+ throw new Error('[Navios Commander] @Command decorator can only be used on classes.')
83
89
  }
84
- const token = InjectionToken.create(target)
90
+ const tokenToUse =
91
+ token ?? InjectionToken.create<ClassTypeWithInstance<CommandHandler<any>>>(target)
92
+
85
93
  if (context.metadata) {
86
94
  getCommandMetadata(target, context, path, description, optionsSchema)
87
95
  }
96
+ // @ts-expect-error Injectable is callable
88
97
  return Injectable({
89
- token,
98
+ token: tokenToUse,
90
99
  scope: InjectableScope.Singleton,
91
100
  priority,
92
101
  registry,
@@ -0,0 +1,46 @@
1
+ import type { ClassType } from '@navios/core'
2
+ import { createClassContext } from '@navios/di/legacy-compat'
3
+
4
+ import {
5
+ CliModule as OriginalCliModule,
6
+ type CliModuleOptions,
7
+ } from '../../decorators/cli-module.decorator.mjs'
8
+
9
+ export type { CliModuleOptions }
10
+
11
+ /**
12
+ * Legacy-compatible CliModule decorator.
13
+ *
14
+ * Works with TypeScript experimental decorators (legacy API).
15
+ *
16
+ * @param options - CLI module configuration options
17
+ * @returns A class decorator compatible with legacy decorator API
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * import { CliModule } from '@navios/commander/legacy-compat'
22
+ * import { GreetCommand } from './greet.command'
23
+ * import { UserModule } from './user.module'
24
+ *
25
+ * @CliModule({
26
+ * commands: [GreetCommand],
27
+ * imports: [UserModule]
28
+ * })
29
+ * export class AppModule {}
30
+ * ```
31
+ */
32
+ export function CliModule(
33
+ options: CliModuleOptions = {
34
+ commands: [],
35
+ controllers: [],
36
+ imports: [],
37
+ guards: [],
38
+ overrides: [],
39
+ },
40
+ ) {
41
+ return function (target: ClassType) {
42
+ const context = createClassContext(target)
43
+ const originalDecorator = OriginalCliModule(options)
44
+ return originalDecorator(target, context)
45
+ }
46
+ }
@@ -0,0 +1,46 @@
1
+ import type { ClassType } from '@navios/core'
2
+ import { createClassContext } from '@navios/di/legacy-compat'
3
+
4
+ import {
5
+ Command as OriginalCommand,
6
+ type CommandOptions,
7
+ } from '../../decorators/command.decorator.mjs'
8
+
9
+ export type { CommandOptions }
10
+
11
+ /**
12
+ * Legacy-compatible Command decorator.
13
+ *
14
+ * Works with TypeScript experimental decorators (legacy API).
15
+ *
16
+ * @param options - Command configuration options
17
+ * @returns A class decorator compatible with legacy decorator API
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * import { Command, CommandHandler } from '@navios/commander/legacy-compat'
22
+ * import { z } from 'zod'
23
+ *
24
+ * const optionsSchema = z.object({
25
+ * name: z.string(),
26
+ * greeting: z.string().optional().default('Hello')
27
+ * })
28
+ *
29
+ * @Command({
30
+ * path: 'greet',
31
+ * optionsSchema: optionsSchema
32
+ * })
33
+ * export class GreetCommand implements CommandHandler<z.infer<typeof optionsSchema>> {
34
+ * async execute(options) {
35
+ * console.log(`${options.greeting}, ${options.name}!`)
36
+ * }
37
+ * }
38
+ * ```
39
+ */
40
+ export function Command(options: CommandOptions) {
41
+ return function (target: ClassType) {
42
+ const context = createClassContext(target)
43
+ const originalDecorator = OriginalCommand(options)
44
+ return originalDecorator(target, context)
45
+ }
46
+ }
@@ -0,0 +1,2 @@
1
+ export * from './command.decorator.mjs'
2
+ export * from './cli-module.decorator.mjs'
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Legacy-compatible decorators for projects using TypeScript experimental decorators.
3
+ *
4
+ * These decorators wrap the Stage 3 decorator implementations and convert
5
+ * the legacy decorator arguments to Stage 3 format internally.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { Command, CliModule, CommandHandler } from '@navios/commander/legacy-compat'
10
+ *
11
+ * @Command({ path: 'greet' })
12
+ * export class GreetCommand implements CommandHandler {
13
+ * async execute() {
14
+ * console.log('Hello!')
15
+ * }
16
+ * }
17
+ *
18
+ * @CliModule({
19
+ * commands: [GreetCommand],
20
+ * })
21
+ * export class AppModule {}
22
+ * ```
23
+ *
24
+ * @packageDocumentation
25
+ */
26
+
27
+ // Export legacy-compatible decorators (commander-specific)
28
+ export * from './decorators/index.mjs'
29
+
30
+ // Re-export core/DI legacy-compat utilities for convenience
31
+ export * from '@navios/core/legacy-compat'
@@ -0,0 +1,40 @@
1
+ import { ScreenLogger } from '@navios/commander-tui'
2
+ import { inject } from '@navios/core'
3
+ import { z } from 'zod'
4
+
5
+ import { Command } from '../decorators/command.decorator.mjs'
6
+ import { CommandRegistryService } from '../services/command-registry.service.mjs'
7
+ import { HelpCommandToken } from '../tokens/help-command.token.mjs'
8
+
9
+ import type { CommandHandler } from '../interfaces/command-handler.interface.mjs'
10
+
11
+ const helpOptionsSchema = z.object({
12
+ command: z.string().optional(),
13
+ })
14
+
15
+ type HelpOptions = z.infer<typeof helpOptionsSchema>
16
+
17
+ /**
18
+ * Built-in help command that lists all available commands or shows help for a specific command.
19
+ *
20
+ * @public
21
+ */
22
+ @Command({
23
+ token: HelpCommandToken,
24
+ path: 'help',
25
+ description: 'Show available commands or help for a specific command',
26
+ optionsSchema: helpOptionsSchema,
27
+ priority: 1000,
28
+ })
29
+ export class HelpCommand implements CommandHandler<HelpOptions> {
30
+ private logger = inject(ScreenLogger, { screen: { name: 'Help', static: true }, context: 'Help' })
31
+ private commandRegistry = inject(CommandRegistryService)
32
+
33
+ async execute(options: HelpOptions): Promise<void> {
34
+ if (options.command) {
35
+ this.logger.log(this.commandRegistry.formatCommandHelp(options.command))
36
+ } else {
37
+ this.logger.log(this.commandRegistry.formatCommandList())
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,5 @@
1
+ import { InjectionToken } from '@navios/core'
2
+
3
+ import type { HelpCommand } from '../overrides/help.command.mjs'
4
+
5
+ export const HelpCommandToken = InjectionToken.create<HelpCommand>('HelpCommand')
package/tsconfig.json CHANGED
@@ -10,9 +10,6 @@
10
10
  },
11
11
  {
12
12
  "path": "./tsconfig.spec.json"
13
- },
14
- {
15
- "path": "../core"
16
13
  }
17
14
  ]
18
15
  }
@@ -2,7 +2,7 @@
2
2
  "extends": "./tsconfig.json",
3
3
  "compilerOptions": {
4
4
  "outDir": "../../dist/out-tsc",
5
- "types": ["bun-types"]
5
+ "types": []
6
6
  },
7
7
  "include": ["src/**/*.spec.mts"],
8
8
  "references": [
package/tsdown.config.mts CHANGED
@@ -3,7 +3,7 @@ import { defineConfig } from 'tsdown'
3
3
  import swc from 'unplugin-swc'
4
4
 
5
5
  export default defineConfig({
6
- entry: ['src/index.mts'],
6
+ entry: ['src/index.mts', 'src/legacy-compat/index.mts'],
7
7
  outDir: 'lib',
8
8
  format: ['esm', 'cjs'],
9
9
  clean: true,
@@ -1,147 +0,0 @@
1
- import type { ClassTypeWithInstance, NaviosModule } from '@navios/core';
2
- import { Container } from '@navios/core';
3
- /**
4
- * Configuration options for CommanderApplication.
5
- *
6
- * @public
7
- */
8
- export interface CommanderApplicationOptions {
9
- }
10
- /**
11
- * Main application class for managing CLI command execution.
12
- *
13
- * This class handles module loading, command registration, and command execution.
14
- * It provides both programmatic and CLI-based command execution capabilities.
15
- *
16
- * @example
17
- * ```typescript
18
- * const app = await CommanderFactory.create(AppModule)
19
- * await app.init()
20
- * await app.run(process.argv)
21
- * ```
22
- */
23
- export declare class CommanderApplication {
24
- private moduleLoader;
25
- private cliParser;
26
- protected container: Container;
27
- private appModule;
28
- private options;
29
- /**
30
- * Indicates whether the application has been initialized.
31
- * Set to `true` after `init()` is called successfully.
32
- */
33
- isInitialized: boolean;
34
- /**
35
- * @internal
36
- * Sets up the application with the provided module and options.
37
- * This is called automatically by CommanderFactory.create().
38
- */
39
- setup(appModule: ClassTypeWithInstance<NaviosModule>, options?: CommanderApplicationOptions): Promise<void>;
40
- /**
41
- * Gets the dependency injection container used by this application.
42
- *
43
- * @returns The Container instance
44
- *
45
- * @example
46
- * ```typescript
47
- * const container = app.getContainer()
48
- * const service = await container.get(MyService)
49
- * ```
50
- */
51
- getContainer(): Container;
52
- /**
53
- * Initializes the application by loading all modules and registering commands.
54
- *
55
- * This method must be called before executing commands or running the CLI.
56
- * It traverses the module tree, loads all imported modules, and collects command metadata.
57
- *
58
- * @throws {Error} If the app module is not set (setup() was not called)
59
- *
60
- * @example
61
- * ```typescript
62
- * const app = await CommanderFactory.create(AppModule)
63
- * await app.init() // Must be called before run() or executeCommand()
64
- * ```
65
- */
66
- init(): Promise<void>;
67
- /**
68
- * Executes a command programmatically with the provided options.
69
- *
70
- * This method is useful for testing, automation, or programmatic workflows.
71
- * The options will be validated against the command's Zod schema if one is provided.
72
- *
73
- * @param commandPath - The command path (e.g., 'greet', 'user:create')
74
- * @param options - The command options object (will be validated if schema exists)
75
- * @throws {Error} If the application is not initialized
76
- * @throws {Error} If the command is not found
77
- * @throws {Error} If the command does not implement the execute method
78
- * @throws {ZodError} If options validation fails
79
- *
80
- * @example
81
- * ```typescript
82
- * await app.executeCommand('greet', {
83
- * name: 'World',
84
- * greeting: 'Hi'
85
- * })
86
- * ```
87
- */
88
- executeCommand(commandPath: string, options?: any): Promise<void>;
89
- /**
90
- * Gets all registered commands with their paths and class references.
91
- *
92
- * @returns An array of objects containing the command path and class
93
- *
94
- * @example
95
- * ```typescript
96
- * const commands = app.getAllCommands()
97
- * commands.forEach(({ path }) => {
98
- * console.log(`Available: ${path}`)
99
- * })
100
- * ```
101
- */
102
- getAllCommands(): {
103
- path: string;
104
- class: ClassTypeWithInstance<any>;
105
- }[];
106
- /**
107
- * Runs the CLI application by parsing command-line arguments and executing the appropriate command.
108
- *
109
- * This is the main entry point for CLI usage. It parses `argv`, validates options,
110
- * and executes the matching command. Supports help command (`help`, `--help`, `-h`)
111
- * which displays all available commands.
112
- *
113
- * @param argv - Command-line arguments array (defaults to `process.argv`)
114
- * @throws {Error} If the application is not initialized
115
- * @throws {Error} If no command is provided
116
- * @throws {Error} If the command is not found
117
- * @throws {ZodError} If options validation fails
118
- *
119
- * @example
120
- * ```typescript
121
- * // Parse and execute from process.argv
122
- * await app.run()
123
- *
124
- * // Or provide custom arguments
125
- * await app.run(['node', 'cli.js', 'greet', '--name', 'World'])
126
- * ```
127
- */
128
- run(argv?: string[]): Promise<void>;
129
- /**
130
- * @internal
131
- * Disposes of resources used by the application.
132
- */
133
- dispose(): Promise<void>;
134
- /**
135
- * Closes the application and cleans up resources.
136
- *
137
- * This should be called when the application is no longer needed to free up resources.
138
- *
139
- * @example
140
- * ```typescript
141
- * await app.run(process.argv)
142
- * await app.close()
143
- * ```
144
- */
145
- close(): Promise<void>;
146
- }
147
- //# sourceMappingURL=commander.application.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"commander.application.d.mts","sourceRoot":"","sources":["../../src/commander.application.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EAErB,YAAY,EACb,MAAM,cAAc,CAAA;AAErB,OAAO,EAAE,SAAS,EAAsB,MAAM,cAAc,CAAA;AAQ5D;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;CAAG;AAE/C;;;;;;;;;;;;GAYG;AACH,qBACa,oBAAoB;IAC/B,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,SAAS,CAA2B;IAC5C,SAAS,CAAC,SAAS,YAAoB;IAEvC,OAAO,CAAC,SAAS,CAAmD;IACpE,OAAO,CAAC,OAAO,CAAkC;IAEjD;;;OAGG;IACH,aAAa,UAAQ;IAErB;;;;OAIG;IACG,KAAK,CACT,SAAS,EAAE,qBAAqB,CAAC,YAAY,CAAC,EAC9C,OAAO,GAAE,2BAAgC;IAM3C;;;;;;;;;;OAUG;IACH,YAAY;IAIZ;;;;;;;;;;;;;OAaG;IACG,IAAI;IAUV;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,GAAQ;IAuD3D;;;;;;;;;;;;OAYG;IACH,cAAc;cAIJ,MAAM;eACL,qBAAqB,CAAC,GAAG,CAAC;;IAarC;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,GAAG,CAAC,IAAI,GAAE,MAAM,EAAiB;IAgDvC;;;OAGG;IACG,OAAO;IAMb;;;;;;;;;;OAUG;IACG,KAAK;CAGZ"}