From 15bd2019b052f08633c6069dcbf659537f24c4b5 Mon Sep 17 00:00:00 2001 From: om-dev007 Date: Sun, 28 Jun 2026 23:03:55 +0530 Subject: [PATCH] refactor: centralize environment variable management and update usage across controllers and middleware --- backend/src/config/env.ts | 26 +++++++++++++++++++++++ backend/src/controllers/authController.ts | 7 +++--- backend/src/controllers/chatController.ts | 3 ++- backend/src/middleware/authMiddleware.ts | 3 ++- backend/src/scripts/migrate_users.ts | 3 ++- backend/src/server.ts | 10 +++------ 6 files changed, 39 insertions(+), 13 deletions(-) create mode 100644 backend/src/config/env.ts diff --git a/backend/src/config/env.ts b/backend/src/config/env.ts new file mode 100644 index 0000000..4c7c9f5 --- /dev/null +++ b/backend/src/config/env.ts @@ -0,0 +1,26 @@ +import dotenv from "dotenv"; +dotenv.config(); + +const requiredEnv = [ + "PORT", + "MONGO_URI", + "JWT_SECRET", + "GOOGLE_CLIENT_ID", + "CLIENT_URL", + "GEMINI_API_KEY" +] + +requiredEnv.forEach((key) => { + if(!process.env[key]) { + throw new Error(`Missing required environment variable: ${key}`); + } +}) + +export const config = { + PORT: process.env.PORT, + MONGO_URI: process.env.MONGO_URI, + JWT_SECRET: process.env.JWT_SECRET, + GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID, + CLIENT_URL: process.env.CLIENT_URL, + GEMINI_API_KEY: process.env.GEMINI_API_KEY +} \ No newline at end of file diff --git a/backend/src/controllers/authController.ts b/backend/src/controllers/authController.ts index c91b8d0..6097a4a 100644 --- a/backend/src/controllers/authController.ts +++ b/backend/src/controllers/authController.ts @@ -3,12 +3,13 @@ import jwt from 'jsonwebtoken'; import bcrypt from 'bcryptjs'; import { prisma } from '../config/db'; import { OAuth2Client } from 'google-auth-library'; +import { config } from '../config/env'; -const client = new OAuth2Client(process.env.GOOGLE_CLIENT_ID); +const client = new OAuth2Client(config.GOOGLE_CLIENT_ID); // Generate JWT const generateToken = (id: string) => { - return jwt.sign({ id }, process.env.JWT_SECRET!, { expiresIn: '30d' }); + return jwt.sign({ id }, config.JWT_SECRET!, { expiresIn: '30d' }); }; // @desc Register new user @@ -97,7 +98,7 @@ export const googleAuth = async (req: Request, res: Response) => { try { const ticket = await client.verifyIdToken({ idToken: token, - audience: process.env.GOOGLE_CLIENT_ID + audience: config.GOOGLE_CLIENT_ID }); const payload = ticket.getPayload(); diff --git a/backend/src/controllers/chatController.ts b/backend/src/controllers/chatController.ts index 01f28d2..20c4d4e 100644 --- a/backend/src/controllers/chatController.ts +++ b/backend/src/controllers/chatController.ts @@ -1,6 +1,7 @@ import { Request, Response } from 'express'; import { GoogleGenerativeAI } from '@google/generative-ai'; import { prisma } from '../config/db'; +import { config } from '../config/env'; const SYSTEM_PROMPT = `You are AlgoBot, a friendly and expert AI tutor for Data Structures & Algorithms on the AlgoForge platform. @@ -24,7 +25,7 @@ export const chat = async (req: Request, res: Response) => { return res.status(400).json({ error: 'Message is required' }); } - const apiKey = process.env.GEMINI_API_KEY; + const apiKey = config.GEMINI_API_KEY; if (!apiKey) { return res.status(500).json({ error: 'Gemini API key not configured' }); } diff --git a/backend/src/middleware/authMiddleware.ts b/backend/src/middleware/authMiddleware.ts index 90c0ffc..b457d17 100644 --- a/backend/src/middleware/authMiddleware.ts +++ b/backend/src/middleware/authMiddleware.ts @@ -1,6 +1,7 @@ import { Request, Response, NextFunction } from 'express'; import jwt from 'jsonwebtoken'; import { prisma } from '../config/db'; +import { config } from '../config/env'; interface JwtPayload { id: string; @@ -24,7 +25,7 @@ const protect = async (req: Request, res: Response, next: NextFunction) => { try { token = req.headers.authorization.split(' ')[1]; - const decoded = jwt.verify(token, process.env.JWT_SECRET!) as JwtPayload; + const decoded = jwt.verify(token, config.JWT_SECRET!) as JwtPayload; const user = await prisma.user.findUnique({ where: { id: decoded.id }, diff --git a/backend/src/scripts/migrate_users.ts b/backend/src/scripts/migrate_users.ts index c541ca3..1fbe3d2 100644 --- a/backend/src/scripts/migrate_users.ts +++ b/backend/src/scripts/migrate_users.ts @@ -1,10 +1,11 @@ import { PrismaClient } from '@prisma/client'; import dotenv from 'dotenv'; import path from 'path'; +import { config } from '../config/env'; dotenv.config({ path: path.join(__dirname, '../../.env') }); -const uri = process.env.MONGO_URI as string; +const uri = config.MONGO_URI as string; async function migrate() { console.log("Starting migration using Prisma engine to bypass DNS issues..."); diff --git a/backend/src/server.ts b/backend/src/server.ts index 5c16df5..d1a7c01 100644 --- a/backend/src/server.ts +++ b/backend/src/server.ts @@ -4,14 +4,10 @@ import cors from 'cors'; import connectDB from './config/db'; dotenv.config(); - -// server.ts — add before app.listen() -if (!process.env.JWT_SECRET) { - throw new Error('FATAL: JWT_SECRET environment variable is not set.'); -} +import { config } from './config/env'; const app: Express = express(); -const port = process.env.PORT || 5000; +const port = config.PORT || 5000; // Middleware const allowedOrigins = [ @@ -19,7 +15,7 @@ const allowedOrigins = [ 'https://algoforge-2-0.onrender.com', 'http://localhost:5173', 'http://localhost:3000', - process.env.CLIENT_URL, + config.CLIENT_URL, ].filter(Boolean) as string[]; app.use(cors({