@oriun/next-api
Version:
Next.js API routes with Zod validation
90 lines (89 loc) • 2.94 kB
JavaScript
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;
}