SupabaseでPostgreSQLのDB作成

## この記事の目的
- Next.jsでDBを使用してサイト構築する際の備忘録
- SupabaseでPostgreSQLのDB作成する際のフロー確認用

## 記事の概要
- Supabase とは
- Supabase登録・プロジェクト作成
- データベーススキーマの設定
- Next.jsに連携

※Next.jsに連携についてはNext.jsのプロジェクトが作成されている前提で進めています

## Supabase とは
>Supabaseは、オープンソースのFirebase代替として注目を集めているBaaS(Backend As A Service)のこと。
PostgreSQLデータベースをベースに、リアルタイム更新、認証、ストレージ、サーバーレス関数など、フルスタック開発に必要な機能が提供されています。

簡単にいうと無料でデータベース（Postgres）を作成できてNext.jsとかでデータベース付きのアプリケーションが作成できる便利なものって感じですかね
バックエンド考えずにフロント部分だけでDB操作できるのはめちゃくちゃ楽だと感じました！
有料プランもあるようですが個人で使う分には無料で十分使える感じです

[オープンソースBaaSプラットフォーム　Supabaseについて](https://techblitz.com/supabase/)

## Supabase登録・プロジェクト作成
### 公式サイトから「Start your project」を選択
![スクリーンショット 2023-04-13 22.30.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/d1ef6dc9-ec98-2dc6-d8da-01e6cb6d67fa.png)

### GitHub でログイン
![スクリーンショット 2023-04-13 22.30.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/c6d84d98-d74e-ce74-a155-f8a77c529810.png)

### 「New Project」を選択しプロジェクトを新規作成します。
![スクリーンショット 2023-04-13 22.31.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/b8e492d7-0096-bca6-c2fe-c33135b7d633.png)

### プロジェクト名等の入力・選択
- 組織：デフォルトだとGitHub名で作成されているかと思います。自由に追加できます
- プロジェクト名：プロジェクト名を入力
- パスワード：パスワードを入力
- リージョン：リージョンを選択
- プラン：Free-$0/monthを選択（個人で使用する分には無料枠で十分だと思います）

![スクリーンショット 2023-04-14 11.07.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/62393957-3ba4-9bf1-a875-9969f9777a4c.png)

## データベーススキーマの設定
データベーススキーマの設定（テーブルの作成）には、いくつか方法がありますが今回はSupabase上でポチポチ設定していく方法で記載していきます。
他にはクエリを実行して行う方法などあります。

まずは左側の「table Editor」を選択した後、「Create Table」を選択して下さい
![スクリーンショット 2023-04-14 11.17.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/a8ac80e8-4811-f455-ab22-ad51b691a079.png)
「Create Table」を選択すると画像のように右側にテーブル設定する画面が出てくるので「テーブル名」と「カラム」の設定を行います
今回はTodoテーブルを作成し、カラムはシンプルにIDとタイトルだけにしています
![スクリーンショット 2023-04-16 22.34.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/3d67f06b-4682-d10c-14ad-8130b6d9e389.png)
設定完了後「save」を選択すると次のようにテーブルが作成されたかと思います。
![スクリーンショット 2023-04-16 22.38.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/262a2977-6f1c-2b90-7360-1d5aedb9aafe.png)



### データの追加
作成されたテーブルにデータを追加していきます
「insert」を選択し「insert row」を選択します
![スクリーンショット 2023-04-16 22.37.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/d5a5b6d2-bd0e-da37-c927-ab7c4616493a.png)

選択後、先ほど同様画面右側に設定画面が表示されるので、追加したい情報を入力し「save」 を選択します
![スクリーンショット 2023-04-16 22.39.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/9a160221-8c56-66d2-fb5e-13aff0fa418e.png)

そうすると実際にデータが追加されていることが確認できます
![スクリーンショット 2023-04-16 22.41.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/df5a5e76-e92a-4a7a-beb0-06939159ad44.png)


## Next.jsに連携
今回は、Todoを取得、追加、削除を行えるNext.jsのプロジェクトに対して連携していきます。
[今回使用しているNext.jsのプロジェクトのソースコードはこちらから](https://github.com/Yuichi-W/Next_Supabase_pre.git)

### 連携のフロー
①supabase-jsのインストール
②Supabase クライアントを初期化（APIキー設定）
③取得、追加、削除処理作成
④Supabaseの「Enable RLS（ロウレベルセキュリティ）」機能を有効にする
※基本的に[supabase公式ドキュメント](https://supabase.com/docs/reference/javascript/installing)に沿って説明しています
※また、コードについてはSupabaseとの連携部分にしかここでは記載しないため、他部分については[こちらのGItHubを参考にしてもらえればと思います](https://github.com/Yuichi-W/Next_Supabase_pre.git)

### ①supabase-jsのインストール
[supabase公式ドキュメント](https://supabase.com/docs/reference/javascript/installing)のも記載ある下記コマンドでインストール
```
npm install @supabase/supabase-js
```

### Supabase クライアントを初期化（APIキー設定）
今回は`lib/supabase.ts`という階層とファイルを作成しこちらに設定しています。
また、下の画像の公式ドキュメントにはキーをこちらでわかりやすく直書きしていますが、今回は定数にして`.env`ファイルに値は記載しています
![スクリーンショット 2023-04-16 23.08.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/b4dcefaf-ab76-54af-0b63-559a0075af7c.png)
```lib/supabase.ts
import { createClient } from "@supabase/supabase-js";

export const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);

// 下記は公式ドキュメントの記載です。
// import { createClient } from '@supabase/supabase-js'
// Create a single supabase client for interacting with your database
// const supabase = createClient(
//   'https://xyzcompany.supabase.co', 
//   'public-anon-key'
// )
```

次に公式ドキュメントでも必須と記載してあるパラメータのsupabaseUrlとsupabaseKeyを設定していきます。
`.env`に`SUPABASE_URL`と`SUPABASE_ANON_KEY`を記載する。
※`NEXT_PUBLIC`を前につけてあげる必要があります。
```.env
NEXT_PUBLIC_SUPABASE_URL=https://XXXXXXXXXXXX.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
```
設定するURLとAPIキーは「ProjectSettings->API」の「Project URL」と「Project API keys」になります。
以下の画像を参考にして下さい
![スクリーンショット 2023-04-15 23.40.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/635b7f28-ef52-057e-e487-ea54299cc77c.png)

### ③取得、追加、削除処理作成
基本的な処理についてはわかりやすいように`lib/supabaseFunctions.ts`まとめて記載しています。
```lib/supabaseFunctions.ts
import { supabase } from './supabase';

// すべてのTodoを取得するための非同期関数
export const getAllTodos = async () => {
// todoテーブルからすべてのカラムを取得し、todosに代入します。
const todos = await supabase.from("todo").select('*');
// todosのデータをログに出力します。
console.log(todos.data);
// todos.dataを返します。
return todos.data;
};

// Todoを追加するための非同期関数
export const addTodo = async (title: string) => {
// todoテーブルにtitleを追加します。
await supabase.from("todo").insert({ title: title });
};

// Todoを削除するための非同期関数
export const deleteTodo = async (id: number) => {
// idが引数のTodoをtodoテーブルから削除します。
await supabase.from("todo").delete().eq("id", id);
};
```


### ④Supabaseの「Enable RLS（ロウレベルセキュリティ）」機能を有効にする
③までで連携は完了しているのですが、このままだとデータが空で空で返ってくるかと思います
これは「テーブルのデータにアクセス許可」がされていないためで、こちらを許可する必要があります。
#### 許可の手順としてはまずSupabase画面右上の「No active RLS policies」を選択
![スクリーンショット 2023-04-16 23.21.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/08ea3abe-34b7-2012-67ed-ac41f97a673b.png)
#### 次に「Disable RLS」を選択
![スクリーンショット 2023-04-16 23.21.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/3110e550-4aba-ee02-7a2c-203d9c357da5.png)
#### 次に「Confirm」を選択
![スクリーンショット 2023-04-16 23.22.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/abe87e01-dc8b-fa5a-4f72-6b86b8a9521d.png)
下記のようになっていれば画面上でデータの取得ができるかと思います。
![スクリーンショット 2023-04-16 23.22.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/438c2a32-9c75-233c-2af8-24dcb40f3c90.png)
![スクリーンショット 2023-04-16 23.27.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/d69984d9-18a3-fe01-643d-ee37bc69da82.png)