UNPKG

@oriun/next-api

Version:

Next.js API routes with Zod validation

90 lines (89 loc) 2.94 kB
const CONTENT_TYPE = "content-type"; const JSON_MIME = "application/json"; const FORM_DATA_MIME = "multipart/form-data"; const BAD_REQUEST = 400; const BODYLESS_METHODS = ["GET", "HEAD", "OPTIONS"]; export async function bodyParser(req, schema) { const request = req.clone(); const contentType = request.headers.get(CONTENT_TYPE); const isFormData = contentType?.startsWith(FORM_DATA_MIME); if (isFormData) return request.formData(); const bodyFormat = contentType?.startsWith(JSON_MIME) ? "json" : "text"; const shouldHaveBody = !BODYLESS_METHODS.includes(request.method); const body = await request[bodyFormat]() .catch(() => { if (!shouldHaveBody) return bodyFormat === "json" ? {} : ""; throw new Response("Invalid body", { status: BAD_REQUEST, }); }); if (schema) { const parsedBody = schema.safeParse(body); if (!parsedBody.success) throw new Response(JSON.stringify(parsedBody.error), { status: BAD_REQUEST, headers: { CONTENT_TYPE: JSON_MIME } }); return parsedBody.data; } return body; } export function queryParser(request, schema) { const searchParams = new URL(request.url).searchParams; const query = Object.fromEntries(searchParams); for (const [key] of Object.entries(query)) { if (key.startsWith("nxtP")) { delete query[key]; } } if (schema) { const parsedQuery = schema.safeParse(query); if (!parsedQuery.success) throw new Response(JSON.stringify(parsedQuery.error), { status: BAD_REQUEST, headers: { CONTENT_TYPE: JSON_MIME } }); return parsedQuery.data; } return query; } export function paramsParser(variables, schema) { let params = variables?.params ?? {}; if (schema) { const parsedParams = schema.safeParse(params); if (!parsedParams.success) throw new Response(JSON.stringify(parsedParams.error), { status: BAD_REQUEST, headers: { CONTENT_TYPE: JSON_MIME } }); return parsedParams.data; } return params; } export function cookiesParser(request, schema) { const cookies = {}; // @ts-ignore for (const [, { name, value }] of request.cookies._parsed) { cookies[name] = value; } if (schema) { const parsedCookies = schema.safeParse(cookies); if (!parsedCookies.success) throw new Response(JSON.stringify(parsedCookies.error), { status: BAD_REQUEST, headers: { CONTENT_TYPE: JSON_MIME } }); return parsedCookies.data; } return cookies; }