> ## Documentation Index
> Fetch the complete documentation index at: https://suvidhajs.is-cool.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Handlers

Suvidha handlers are essential for customizing request processing.
They handle validation, responses, and more.

All handlers receive a `Conn` object, which contains the following:

* `req`: An extended Express' `Request` object, which includes the `context`.
  property for accessing request-specific data added by middlewares.
* `res`: The standard Express `Response` object.

```ts theme={"system"}
/**
 * CtxRequest adds context to the Express' Request object
 * CtxRequest<Context, Params, ResBody, ReqBody, ReqQuery>,
 * Request<            Params, ResBody, ReqBody, ReqQuery>
 */
export type Conn<T extends Context, ...> = {
    req: CtxRequest<T, ...>;
    res: Response;
};
```

```ts theme={"system"}
class Suvidha {
    constructor(handlers: Handlers);
}
```

The `Suvidha` constructor takes any object that implements the `Handlers` interface, which is defined as follows:

```ts theme={"system"}
export interface Handlers {
    onErr(err: unknown, conn: Conn, next: NextFunction): Promise<void> | void;
    onSchemaErr(
        err: ZodError,
        conn: Conn,
        next: NextFunction,
    ): Promise<void> | void;
    onComplete(
        output: unknown,
        conn: Conn,
        next: NextFunction,
    ): Promise<void> | void;
    onPostResponse(
        outputOrErr: unknown,
        conn: Conn,
        next: NextFunction,
    ): Promise<void> | void;
}
```

## Understanding the Handlers

Here's a breakdown of each handler:

