Skip to content

Commit

Permalink
chore: update README and example
Browse files Browse the repository at this point in the history
  • Loading branch information
hoangvvo committed May 4, 2023
1 parent 1bbaa40 commit 5a37f19
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 105 deletions.
154 changes: 78 additions & 76 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,7 @@
[![minified size](https://badgen.net/bundlephobia/min/next-connect)](https://bundlephobia.com/result?p=next-connect)
[![download/year](https://badgen.net/npm/dy/next-connect)](https://www.npmjs.com/package/next-connect)

The promise-based method routing and middleware layer for [Next.js](https://nextjs.org/) (API Routes, Edge API Routes, getServerSideProps, Middleware) and many other frameworks.

> **Warning**
> v1 is a complete rewrite of v0 and is **not** backward-compatible. See [Releases](https://github.com/hoangvvo/next-connect/releases) to learn about the changes.
> [v0](https://github.com/hoangvvo/next-connect/tree/v0), which is written to be compatible with Express.js middleware, is still maintained with bug fixes. v1 drops explicit support for Express.js middleware, but still provide a way to use them through a wrapper (see below)
The promise-based method routing and middleware layer for [Next.js](https://nextjs.org/) [API Routes](#nextjs-api-routes), [Edge API Routes](#nextjs-edge-api-routes), [Middleware](#nextjs-middleware), Next.js App Router, and [getServerSideProps](#nextjs-getserversideprops).

## Features

Expand All @@ -29,14 +24,10 @@ npm install next-connect@next

## Usage

> **Note**
>
> Although `next-connect` is initially written for Next.js, it can be used in [http server](https://nodejs.org/api/http.html#httpcreateserveroptions-requestlistener), [Vercel](https://vercel.com/docs/concepts/functions/serverless-functions). See [Examples](./examples/) for more integrations.
Below are some use cases.

### Next.js API Routes

`next-connect` can be used in [API Routes](https://nextjs.org/docs/api-routes/introduction).

```typescript
// pages/api/hello.js
import type { NextApiRequest, NextApiResponse } from "next";
Expand Down Expand Up @@ -65,8 +56,6 @@ router
})
.put(
async (req, res, next) => {
// You may want to pass in NextApiRequest & { isLoggedIn: true }
// in createRouter generics to define this extra property
if (!req.isLoggedIn) throw new Error("thrown stuff will be caught");
// go to the next in chain
return next();
Expand All @@ -77,6 +66,10 @@ router
}
);

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

// create a handler from router with custom
// onError and onNoMatch
export default router.handler({
Expand All @@ -90,60 +83,12 @@ export default router.handler({
});
```

### Next.js getServerSideProps

```jsx
// page/users/[id].js
import { createRouter } from "next-connect";

export default function Page({ user, updated }) {
return (
<div>
{updated && <p>User has been updated</p>}
<div>{JSON.stringify(user)}</div>
<form method="POST">{/* User update form */}</form>
</div>
);
}

const router = createRouter()
.use(async (req, res, next) => {
// this serve as the error handling middleware
try {
return await next();
} catch (e) {
return {
props: { error: e.message },
};
}
})
.use(async (req, res, next) => {
logRequest(req);
return next();
})
.get(async (req, res) => {
const user = await getUser(req.params.id);
if (!user) {
// https://nextjs.org/docs/api-reference/data-fetching/get-server-side-props#notfound
return { props: { notFound: true } };
}
return { props: { user } };
})
.post(async (req, res) => {
const user = await updateUser(req);
return { props: { user, updated: true } };
});

export async function getServerSideProps({ req, res }) {
return router.run(req, res);
}
```

### Next.js Edge API Routes (Beta)
### Next.js Edge API Routes

Edge Router can be used in [Edge Runtime](https://nextjs.org/docs/api-reference/edge-runtime)
`next-connect` can be used in [Edge API Routes](https://nextjs.org/docs/api-routes/edge-api-routes)

```ts
// pages/api/hello.js
import type { NextFetchEvent, NextRequest } from "next/server";
import { createEdgeRouter } from "next-connect";
import cors from "cors";
Expand All @@ -153,28 +98,26 @@ import cors from "cors";
const router = createEdgeRouter<NextRequest, NextFetchEvent>();

router
.use(expressWrapper(cors())) // express middleware are supported if you wrap it with expressWrapper
.use(async (req, evt, next) => {
.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, res) => {
.get((req) => {
return new Response("Hello world");
})
.post(async (req, res) => {
.post(async (req) => {
// use async/await
const user = await insertUser(req.body.user);
res.json({ user });
return new Response(JSON.stringify({ user }), {
status: 200,
headers: {
"content-type": "application/json",
},
});
})
.put(async (req, res) => {
.put(async (req) => {
const user = await updateUser(req.body.user);
return new Response(JSON.stringify({ user }), {
status: 200,
Expand All @@ -187,23 +130,31 @@ router
// create a handler from router with custom
// onError and onNoMatch
export default router.handler({
onError: (err, req, evt) => {
onError: (err, req, event) => {
console.error(err.stack);
return new NextResponse("Something broke!", {
status: 500,
});
},
onNoMatch: (req, res) => {
onNoMatch: (req, event) => {
return new NextResponse("Page is not found", {
status: 404,
});
},
});
```

### Next.js App Router

`next-connect` can be used in [Next.js 13 Route Handler](https://beta.nextjs.org/docs/routing/route-handlers). The way handlers are written is almost the same to [Next.js Edge API Routes](#nextjs-edge-api-routes).

```ts

```

### Next.js Middleware

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

```ts
// middleware.ts
Expand All @@ -215,7 +166,7 @@ import { createEdgeRouter } from "next-connect";

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

router.use(async (request, _, next) => {
router.use(async (request, event, next) => {
await logRequest(request);
return next();
});
Expand All @@ -241,6 +192,57 @@ export function middleware(request: NextRequest) {
}
```

### Next.js getServerSideProps

`next-connect` can be used in [getServerSideProps](https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props).

```jsx
// pages/users/[id].js
import { createRouter } from "next-connect";

export default function Page({ user, updated }) {
return (
<div>
{updated && <p>User has been updated</p>}
<div>{JSON.stringify(user)}</div>
<form method="POST">{/* User update form */}</form>
</div>
);
}

const router = createRouter()
.use(async (req, res, next) => {
// this serve as the error handling middleware
try {
return await next();
} catch (e) {
return {
props: { error: e.message },
};
}
})
.use(async (req, res, next) => {
logRequest(req);
return next();
})
.get(async (req, res) => {
const user = await getUser(req.params.id);
if (!user) {
// https://nextjs.org/docs/api-reference/data-fetching/get-server-side-props#notfound
return { props: { notFound: true } };
}
return { props: { user } };
})
.post(async (req, res) => {
const user = await updateUser(req);
return { props: { user, updated: true } };
});

export async function getServerSideProps({ req, res }) {
return router.run(req, res);
}
```

## API

The following APIs are rewritten in term of `NodeRouter` (`createRouter`), but they apply to `EdgeRouter` (`createEdgeRouter`) as well.
Expand Down Expand Up @@ -533,7 +535,7 @@ export async function getServerSideProps({ req, res }) {
<details>
<summary>Match multiple routes</summary>

If you created the file `/api/<specific route>.js` folder, the handler will only run on that specific route.
If you created the file `/api/<specific route>.js`, the handler will only run on that specific route.

If you need to create all handlers for all routes in one file (similar to `Express.js`). You can use [Optional catch-all API routes](https://nextjs.org/docs/api-routes/dynamic-api-routes#optional-catch-all-api-routes).

Expand Down
14 changes: 7 additions & 7 deletions examples/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@
},
"dependencies": {
"cookie": "^0.5.0",
"next": "12.2.0",
"next": "13.3.4",
"next-connect": "1.0.0-next.2",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"devDependencies": {
"@types/cookie": "^0.5.1",
"@types/node": "18.0.0",
"@types/react": "18.0.14",
"@types/react-dom": "18.0.5",
"eslint": "8.19.0",
"eslint-config-next": "12.2.0",
"typescript": "4.7.4"
"@types/node": "18.16.3",
"@types/react": "18.2.4",
"@types/react-dom": "18.2.3",
"eslint": "8.39.0",
"eslint-config-next": "13.3.4",
"typescript": "5.0.4"
}
}
2 changes: 1 addition & 1 deletion examples/nextjs/src/pages/api/edge-users/[id].ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { NextResponse } from "next/server";
import { getUsers } from "../../../utils/edge-api";

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

const router = createEdgeRouter<
Expand Down
2 changes: 1 addition & 1 deletion examples/nextjs/src/pages/api/edge-users/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { validateUser } from "../../../utils/common";
import { getUsers, randomId, saveUsers } from "../../../utils/edge-api";

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

const router = createEdgeRouter<NextRequest, NextFetchEvent>();
Expand Down
12 changes: 7 additions & 5 deletions examples/nextjs/src/pages/gssp-users/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,13 @@ const UsersPage: NextPage<PageProps> = ({ users, error }) => {
<div className={styles.grid}>
{users?.length ? (
users.map((user) => (
<Link href={`/gssp-users/${user.id}`} key={user.id}>
<a className={styles.card}>
<h2>{user.name}</h2>
<p>{user.age}</p>
</a>
<Link
href={`/gssp-users/${user.id}`}
key={user.id}
className={styles.card}
>
<h2>{user.name}</h2>
<p>{user.age}</p>
</Link>
))
) : (
Expand Down
24 changes: 9 additions & 15 deletions examples/nextjs/src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,19 @@ const Home: NextPage = () => {
<code className={styles.code}>npm i next-connect</code>
</p>
<div className={styles.grid}>
<Link href="/gssp-users">
<a className={styles.card}>
<h2>Get Server Side Props</h2>
<p>Use next-connect in getServerSideProps</p>
</a>
<Link href="/gssp-users" className={styles.card}>
<h2>Get Server Side Props</h2>
<p>Use next-connect in getServerSideProps</p>
</Link>

<Link href="/api-routes">
<a className={styles.card}>
<h2>API Routes</h2>
<p>Use next-connect in API Routes</p>
</a>
<Link href="/api-routes" className={styles.card}>
<h2>API Routes</h2>
<p>Use next-connect in API Routes</p>
</Link>

<Link href="/edge-api-routes">
<a className={styles.card}>
<h2>Edge API Routes (Beta)</h2>
<p>Use next-connect in API Routes</p>
</a>
<Link href="/edge-api-routes" className={styles.card}>
<h2>Edge API Routes</h2>
<p>Use next-connect in API Routes</p>
</Link>
</div>
</main>
Expand Down

0 comments on commit 5a37f19

Please sign in to comment.