Reputation: 445
I am developing a NestJS project. And here is my project structure:
-src
-config
-configuration.ts
-modules
-auth
-user
-utils
-util.ts
In my auth and user module, I import ConfigModule
and then I can use ConfigService
to get config values from configuration.ts file.
But how do I get config values in utils/util.ts
file?
It's just a dir that holds some helper files instead of a module dir.
Upvotes: 6
Views: 9758
Reputation: 87
when declaring a config module you can pass an object like that:
ConfigModule.forRoot({
envFilePath: ['.env'],
isGlobal: true,
load: [config],
}),
this load parameter is a list of functions that return javascript objects which are then added to your configuration, Then you can use ConfigService to get your configuration like that:
ConfigService.get("NODE_ENV") //This gets a configuration loaded from .env file
ConfigService.get("mongoose.connectionOptions") //This is a config you setted in app.config.ts for example and return an object containing mongoose connection options
your config file may look something like this:
var config = {
app: {
environment: process.env.NODE_ENV,
},
sentry: {
dsn: process.env.SENTRY_DSN,
tracesSampleRate: 1.0,
},
rabbit: {
connection: {
protocol: process.env.RABBITMQ_PROTOCOL,
hostname: process.env.RABBITMQ_HOST,
port: process.env.RABBITMQ_PORT,
vhost: process.env.RABBITMQ_VHOST,
username: process.env.RABBITMQ_USERNAME,
password: process.env.RABBITMQ_PASSWORD,
},
},
mongo: {
user: process.env.MONGO_USER,
password: process.env.MONGO_PASS,
dbName: process.env.MONGO_NAME,
port: process.env.MONGO_PORT,
host: process.env.MONGO_HOST,
connString: `mongodb://${process.env.MONGO_HOST}:${process.env.MONGO_PORT}/${process.env.MONGO_NAME}?authSource=admin`,
},
mongooseOptions: {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
user: process.env.MONGO_USER,
pass: process.env.MONGO_PASS,
keepAlive: true,
uri: `mongodb://${process.env.MONGO_HOST}:${process.env.MONGO_PORT}/${process.env.MONGO_NAME}?authSource=admin`,
},
};
var {
protocol,
username,
password,
hostname,
port,
vhost,
} = config.rabbit.connection;
config.rabbit.connection.connString = `${protocol}://${username}:${password}@${hostname}:${port}/${vhost}`;
export default () => config;
Upvotes: 0
Reputation: 2720
Assuming that you want the same instance of ConfigService
to be used... From a NestJS perspective, I see two options:
util
functions into a single Provider and treat it as a legit component of your NestJS application (or group them by responsibilities, into multiple Providers, this could make more sense too)util
, and declare as a custom Provider
from your NestJS app.Regarding the second option:
// regular typescript class
// exported so you can type your injected "configService" in other classes
export class ConfigService {
// your code
}
export default new ConfigService();
This can be imported as is by util
.
And injected into your NestJS application by creating a custom provider:
import configService, { ConfigService } from './somewhere/config-service.ts';
const configServiceProvider = {
provide: ConfigService,
useValue: configService,
};
// and use it in your ConfigModule
@Module({
providers: [configServiceProvider],
exports: [configServiceProvider],
})
export class ConfigModule {}
When injecting ConfigService
in your NestJS app, the value will be resolved to configService
(as long as ConfigModule
is in the scope, obviously).
However, this does not allow your ConfigService
to inject anything in its constructor parameters... Unless you are ready to use two different instances of ConfigService
(one for util
, one for your NestJS app). In this case, you could use a Factory provider, looking like the following:
const configServiceProvider = {
provide: ConfigService,
useFactory: (somethingService: SomethingService) => new ConfigService(somethingService),
inject: [SomethingService],
};
// and in the ConfigModule
@Module({
imports: [SomethingModule], // so you can inject SomethingService
providers: [configServiceProvider],
exports: [configServiceProvider],
})
export class ConfigModule {}
Yet this doesn't make much sense, as you would also need the dependencies of ConfigService
available out of the scope of NestJS, in order to use it in util
functions.
An other option (not considering any framework) would be to allow yourself passing (by parameter) the ConfigService
in your util
... e.g.:
// old version
export const readDeploymentConfigFile = (filePath: string) => {
// ...
};
// new version
export const readDeploymentConfigFile = (configService: ConfigService) => (filePath: string) => {
// ...
};
This video might be inspiring ("Dead-Simple Dependency Injection" by Rúnar Óli Bjarnason, 2012), even if that's not related to TypeScript nor Nest.
But this is not ideal to use as an API and it might also reveal some design flaws... If your util
functions need some dynamic/external config values, can we still consider them as util
functions?
Upvotes: 3