Supabase を使ったクイックスタート
はじめに
Supabase はオープンソースの Firebase 代替品です。
このクイックスタートは、Plasmo で Supabase を使用する簡単な例を示しています。
事前準備
- Supabase (opens in a new tab) アカウント
- Supabase プロジェクト
Supabase を使用して Plasmo プロジェクトを初期化
pnpm create plasmo --with-supabase
環境変数の設定
Supabase を動作させるには、URL と KEY を定義する必要があります。
これらの情報は、Supabase プロジェクトのダッシュボードで見つけることができます。
.env
ファイルにそれらを追加しましょう。
PLASMO_PUBLIC_SUPABASE_URL="CHANGE ME"
PLASMO_PUBLIC_SUPABASE_KEY="CHANGE ME"
Supabase ストア
Supabase を初期化する必要があるため、core/supabase.ts
というファイルを追加しましょう。
import { createClient } from "@supabase/supabase-js"
import { Storage } from "@plasmohq/storage"
const storage = new Storage({
area: "local"
})
export const supabase = createClient(
process.env.PLASMO_PUBLIC_SUPABASE_URL,
process.env.PLASMO_PUBLIC_SUPABASE_KEY,
{
auth: {
storage,
autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: true
}
}
)
リダイレクト URL の追加
ユーザーがサインアップすると、メールアドレスを確認する必要があります。これを行うには、Supabase プロジェクトにリダイレクト URL を追加する必要があります。
まず、開発用の拡張機能の一貫した ID を作成する必要があります。異なるウェブストアにプッシュすると、異なる ID が取得されます。この仕組みの詳細については、一貫性のある拡張機能IDの作成 (opens in a new tab)に関するブログ投稿をご覧ください。
Itero KeyPair ツール (opens in a new tab) にアクセスして、一貫性のある拡張機能 ID を生成します。
ID と公開鍵を .env
ファイルに保存できます。
CRX_ID="Itero KeyPair ツールから取得した CRX ID の値をここに置き換えてください"
CRX_KEY="Itero KeyPair ツールから取得した公開鍵の値をここに置き換えてください"
次に、package.json
の manifest.key
値で公開鍵を参照します。
"manifest": {
"host_permissions": [
"https://*/*"
],
"key": "$CRX_KEY",
}
次に、ブラウザがオプションページへのアクセスをブロックしないようにする必要があります。これを行うには、manifest
の web_accessible_resources
に追加する必要があります。
"web_accessible_resources": [
{
"resources": [
"options.html"
],
"matches": [
"<all_urls>"
],
"extension_ids": [
"$CRX_ID"
]
}
]
Supabase コンソールにアクセスし、「認証」タブをクリックして、URL 設定をクリックします。
次に、サイト URL とリダイレクト URL の両方に次の URL を追加します。
chrome-extension://<CRX_ID>/options.html
CRX_ID
を、Itero KeyPairs ツールで提供された生成された拡張機能 ID、または本番 Web ストアで提供された実際の ID に置き換えてください。
React コンポーネントとの統合
これで、React コンポーネントで Supabase を使用したコードを記述できます!
拡張機能のオプションページで Supabase を使用する React コンポーネントの例を以下に示します。
import type { Provider, User } from "@supabase/supabase-js"
import { useEffect, useState } from "react"
import { Storage } from "@plasmohq/storage"
import { useStorage } from "@plasmohq/storage/hook"
import { supabase } from "~core/supabase"
function IndexOptions() {
const [user, setUser] = useStorage<User>({
key: "user",
instance: new Storage({
area: "local"
})
})
const [username, setUsername] = useState("")
const [password, setPassword] = useState("")
useEffect(() => {
async function init() {
const { data, error } = await supabase.auth.getSession()
if (error) {
console.error(error)
return
}
if (!!data.session) {
setUser(data.session.user)
}
}
init()
}, [])
const handleEmailLogin = async (
type: "LOGIN" | "SIGNUP",
username: string,
password: string
) => {
try {
const {
error,
data: { user }
} =
type === "LOGIN"
? await supabase.auth.signInWithPassword({
email: username,
password
})
: await supabase.auth.signUp({ email: username, password })
if (error) {
alert("Error with auth: " + error.message)
} else if (!user) {
alert("Signup successful, confirmation mail should be sent soon!")
} else {
setUser(user)
}
} catch (error) {
console.log("error", error)
alert(error.error_description || error)
}
}
const handleOAuthLogin = async (provider: Provider, scopes = "email") => {
await supabase.auth.signInWithOAuth({
provider,
options: {
scopes,
redirectTo: location.href
}
})
}
return (
<main
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
width: "100%",
top: 240,
position: "relative"
}}>
<div
style={{
display: "flex",
flexDirection: "column",
width: 240,
justifyContent: "space-between",
gap: 4.2
}}>
{user && (
<>
<h3>
{user.email} - {user.id}
</h3>
<button
onClick={() => {
supabase.auth.signOut()
setUser(null)
}}>
ログアウト
</button>
</>
)}
{!user && (
<>
<label>メールアドレス</label>
<input
type="text"
placeholder="ユーザー名"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
<label>パスワード</label>
<input
type="password"
placeholder="パスワード"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<button
onClick={(e) => {
handleEmailLogin("SIGNUP", username, password)
}}>
サインアップ
</button>
<button
onClick={(e) => {
handleEmailLogin("LOGIN", username, password)
}}>
ログイン
</button>
<button
onClick={(e) => {
handleOAuthLogin("github")
}}>
GitHub でサインイン
</button>
</>
)}
</div>
</main>
)
}
export default IndexOptions
完全な例
完全な例を見るには、 examples リポジトリにある with-supabase (opens in a new tab) を確認してください!