Skip to content

Commit

Permalink
[typescript-nestjs] allow configuration with forRootAsync (#15269) (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
BerniWittmann committed Jul 22, 2023
1 parent 3c5b119 commit b7346d0
Show file tree
Hide file tree
Showing 9 changed files with 288 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,31 @@ import { BASE_PATH } from '{{npmName}}';
export class AppModule {}
```

### Configuring the module with `forRootAsync`

You can also use the Nestjs Config Module/Service to configure your app with `forRootAsync`.

```
@Module({
imports: [
ApiModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService): Configuration => {
const params: ConfigurationParameters = {
// set configuration parameters here.
basePath: config.get('API_URL'),
};
return new Configuration(params);
},
})
],
declarations: [ AppComponent ],
providers: [],
bootstrap: [ AppComponent ]
})
export class AppModule {}
```

#### Using @nestjs/cli
First extend your `src/environments/*.ts` files by adding the corresponding base path:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { HttpModule, HttpService } from '@nestjs/axios';
{{^useAxiosHttpModule}}
import { DynamicModule, HttpService, HttpModule, Module, Global } from '@nestjs/common';
{{/useAxiosHttpModule}}
import { Configuration } from './configuration';
import { AsyncConfiguration, Configuration, ConfigurationFactory } from './configuration';

{{#apiInfo}}
{{#apis}}
Expand Down Expand Up @@ -33,5 +33,49 @@ export class ApiModule {
};
}

/**
* Register the module asynchronously.
*/
static forRootAsync(options: AsyncConfiguration): DynamicModule {
const providers = [...this.createAsyncProviders(options)];
return {
module: ApiModule,
imports: options.imports || [],
providers,
exports: providers,
};
}

private static createAsyncProviders(options: AsyncConfiguration): Provider[] {
if (options.useExisting || options.useFactory) {
return [this.createAsyncConfigurationProvider(options)];
}
return [
this.createAsyncConfigurationProvider(options),
{
provide: options.useClass,
useClass: options.useClass,
},
];
}

private static createAsyncConfigurationProvider(
options: AsyncConfiguration,
): Provider {
if (options.useFactory) {
return {
provide: Configuration,
useFactory: options.useFactory,
inject: options.inject || [],
};
}
return {
provide: Configuration,
useFactory: async (optionsFactory: ConfigurationFactory) =>
await optionsFactory.createConfiguration(),
inject: [options.useExisting || options.useClass],
};
}

constructor( httpService: HttpService) { }
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ModuleMetadata, Type } from '@nestjs/common/interfaces';

export interface ConfigurationParameters {
apiKeys?: {[ key: string ]: string};
username?: string;
Expand Down Expand Up @@ -77,3 +79,27 @@ export class Configuration {
return mime != null && (jsonMime.test(mime) || mime.toLowerCase() === 'application/json-patch+json');
}
}

export interface ConfigurationFactory {
createConfiguration(): Promise<Configuration> | Configuration;
}

export interface AsyncConfiguration extends Pick<ModuleMetadata, 'imports'> {
/**
* The `useExisting` syntax allows you to create aliases for existing providers.
*/
useExisting?: Type<ConfigurationFactory>;
/**
* The `useClass` syntax allows you to dynamically determine a class
* that a token should resolve to.
*/
useClass?: Type<ConfigurationFactory>;
/**
* The `useFactory` syntax allows for creating providers dynamically.
*/
useFactory?: (...args: any[]) => Promise<Configuration> | Configuration;
/**
* Optional list of providers to be injected into the context of the Factory function.
*/
inject?: any[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,31 @@ import { BASE_PATH } from '@openapitools/typescript-nestjs-petstore';
export class AppModule {}
```

### Configuring the module with `forRootAsync`

You can also use the Nestjs Config Module/Service to configure your app with `forRootAsync`.

```
@Module({
imports: [
ApiModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService): Configuration => {
const params: ConfigurationParameters = {
// set configuration parameters here.
basePath: config.get('API_URL'),
};
return new Configuration(params);
},
})
],
declarations: [ AppComponent ],
providers: [],
bootstrap: [ AppComponent ]
})
export class AppModule {}
```

#### Using @nestjs/cli
First extend your `src/environments/*.ts` files by adding the corresponding base path:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DynamicModule, HttpService, HttpModule, Module, Global } from '@nestjs/common';
import { Configuration } from './configuration';
import { AsyncConfiguration, Configuration, ConfigurationFactory } from './configuration';

import { PetService } from './api/pet.service';
import { StoreService } from './api/store.service';
Expand Down Expand Up @@ -27,5 +27,49 @@ export class ApiModule {
};
}

/**
* Register the module asynchronously.
*/
static forRootAsync(options: AsyncConfiguration): DynamicModule {
const providers = [...this.createAsyncProviders(options)];
return {
module: ApiModule,
imports: options.imports || [],
providers,
exports: providers,
};
}

