Skip to content

Commit

Permalink
chore: update README
Browse files Browse the repository at this point in the history
  • Loading branch information
hoangvvo committed May 4, 2023
1 parent 5a37f19 commit 22a2925
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 125 deletions.
110 changes: 44 additions & 66 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,56 +29,43 @@ npm install next-connect@next
`next-connect` can be used in [API Routes](https://nextjs.org/docs/api-routes/introduction).

```typescript
// pages/api/hello.js
// pages/api/user/[id].ts
import type { NextApiRequest, NextApiResponse } from "next";
import { createRouter, expressWrapper } from "next-connect";
import cors from "cors";

// Default Req and Res are IncomingMessage and ServerResponse
// You may want to pass in NextApiRequest and NextApiResponse
const router = createRouter<NextApiRequest, NextApiResponse>();

router
.use(expressWrapper(cors())) // express middleware are supported if you wrap it with expressWrapper
// Use express middleware in next-connect with expressWrapper function
.use(expressWrapper(passport.session()))
// A middleware example
.use(async (req, res, next) => {
const start = Date.now();
await next(); // call next in chain
const end = Date.now();
console.log(`Request took ${end - start}ms`);
})
.get((req, res) => {
res.send("Hello world");
})
.post(async (req, res) => {
// use async/await
const user = await insertUser(req.body.user);
const user = getUser(req.query.id);
res.json({ user });
})
.put(
async (req, res, next) => {
if (!req.isLoggedIn) throw new Error("thrown stuff will be caught");
// go to the next in chain
return next();
},
async (req, res) => {
const user = await updateUser(req.body.user);
res.json({ user });
.put((req, res) => {
if (req.user.id !== req.query.id) {
throw new ForbiddenError("You can't update other user's profile");
}
);
const user = await updateUser(req.body.user);
res.json({ user });
});

export const config = {
runtime: "edge",
};

// create a handler from router with custom
// onError and onNoMatch
export default router.handler({
onError: (err, req, res) => {
console.error(err.stack);
res.status(500).end("Something broke!");
},
onNoMatch: (req, res) => {
res.status(404).end("Page is not found");
res.status(err.statusCode || 500).end(err.message);
},
});
```
Expand All @@ -88,57 +75,40 @@ export default router.handler({
`next-connect` can be used in [Edge API Routes](https://nextjs.org/docs/api-routes/edge-api-routes)

```ts
// pages/api/hello.js
// pages/api/user/[id].ts
import type { NextFetchEvent, NextRequest } from "next/server";
import { createEdgeRouter } from "next-connect";
import cors from "cors";

// Default Req and Evt are Request and unknown
// You may want to pass in NextRequest and NextFetchEvent
const router = createEdgeRouter<NextRequest, NextFetchEvent>();

router
// A middleware example
.use(async (req, event, next) => {
const start = Date.now();
await next(); // call next in chain
const end = Date.now();
console.log(`Request took ${end - start}ms`);
})
.get((req) => {
return new Response("Hello world");
const id = req.nextUrl.searchParams.get("id");
const user = getUser(id);
return NextResponse.json({ user });
})
.post(async (req) => {
// use async/await
const user = await insertUser(req.body.user);
return new Response(JSON.stringify({ user }), {
status: 200,
headers: {
"content-type": "application/json",
},
});
})
.put(async (req) => {
.put((req) => {
const id = req.nextUrl.searchParams.get("id");
if (req.user.id !== id) {
throw new ForbiddenError("You can't update other user's profile");
}
const user = await updateUser(req.body.user);
return new Response(JSON.stringify({ user }), {
status: 200,
headers: {
"content-type": "application/json",
},
});
return NextResponse.json({ user });
});

// create a handler from router with custom
// onError and onNoMatch
export default router.handler({
onError: (err, req, event) => {
console.error(err.stack);
return new NextResponse("Something broke!", {
status: 500,
});
},
onNoMatch: (req, event) => {
return new NextResponse("Page is not found", {
status: 404,
status: err.statusCode || 500,
});
},
});
Expand All @@ -156,18 +126,17 @@ export default router.handler({

`next-connect` can be used in [Next.js Middleware](https://nextjs.org/docs/advanced-features/middleware)

```ts
```typescript
// middleware.ts
import { NextResponse } from "next/server";
import type { NextRequest, NextFetchEvent } from "next/server";
import { createEdgeRouter } from "next-connect";

// This function can be marked `async` if using `await` inside

const router = createEdgeRouter<NextRequest, NextFetchEvent>();

router.use(async (request, event, next) => {
await logRequest(request);
// logging request example
console.log(`${request.method} ${request.url}`);
return next();
});

Expand All @@ -182,14 +151,27 @@ router.use("/dashboard", (request) => {
return NextResponse.next();
});

router.all((request) => {
router.all(() => {
// default if none of the above matches
return NextResponse.next();
});

export function middleware(request: NextRequest) {
return NextResponse.redirect(new URL("/about-2", request.url));
export function middleware(request: NextRequest, event: NextFetchEvent) {
return router.run(request, event);
}

export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - api (API routes)
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
*/
"/((?!api|_next/static|_next/image|favicon.ico).*)",
],
};
```

### Next.js getServerSideProps
Expand Down Expand Up @@ -221,10 +203,6 @@ const router = createRouter()
};
}
})
.use(async (req, res, next) => {
logRequest(req);
return next();
})
.get(async (req, res) => {
const user = await getUser(req.params.id);
if (!user) {
Expand All @@ -233,7 +211,7 @@ const router = createRouter()
}
return { props: { user } };
})
.post(async (req, res) => {
.put(async (req, res) => {
const user = await updateUser(req);
return { props: { user, updated: true } };
});
Expand Down
33 changes: 33 additions & 0 deletions examples/nextjs/src/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// middleware.ts
import { createEdgeRouter } from "next-connect";
import type { NextFetchEvent, NextRequest } from "next/server";
import { NextResponse } from "next/server";

const router = createEdgeRouter<NextRequest, NextFetchEvent>();

router.use(async (request, event, next) => {
console.log(`${request.method} ${request.url}`);
return next();
});

router.all(() => {
// default if none of the above matches
return NextResponse.next();
});

export function middleware(request: NextRequest, event: NextFetchEvent) {
return router.run(request, event);
}

export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - api (API routes)
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
*/
"/((?!api|_next/static|_next/image|favicon.ico).*)",
],
};
38 changes: 6 additions & 32 deletions examples/nextjs/src/pages/api/edge-users/[id].ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,49 +7,23 @@ export const config = {
runtime: "edge",
};

