[update] - latest code

This commit is contained in:
Swapnil Bendal
2024-12-10 17:13:27 +05:30
parent 70ed1e2782
commit ca6d4551ca
16 changed files with 3999 additions and 434 deletions

View File

@@ -1,61 +1,73 @@
import { Request, Response, NextFunction } from 'express';
import ApiError from '../utils/helper/ApiError';
import config from '../config/config';
import logger from '../config/logger';
// Middleware to convert different error types to ApiError
export const errorConverter = (
err: any, // Use a broad type to handle various error types
req: Request,
res: Response,
next: NextFunction
): void => {
let error = err;
class error {
static errorConverter(
err: any,
req: Request,
res: Response,
next: NextFunction
): void {
let error = err;
if (!(err instanceof ApiError)) {
// Handle all other errors
const statusCode =
err.statusCode
? 400
: 500;
const message = err.message || "Internal Server Error";
error = new ApiError(statusCode, message, [err.message], false, err.stack);
// Handle Sequelize validation and unique constraint errors
const messages = error.errors.map((e: Error) => e.message);
error = new ApiError(
400,
messages.join(', '),
messages,
true,
err.stack
);
if (!(error instanceof ApiError)) {
// Handle other errors
const statusCode =
error.statusCode
? 400
: 500;
const message = error.message || "Something went wrong";
error = new ApiError(statusCode, message, error, false, err.stack);
}
next(error);
}
next(error);
};
static errorHandler(
err: any,
req: Request,
res: Response,
next: NextFunction
): void {
let { statusCode, message } = err;
// Middleware to handle errors and send responses
export const errorHandler = (
err: ApiError,
req: Request,
res: Response,
next: NextFunction
): void => {
// Determine the status code and message
let { statusCode, message } = err;
// Production environment: Ensure only operational errors are shown
if (config.env === 'production' && !err.isOperational) {
statusCode = 500;
message = "Internal server error";
}
if (config.env === 'production' && !err.isOperational) {
// Hide sensitive error details in production
statusCode = 500;
message = "Internal Server Error" as string;
res.locals.errorMessage = err.message;
// Response structure
const response = {
code: statusCode,
message,
...(config.env === 'development' && { stack: err.stack })
};
// Log error in development
if (config.env === 'development') {
logger.error(err);
}
// Ensure the response is sent
res.status(statusCode).send(response);
// Don't call next() unless you want to propagate the error further
// If this is the final middleware, remove next()
}
}
// Attach the error message to response locals for debugging
res.locals.errorMessage = err.message;
// Construct the response object
const response = {
code: statusCode,
message,
...(config.env === 'development' && { stack: err.stack }), // Include stack trace in development
};
// Log the error in development mode
if (config.env === 'development') {
console.error(err.stack || err.message);
}
// Send the error response
res.status(statusCode).json(response);
};
export default error;

View File

@@ -0,0 +1,45 @@
import { pick } from '../utils/handler/pick.handler';
import { Request, Response, NextFunction } from 'express';
import * as Yup from 'yup';
import ApiError from '../utils/helper/ApiError';
/**
* Validation middleware for Express routes.
* @param schema - Validation schema object (Yup schema for request parts like params, query, body, etc.).
* @returns Middleware function to validate request properties.
*/
const validate =
(schema: Partial<Record<keyof Request, Yup.ObjectSchema<any>>>) =>
(req: Request, res: Response, next: NextFunction): void => {
// Define valid request keys explicitly
const validRequestKeys = ['params', 'query', 'body', 'file', 'files'] as (keyof Request)[];
// Extract the schemas for valid parts of the request
const validSchema = pick(schema, validRequestKeys);
// Extract the corresponding request properties
const object = pick(req, Object.keys(validSchema) as (keyof Request)[]);
// Validate each part of the request
const promises = Object.keys(validSchema).map((key) =>
validSchema[key as keyof Request]?.validate(object[key as keyof Request], { abortEarly: false })
);
// Process validation results
Promise.all(promises)
.then((validatedValues) => {
// Assign validated values back to the request object
validatedValues.forEach((value, index) => {
const key = Object.keys(validSchema)[index];
(req as any)[key] = value; // Type assertion since req is mutable
});
next();
})
.catch((err: Yup.ValidationError) => {
// Collect and format error messages
const errorMessage = err.inner.map((detail) => detail.message).join(', ');
next(new ApiError(400, errorMessage));
});
};
export default validate;