steelydylan/next-zod-router(新しいタブで開きます)
主要言語: TypeScript
Zod driven simple method routing for Next.js
- star 数
- 41
- watcher 数
- 1
- fork 数
- 2
- issue 数
- 0
- 最終更新
- 2024/07/19
主要言語: TypeScript
Zod driven simple method routing for Next.js
A library for simple API routing in Next.js while leveraging Zod and Typescript to create typesafe routes and middlewares with built in validation.
I wanted to create type-safe APIs in Next.js using zod and also wanted to generate type definition files for client-side use so that I could use intuitive API calls. But I couldn't find a library that met my needs, so I created this library.
## npm npm install next-zod-router ## yarn yarn add next-zod-router
// pages/api/sample.ts import { ApiHandler, createRouter, validate } from "next-zod-router"; import { z } from "zod"; /* Schema definition using zod */ const postValidation = { body: z.object({ foo: z.string(), }), query: z.object({ bar: z.string().optional(), }), res: z.object({ message: z.string(), }), } const getValidation = { query: z.object({ bar: z.string().optional(), }), res: z.object({ message: z.string(), }), } /* Routing */ const router = createRouter() router .use((req, res, next) => { console.log("middleware"); return next() }) .post( validate(postValidation), (req, res) => { req.body.foo; req.query.bar; res.status(200).json({ message: "ok" }); }) .get( validate(getValidation), (req, res) => { req.query.bar; res.status(200).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 default router.run()
## npm npx next-zod-router ## yarn yarn next-zod-router
Adding a script to your package.json is convenient.
{
"scripts": {
"apigen": "next-zod-router"
}
}npm run apigen
import { client } from "next-zod-router"; // Type-safe API call const { data, error } = await client.post("/api/sample", { query: { bar: "baz", }, body: { foo: "bar", }, })
// pages/api/[id].ts const getValidation = { // 👇 for server side validation // 👇 also necessary for client side url construction query: z.object({ id: z.string().optional(), }), } router .get( validate(getValidation), (req, res) => { req.query.id; res.status(200).json({ message: "ok" }); })
// client.ts import { client } from "next-zod-router"; client.get("/api/[id]", { query: { id: "1", }, }) // url will be /api/1
// pages/api/sample.ts router .post( validate(postValidation), (req, res) => { const session = getSession(req) if (!session) { throw createError(401, "Unauthorized") } res.status(200).json({ message: "ok" }); })
// pages/api/sample.ts router .onError((err, req, res) => { // custom error handling res.status(err.statusCode).json({ message: err.message }); })
express-like middleware is supported.
// pages/api/sample.ts import cors from "cors"; import { createRouter, validate } from "next-zod-router"; import { z } from "zod"; const postValidation = { res: z.object({ message: z.string(), }), } router .use(cors()) .post( validate(postValidation), (req, res) => { res.status(200).json({ message: "ok" }); })
The default pages directory is pages, so if you want to change it, you can use the --pagesDir option.
next-zod-router --pagesDir=src/pages
| Option | Description | Default value |
|---|---|---|
| --pagesDir | Pages directory | pages |
| --baseDir | Project directory | . |
| --distDir | Type definition file output destination | node_modules/.next-zod-router |
| --moduleNameSpace | Type definition file module name | .next-zod-router |
| --watch | Watch mode | false |
If you want to add session property to Request type, you can use the following code.
// global.d.ts import { IncomingMessage } from "http"; declare module 'next' { export interface NextApiRequest extends IncomingMessage { session: Session } }
When developing with Next.js, you can use the following code to generate type definition files automatically.
{
"scripts": {
"dev": "npm-run-all -p dev:*",
"dev:next": "next dev",
"dev:apigen": "next-zod-router -w"
}
}