/**
* Async Handler Wrapper - Eliminates try-catch boilerplate
*
* Wraps async route handlers to automatically catch promise rejections
* and forward them to Express error handling middleware.
*/
import type { NextFunction, Request, RequestHandler, Response } from "express";
/**
* Async route handler function type
*
* Standard Express handler signature but returns a Promise.
* Used by asyncHandler to wrap async route handlers.
*/
export type AsyncRouteHandler = (req: Request, res: Response, next: NextFunction) => Promise<void>;
/**
* Wraps async route handlers to catch promise rejections
*
* Eliminates the need for try-catch blocks in every async route handler.
* Any promise rejection is automatically caught and forwarded to the
* Express error handling middleware via next(error).
*
* Uses Promise.resolve() to handle both async functions and functions
* that return promises, ensuring all rejections are caught.
*
* @param handler - Async route handler function to wrap
* @returns Wrapped Express RequestHandler that catches errors
*
* @example
* ```typescript
* // Without asyncHandler (verbose):
* app.get("/data", async (req, res, next) => {
* try {
* const data = await fetchData();
* res.json(data);
* } catch (error) {
* next(error);
* }
* });
*
* // With asyncHandler (clean):
* app.get("/data", asyncHandler(async (req, res) => {
* const data = await fetchData(); // Errors automatically caught
* res.json(data);
* }));
* ```
*
* @example
* ```typescript
* // Works with any async operation:
* app.post("/users", asyncHandler(async (req, res) => {
* const user = await createUser(req.body);
* res.status(201).json(user);
* }));
*
* app.delete("/users/:id", asyncHandler(async (req, res) => {
* await deleteUser(req.params.id);
* res.status(204).send();
* }));
* ```
*/
export function asyncHandler(handler: AsyncRouteHandler): RequestHandler {
return (req: Request, res: Response, next: NextFunction): void => {
Promise.resolve(handler(req, res, next)).catch(next);
};
}