-
[Nest.js] 15 - ConfigurationNest.js 2021. 9. 22. 02:25
Contents
1. Configuration?
2. Codebase vs Environment Variables
3. Module Installation
4. Configuration implementation
1. Configuration?
- In our source code, some of codes that we have written may be affected by Application Environment, Development Environment, or be protected from others.
- Therefore, we will deal with those code to save in much securer way, which is called Configuration File.
- Configuration files are not usually changed during runtime, these are loaded and defined when an application starts.
- It could be a XML, JSON, YAML, or Environment Variables type.
- let's start to manage and protect our configuration information.
2. Codebase vs Environment Variables
Codebase
- Usually, Codebase configuration files have information, which is OK to be exposed, such as Port number.
- XML, JASON, or YAML are Codebase configuration file.
Environment Variables
- It is much focused on secure informtaion of application, such as API key, or password.
3. Module Installation
Window only
$ npm install -g win-node-env
and then, Window & MAC OS
$ npm install config --save
4. Configuration Implementation
1. create a config directory to manage all configuration files.
2. create 3 YAML(YML) files
3. cofig/default.yaml
server: port: 3000 db: type: 'mysql' port: 3306 database: 'test' jwt: expiresIn: 3600
4. config/development.yml => default.yml + information in Development environment
db: host: 'localhost' username: 'root' password: '1234' synchronize: true jwt: secret: 'Secret1234'
5. config/production.yml => => default.yml + information in Production environment
db: synchronize: false
6. src/main.ts
... import * as config from 'config'; // 1 async function bootstrap() { const logger = new Logger(); const app = await NestFactory.create(AppModule); const serverConfig = config.get('server'); // 2 const port = serverConfig.port; // 3 // Global Pipe ... // const port = 3000; // 4 await app.listen(port); Logger.log(`Application running on port ${port}`); logger.log(`Application running on port ${port}`); } bootstrap();
// 1. import all files in config directory.
// 2. config.get('server') - search a scope, which is named as 'server'.
// 3. serverConfig.port - read the Key, which is named as 'port', and then return its value.
// 4. now we manage port number in configuration file, default.yaml.
7.1 src/configs/typeorm.config.ts : before using configuration files
import { TypeOrmModuleOptions } from '@nestjs/typeorm'; export const TypeORMConfig: TypeOrmModuleOptions = { type: 'mysql', host: 'localhost', port: 3306, username: 'root', password: '1234', database: 'test', entities: [__dirname + '/../**/*.entity.{js,ts}'], synchronize: true, };
// this file exposes all secure information directly, even though I put this path in .gitignore
// let's change this with configuration file.
7.2 src/configs/typeorm.config.ts : after using configuration files
import { TypeOrmModuleOptions } from '@nestjs/typeorm'; import * as config from 'config'; const dbConfig = config.get('db'); // 1 export const TypeORMConfig: TypeOrmModuleOptions = { type: dbConfig.type, // 2 host: process.env.RDS_HOSTNAME || dbConfig.host, // 3 port: process.env.RDS_PORT || dbConfig.port, // 2 username: process.env.RDS_USERNAME || dbConfig.username, // 3 password: process.env.RDS_PASSWORD || dbConfig.password, // 3 database: process.env.RDS_DB_NAME || dbConfig.database, // 2 entities: [__dirname + '/../**/*.entity.{js,ts}'], synchronize: dbConfig.synchronize, // 4 };
### process.env.XXX are not defined yet, it will apply if process.env.XXX exists in a real server environment
// 1. load a scope, named as 'db', thus default.yaml, development.yml, and production.yml are all loaded to the variable.
// 2. those key and value are defined in default.yaml
// 3. those key ans value are defined in development.yml
// 4. dbConfig.synchronize - are defined in both development.yml and production.yml,
so we can easily change based on running environment.8. src/auth/auth.module.ts
... import * as config from 'config'; const jwtConfig = config.get('jwt'); // 1 @Module({ imports: [ PassportModule.register({ defaultStrategy: 'jwt' }), JwtModule.register({ secret: process.env.JWT_SECRET || jwtConfig.secret, // 2 signOptions: { expiresIn: jwtConfig.expiresIn, // 3 }, }), TypeOrmModule.forFeature([UserRepository]), ], controllers: [AuthController], providers: [AuthService, JwtStrategy], exports: [JwtStrategy, PassportModule], }) export class AuthModule {}
// 1. load a scope, named as 'jwt', thus default.yaml, and development.yml are all loaded to the variable.
// 2. process.env.JWT_SECRET - look for a key first in a server, if not found, use development.yml's value
// 3. this key and value is defined in defualt.yaml
// 9. src/auth/jwt.strategy.ts
... import * as config from 'config'; @Injectable() export class JwtStrategy extends PassportStrategy(Strategy) { constructor( @InjectRepository(UserRepository) private userRepository: UserRepository ) { super({ secretOrKey: process.env.JWT_SECRET || config.get('jwt.secret'), // 1 jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), }) } ... }
// 1. config.get('jwt.secret') - use directly scope('jwt'), key('secret') and value('Secret1234') from config directory.
'Nest.js' 카테고리의 다른 글
[Nest.js] simple project (0) 2021.09.27 [Nest.js] 16 - Log with Winston and WebHook (0) 2021.09.25 [Nest.js] 14 - Log basic (0) 2021.09.17 [Nest.js] 13 - Relations - One To One, Many To One (0) 2021.09.15 [Nest.js] 12 - Authentification - Passport & JWT (0) 2021.09.15