Supabaseの関数をNext.jsアプリから呼び出す
前回の記事でSupabaseの認証と認可について紹介しました。
Supabaseでは、ミドルウェアを介さずに、クライアントが直接データベースに接続するアーキテクチャーを実現できます。
このようなアーキテクチャーを構築する上で、もう1つ便利な機能として関数があります。
Supabaseでは、データベースにRESTfulなAPIを自動で生成し、基本的なデータ操作ができます。関数を利用することで、より複雑な処理をバックエンドで処理できるようになります。
今回は、Supabaseで関数を作成して、この関数をNext.jsアプリから呼びだすまでの手順をご紹介します。
Supbaseで関数を作成
プロジェクトのダッシュボードから、SQL Editorを開きます。

「+ New query」ボタンをクリックすると、「SQL snippets」の下に「New Query」が作成されます。
次のSQLを入力します。
create or replace function hello_world()
returns text
language sql
as $$
  select 'Hello world, Supabase!';
$$;
- 
createでhello_worldという名前の関数を作成することを宣言します。orにreplaceを指定することで、すでに同名の関数がある場合は更新します。 - 
returnsに型を渡すことで、この関数の返り値の型を指定します。ここでは、テキスト型を返します。 - 
languageに関数で処理するために使用する言語を指定します。ここでは、SQLを使用します。その他にも、plsqlやJavaScriptなど利用できます。 - 
as句に処理の内容を、$$で囲んで記述します。 
「RUN」をクリックするとSQLが実行され、関数が作成されます。

関数を呼びだすために、新しくスニペットを作成するか、先ほどのエディターの中身を次の通り変更します。
select hello_world()
「RUN」をクリックします。関数の実行結果(Results)を確認できます。

Next.jsアプリをセットアップ
作成した関数を呼びだすために、Next.jsアプリをセットアップします。
前回の記事で作成したものをベースに追加していきます。
degit経由で取得して、必要なパッケージをインストールします。
npx degit hirotaka/examples/supabase-nextjs-database#atlanta-0.0.3 supabase-nextjs-database
cd supabase-nextjs-database
npm install
環境変数のセットなどは次を参考にしくてださい。
Next.jsアプリから関数を呼びだす
ダッシュボードで表示している文字列を、Supbaseの関数を呼び出した結果を表示するようにしてみます。
contexts/user.tsxを次の内容に変更します。
import { useState, useEffect } from 'react'
import { useUser } from '@/contexts/user'
import { supabase } from '@/lib/supabase-client'
export default function Message() {
  const { user } = useUser()
  const [loading, setLoading] = useState(false)
  const [message, setMessage] = useState()
  useEffect(() => {
    const rpcHello = async () => {
      try {
        setLoading(true)
        const { data } = await supabase.rpc('hello_world')
        setMessage(data)
      } catch (error) {
        alert(error.message)
      } finally {
        setLoading(false)
      }
    }
    if (user) rpcHello()
  }, [user])
  return (
    <div className="mt-6">
      <p>{loading ? '読み込み中...' : message}</p>
    </div>
  )
}
userに値が入っている(ログインしている状態)とき、先ほど作成した関数を呼びだすようにします。
関数を呼びだすには、Supabaseクライアントのrpcメソッドに呼び出したい関数名を渡します。
Supabaseで関数が実行されて、その結果をmessageとういうステートにセットします。
ダッシュボードで先ほど作成したコンポーネントを読み込むようにします。
@@ -1,4 +1,5 @@
 import { useUser } from '@/contexts/user'
+import Message from '@/components/message'
 import Profile from '@/components/profile'
 
 export default function Dashboard() {
@@ -7,9 +8,7 @@ export default function Dashboard() {
   return (
     <div className="max-w-md mx-auto">
       <h1 className="text-2xl">ダッシュボード</h1>
-      <div className="mt-6">
-        <p>Hello, {user.email}!</p>
-      </div>
+      <Message />
       <Profile />
       <div className="mt-6">
         <button className="secondary" onClick={() => logout()}>
実行結果の文字列「Hello world, Supabase!」が画面に表示されることを確認できます。

動的なメッセージを表示
固定的な文字列を表示したので、次に動的な結果を表示してみます。
SQL Editorで次のSQLを入力して、実行します。
create or replace function hello_world()
  returns text
  language sql
as $$
  select concat('Hello, ', auth.email(), '!');
$$;
すでに、hellow_worldという名前の関数は作成しているので、replaceにより関数の処理が更新されます。
auth.email()が実行されると、ログインしているユーザーのEメールを取得します。その結果と文字列を連結して返すようにします。
先ほどの、画面を再読み込みすると、Eメールが表示されることを確認できます。

最終的なコードはこちらで参照できます。
おわりに
関数をうまく使えると、バックエンドへのリクエストを少なくしたり、クライアントでの処理の軽減が期待できます。
また、Supabaseではよく使われる処理が拡張として提供されているので、目的にあったものがあれば簡単に使えるのはうれしいです。
関数はデータベースの処理と組み合わせるとより便利さが実感できます。
次回は、テーブルの操作と絡めて関数を作成してみます。
参考
Supbaseの知識を深めるために、ドキュメントの翻訳に取り組んでいます。
関数について、こちらも参考にしてください。
Discussion