Skip to content

Commit c583b65

Browse files
authored
fix: support dynamic modules in CommandFactory (#1229)
`CommandFactory.run()` already supports running dynamic modules, but the type `Type<any>` doesn't allow passing `DynamicModule`.
2 parents c688a39 + f2d6228 commit c583b65

File tree

3 files changed

+83
-67
lines changed

3 files changed

+83
-67
lines changed

.changeset/soft-geckos-know.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'nest-commander': patch
3+
---
4+
5+
Support dynamic modules in `CommandFactory.run()`

apps/docs/src/pages/en/api.md

Lines changed: 75 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ layout: ../../layouts/MainLayout.astro
99

1010
#### @Command()
1111

12-
This class decorator is pretty much what everything else in this package relies on existing. This is
13-
the decorator that sets up the sub commands for the application that are to be consumed.
12+
This class decorator is pretty much what everything else in this package relies
13+
on existing. This is the decorator that sets up the sub commands for the
14+
application that are to be consumed.
1415

1516
| Property | Type | Required | Description |
1617
| --------------- | ------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
@@ -24,15 +25,15 @@ the decorator that sets up the sub commands for the application that are to be c
2425

2526
:::note
2627

27-
The above information holds for `@SubCommand()` as well, though `default` under `options` has no
28-
effect.
28+
The above information holds for `@SubCommand()` as well, though `default` under
29+
`options` has no effect.
2930

3031
:::
3132

3233
#### @RootCommand()
3334

34-
Just like `@Command()` except without the `name` property, and can only be used once per
35-
application.
35+
Just like `@Command()` except without the `name` property, and can only be used
36+
once per application.
3637

3738
| Property | Type | Required | Description |
3839
| --------------- | ------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
@@ -45,9 +46,9 @@ application.
4546

4647
#### @Option()
4748

48-
This method decorator allows for users to pass in extra options for commands defined with
49-
`@Command()`. These options allow for the program to act in slightly different, yet predictable
50-
ways.
49+
This method decorator allows for users to pass in extra options for commands
50+
defined with `@Command()`. These options allow for the program to act in
51+
slightly different, yet predictable ways.
5152

5253
| Property | Type | Required | Description |
5354
| ------------ | ------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -60,18 +61,18 @@ ways.
6061

6162
#### @OptionChoicesFor()
6263

63-
This method decorator allows you to get chocies for an `@Option()` in a dynamic manner rather than
64-
hard coding them into the `@Option()` decorator. The method this decorator decorates should return a
65-
string array of options.
64+
This method decorator allows you to get chocies for an `@Option()` in a dynamic
65+
manner rather than hard coding them into the `@Option()` decorator. The method
66+
this decorator decorates should return a string array of options.
6667

6768
| Property | Type | Requried | Description |
6869
| -------- | -------- | -------- | ------------------------------------------------------------------------------------------------------ |
6970
| name | `string` | true | The name to match back to the `@Option()` decorator. This is how the two decorators are tied together. |
7071

7172
#### @Help()
7273

73-
This method decorator allows you to add custom help text for your command in a specified position
74-
with respect to the original help text
74+
This method decorator allows you to add custom help text for your command in a
75+
specified position with respect to the original help text
7576

7677
```ts
7778
Help(position: 'before' | 'beforeAll' | 'after' | 'afterAll'): MethodDecorator
@@ -81,8 +82,8 @@ Help(position: 'before' | 'beforeAll' | 'after' | 'afterAll'): MethodDecorator
8182

8283
#### `ask<T>`
8384

84-
An asynchronous command to allow for getting user input based on existing options from commander and
85-
the name of a question set.
85+
An asynchronous command to allow for getting user input based on existing
86+
options from commander and the name of a question set.
8687

8788
```typescript
8889
ask<T>(name: string, options: Partial<T> | undefined): Promise<T>
@@ -107,9 +108,9 @@ This class decorator allows for the setup of a set of questions to ask.
107108

108109
#### @Question()
109110

110-
This method decorator allows for creating questions to ask the user. For information on each
111-
specific kind of question, [Inquirer's docs](https://www.npmjs.com/package/inquirer) should be
112-
consulted.
111+
This method decorator allows for creating questions to ask the user. For
112+
information on each specific kind of question,
113+
[Inquirer's docs](https://www.npmjs.com/package/inquirer) should be consulted.
113114

114115
| Property | Type | Required | Description |
115116
| ----------- | ---------------------------------------------------------------------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -129,61 +130,64 @@ consulted.
129130

130131
:::note
131132

132-
When you use the `@*For()` decorator factories, the equivalent option on `@Question()` (eg:
133-
`message`) will not be used.
133+
When you use the `@*For()` decorator factories, the equivalent option on
134+
`@Question()` (eg: `message`) will not be used.
134135

135136
:::
136137

137-
\* The property itself is not required, but there must be a value for this, whether through dynamic
138-
decorator or the `@Question()` decorator.
138+
\* The property itself is not required, but there must be a value for this,
139+
whether through dynamic decorator or the `@Question()` decorator.
139140

140141
#### @ValidateFor()
141142

142-
This method decorator allows a user to define a dynamic value for inquirer's `validate` option for
143-
the named question. The method this decorator decorates takes in the user input and answer hashes
144-
and returns a boolean.
143+
This method decorator allows a user to define a dynamic value for inquirer's
144+
`validate` option for the named question. The method this decorator decorates
145+
takes in the user input and answer hashes and returns a boolean.
145146

146147
| Property | Type | Required | Description |
147148
| -------- | -------- | -------- | ------------------------------------------------ |
148149
| name | `string` | true | The name of the question this decorator effects. |
149150

150151
#### @TransformFor()
151152

152-
This method decorator allows a user to define a dynamic value for inquirer's `transform` option for
153-
the named question. The method this decorator decorates takes in the user input, answer hashes, and
154-
option flags and returns the input after transformation. This transformation **does not** impact
155-
what is returned by Inquirer, only what is shown back to the user.
153+
This method decorator allows a user to define a dynamic value for inquirer's
154+
`transform` option for the named question. The method this decorator decorates
155+
takes in the user input, answer hashes, and option flags and returns the input
156+
after transformation. This transformation **does not** impact what is returned
157+
by Inquirer, only what is shown back to the user.
156158

157159
| Property | Type | Required | Description |
158160
| -------- | -------- | -------- | ------------------------------------------------ |
159161
| name | `string` | true | The name of the question this decorator effects. |
160162

161163
#### @WhenFor()
162164

163-
This method decorator allows a user to define a dynamic value for inquirer's `when` option for the
164-
named question. The method this decorator decorates takes in the answer hashes and returns a boolean
165-
for if the question should be shown or not.
165+
This method decorator allows a user to define a dynamic value for inquirer's
166+
`when` option for the named question. The method this decorator decorates takes
167+
in the answer hashes and returns a boolean for if the question should be shown
168+
or not.
166169

167170
| Property | Type | Required | Description |
168171
| -------- | -------- | -------- | ------------------------------------------------ |
169172
| name | `string` | true | The name of the question this decorator effects. |
170173

171174
#### @MessageFor()
172175

173-
This method decorator allows a user to define a dynamic value for inquirer's `message` option for
174-
the named question. The method this decorator decorates takes in the current set of answers and
175-
returns a string.
176+
This method decorator allows a user to define a dynamic value for inquirer's
177+
`message` option for the named question. The method this decorator decorates
178+
takes in the current set of answers and returns a string.
176179

177180
| Property | Type | Required | Description |
178181
| -------- | -------- | -------- | ------------------------------------------------ |
179182
| name | `string` | true | The name of the question this decorator effects. |
180183

181184
#### @ChoicesFor()
182185

183-
This method decorator allows a user to define a dynamic value for inquirer's `choices` option for
184-
the named question. The method this decorator decorates takes in the current answer hashes and
185-
returns an array of choices. These choices can be an array of `string`, `number`, or objects
186-
containing a `name`, `value`, and `short`. The choices array can also contain a separator which can
186+
This method decorator allows a user to define a dynamic value for inquirer's
187+
`choices` option for the named question. The method this decorator decorates
188+
takes in the current answer hashes and returns an array of choices. These
189+
choices can be an array of `string`, `number`, or objects containing a `name`,
190+
`value`, and `short`. The choices array can also contain a separator which can
187191
be read about in [Inquirer's docs](https://www.npmjs.com/package/inquirer).
188192

189193
| Property | Type | Required | Description |
@@ -192,18 +196,19 @@ be read about in [Inquirer's docs](https://www.npmjs.com/package/inquirer).
192196

193197
#### @DefaultFor()
194198

195-
This method decorator allows a user to define a dynamic value for inquirer's `default` option for
196-
the named question. The method this decorator decorates takes in the current hash of answers and
197-
returns a `number`, `string`, or `boolean`.
199+
This method decorator allows a user to define a dynamic value for inquirer's
200+
`default` option for the named question. The method this decorator decorates
201+
takes in the current hash of answers and returns a `number`, `string`, or
202+
`boolean`.
198203

199204
| Property | Type | Required | Description |
200205
| -------- | -------- | -------- | ------------------------------------------------ |
201206
| name | `string` | true | The name of the question this decorator effects. |
202207

203208
:::tip
204209

205-
Most of the decorators for the `@QuestionSet()` decorated class are just dynamic setters for
206-
inquirer's options.
210+
Most of the decorators for the `@QuestionSet()` decorated class are just dynamic
211+
setters for inquirer's options.
207212
[Their docs will go more in depth about what each one does](https://www.npmjs.com/package/inquirer).
208213

209214
:::
@@ -245,25 +250,28 @@ A simple wrapper around `Number.parseFloat()`
245250

246251
#### run
247252

248-
A static method that kicks off the command and manages the Nest application lifecycle.
253+
A static method that kicks off the command and manages the Nest application
254+
lifecycle.
249255

250256
```typescript
251-
CommandFactory.run(rootModule: Type<any>, optionsOrLogger?: CommandFactoryRunOptions | NestLogger): Promise<void>
257+
CommandFactory.run(rootModule: Type<any> | DynamicModule, optionsOrLogger?: CommandFactoryRunOptions | NestLogger): Promise<void>
252258
```
253259

254260
| Parameter | Type | Required | Description |
255261
| --------------- | ------------------------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------- |
256-
| rootModule | `Type<any>` | true | The module, or module metadata, required to run the command. This is the same module metadata passed to `NestFactory.create`. |
262+
| rootModule | `Type<any>` or `DynamicModule` | true | The module, or module metadata, required to run the command. This is the same module metadata passed to `NestFactory.create`. |
257263
| optionsOrLogger | `CommandFactoryRunOptions` or `NestLogger` | false | Options or a Nest logger instance for the `CommandFactory` to pass on to `NestLogger`. See below for more information. |
258264

259265
#### runWithoutClosing
260266

261-
The same static method as above, but without handling the closing of the Nest application when the
262-
command finishes. This is to allow the setup of things like file watchers or pollers.
267+
The same static method as above, but without handling the closing of the Nest
268+
application when the command finishes. This is to allow the setup of things like
269+
file watchers or pollers.
263270

264271
#### CommandFactoryRunOptions
265272

266-
Options that can be passed to the `run` or `runWithoutClosing` method to modify the behavior.
273+
Options that can be passed to the `run` or `runWithoutClosing` method to modify
274+
the behavior.
267275

268276
| Property | Type | Required | Description |
269277
| ----------------------- | ------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -277,14 +285,15 @@ Options that can be passed to the `run` or `runWithoutClosing` method to modify
277285

278286
### CommandRunner
279287

280-
The `CommandRunner` is abstract class to define your command. You define the command in the class
281-
inherits it.
288+
The `CommandRunner` is abstract class to define your command. You define the
289+
command in the class inherits it.
282290

283291
#### registerWithSubCommands
284292

285-
A static method that returns a list of the root command class, which calls this api, and all sub
286-
command classes set via the metadata of the `@Command()` and `@SubCommand()` decorators in the scope
287-
of module tree that the root command class traverses.
293+
A static method that returns a list of the root command class, which calls this
294+
api, and all sub command classes set via the metadata of the `@Command()` and
295+
`@SubCommand()` decorators in the scope of module tree that the root command
296+
class traverses.
288297

289298
```typescript title="src/app.module.ts"
290299
@Module({
@@ -299,8 +308,8 @@ export class AppModule {}
299308

300309
### @RequestModule()
301310

302-
A wrapper decorator for Nest's `@Module()` that exposes a way to set a request object mock for the
303-
`REQUEST` injection token.
311+
A wrapper decorator for Nest's `@Module()` that exposes a way to set a request
312+
object mock for the `REQUEST` injection token.
304313

305314
```typescript
306315
@RequestModule({
@@ -324,9 +333,9 @@ export class SomeCommandModule {}
324333

325334
#### createTestingCommand
326335

327-
Similar to `@nestjs/testing`'s `createTestingModule`, this static method sets up a
328-
`TestingModuleBuilder` that can be used with Nest's `overrideProvider` and `compile` methods for
329-
creating a `TestingModule`.
336+
Similar to `@nestjs/testing`'s `createTestingModule`, this static method sets up
337+
a `TestingModuleBuilder` that can be used with Nest's `overrideProvider` and
338+
`compile` methods for creating a `TestingModule`.
330339

331340
```typescript
332341
CommandFactory.createTestingCommand(moduleMetadata: CommandModuleMetadata): TestingModuleBuilder
@@ -351,7 +360,8 @@ CommandTestFactory.run(app: TestingModule, args?: string[]): Promise<void>
351360

352361
#### setAnswers
353362

354-
A command to mock the gathering of information from a user, to help with automated testing.
363+
A command to mock the gathering of information from a user, to help with
364+
automated testing.
355365

356366
```typescript
357367
CommandFactory.setAnswers(value: any | any[]): void
@@ -363,8 +373,9 @@ CommandFactory.setAnswers(value: any | any[]): void
363373

364374
#### useDefaultInquirer
365375

366-
A method to sub back in the regular `Inquirer` instance instead of the mock used for testing. If
367-
this is used, the `setAnswers` will have no effect, and `stdin` data must be passed manually
376+
A method to sub back in the regular `Inquirer` instance instead of the mock used
377+
for testing. If this is used, the `setAnswers` will have no effect, and `stdin`
378+
data must be passed manually
368379

369380
```typescript
370381
CommandFactory.useDefaultInquirer(): typeof CommandTestFactory

packages/nest-commander/src/command.factory.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { CompletionFactory } from './completion.factory';
1515

1616
export class CommandFactory {
1717
static async run(
18-
rootModule: Type<any>,
18+
rootModule: Type<any> | DynamicModule,
1919
optionsOrLogger?: CommandFactoryRunOptions | NestLogger,
2020
): Promise<void> {
2121
const app = await this.createWithoutRunning(rootModule, optionsOrLogger);
@@ -24,7 +24,7 @@ export class CommandFactory {
2424
}
2525

2626
static async runWithoutClosing(
27-
rootModule: Type<any>,
27+
rootModule: Type<any> | DynamicModule,
2828
optionsOrLogger?: CommandFactoryRunOptions | NestLogger,
2929
): Promise<INestApplicationContext> {
3030
const app = await this.createWithoutRunning(rootModule, optionsOrLogger);
@@ -33,7 +33,7 @@ export class CommandFactory {
3333
}
3434

3535
static async createWithoutRunning(
36-
rootModule: Type<any>,
36+
rootModule: Type<any> | DynamicModule,
3737
optionsOrLogger: CommandFactoryRunOptions | NestLogger = false,
3838
): Promise<INestApplicationContext> {
3939
const options = this.getOptions(optionsOrLogger);

0 commit comments

Comments
 (0)