Skip to content

Instantly share code, notes, and snippets.

@caferrari
Last active January 25, 2023 17:45
Show Gist options
  • Save caferrari/97ddde2dbf51a4d7065021f04a067a28 to your computer and use it in GitHub Desktop.
Save caferrari/97ddde2dbf51a4d7065021f04a067a28 to your computer and use it in GitHub Desktop.
Nice Router
import { Request, Response, NextFunction, Router } from 'express';
import { Schema } from 'zod';
type tParams<B = unknown, P = unknown, Q = unknown> = {
body?: Schema<B>;
params?: Schema<P>;
query?: Schema<Q>;
};
type callbackFn<B, P, Q> = (req: Request<P, any, B, Q>, res: Response, next: NextFunction) => Promise<void>;
type postParams<B, P> = Pick<tParams<B, P, never>, 'params' | 'body'>;
type putParams<B, P> = Pick<tParams<B, P, never>, 'params' | 'body'>;
type getParams<P, Q> = Pick<tParams<never, P, Q>, 'params' | 'query'>;
type deleteParams<P, Q> = Pick<tParams<never, P, Q>, 'params' | 'query'>;
const validateParams = <B, P, Q>(params: tParams, callback: callbackFn<B, P, Q>) => {
return async (req: Request, res: Response, next: NextFunction) => {
const queryResults: any = params.query?.safeParse(req?.query);
const bodyResults: any = params.body?.safeParse(req?.body);
const paramResults: any = params.params?.safeParse(req?.params);
const errors = queryResults?.error ?? bodyResults?.error ?? paramResults?.error ?? undefined;
if (errors) {
return res.status(400).json({ errors });
}
try {
await callback(req as any, res, next);
} catch (err) {
next(err);
}
};
};
export const NiceRouter = () => {
const router = Router();
return {
get: <P, Q>(path: string, params: getParams<P, Q>, callback: callbackFn<never, P, Q>) => {
router.get(path, validateParams(params, callback));
},
post: <B, P>(path: string, params: postParams<B, P>, callback: callbackFn<B, P, never>) => {
router.post(path, validateParams(params, callback));
},
put: <B, P>(path: string, params: putParams<B, P>, callback: callbackFn<B, P, never>) => {
router.put(path, validateParams(params, callback));
},
delete: <P, Q>(path: string, params: deleteParams<P, Q>, callback: callbackFn<never, P, Q>) => {
router.get(path, validateParams(params, callback));
},
toExpress: () => router as Router,
};
};
import { z } from 'zod';
import { JWT_SECRET } from '../../config';
import { NiceRouter } from '../../infra/handler';
const router = NiceRouter();
router.post(
'/login',
{
body: z.object({
token: z.string()
}),
},
async (req, res) => {
res.json(req.body);
}
);
export const authRouter = router.toExpress();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment