Skip to content

Next.js serverless CRUD

1 serverless function, multiple requests

Naive implementation, need to revisit. No e2e type safety. I would probably use next-connect.
TypeScript
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

TypeScript
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,
};