Reputation: 2019
is it possible to access nested configurations made by a configuration factory inside a simple provider class?
like:
/*Can't use ConfigService because there is no way of injecting it seemingly*/
export const databaseProviders = [
{
provide: 'SEQUELIZE',
useFactory: async () => {
const sequelize = new Sequelize({
host: ConfigService.get<string>('pg.host'),
port: ConfigService.get<number>('pg.port'),
dialect: 'postgres',
username: ConfigService.get<string>('pg.username'),
password: ConfigService.get<string>('pg.password'),
database: ConfigService.get<string>('pg.database')
});
sequelize.addModels([
models...
]);
await sequelize.sync(
process.env.NODE_ENV === 'developent' && {
force: true
}
);
return sequelize;
}
}
];
config/configuration.ts
export default () => ({
pg: {
host: 'localhost',
port: 5432,
username: process.env.NODE_ENV logic...
password: process.env.NODE_ENV logic...
database: process.env.NODE_ENV logic...
}
});
root.module.ts
...
import { ConfigModule } from '@nestjs/config';
import configuration from './config/configuration';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
load: [configuration]
}),
...
if not - is it possible to include ConfigService
inside a simple provider class, that isn't annotated with @Injectable()
I would think not becuase https://docs.nestjs.com/techniques/configuration#getting-started
Using the ConfigService# To access configuration values from our ConfigService, we first need to >inject ConfigService. As with any provider, we need to import its >containing module - the ConfigModule - into the module that will use it (unless you set the isGlobal property in the options object passed to the ConfigModule.forRoot() method to true). Import it into a feature module as shown below.
However it is pretty clever that you can perform some logic based on process.env.NODE_ENV
and dynamically change database configs between production, staging, development etc. So I would very much like a solution that would make this usable outside of just @Injectable
s
I assume one could make a simple util class in the root of the project that achieves the same thing, and use it inside of the application. But I think that solution has a lot of overhead.
Upvotes: 17
Views: 12551
Reputation: 70111
You're so close to having the correct setup. As you're creating a factory provider, you can inject dependencies into the factory by using the inject
key followed by an array of what to inject. In your case, it would look like this:
/*Can't use ConfigService because there is no way of injecting it seemingly*/
export const databaseProviders = [
{
provide: 'SEQUELIZE',
inject: [ConfigService], //no worries for imports because you're using a global module
useFactory: async (configService: ConfigService) => {
const sequelize = new Sequelize({
host: configService.get<string>('pg.host'),
port: configService.get<number>('pg.port'),
dialect: 'postgres',
username: configService.get<string>('pg.username'),
password: configService.get<string>('pg.password'),
database: configService.get<string>('pg.database')
});
sequelize.addModels([
models...
]);
await sequelize.sync(
process.env.NODE_ENV === 'developent' && {
force: true
}
);
return sequelize;
}
}
];
Upvotes: 32