private static createAsyncProviders(options: AsyncConfiguration): Provider[] {
if (options.useExisting || options.useFactory) {
return [this.createAsyncConfigurationProvider(options)];
}
return [
this.createAsyncConfigurationProvider(options),
{
provide: options.useClass,
useClass: options.useClass,
},
];
}

private static createAsyncConfigurationProvider(
options: AsyncConfiguration,
): Provider {
if (options.useFactory) {
return {
provide: Configuration,
useFactory: options.useFactory,
inject: options.inject || [],
};
}
return {
provide: Configuration,
useFactory: async (optionsFactory: ConfigurationFactory) =>
await optionsFactory.createConfiguration(),
inject: [options.useExisting || options.useClass],
};
}

constructor( httpService: HttpService) { }
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ModuleMetadata, Type } from '@nestjs/common/interfaces';

export interface ConfigurationParameters {
apiKeys?: {[ key: string ]: string};
username?: string;
Expand Down Expand Up @@ -77,3 +79,27 @@ export class Configuration {
return mime != null && (jsonMime.test(mime) || mime.toLowerCase() === 'application/json-patch+json');
}
}

export interface ConfigurationFactory {
createConfiguration(): Promise<Configuration> | Configuration;
}

export interface AsyncConfiguration extends Pick<ModuleMetadata, 'imports'> {
/**
* The `useExisting` syntax allows you to create aliases for existing providers.
*/
useExisting?: Type<ConfigurationFactory>;
/**
* The `useClass` syntax allows you to dynamically determine a class
* that a token should resolve to.
*/
useClass?: Type<ConfigurationFactory>;
/**
* The `useFactory` syntax allows for creating providers dynamically.
*/
useFactory?: (...args: any[]) => Promise<Configuration> | Configuration;
/**
* Optional list of providers to be injected into the context of the Factory function.
*/
inject?: any[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,31 @@ import { BASE_PATH } from '@openapitools/typescript-nestjs-petstore';
export class AppModule {}
```

### Configuring the module with `forRootAsync`

You can also use the Nestjs Config Module/Service to configure your app with `forRootAsync`.

```
@Module({
imports: [
ApiModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService): Configuration => {
const params: ConfigurationParameters = {
// set configuration parameters here.
basePath: config.get('API_URL'),
};
return new Configuration(params);
},
})
],
declarations: [ AppComponent ],
providers: [],
bootstrap: [ AppComponent ]
})
export class AppModule {}
```

#### Using @nestjs/cli
First extend your `src/environments/*.ts` files by adding the corresponding base path:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DynamicModule, Module, Global } from '@nestjs/common';
import { HttpModule, HttpService } from '@nestjs/axios';
import { Configuration } from './configuration';
import { AsyncConfiguration, Configuration, ConfigurationFactory } from './configuration';

import { PetService } from './api/pet.service';
import { StoreService } from './api/store.service';
Expand Down Expand Up @@ -28,5 +28,49 @@ export class ApiModule {
};
}

/**
* Register the module asynchronously.
*/
static forRootAsync(options: AsyncConfiguration): DynamicModule {
const providers = [...this.createAsyncProviders(options)];
return {
module: ApiModule,
imports: options.imports || [],
providers,
exports: providers,
};
}

private static createAsyncProviders(options: AsyncConfiguration): Provider[] {
if (options.useExisting || options.useFactory) {
return [this.createAsyncConfigurationProvider(options)];
}
return [
this.createAsyncConfigurationProvider(options),
{
provide: options.useClass,
useClass: options.useClass,
},
];
}

private static createAsyncConfigurationProvider(
options: AsyncConfiguration,
): Provider {
if (options.useFactory) {
return {
provide: Configuration,
useFactory: options.useFactory,
inject: options.inject || [],
};
}
return {
provide: Configuration,
useFactory: async (optionsFactory: ConfigurationFactory) =>
await optionsFactory.createConfiguration(),
inject: [options.useExisting || options.useClass],
};
}

constructor( httpService: HttpService) { }
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ModuleMetadata, Type } from '@nestjs/common/interfaces';

export interface ConfigurationParameters {
apiKeys?: {[ key: string ]: string};
username?: string;
Expand Down Expand Up @@ -77,3 +79,27 @@ export class Configuration {
return mime != null && (jsonMime.test(mime) || mime.toLowerCase() === 'application/json-patch+json');
}
}

export interface ConfigurationFactory {
createConfiguration(): Promise<Configuration> | Configuration;
}

export interface AsyncConfiguration extends Pick<ModuleMetadata, 'imports'> {
/**
* The `useExisting` syntax allows you to create aliases for existing providers.
*/
useExisting?: Type<ConfigurationFactory>;
/**
* The `useClass` syntax allows you to dynamically determine a class
* that a token should resolve to.
*/
useClass?: Type<ConfigurationFactory>;
/**
* The `useFactory` syntax allows for creating providers dynamically.
*/
useFactory?: (...args: any[]) => Promise<Configuration> | Configuration;
/**
* Optional list of providers to be injected into the context of the Factory function.
*/
inject?: any[];
}

0 comments on commit b7346d0

Please sign in to comment.