<AccordionGroup>
  <Accordion title="onSchemaErr" icon="code">
    ```ts theme={"system"}
    interface Handlers {
        onSchemaErr(
            err: ZodError,
            conn: Conn,
            next: NextFunction,
        ): Promise<void> | void;
        // ... other handlers
    }
    ```

    **Responsibilities:**

    * Handles Zod schema validation failures gracefully.
    * Typically sends an appropriate error response.
    * It can call `next(err)` to delegate error handling to Express' default error handler or other middleware.

    **Trigger Conditions:**

    * This is called when a Zod schema validation fails (e.g., when the request body, query parameters, or path parameters do not match the defined schema).

    **Arguments:**

    * `err`: The `ZodError` object containing details about the validation failure.
    * `conn`: The `Conn` object containing the request (`conn.req`) and response (`conn.res`) objects.
    * `next`: The Express' `next` function.

    Example implementation:

    ```ts theme={"system"}
    class CustomHandlers implements Handlers {
        onSchemaErr(err: ZodError, conn: Conn, next: NextFunction) {
            console.error("Schema validation failed:", err.errors); // Log the errors
            conn.res.status(400).json({ error: "Invalid request data" }); // Send a 400 response
        }

        // ... other handlers
    }
    ```
  </Accordion>

  <Accordion title="onErr" icon="code">
    ```ts theme={"system"}
    interface Handlers {
        onErr(err: unknown, conn: Conn, next: NextFunction): Promise<void> | void;
        // ... other handlers
    }
    ```

    **Responsibilities:**

    * Handle errors that occur *before* a response has been sent.
    * Can log the error, send an error response, or pass the error to Express's default error handler using `next(err)`.

    **Trigger Conditions:**

    * Called when an error is thrown during middleware or request handler execution *before* any part of the response has been sent (headers or body).

    **Arguments:**

    * `err`: This can be of any type, depending on what caused the error.
    * `conn`: The `Conn` object containing the request and response objects.
    * `next`: The Express `next` function.

    Example implementation:

    ```ts theme={"system"}
    class CustomHandlers implements Handlers {
        onErr(err: unknown, conn: Conn, next: NextFunction) {
            console.error("An error occurred:", err);
            conn.res.status(500).json({ error: "Internal server error" }); // Or call next(err)
        }

        // ... other handlers
    }
    ```
  </Accordion>

  <Accordion title="onComplete" icon="code">
    ```ts theme={"system"}
    interface Handlers {
        onComplete(
            output: unknown,
            conn: Conn,
            next: NextFunction,
        ): Promise<void> | void;
        // ... other handlers
    }
    ```

    **Responsibilities:**

    * Handles the successful completion of the request handler function when a response has not already been sent.
    * Typically send the successful response based on the `output` from the request handler.

    **Trigger Conditions:**

    * This is called when the request handler function executes successfully and no part of the response (headers or body) has been sent yet.

    **Arguments:**

    * `output`: The value returned by the request handler function. This can be of any type.
    * `conn`: The `Conn` object containing the request and response objects.
    * `next`: The Express `next` function. While available, it's typically not needed in `onComplete`.

    Example implementation:

    ```ts theme={"system"}
    class CustomHandlers implements Handlers {
        onComplete(output: unknown, conn: Conn, next: NextFunction) {
            conn.res.json(output); // Send the output as JSON
        }

        // ... other handlers
    }
    ```
  </Accordion>

  <Accordion title="onPostResponse" icon="code">
    ```ts theme={"system"}
    interface Handlers {
        onPostResponse(
            outputOrErr: unknown,
            conn: Conn,
            next: NextFunction,
        ): Promise<void> | void;
        // ... other handlers
    }
    ```

    **Responsibilities:**

    * Handles anything that happens after a response has been initiated (headers sent). This includes both errors and returned values.
    * Log errors that occur after the response has begun.
    * Handles the (usually unintentional) scenario where the request handler returns a value after sending a response.

    **Trigger Conditions:**

    <Note>
      Methods such as `res.send()` and `res.json()`, or any other method that
      sends headers or a body, are considered equivalent and indicate that the
      response has been initiated.
    </Note>

    * This is called when something happens after a response has started (headers sent).
      This can be:
      * Errors thrown by middleware *after* using `conn.res.send()`.
      * Errors thrown by the request handler *after* using `res.send()`.
      * The request handler returning a value *after* using `res.send()`. (This is primarily for bug detection).

    **Arguments:**

    * `outputOrErr`: Either the error object (if an error occurred) or the returned value from the request handler (if the request handler returned a value after sending the response). The type will be `unknown`.
    * `conn`: The `Conn` object containing the request and response objects.
    * `next`: The Express `next` function. While available, it's typically not needed in `onPostResponse`.

    It's important to note:

    * If the request handler throws an error *before* sending a response, `onErr` is called, *not* `onPostResponse`.
    * If middleware sends a response, the request handler will not be executed. Any errors thrown by the middleware *after* sending the response are caught by `onPostResponse`.

    Example implementation:

    ```ts theme={"system"}
    class CustomHandlers implements Handlers {
        onPostResponse(outputOrErr: unknown, conn: Conn, next: NextFunction) {
            if (outputOrErr instanceof Error) {
                // Check if it's an error
                console.error("Error after response:", outputOrErr);
                // Log the error or perform cleanup tasks.
            } else {
                console.warn(
                    "Request handler returned value after sending response:",
                    outputOrErr,
                );
                // This is usually a bug. Log it and possibly take corrective action.
            }
        }
        // ... other handlers
    }
    ```
  </Accordion>
</AccordionGroup>

**Example Implementation**

```ts theme={"system"}
class CustomHandlers implements Handlers {
    onSchemaErr(err: ZodError, conn: Conn, next: NextFunction) {
        console.error("Schema validation failed:", err.errors); // Log the errors
        conn.res.status(400).json({ error: "Invalid request data" }); // Send a 400 response
    }

    onErr(err: unknown, conn: Conn, next: NextFunction) {
        console.error("An error occurred:", err);
        conn.res.status(500).json({ error: "Internal server error" }); // Or call next(err)
    }

    onComplete(output: unknown, conn: Conn, next: NextFunction) {
        conn.res.json(output); // Send the output as JSON
    }

    onPostResponse(outputOrErr: unknown, conn: Conn, next: NextFunction) {
        if (outputOrErr instanceof Error) {
            // Check if it's an error
            console.error("Error after response:", outputOrErr);
            // You might not be able to send a *new* response here.
            // Log the error or perform cleanup tasks.
        } else {
            console.warn(
                "Request handler returned value after sending response:",
                outputOrErr,
            );
            // This is usually a bug. Log it and possibly take corrective action.
        }
    }
}

// Creating a Suvidha instance with custom handlers
const suvidha = () => new Suvidha(new CustomHandlers());

app.get(
    "/reports",
    suvidha().handler((req) => {
        // Business logic
    }),
);
```
