nextjs App Routerでjson-serverを作ってみた

# 3 行要約

1. json-server は、json ファイルを使って簡単に RESTful API を作成できるツールで、Next.js を使って同様の機能を実現しました
2. Next.js の app router を利用して、GET、POST、PUT 操作が可能な API エンドポイントを動的に作成し、開発時に便利な機能を提供します
3. Copilot Edits を活用してコードを自動生成し、効率的に API を実装しましたが、生成されたコードの品質を管理する必要があります

# はじめに

## json-server とは何か

自分がよく使うお気に入りの[オープンソース](https://github.com/typicode/json-server)です。

json-server は、json ファイルを使って簡単に RESTful API を作成できるツールです。

例えば、以下のような json ファイルを用意して、json-server を起動すると、その json ファイルを元に、CRUD 操作が可能な RESTful API が作成されます。

```json
{
  "posts": [
    { "id": "1", "title": "a title", "views": 100 },
    { "id": "2", "title": "another title", "views": 200 }
  ],
  "comments": [
    { "id": "1", "text": "a comment about post 1", "postId": "1" },
    { "id": "2", "text": "another comment about post 1", "postId": "1" }
  ],
  "profile": {
    "name": "typicode"
  }
}
```

```bash
npx json-server db.json
```

このように、json-server を使うことで、欲しいデータを持つ RESTful API を簡単に作成できます。

今回、これを nextjs で同じように実装してみました。

[リポジトリはこちら](https://github.com/yuyakinjo/next-json-server)

## 使い方

※注意：まだ npm で配布しておりません。

### 準備

```bash
bun i --frozen-lockfile
```

## db.json の用意

```json
// db.json
{
  "posts": [
    { "id": "1", "title": "a title", "views": 100 },
    { "id": "2", "title": "another title", "views": 200 }
  ],
  "comments": [
    { "id": "1", "text": "a comment about post 1", "postsId": "1" },
    { "id": "2", "text": "another comment about post 1", "postsId": "1" }
  ],
  "profile": {
    "name": "yuyakinjo"
  }
}
```

### route.ts の生成

```bash
bun gen:json:route
```

### 起動

```bash
bun dev
```

### 使い方

### GET

```bash
http://localhost:3000/json/posts
```

```json
[
  {
    "id": "1",
    "title": "a title",
    "views": 100,
    "comments": [
      {
        "id": "1",
        "text": "a comment about post 1",
        "postsId": "1"
      },
      {
        "id": "2",
        "text": "another comment about post 1",
        "postsId": "1"
      }
    ]
  },
  {
    "id": "2",
    "title": "another title",
    "views": 200,
    "comments": []
  }
]
```

db.json の comments に postsId があるので、`db.json` の `comments` の `postsId` も紐付けられて返ってきます。

### GET（ID 指定）

```bash
http://localhost:3000/json/posts/1
```

```json
{ "id": "1", "title": "a title", "views": 100 }
```

### GET(配列じゃない json)

配列じゃないデータも取得できます。

```bash
http://localhost:3000/json/profile
```

```json
{ "name": "yuyakinjo" }
```

POST や PUT もできます。

`http://localhost:3000/json/posts` に POST すると、`db.json` の `posts` にデータが追加されます。

```json
{ "title": "new title", "views": 300 }
```

## その他

operators を使うことで、より複雑なクエリも可能です。

例えば、`http://localhost:3000/json/posts?views_gte=200` にアクセスすると、`db.json` の `posts` の `views` が `200` 以上のデータが返ってきます。

```json
[{ "id": "2", "title": "another title", "views": 200 }]
```

## nextjs の app router で json-server を実現するには

json-server を nextjs で実現するには、`db.json` のデータを読み込んで、それを元に 動的に API を作成する必要があります。

nextjs では、フォルダ構造とファイル名によって、動的に [route handlers](https://nextjs.org/docs/app/building-your-application/routing/route-handlers) を作成することで、API を作成できました。

# json を冗長化させてるメリット

1. git に`db.json`を push すれば、操作後、いつでもデータを戻すことができる
2. `db.json`が seed データになっている、と同時にレスポンスの形にもなっている
3. typescript なら、[json から型がとれる](https://www.typescriptlang.org/tsconfig/#resolveJsonModule)
4. ある規則に沿えば、

# 実は

これほぼすべて、[Copilot Edits](https://code.visualstudio.com/docs/copilot/copilot-edits) で実行させました。

nextjs の app router で json-server を実装を英語にしたり、汎用的にやるとき、配列を返す時の型、そうじゃない時の型など、ある程度のコードは自動生成されました。

やりたいことを実行してはくれるのですが、どういうコードを許容するしない（例えば forEach ではなく、forof を使わせたり）は、自分で決める必要があるので、それを考えるのは大変でした。

ただ、今なら [copilot instruction](https://docs.github.com/ja/copilot/customizing-copilot/adding-custom-instructions-for-github-copilot)があるので、それを使うと、毎回生成してくるコードを指摘して直させることは減りそうです。

ちゃんとゴールや自分の中での設計図が思い浮かぶ状態であれば、スタートが軽くなるとてもいいツールだと思います。

まだまだ[cursor](https://www.cursor.com/)が AI 機能豊富ですが、VSCode も AI 機能が充実してきているので、今後が楽しみです。

# 今後の展望

json-server で生成することはできたので、エンティティ違い（`mysql/posts`みたいな）で、冗長化の方法が違うだけの API 作成するのと、npm 配布して、いつでも自分で使えるようにしたい（copilot やってくれ願望）