Skip to content

Instantly share code, notes, and snippets.

@melbourne2991
Last active June 6, 2021 06:51

Revisions

  1. melbourne2991 renamed this gist Jun 6, 2021. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  2. melbourne2991 created this gist Jun 6, 2021.
    63 changes: 63 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,63 @@
    import { NextApiRequest, NextApiResponse } from "next";
    import { StatusCodes, getReasonPhrase } from "http-status-codes";

    type NextHandler<R> = (req: NextApiRequest, res: NextApiResponse<R>) => void;

    type ResponseEnhanced<R> = {
    status?: StatusCodes | number;
    headers?: Record<string, string>;
    body?: R;
    };

    export type TypedNextApiRequest<Q> = Omit<NextApiRequest, "query"> & {
    query: Q;
    };

    type HandlerParam<R, Q> = (
    req: TypedNextApiRequest<Q>
    ) => Promise<ResponseEnhanced<R>>;

    type Method = "post" | "get" | "delete" | "patch" | "put";

    function makeHandler(method?: Method) {
    return <Q, R>(inner: HandlerParam<R, Q>): NextHandler<R> => {
    return (req: NextApiRequest, res: NextApiResponse) => {
    if (method && req.method?.toLowerCase() !== method) {
    return res.status(StatusCodes.METHOD_NOT_ALLOWED).send({
    error: getReasonPhrase(StatusCodes.METHOD_NOT_ALLOWED),
    });
    }

    return inner(req as NextApiRequest & { query: Q })
    .then((_res) => {
    const status = _res.status || StatusCodes.OK;
    const headers = _res.headers || {};

    Object.keys(headers).forEach((key) =>
    res.setHeader(key, headers[key])
    );

    res.status(status).send(_res.body || "");
    })
    .catch((err) => {
    console.log(`Uncaught error: ${err}`);

    res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
    error: getReasonPhrase(StatusCodes.INTERNAL_SERVER_ERROR),
    });
    });
    };
    };
    }

    const _defaultHandler = makeHandler();

    export function handler<Q, R>(inner: HandlerParam<R, Q>) {
    return _defaultHandler<Q, R>(inner);
    }

    handler.get = makeHandler("get");
    handler.post = makeHandler("post");
    handler.delete = makeHandler("delete");
    handler.put = makeHandler("get");
    handler.patch = makeHandler("get");