feat: stabilize API startup and lifecycle management
- Refactor server initialization to separate concerns and improve error handling. - Implement centralized environment validation using Zod. - Introduce database, Redis, and queue lifecycle management. - Add health check endpoints for liveness and readiness. - Enhance error handling middleware for better response structure. - Implement rate limiting for API endpoints. - Add request ID middleware for traceability. - Create Sequelize CLI configuration and baseline migration for schema management. - Establish CI workflow with Gitea for testing and syntax checks. - Document foundational changes and migration strategy in PHASE_0_FOUNDATION_STABILIZATION.md. - Add Docker Compose configuration for local development and testing. - Implement unit and integration tests for critical functionality.
This commit is contained in:
+10
-6
@@ -12,19 +12,23 @@
|
||||
const jwt = require("jsonwebtoken");
|
||||
require("dotenv").config();
|
||||
|
||||
const JWT_SECRET = process.env.JWT_SECRET || "your_jwt_secret_key";
|
||||
const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || "15m"; // token validity
|
||||
|
||||
const REFRESH_TOKEN_SECRET = process.env.REFRESH_TOKEN_SECRET || "your_refresh_token_secret_key";
|
||||
const REFRESH_TOKEN_DAYS = process.env.REFRESH_TOKEN_DAYS || "7d"; // refresh token validity
|
||||
|
||||
const getSecret = (name) => {
|
||||
const value = process.env[name];
|
||||
if (!value || value.length < 32) throw new Error(`${name} is not configured securely`);
|
||||
return value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate JWT token
|
||||
* @param {Object} payload - usually { id, email, role }
|
||||
* @returns string
|
||||
*/
|
||||
const generateToken = (payload) => {
|
||||
return jwt.sign(payload, JWT_SECRET, { expiresIn: JWT_EXPIRES_IN });
|
||||
return jwt.sign(payload, getSecret("JWT_SECRET"), { expiresIn: JWT_EXPIRES_IN });
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -33,15 +37,15 @@ const generateToken = (payload) => {
|
||||
* @returns payload or throws error
|
||||
*/
|
||||
const verifyToken = (token) => {
|
||||
return jwt.verify(token, JWT_SECRET);
|
||||
return jwt.verify(token, getSecret("JWT_SECRET"));
|
||||
};
|
||||
|
||||
const generateRefreshToken = (payload) => {
|
||||
return jwt.sign(payload, REFRESH_TOKEN_SECRET, { expiresIn: REFRESH_TOKEN_DAYS });
|
||||
return jwt.sign(payload, getSecret("REFRESH_TOKEN_SECRET"), { expiresIn: REFRESH_TOKEN_DAYS });
|
||||
}
|
||||
|
||||
const verifyRefreshToken = (token) => {
|
||||
return jwt.verify(token, REFRESH_TOKEN_SECRET);
|
||||
return jwt.verify(token, getSecret("REFRESH_TOKEN_SECRET"));
|
||||
}
|
||||
|
||||
module.exports = { generateToken, verifyToken, generateRefreshToken, verifyRefreshToken };
|
||||
|
||||
@@ -23,10 +23,12 @@ const transporter = nodemailer.createTransport({
|
||||
auth: mailConfig.auth,
|
||||
});
|
||||
|
||||
transporter.verify((err) => {
|
||||
if (err) console.error("Mail server connection failed", err);
|
||||
else console.log("Mail server ready");
|
||||
});
|
||||
if (process.env.NODE_ENV !== "test" && process.env.ENABLE_MAIL === "true") {
|
||||
transporter.verify((err) => {
|
||||
if (err) console.error("Mail server connection failed", { message: err.message });
|
||||
else console.log("Mail server ready");
|
||||
});
|
||||
}
|
||||
|
||||
// Utility to load template and replace placeholders
|
||||
const loadTemplate = (templateName, variables = {}) => {
|
||||
@@ -42,6 +44,9 @@ const loadTemplate = (templateName, variables = {}) => {
|
||||
};
|
||||
|
||||
const send = async ({ to, subject, templateName, templateVars = {}, text }) => {
|
||||
if (process.env.ENABLE_MAIL !== "true") {
|
||||
throw new Error("Email functionality is not enabled");
|
||||
}
|
||||
const html = templateName ? loadTemplate(templateName, templateVars) : undefined;
|
||||
|
||||
const mailOptions = {
|
||||
|
||||
@@ -15,8 +15,7 @@ const { getSignedUrl } = require("@aws-sdk/s3-request-presigner");
|
||||
const s3 = require("../config/s3.config");
|
||||
const { v4: uuidv4 } = require("uuid");
|
||||
const path = require("path");
|
||||
const createRedisConnection = require("../config/redis.config");
|
||||
const redis = createRedisConnection();
|
||||
const redis = require("../config/redisClient");
|
||||
const { log } = require("./consoleLog.utill");
|
||||
|
||||
// Upload + return key (BEST PRACTICE)
|
||||
|
||||
Reference in New Issue
Block a user