Naive implementation, need to revisit. No e2e type safety. I would probably use next-connect.
createHandlers.ts
import type {NextApiRequest, NextApiResponse} from 'next';
type Handlers = {
GET?: (req: NextApiRequest, res: NextApiResponse) => Promise<unknown>;
POST?: (req: NextApiRequest, res: NextApiResponse) => Promise<unknown>;
PATCH?: (req: NextApiRequest, res: NextApiResponse) => Promise<unknown>;
DELETE?: (req: NextApiRequest, res: NextApiResponse) => Promise<unknown>;
};
export function createHandlers(handlers: Handlers) {
return async (req: NextApiRequest, res: NextApiResponse): Promise<void> => {
if (req.method && req.method in handlers) {
const handler = handlers[req.method];
try {
await handler(req, res);
} catch (err) {
res.status(err.status || 500).end(err.message);
}
} else {
res.setHeader('Allow', Object.keys(handlers));
res.status(405).end(`Method ${req.method} Not Allowed`);
}
};
}
Usage
pages/api/teams/[teamId]/teammates.ts
import type {NextApiRequest, NextApiResponse} from 'next';
import {deleteTeammate} from '@/api/services/teammate-delete';
import {getTeammate} from '@/api/services/teammate-get';
import {patchTeammate} from '@/api/services/teammate-patch';
import {createHandlers} from '@/utils/rest';
export default function teammate(
req: NextApiRequest,
res: NextApiResponse
): Promise<unknown> {
const handler = createHandlers(handlers);
return handler(req, res);
}
const handlers = {
GET: getTeammate,
PATCH: patchTeammate,
DELETE: deleteTeammate,
};