From 171394d9500562beb519859d3d2901e96db5e0fc Mon Sep 17 00:00:00 2001 From: Glemen Neo Date: Sat, 21 Sep 2024 01:25:02 +0800 Subject: [PATCH] [#12] feat: add env validation --- .../user-service/src/common/config.util.ts | 13 +++++ backend/user-service/src/server.ts | 14 ++---- backend/user-service/src/types/Config.ts | 48 +++++++++++++++++++ 3 files changed, 65 insertions(+), 10 deletions(-) create mode 100644 backend/user-service/src/common/config.util.ts create mode 100644 backend/user-service/src/types/Config.ts diff --git a/backend/user-service/src/common/config.util.ts b/backend/user-service/src/common/config.util.ts new file mode 100644 index 0000000000..76059ccb35 --- /dev/null +++ b/backend/user-service/src/common/config.util.ts @@ -0,0 +1,13 @@ +import { ValidationError } from 'class-validator' +import { Config } from '../types/Config' +import logger from './logger.util' + +const config: Config = Config.fromEnv(process.env) +config.validateOrReject().catch((errors: ValidationError[]) => { + logger.error( + `[Config] Invalid or missing configuration: ${errors.map((error: ValidationError) => error.property).join(', ')}` + ) + process.exit(1) +}) + +export default config diff --git a/backend/user-service/src/server.ts b/backend/user-service/src/server.ts index b900ae4115..65b2b1b4ba 100644 --- a/backend/user-service/src/server.ts +++ b/backend/user-service/src/server.ts @@ -1,19 +1,13 @@ import 'dotenv/config' import http, { Server } from 'http' +import config from './common/config.util' import logger from './common/logger.util' import connectToDatabase from './common/mongodb.util' import index from './index' -const port: string = process.env.PORT ?? '3000' const server: Server = http.createServer(index) -server.listen(port, async () => { - logger.info(`[Init] Server is listening on port ${port}`) +server.listen(config.PORT, async () => { + logger.info(`[Init] Server is listening on port ${config.PORT}`) }) -const connectionString: string | undefined = process.env.DB_URL -if (!connectionString) { - logger.error(`[Init] DB_URL is not set`) - process.exit(1) -} - -connectToDatabase(connectionString) +connectToDatabase(config.DB_URL) diff --git a/backend/user-service/src/types/Config.ts b/backend/user-service/src/types/Config.ts new file mode 100644 index 0000000000..d70f825259 --- /dev/null +++ b/backend/user-service/src/types/Config.ts @@ -0,0 +1,48 @@ +import { IsBase64, IsEnum, IsNotEmpty, IsNumberString, IsString, validateOrReject } from 'class-validator' + +export class Config { + @IsEnum(['development', 'production', 'test']) + NODE_ENV: string + + @IsNumberString() + @IsNotEmpty() + PORT: string + + @IsString() + @IsNotEmpty() + DB_URL: string + + @IsBase64() + ACCESS_TOKEN_PRIVATE_KEY: string + + @IsBase64() + ACCESS_TOKEN_PUBLIC_KEY: string + + constructor( + NODE_ENV: string, + PORT: string, + DB_URL: string, + ACCESS_TOKEN_PRIVATE_KEY: string, + ACCESS_TOKEN_PUBLIC_KEY: string + ) { + this.NODE_ENV = NODE_ENV ?? 'development' + this.PORT = PORT ?? '3002' + this.DB_URL = DB_URL + this.ACCESS_TOKEN_PRIVATE_KEY = ACCESS_TOKEN_PRIVATE_KEY + this.ACCESS_TOKEN_PUBLIC_KEY = ACCESS_TOKEN_PUBLIC_KEY + } + + static fromEnv(env: { [key: string]: string | undefined }): Config { + return new Config( + env.NODE_ENV!, + env.PORT!, + env.DB_URL!, + env.ACCESS_TOKEN_PRIVATE_KEY!, + env.ACCESS_TOKEN_PUBLIC_KEY! + ) + } + + async validateOrReject(): Promise { + await validateOrReject(this) + } +}