const router = createEdgeRouter<
NextRequest & { params?: Record<string, string> },
NextFetchEvent
>();
const router = createEdgeRouter<NextRequest, NextFetchEvent>();

// edge api route does not parse params
// so we rely on next-connect this time
router.get("/api/edge-users/:id", (req) => {
router.get((req) => {
const id = req.nextUrl.searchParams.get("id");
const users = getUsers(req);
const user = users.find((user) => user.id === req.params?.id);
const user = users.find((user) => user.id === id);
if (!user) {
return new NextResponse(JSON.stringify({ error: "User not found" }), {
status: 404,
headers: {
"content-type": "application/json",
},
});
return NextResponse.json({ error: "User not found" }, { status: 404 });
}
return new NextResponse(JSON.stringify({ user }), {
status: 200,
headers: {
"content-type": "application/json",
},
});
return NextResponse.json({ user });
});

// this will run if none of the above matches
router.all(() => {
return new NextResponse(JSON.stringify({ error: "Method not allowed" }), {
status: 405,
headers: {
"content-type": "application/json",
},
});
});

export default router.handler({
onError(err) {
return new NextResponse(JSON.stringify({ error: (err as Error).message }), {
status: 500,
headers: {
"content-type": "application/json",
},
});
},
});
31 changes: 5 additions & 26 deletions examples/nextjs/src/pages/api/edge-users/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,7 @@ const router = createEdgeRouter<NextRequest, NextFetchEvent>();

router.get((req) => {
const users = getUsers(req);
return new Response(JSON.stringify({ users }), {
status: 200,
headers: {
"content-type": "application/json",
},
});
return NextResponse.json({ users });
});

router.post(async (req) => {
Expand All @@ -30,38 +25,22 @@ router.post(async (req) => {
} as User;
validateUser(newUser);
users.push(newUser);
const res = new NextResponse(
JSON.stringify({
message: "User has been created",
}),
{
status: 200,
headers: {
"content-type": "application/json",
},
}
);
const res = NextResponse.json({
message: "User has been created",
});
saveUsers(res, users);
return res;
});

// this will run if none of the above matches
router.all(() => {
return new NextResponse(JSON.stringify({ error: "Method not allowed" }), {
status: 405,
headers: {
"content-type": "application/json",
},
});
return NextResponse.json({ error: "Method not allowed" }, { status: 405 });
});

export default router.handler({
onError(err) {
return new NextResponse(JSON.stringify({ error: (err as Error).message }), {
status: 500,
headers: {
"content-type": "application/json",
},
});
},
});
2 changes: 1 addition & 1 deletion examples/nextjs/src/utils/edge-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const getUsers = (req: NextRequest): User[] => {
// we store all data in cookies for demo purposes
const cookie = req.cookies.get(COOKIE_NAME);
if (cookie) {
return JSON.parse(cookie);
return JSON.parse(cookie.value);
}
return [];
};
Expand Down

0 comments on commit 22a2925

Please sign in to comment.