Next.js Server Adapter
The @zenstackhq/server/next module provides a quick way to install a full set of CRUD API onto Next.js apps. Combined with ZenStack's powerful access policies, you can achieve a secure data backend without manually coding it.
The server adapter supports both the traditional "pages" router and the new "app" router.
Installation​
- npm
- pnpm
- bun
- yarn
npm install @zenstackhq/server@next
pnpm add @zenstackhq/server@next
bun add @zenstackhq/server@next
yarn add @zenstackhq/server@next
Mounting the API​
You can use it to create a request handler in an API endpoint like:
- App Router
- Pages Router
import type { NextRequest } from "next/server";
import { NextRequestHandler } from '@zenstackhq/server/next';
import { RPCApiHandler } from '@zenstackhq/server/api';
import { getSessionUser } from '~/auth';
import { client } from '~/db';
import { schema } from '~/zenstack/schema';
const handler = NextRequestHandler({
apiHandler: new RPCApiHandler({ schema }),
// getSessionUser extracts the current session user from the request, its
// implementation depends on your auth solution
getClient: (req: NextRequest) => client.$setAuth(getSessionUser(req)),
useAppDir: true });
export {
handler as GET,
handler as POST,
handler as PUT,
handler as PATCH,
handler as DELETE,
};
The Next.js API route handler takes the following options to initialize:
-
getClient (required)
(req: NextRequest) => ClientContract<Schema> | Promise<ClientContract<Schema>>
A callback for getting a ZenStackClient instance for talking to the database. Usually you'll return a client instance with access policy enabled and user identity bound.
-
apiHandler (required)
ApiHandler
The API handler instance that determines the API specification.
import type { NextApiRequest, NextApiResponse } from 'next';
import { NextRequestHandler } from '@zenstackhq/server/next';
import { RPCApiHandler } from '@zenstackhq/server/api';
import { getSessionUser } from '~/auth';
import { client } from '~/db';
import { schema } from '~/zenstack/schema';
export default NextRequestHandler({
apiHandler: new RPCApiHandler({ schema }),
// getSessionUser extracts the current session user from the request, its
// implementation depends on your auth solution
getClient: (req: NextApiRequest, res: NextApiResponse) => client.$setAuth(getSessionUser(req, res)),
});
The Next.js API route handler takes the following options to initialize:
-
getClient (required)
(req: NextApiRequest, res: NextApiResponse) => ClientContract<Schema> | Promise<ClientContract<Schema>>
A callback for getting a ZenStackClient instance for talking to the database. Usually you'll return a client instance with access policy enabled and user identity bound.
-
apiHandler (required)
ApiHandler
The API handler instance that determines the API specification.
Controlling what endpoints to expose​
You can use a Next.js middleware to further control what endpoints to expose. For example, if you're using a RESTful API handler installed at "/api/model", you can disallow listing all User entities by adding a middleware like:
import { type NextRequest, NextResponse } from 'next/server';
export function middleware(request: NextRequest) {
const url = new URL(request.url);
if (
request.method === 'GET' &&
url.pathname.match(/^\/api\/model\/user\/?$/)
) {
return NextResponse.json({ error: 'Not allowed' }, { status: 405 });
}
}
export const config = {
matcher: '/api/model/:path*',
};
Error Handling​
Refer to the specific sections for RPC Handler and RESTful Handler.