🦕

Edge Functionsに複数の関数をデプロイする

2024/05/23に公開

🤔やってみたいこと

Edge Functionsに複数の関数をデプロイしたい。レイヤーを分けて関数をexport && importすれば良いのかと思ったがそうではなさそうだな。

[公式ドキュメントにはこんなこと書いてある]
https://supabase.com/docs/guides/functions/quickstart

Organizing your Edge Functions

We recommend developing “fat functions”. This means that you should develop few large functions, rather than many small functions. One common pattern when developing Functions is that you need to share code between two or more Functions. To do this, you can store any shared code in a folder prefixed with an underscore (_). We also recommend a separate folder for Unit Tests including the name of the function followed by a -test suffix.
We recommend this folder structure:

Edge 関数の整理

「ファット関数」を開発することをお勧めします。つまり、多数の小さな関数ではなく、少数の大きな関数を開発する必要があります。関数を開発する際の一般的なパターンの 1 つは、2 つ以上の関数間でコードを共有する必要があることです。これを行うには、共有コードをアンダースコア (_) で始まるフォルダーに保存します。また、関数名の後に -test サフィックスが付いたユニット テスト用の別のフォルダーもお勧めします。
次のフォルダー構造をお勧めします。

└── supabase
    ├── functions
    │   ├── import_map.json # A top-level import map to use across functions.
    │   ├── _shared
    │   │   ├── supabaseAdmin.ts # Supabase client with SERVICE_ROLE key.
    │   │   └── supabaseClient.ts # Supabase client with ANON key.
    │   │   └── cors.ts # Reusable CORS headers.
    │   ├── function-one # Use hyphens to name functions.
    │   │   └── index.ts
    │   └── function-two
    │   │   └── index.ts
    │   └── tests
    │       └── function-one-test.ts
    │       └── function-two-test.ts
    ├── migrations
    └── config.toml

🚀やってみたこと

公式ドキュメントとGithubのOSSのソースコードを参考にレイヤーを分けてみた。

[supabasecreateClient.tsだけで今回は使える]

import { createClient } from "npm:@supabase/supabase-js@2.39.3";

export const supabase = createClient(
  Deno.env.get("SUPABASE_URL") ?? "",
  Deno.env.get("SUPABASE_ANON_KEY") ?? "",
);

何か、logを出すなりDBのデータを表示するなりするロジックを書く。関数をデプロイして、URLにアクセスすると、表示されるはずです。JWTのswichはOFFにしてください。

[1個目の関数]

function-foo/index.ts
import { supabase } from "../_shared/supabaseClient.ts";

console.log("Running function foo...")

  Deno.serve(async (req) => {
    const {data: name, error} = await supabase.from("t_user").select("id, name").eq("id", "1")
      .limit(1).single()
    if(error) console.log(error)
    
    const data = {
      message: `function fooの実行結果 ${name?.name}!`,
    }
  
    return new Response(
      JSON.stringify(data),
      { headers: { "Content-Type": "application/json" } },
    )
  })

[2個目の関数]

function-hoge/index.ts
import { supabase } from "../_shared/supabaseClient.ts";

console.log("Running function hoge...")

  Deno.serve(async (req) => {
    const {data: name, error} = await supabase.from("t_task").select("status, task_name").eq("id", "4")
      .limit(1).single()
    if(error) console.log(error)
    
    const data = {
      message: `function hogeの実行結果 ${name?.status} | ${name?.task_name}!`,
    }
  
    return new Response(
      JSON.stringify(data),
      { headers: { "Content-Type": "application/json" } },
    )
  })

関数を複数デプロイするときは、1回ずつコマンドを実行する。フォルダ名を指定すればEdget Functionsにデプロイされる。

[見本]

supabase functions deploy [関数のフォルダ名] --project-ref [id]

[実行するコマンド]

supabase functions deploy function-foo --project-ref [id]
supabase functions deploy function-hoge --project-ref [id]

できた🙌

[URLにアクセスするとこんな感じで表示されました]

🙂最後に

今回は複数の関数を作って、Edge Functionsにデプロイする方法について調べてみました。最初はレイヤーを分けて関数をデプロイしてたのですが、変なコードになっていたので、「これで良いのかと悩みました(^^;;」

ネットで調べてもレイヤーを分けて、作る例はなかったので関数を1個ずつ作ってデプロイすれば良いみたいです。

return new Responseを私は、1個しか書いてなくて、この上に他のファイルに書いた関数を呼び出して実行してました笑

無駄なことしてた...

// この上に、notification();って感じのとか、hoge();を書いてた笑
return new Response(
      JSON.stringify(data),
      { headers: { "Content-Type": "application/json" } },
    )

Discussion