Nextjs routes
majeed4u opened this issue · comments
not working with nextjs 13 app directory api
i have trieded many times
What problems are you facing?
So... Next-connect, The example provided looks like it is used in "one file"
I will refer as nextjs pages as "pages", and nextjs-13 as "app".
Example with nextjs-13: https://github.com/hoangvvo/next-connect/blob/main/examples/nextjs-13/src/app/api/users/route.ts
But the beauty of next-connect seems to be it can be defined as a "centralized hub" for api routes.
In "Pages" app shown here you can create a wrapper with next-connect
/api/shows/index.ts
const handler = createHandler();
handler.get(async (req: NextApiRequest, res: NextApiResponse) => {
let shows = await getShows();
// generate shows if there aren't any
if (shows.length === 0) {
await generateData();
shows = await getShows();
}
return res.status(200).json({ shows });
});
createHandler is stored in a api/handler file.
import type { NextApiRequest, NextApiResponse } from "next";
import nextConnect from "next-connect";
import { validateToken } from "@/lib/auth/utils";
import { processApiError } from "./utils";
// base handler for centralized error and method handling
export const createHandler = ({
authRequired,
}: { authRequired?: boolean } = {}) => {
const handler = nextConnect({
onError(error, req: NextApiRequest, res: NextApiResponse) {
const { status, message } = processApiError(error);
res.status(status).json({ message });
},
onNoMatch(req: NextApiRequest, res: NextApiResponse) {
res.status(405).end(`Method ${req.method} Not Allowed`);
},
});
if (authRequired) {
handler.use(async (req, res, next) => {
const tokenIsValid = await validateToken(req);
if (!tokenIsValid) return res.status(401).end();
return next();
});
}
return handler;
};
With this setup. We don't need to add useSession in every page.tsx file. It can be handled during api call as well.
// As example an reservation page - requires authenticated calls
const handler = createHandler({ authRequired: true });
handler.post(async (req: NextApiRequest, res: NextApiResponse) => {
My own attempt of doing in "app":
import { NextFetchEvent, NextRequest, NextResponse } from "next/server";
import { createEdgeRouter } from "next-connect";
import { validateToken } from "@/lib/auth/utils";
import { processApiError } from "./utils";
// base handler for centralized error and method handling
export const createHandler = ({
authRequired,
}: { authRequired?: boolean } = {}) => {
const handler = createEdgeRouter<NextRequest, NextFetchEvent>();
handler.handler({
onError(error, req, res) {
const { status, message } = processApiError(error);
NextResponse.json( { message },{ status });
},
onNoMatch(req, res) {
NextResponse.json(`Method ${req.method} Not Allowed`);
},
});
if (authRequired) {
handler.use(async (req, res, next) => {
const tokenIsValid = await validateToken(req, req.nextUrl.searchParams.get("userId"));
if (!tokenIsValid) return NextResponse.json({status: 401});
return next();
});
}
return handler;
};
Used in route.ts /api/shows/ as:
export async function GET(req: Request) {
return handler.get(async (req: Request) => {
let shows = await getShows();
// generate shows if there aren't any
if (shows.length === 0) {
await generateData();
shows = await getShows();
}
return NextResponse.json({ shows });
});
}
But I don't get it working yet because I think nextConnect wrapper is used in handler.ts
EDIT:
Continuing on this. Looking at the types for "Old" nextConnect is
export default function <Req = IncomingMessage, Res = ServerResponse>(
options?: Options<Req, Res>
): NextConnect<Req, Res>;
In new one it alittle different.
export { createEdgeRouter } from "./edge.js";
export { expressWrapper } from "./express.js";
export { createRouter } from "./node.js";
export type { HandlerOptions, NextHandler } from "./types.js";
One thing that gets me , most of times, is people built perfect libraries but then when it refactored many use-cases in the old ones are lost for "faster" way of writing. Having a page with "old code" - for this scenario. Here's the exact same scenario but with using new version.
This is such a bummer for developers who are really used using older libraries and to their capabilities only to be thrown down into the bottom, to re-learn everything yet again.