初サイト制作メモ4: Prismaを使ってVercel上のpostgresにレコード作成する

# Prisma Clientとは
Prisma Clientは、Prismaフレームワークの一部であり、Node.jsとTypeScriptのための自動生成される型安全なデータベースクライアント。
Prismaを使用すると、データベーススキーマからコードを自動生成し、データベース操作を簡単かつ安全に行うことができる。
Prisma Clientは、開発者がSQLやデータベース特有のクエリ言語を直接扱う代わりに、プログラム言語のように直感的で理解しやすいAPIを提供している。

`yarn add @prisma/client`

# Prismaを使ってPOSTを実装
```prisma/schema.prisma
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url = env("POSTGRES_PRISMA_URL") // uses connection pooling
  directUrl = env("POSTGRES_URL_NON_POOLING") // uses a direct connection
}
model Ramen {
  id          Int      @id @default(autoincrement())
  name        String   @db.VarChar(255)
  image       String
  description String?
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
}


```


```src/pages/api/ramen/index.ts
import { PrismaClient } from "@prisma/client";
import type { NextApiRequest, NextApiResponse } from "next";

const prisma = new PrismaClient();

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  try {
    if (req.method === "GET") {
      const ramenList = await prisma.ramen.findMany();
      res.status(200).json(ramenList);
    } else if (req.method === "POST") {
      const ramen = req.body;
      const newRamen = await prisma.ramen.create({
        data: ramen,
      });
      res.status(201).json(newRamen);
    } else {
      res.status(405).end();
    }
  } catch (error: unknown) {
    if (error instanceof Error) {
      res.status(500).json({ error: error.message });
    } else {
      res.status(500).json({ error: "An unexpected error occurred" });
    }
  }
}
```

※Prismaを使わなかった時の実装は以下のような感じだった（DBを模したリストからデータ取得）
Prisma使うと、簡単にDB接続してfindManyとかcreateとかでバシッと動いてくれてすごいな〜

```src/pages/api/ramen/index.ts
import type { NextApiRequest, NextApiResponse } from "next";
import type { Ramen } from "@/db/ramen";
import { addRamen, getRamenList } from "@/db/ramen";

export default function handler(
  req: NextApiRequest,
  res: NextApiResponse<Ramen[]>
) {
  if (req.method === "GET") {
    res.status(200).json(getRamenList());
  } else if (req.method === "POST") {
    const ramen = req.body as Ramen;
    addRamen(ramen);
    res.status(201).json([ramen]);
  } else {
    //一括削除の時などの処理をここに書く
    res.status(404).end();
```

```src/db/ramen.ts
export type Ramen = {
  id: string;
  name: string;
  image?: string;
  custom?: {
    volume: string;
    toppings: string;
  };
  description?: string;
};

const ramenList: Ramen[] = [
  {
    id: "1",
    name: "Shoyu Ramen",
    image: "/images/shoyu-ramen.jpg",
    description:
      "Shoyu ramen is a Japanese noodle soup that is flavored with soy sauce. It is one of the most popular and classic ramen in Japan.",
  },
  {
    id: "2",
    name: "Miso Ramen",
    image: "/images/miso-ramen.jpg",
    description:
      "Miso ramen is a Japanese noodle soup that is flavored with miso. It is one of the most popular and classic ramen in Japan.",
  },
  {
    id: "3",
    name: "Tonkotsu Ramen",
    image: "/images/tonkotsu-ramen.jpg",
    description:
      "Tonkotsu ramen is a Japanese noodle soup that is flavored with pork bone broth. It is one of the most popular and classic ramen in Japan.",
  },
];

export function getRamenList(): Ramen[] {
  return ramenList;
}

export function getRamenById(id: string): Ramen | undefined {
  return ramenList.find((ramen) => ramen.id === id);
}

export function addRamen(ramen: Ramen) {
  ramenList.push(ramen);
}

export function deleteRamen(id: string) {
  const index = ramenList.findIndex((ramen) => ramen.id === id);
  if (index !== -1) {
    ramenList.splice(index, 1);
  }
}

export function updateRamen(ramen: Ramen) {
  const index = ramenList.findIndex((r) => r.id === ramen.id);
  if (index !== -1) {
    ramenList[index] = ramen;
  }
}


```

# APIの挙動確認

`yarn dev`してから、PostmanでAPIを叩いてみて、Postgres上にレコード作成できることを確認。
やったぜ。
![スクリーンショット 2024-04-22 0.06.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366676/f24bb6f8-ecc2-3c5f-1ca7-1e7f9a7cdd38.png)
![スクリーンショット 2024-04-22 0.07.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366676/f71e0aee-6c5e-b4c2-a01c-ddee551e0f95.png)

GETもできた！
![スクリーンショット 2024-04-22 0.10.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366676/9466c434-e9ac-70a1-0740-8a6fb4623a37.png)