nuxt-apex
Version:
Auto-generates fully typed useFetch composables for Nuxt 3/4 server endpoints with Zod validation and zero boilerplate
49 lines (48 loc) • 1.65 kB
JavaScript
import { isError, createError, defineEventHandler, readBody, getRouterParams, getQuery } from "h3";
import { z } from "zod";
import { useEvent } from "nitropack/runtime";
export function defineApexHandler(handler, validator) {
return defineEventHandler(async (event) => {
let shape;
let parsed;
try {
const raw = await useData();
if (validator) {
shape = typeof validator === "function" ? validator(z, raw) : validator;
const schema = shape ? z.object(validator) : null;
const parsed2 = schema?.safeParse(raw);
if (!parsed2?.success) {
throw createError({
statusCode: 422,
message: JSON.stringify(parsed2?.error.flatten().fieldErrors)
});
}
}
return await handler(parsed?.data || raw, event);
} catch (error) {
console.error(error);
if (isError(error)) throw error;
throw createError({ message: error.message, statusCode: error.statusCode || 500 });
}
});
}
export async function useData() {
const e = useEvent();
const hasBody = ["POST", "PUT", "PATCH"].includes(e.method.toUpperCase());
const bodyInfo = hasBody ? await readBody(e) ?? {} : {};
const paramsInfo = getRouterParams(e) ?? {};
const queryInfo = getQuery(e) ?? {};
return mergeSources(bodyInfo, paramsInfo, queryInfo);
}
function mergeSources(...sources) {
const result = {};
for (const src of sources) {
for (const key of Object.keys(src)) {
if (key in result) {
throw createError({ statusCode: 500, message: `Duplicate key "${key}"` });
}
result[key] = src[key];
}
}
return result;
}