diff --git a/package-lock.json b/package-lock.json index f9ea19d..85a8f8d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1034,6 +1034,25 @@ "uuid": "7.0.3" } }, + "@nestjs/config": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-0.4.1.tgz", + "integrity": "sha512-rK8BVQsOk7ba4dbLVc7KOCAABhzD2Pb76Udd8DFyHef++DPJMOMI0RsYAuxLCw01tL+CStuk4R+nz6fYuCWriQ==", + "requires": { + "dotenv": "8.2.0", + "dotenv-expand": "5.1.0", + "lodash.get": "4.4.2", + "lodash.set": "4.3.2", + "uuid": "8.0.0" + }, + "dependencies": { + "uuid": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", + "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==" + } + } + }, "@nestjs/core": { "version": "7.0.9", "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-7.0.9.tgz", @@ -3844,6 +3863,11 @@ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" }, + "dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" + }, "duplexer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", @@ -7682,6 +7706,11 @@ "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, "lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -7723,6 +7752,11 @@ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" }, + "lodash.set": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", + "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=" + }, "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", diff --git a/package.json b/package.json index 74da270..8c7c669 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "@hapi/joi": "^17.1.0", "@nestjs/cli": "^7.1.2", "@nestjs/common": "^7.0.9", + "@nestjs/config": "^0.4.1", "@nestjs/core": "^7.0.9", "@nestjs/jwt": "^7.0.0", "@nestjs/passport": "^6.1.0", diff --git a/src/app.module.ts b/src/app.module.ts index 1fe16a8..ec0d94e 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,10 +1,11 @@ +import Joi = require('@hapi/joi'); import { Module } from '@nestjs/common'; +import { ConfigModule, ConfigService } from '@nestjs/config'; import { TypeOrmModule } from '@nestjs/typeorm'; import * as dotenv from 'dotenv'; import { AppController } from './app.controller'; import { AuthModule } from './auth/auth.module'; -import { ConfigService } from './config/config.service'; import { NotificationsModule } from './notifications/notifications.module'; import { UserSettingsModule } from './user-settings/user-settings.module'; import { UserModule } from './user/user.module'; @@ -15,6 +16,35 @@ const isTest = process.env.BANTR_IS_TEST; @Module({ imports: [ + ConfigModule.forRoot({ + envFilePath: ['.env', '.env.example'], + isGlobal: true, + validationSchema: Joi.object({ + NODE_ENV: Joi.string() + .valid('development', 'production', 'test') + .default('development'), + PORT: Joi.number().default(3000), + BANTR_PG_USER: Joi.string().required(), + BANTR_PG_PW: Joi.string().required(), + BANTR_PG_DB: Joi.string().required(), + BANTR_PG_HOST: Joi.string().default('localhost'), + BANTR_PG_PORT: Joi.number().default(5432), + BANTR_JWT_SECRET: Joi.string().required(), + BANTR_STEAM_API: Joi.string().required(), + BANTR_DISCORD_CLIENTID: Joi.string().required(), + BANTR_DISCORD_CLIENTSECRET: Joi.string().required(), + BANTR_FACEIT_CLIENTID: Joi.string().required(), + BANTR_FACEIT_CLIENTSECRET: Joi.string().required(), + REDIS_PORT: Joi.number().default(6379), + REDIS_HOST: Joi.string().default('localhost'), + REDIS_PASSWORD: Joi.string().allow(''), + REDIS_PREFIX: Joi.string().default('bantr'), + REDIS_DB: Joi.number().default(0), + HOSTNAME: Joi.string().default('http://localhost:3000'), + BANTR_SENTRY_DSN: Joi.string().default(''), + BANTR_IS_TEST: Joi.boolean().default(false) + }) +}), TypeOrmModule.forRoot({ // TODO: Handle this config via config service type: "postgres", diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts index afcb22e..d8c255b 100644 --- a/src/auth/auth.module.ts +++ b/src/auth/auth.module.ts @@ -4,7 +4,6 @@ import { PassportModule } from '@nestjs/passport'; import { TypeOrmModule } from '@nestjs/typeorm'; import * as dotenv from 'dotenv'; -import { ConfigModule } from '../config/config.module'; import { UserRepository } from '../user/user.repository'; import { AuthController } from './auth.controller'; import { AuthService } from './auth.service'; @@ -22,7 +21,6 @@ dotenv.config(); session: true }), TypeOrmModule.forFeature([UserRepository]), - ConfigModule, HttpModule, JwtModule.register({ secret: process.env.BANTR_JWT_SECRET }) ], diff --git a/src/auth/discord.strategy.ts b/src/auth/discord.strategy.ts index 2d25faa..8d35ca2 100644 --- a/src/auth/discord.strategy.ts +++ b/src/auth/discord.strategy.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; import { PassportStrategy } from '@nestjs/passport'; import { Strategy } from 'passport-discord'; -import { ConfigService } from '../config/config.service'; import { UserRepository } from '../user/user.repository'; import { AuthService } from './auth.service'; import { ISessionInterface } from './session.interface'; diff --git a/src/auth/faceit.strategy.ts b/src/auth/faceit.strategy.ts index 1d4cc38..98c71eb 100644 --- a/src/auth/faceit.strategy.ts +++ b/src/auth/faceit.strategy.ts @@ -1,8 +1,8 @@ /* eslint-disable */ import { HttpService, Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; import { PassportStrategy } from '@nestjs/passport'; -import { ConfigService } from '../config/config.service'; import { UserRepository } from '../user/user.repository'; import { AuthService } from './auth.service'; import { ISessionInterface } from './session.interface'; diff --git a/src/auth/steam.strategy.ts b/src/auth/steam.strategy.ts index 5c7f3bc..3b1fb09 100644 --- a/src/auth/steam.strategy.ts +++ b/src/auth/steam.strategy.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; import { PassportStrategy } from '@nestjs/passport'; import { Strategy } from 'passport-steam'; -import { ConfigService } from '../config/config.service'; import { UserRepository } from '../user/user.repository'; import { AuthService } from './auth.service'; import { ISessionInterface } from './session.interface'; diff --git a/src/config/config.module.ts b/src/config/config.module.ts deleted file mode 100644 index 748c1ba..0000000 --- a/src/config/config.module.ts +++ /dev/null @@ -1,15 +0,0 @@ - -import { Module, Global } from '@nestjs/common'; -import { ConfigService } from './config.service'; - -@Global() -@Module({ - providers: [ - { - provide: ConfigService, - useValue: new ConfigService(`.env`) - } - ], - exports: [ConfigService] -}) -export class ConfigModule { } diff --git a/src/config/config.service.spec.ts b/src/config/config.service.spec.ts deleted file mode 100644 index 25d93e1..0000000 --- a/src/config/config.service.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { ConfigService } from './config.service'; - -describe('ConfigService', () => { - let service: ConfigService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ConfigService] - }).compile(); - - service = module.get(ConfigService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/src/config/config.service.ts b/src/config/config.service.ts deleted file mode 100644 index fdfac2e..0000000 --- a/src/config/config.service.ts +++ /dev/null @@ -1,94 +0,0 @@ -import * as Joi from '@hapi/joi'; -import { Logger } from '@nestjs/common'; -import * as dotenv from 'dotenv'; - -// TODO: #5 Refactor to use @nest/config module - -/** - * .env config - */ -export interface IEnvConfig { - [key: string]: string -} - -/** - * Handle configuration values - */ -export class ConfigService { - - logger = new Logger('ConfigService'); - /** - * Holds the env config - */ - private envConfig: IEnvConfig; - - /** - * Reads the .env file - * @param filePath - */ - constructor(filePath: string) { - this.envConfig = {}; - const isTest = process.env.BANTR_IS_TEST; - - const path = isTest ? '.env.example' : filePath; - dotenv.config({ path }); - - this.logger.log(`Loading file ${path} for env config`); - - this.envConfig = this.validateInput(process.env); - } - - /** - * Ensures all needed variables are set, and returns the validated JavaScript object - * including the applied default values. - * @param envConfig - */ - private validateInput(envConfig: IEnvConfig): IEnvConfig { - const envVarsSchema: Joi.ObjectSchema = Joi.object({ - NODE_ENV: Joi.string() - .valid('development', 'production', 'test') - .default('development'), - PORT: Joi.number().default(3000), - BANTR_PG_USER: Joi.string().required(), - BANTR_PG_PW: Joi.string().required(), - BANTR_PG_DB: Joi.string().required(), - BANTR_PG_HOST: Joi.string().default('localhost'), - BANTR_PG_PORT: Joi.number().default(5432), - BANTR_JWT_SECRET: Joi.string().required(), - BANTR_STEAM_API: Joi.string().required(), - BANTR_DISCORD_CLIENTID: Joi.string().required(), - BANTR_DISCORD_CLIENTSECRET: Joi.string().required(), - BANTR_FACEIT_CLIENTID: Joi.string().required(), - BANTR_FACEIT_CLIENTSECRET: Joi.string().required(), - REDIS_PORT: Joi.number().default(6379), - REDIS_HOST: Joi.string().default('localhost'), - REDIS_PASSWORD: Joi.string().allow(''), - REDIS_PREFIX: Joi.string().default('bantr'), - REDIS_DB: Joi.number().default(0), - HOSTNAME: Joi.string().default('http://localhost:3000'), - BANTR_SENTRY_DSN: Joi.string().default(''), - BANTR_IS_TEST: Joi.boolean().default(false) - }); - - const { error, value: validatedEnvConfig } = envVarsSchema.validate( - envConfig, { allowUnknown: true } - ); - if (error) { - throw new Error(`Config validation error: ${error.message}`); - } - return validatedEnvConfig; - } - - /** - * Get a config value - * @param key - */ - get(key: string): string { - if (this.envConfig[key]) { - return this.envConfig[key]; - - } else { - throw new Error(`${key} was not found in configuration!`); - } - } -}