Skip to content

Commit a7ce2d7

Browse files
docs: cover useexisting variant for configurable module cls
1 parent 88ca596 commit a7ce2d7

File tree

1 file changed

+65
-14
lines changed

1 file changed

+65
-14
lines changed

content/fundamentals/dynamic-modules.md

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,45 @@ Extending the `ConfigurableModuleClass` means that `ConfigModule` provides now n
343343
export class AppModule {}
344344
```
345345

346+
The `registerAsync` method takes the following object as an argument:
347+
348+
```typescript
349+
{
350+
/**
351+
* Injection token resolving to a class that will be instantiated as a provider.
352+
* The class must implement the corresponding interface.
353+
*/
354+
useClass?: Type<
355+
ConfigurableModuleOptionsFactory<ModuleOptions, FactoryClassMethodKey>
356+
>;
357+
/**
358+
* Function returning options (or a Promise resolving to options) to configure the
359+
* module.
360+
*/
361+
useFactory?: (...args: any[]) => Promise<ModuleOptions> | ModuleOptions;
362+
/**
363+
* Dependencies that a Factory may inject.
364+
*/
365+
inject?: FactoryProvider['inject'];
366+
/**
367+
* Injection token resolving to an existing provider. The provider must implement
368+
* the corresponding interface.
369+
*/
370+
useExisting?: Type<
371+
ConfigurableModuleOptionsFactory<ModuleOptions, FactoryClassMethodKey>
372+
>;
373+
}
374+
```
375+
376+
Let's go through the above properties one by one:
377+
378+
- `useFactory` - a function that returns the configuration object. It can be either synchronous or asynchronous. To inject dependencies into the factory function, use the `inject` property. We used this variant in the example above.
379+
- `inject` - an array of dependencies that will be injected into the factory function. The order of the dependencies must match the order of the parameters in the factory function.
380+
- `useClass` - a class that will be instantiated as a provider. The class must implement the corresponding interface. Typically, this is a class that provides a `create()` method that returns the configuration object. Read more about this in the [Custom method key](/fundamentals/dynamic-modules#custom-method-key) section below.
381+
- `useExisting` - a variant of `useClass` that allows you to use an existing provider instead of instructing Nest to create a new instance of the class. This is useful when you want to use a provider that is already registered in the module. Keep in mind that the class must implement the same interface as the one used in `useClass` (and so it must provide the `create()` method, unless you override the default method name, see [Custom method key](/fundamentals/dynamic-modules#custom-method-key) section below).
382+
383+
Always choose one of the above options (`useFactory`, `useClass`, or `useExisting`), as they are mutually exclusive.
384+
346385
Lastly, let's update the `ConfigService` class to inject the generated module options' provider instead of the `'CONFIG_OPTIONS'` that we used so far.
347386

348387
```typescript
@@ -431,17 +470,18 @@ There are edge-cases when your module may need to take extra options that determ
431470
In such cases, the `ConfigurableModuleBuilder#setExtras` method can be used. See the following example:
432471

433472
```typescript
434-
export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } = new ConfigurableModuleBuilder<ConfigModuleOptions>()
435-
.setExtras(
436-
{
437-
isGlobal: true,
438-
},
439-
(definition, extras) => ({
440-
...definition,
441-
global: extras.isGlobal,
442-
}),
443-
)
444-
.build();
473+
export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } =
474+
new ConfigurableModuleBuilder<ConfigModuleOptions>()
475+
.setExtras(
476+
{
477+
isGlobal: true,
478+
},
479+
(definition, extras) => ({
480+
...definition,
481+
global: extras.isGlobal,
482+
}),
483+
)
484+
.build();
445485
```
446486

447487
In the example above, the first argument passed into the `setExtras` method is an object containing default values for the "extra" properties. The second argument is a function that takes an auto-generated module definitions (with `provider`, `exports`, etc.) and `extras` object which represents extra properties (either specified by the consumer or defaults). The returned value of this function is a modified module definition. In this specific example, we're taking the `extras.isGlobal` property and assigning it to the `global` property of the module definition (which in turn determines whether a module is global or not, read more [here](/modules#dynamic-modules)).
@@ -465,7 +505,9 @@ However, since `isGlobal` is declared as an "extra" property, it won't be availa
465505
```typescript
466506
@Injectable()
467507
export class ConfigService {
468-
constructor(@Inject(MODULE_OPTIONS_TOKEN) private options: ConfigModuleOptions) {
508+
constructor(
509+
@Inject(MODULE_OPTIONS_TOKEN) private options: ConfigModuleOptions,
510+
) {
469511
// "options" object will not have the "isGlobal" property
470512
// ...
471513
}
@@ -479,7 +521,11 @@ The auto-generated static methods (`register`, `registerAsync`, etc.) can be ext
479521
```typescript
480522
import { Module } from '@nestjs/common';
481523
import { ConfigService } from './config.service';
482-
import { ConfigurableModuleClass, ASYNC_OPTIONS_TYPE, OPTIONS_TYPE } from './config.module-definition';
524+
import {
525+
ConfigurableModuleClass,
526+
ASYNC_OPTIONS_TYPE,
527+
OPTIONS_TYPE,
528+
} from './config.module-definition';
483529

484530
@Module({
485531
providers: [ConfigService],
@@ -505,5 +551,10 @@ export class ConfigModule extends ConfigurableModuleClass {
505551
Note the use of `OPTIONS_TYPE` and `ASYNC_OPTIONS_TYPE` types that must be exported from the module definition file:
506552

507553
```typescript
508-
export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN, OPTIONS_TYPE, ASYNC_OPTIONS_TYPE } = new ConfigurableModuleBuilder<ConfigModuleOptions>().build();
554+
export const {
555+
ConfigurableModuleClass,
556+
MODULE_OPTIONS_TOKEN,
557+
OPTIONS_TYPE,
558+
ASYNC_OPTIONS_TYPE,
559+
} = new ConfigurableModuleBuilder<ConfigModuleOptions>().build();
509560
```

0 commit comments

Comments
 (0)