1010import * as getopts from 'getopts'
1111
1212import { Parser } from '../Parser'
13+ import { Manifest } from '../Manifest'
1314import { validateCommand } from '../utils/validateCommand'
1415import { printHelp , printHelpFor } from '../utils/help'
15- import { CommandConstructorContract , CommandFlag , GlobalFlagHandler } from '../Contracts'
16+ import {
17+ CommandConstructorContract ,
18+ CommandFlag ,
19+ GlobalFlagHandler ,
20+ ManifestCommand ,
21+ ManifestNode ,
22+ } from '../Contracts'
1623
1724/**
1825 * Ace kernel class is used to register, find and invoke commands by
@@ -24,11 +31,24 @@ export class Kernel {
2431 */
2532 public commands : { [ name : string ] : CommandConstructorContract } = { }
2633
34+ /**
35+ * Reference to commands defined inside the manifest file. This only exists
36+ * when you call [[Kernel.useManifest]].
37+ */
38+ public manifestCommands ?: ManifestNode
39+
2740 /**
2841 * List of registered flags
2942 */
3043 public flags : { [ name : string ] : CommandFlag & { handler : GlobalFlagHandler } } = { }
3144
45+ /**
46+ * Reference to the manifest instance. When this exists, the kernel
47+ * will give prefrence to the manifest file over the registered
48+ * commands
49+ */
50+ private _manifest ?: Manifest
51+
3252 /**
3353 * Executing global flag handlers. The global flag handlers are
3454 * not async as of now, but later we can look into making them
@@ -95,6 +115,7 @@ export class Kernel {
95115 */
96116 public find ( argv : string [ ] ) : CommandConstructorContract | null {
97117 /**
118+ * ----------------------------------------------------------------------------
98119 * Even though in `Unix` the command name may appear in between or at last, with
99120 * ace we always want the command name to be the first argument. However, the
100121 * arguments to the command itself can appear in any sequence. For example:
@@ -105,6 +126,19 @@ export class Kernel {
105126 *
106127 * Doesn't work
107128 * - node ace foo make:controller
129+ * ----------------------------------------------------------------------------
130+ */
131+
132+ /**
133+ * Manifest commands gets preference over manually registered commands.
134+ */
135+ if ( this . manifestCommands && this . manifestCommands [ argv [ 0 ] ] ) {
136+ return this . _manifest ! . loadCommand ( this . manifestCommands [ argv [ 0 ] ] . commandPath )
137+ }
138+
139+ /**
140+ * Try to find command inside manually registered command or fallback
141+ * to null
108142 */
109143 return this . commands [ argv [ 0 ] ] || null
110144 }
@@ -165,6 +199,15 @@ export class Kernel {
165199 return
166200 }
167201
202+ /**
203+ * Load manifest commands when instance of manifest exists. From here the
204+ * kernel will give preference to the `manifest` file vs manually
205+ * registered commands.
206+ */
207+ if ( this . _manifest ) {
208+ this . manifestCommands = await this . _manifest . load ( )
209+ }
210+
168211 const hasMentionedCommand = ! argv [ 0 ] . startsWith ( '-' )
169212
170213 /**
@@ -179,22 +222,40 @@ export class Kernel {
179222 /**
180223 * If command doesn't exists, then raise an error for same
181224 */
182- const command = this . find ( argv )
225+ let command = this . find ( argv )
183226 if ( ! command ) {
184227 throw new Error ( `${ argv [ 0 ] } is not a registered command` )
185228 }
186229
187230 return this . runCommand ( argv . splice ( 1 ) , command )
188231 }
189232
233+ /**
234+ * Use manifest instance to lazy load commands
235+ */
236+ public useManifest ( manifest : Manifest ) : this {
237+ this . _manifest = manifest
238+ return this
239+ }
240+
190241 /**
191242 * Print the help screen for a given command or all commands/flags
192243 */
193244 public printHelp ( command ?: CommandConstructorContract ) {
194245 if ( command ) {
195246 printHelpFor ( command )
196247 } else {
197- const commands = Object . keys ( this . commands ) . map ( ( name ) => this . commands [ name ] )
248+ let commands : ManifestCommand [ ] | CommandConstructorContract [ ]
249+
250+ /**
251+ * Using manifest commands over registered commands
252+ */
253+ if ( this . manifestCommands ) {
254+ commands = Object . keys ( this . manifestCommands ) . map ( ( name ) => this . commands [ name ] )
255+ } else {
256+ commands = Object . keys ( this . commands ) . map ( ( name ) => this . commands [ name ] )
257+ }
258+
198259 const flags = Object . keys ( this . flags ) . map ( ( name ) => this . flags [ name ] )
199260 printHelp ( commands , flags )
200261 }
0 commit comments