A library for simple API routing in Next.js while leveraging valibot and Typescript to create typesafe routes and middlewares with built in validation.
I wanted to create type-safe APIs in Next.js using valibot and also wanted to generate type definition files for client-side use so that I could use intuitive API calls. This library is easier to use than tRPC, which is a great library, but it is difficult to use for beginners.
## npm
npm install next-valibot-api
## yarn
yarn add next-valibot-api
// pages/api/sample.ts
import { ApiHandler, createRouter } from "next-valibot-api";
import { validate } from "next-valibot-api/validation";
import { object, string, optional } from "valibot";
/* Schema definition using valibot */
const postValidation = {
body: object({
foo: string(),
}),
query: object({
bar: optional(string()),
}),
res: object({
message: string(),
}),
};
const getValidation = {
query: object({
bar: optional(string()),
}),
res: object({
message: string(),
}),
};
/* Routing */
const router = createRouter();
router
.use((ctx) => {
console.log("middleware");
return ctx.next();
})
.post(validate(postValidation), (ctx) => {
ctx.body.foo;
ctx.query.bar;
ctx.json({ message: "ok" });
})
.get(validate(getValidation), (ctx) => {
ctx.query.bar;
ctx.json({ message: "ok" });
});
/* Type export */
// the export type name should be as follows
// so that the type definition file can be generated correctly via the command.
export type PostHandler = ApiHandler<typeof postValidation>;
export type GetHandler = ApiHandler<typeof getValidation>;
/* Routing handling export */
export const GET = router.run();
export const POST = router.run();
// pages/api/[id].ts
const getValidation = {
// 👇 for server side validation
// 👇 also necessary for client side url construction
query: object({
id: string().optional(),
}),
};
router.get(validate(getValidation), (ctx) => {
ctx.query.id;
ctx.json({ message: "ok" });
});
// client.ts
import { client } from "next-valibot-api";
client.get("/api/[id]", {
query: {
id: "1",
},
});
// url will be /api/1
// pages/api/sample.ts
router.post(validate(postValidation), (ctx) => {
const session = getSession(ctx);
if (!session) {
throw createError(401, "Unauthorized");
}
ctx.json({ message: "ok" });
});
// pages/api/sample.ts
router.onError((err) => {
// custom error handling
res.status(err.statusCode).json({ message: err.message });
});
You have to use the plugin to generate the type definition file.
next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {};
const withValibotApi = require("next-valibot-api/plugin")(/* options */);
module.exports = withValibotApi(nextConfig);
The default pages directory is app
, so if you want to change it, you can use the --appDir
option.
Option | Description | Default value |
---|---|---|
appDir | app directory path | app |
baseDir | Project directory | . |
distDir | Type definition file output destination | node_modules/.next-valibot-api |
moduleNameSpace | Type definition file module name | .next-valibot-api |