mcpField
S
supabase-realtime

supabase-realtime

github.com/nice-wolf-studio開発19321 回インストール53 週間前に更新
リポジトリ

supabase-realtime について

シェルスクリプトから Supabase Realtime を扱うためのスキルです。データベース変更、ブロードキャスト、プレゼンスの WebSocket パターンと、代替手段としての REST ポーリングを紹介します。

主な機能

  1. 01WebSocket 接続例
  2. 02テーブル変更の購読とフィルター
  3. 03ブロードキャストのパターン
  4. 04プレゼンス追跡の例
  5. 05REST ポーリングの代替案

活用シーン

  1. 01開発中のテーブル変更の監視
  2. 02スクリプトでのログやイベントのストリーミング
  3. 03Supabase Realtime 購読のテスト

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/nice-wolf-studio/claude-code-supabase-skills --skill supabase-realtime

インストール後、Claude Code で/supabase-realtimeを入力して読み込まれたか確認します。

詳細

Supabase Realtime

概要

このスキルでは、Supabase Realtime の機能を使用する方法を説明します。Realtime では、WebSocket 接続を使用してデータベースの変更をリッスンしたり、メッセージをブロードキャストしたり、プレゼンスを追跡したりできます。

注: Realtime の操作には WebSocket のサポートが必要で、bash での実装はより複雑です。このスキルでは、利用可能なツールを使った実用的なパターンと例に焦点を当てます。

前提条件

必須の環境変数:

export SUPABASE_URL="https://your-project.supabase.co"
export SUPABASE_KEY="your-anon-or-service-role-key"

追加ツール:

  • WebSocket 接続用の websocat または wscat
  • JSON 処理用の jq

websocat のインストール:

# macOS
brew install websocat

# Linux
wget https://github.com/vi/websocat/releases/download/v1.12.0/websocat.x86_64-unknown-linux-musl
chmod +x websocat.x86_64-unknown-linux-musl
sudo mv websocat.x86_64-unknown-linux-musl /usr/local/bin/websocat

WebSocket 接続

Supabase Realtime に接続する:

SUPABASE_URL="https://your-project.supabase.co"
SUPABASE_KEY="your-anon-key"

# Extract WebSocket URL (replace https:// with wss://)
WS_URL=$(echo "$SUPABASE_URL" | sed 's/https:/wss:/')

# Connect to realtime
websocat "${WS_URL}/realtime/v1/websocket?apikey=${SUPABASE_KEY}&vsn=1.0.0"

データベース変更のサブスクリプション

テーブルの変更をサブスクライブする

テーブルのすべての変更をリッスンする:

#!/bin/bash

SUPABASE_URL="https://your-project.supabase.co"
SUPABASE_KEY="your-anon-key"
WS_URL=$(echo "$SUPABASE_URL" | sed 's/https:/wss:/')

# Create subscription message
SUB_MESSAGE='{
  "topic": "realtime:public:users",
  "event": "phx_join",
  "payload": {},
  "ref": "1"
}'

# Connect and subscribe
echo "$SUB_MESSAGE" | websocat "${WS_URL}/realtime/v1/websocket?apikey=${SUPABASE_KEY}&vsn=1.0.0"

特定のイベントをサブスクライブする:

# Listen for INSERT events only
SUB_MESSAGE='{
  "topic": "realtime:public:users",
  "event": "phx_join",
  "payload": {
    "config": {
      "postgres_changes": [
        {
          "event": "INSERT",
          "schema": "public",
          "table": "users"
        }
      ]
    }
  },
  "ref": "1"
}'

echo "$SUB_MESSAGE" | websocat "${WS_URL}/realtime/v1/websocket?apikey=${SUPABASE_KEY}&vsn=1.0.0"

UPDATE イベントをサブスクライブする:

SUB_MESSAGE='{
  "topic": "realtime:public:products",
  "event": "phx_join",
  "payload": {
    "config": {
      "postgres_changes": [
        {
          "event": "UPDATE",
          "schema": "public",
          "table": "products"
        }
      ]
    }
  },
  "ref": "1"
}'

DELETE イベントをサブスクライブする:

SUB_MESSAGE='{
  "topic": "realtime:public:posts",
  "event": "phx_join",
  "payload": {
    "config": {
      "postgres_changes": [
        {
          "event": "DELETE",
          "schema": "public",
          "table": "posts"
        }
      ]
    }
  },
  "ref": "1"
}'

すべてのイベント(*、INSERT、UPDATE、DELETE)をサブスクライブする:

SUB_MESSAGE='{
  "topic": "realtime:public:orders",
  "event": "phx_join",
  "payload": {
    "config": {
      "postgres_changes": [
        {
          "event": "*",
          "schema": "public",
          "table": "orders"
        }
      ]
    }
  },
  "ref": "1"
}'
サブスクリプションのフィルター

フィルターに一致する変更をリッスンする:

# Only listen to changes where status = 'active'
SUB_MESSAGE='{
  "topic": "realtime:public:users",
  "event": "phx_join",
  "payload": {
    "config": {
      "postgres_changes": [
        {
          "event": "*",
          "schema": "public",
          "table": "users",
          "filter": "status=eq.active"
        }
      ]
    }
  },
  "ref": "1"
}'

ブロードキャストメッセージ

ブロードキャストメッセージを送信する

チャンネルにメッセージをブロードキャストする:

#!/bin/bash

SUPABASE_URL="https://your-project.supabase.co"
SUPABASE_KEY="your-anon-key"
WS_URL=$(echo "$SUPABASE_URL" | sed 's/https:/wss:/')

# Join channel first
JOIN_MESSAGE='{
  "topic": "realtime:chat-room-1",
  "event": "phx_join",
  "payload": {
    "config": {
      "broadcast": {
        "self": true
      }
    }
  },
  "ref": "1"
}'

# Broadcast message
BROADCAST_MESSAGE='{
  "topic": "realtime:chat-room-1",
  "event": "broadcast",
  "payload": {
    "type": "message",
    "event": "new_message",
    "payload": {
      "user": "Alice",
      "message": "Hello, World!"
    }
  },
  "ref": "2"
}'

# Send messages
{
  echo "$JOIN_MESSAGE"
  sleep 1
  echo "$BROADCAST_MESSAGE"
} | websocat "${WS_URL}/realtime/v1/websocket?apikey=${SUPABASE_KEY}&vsn=1.0.0"
ブロードキャストメッセージをリッスンする

ブロードキャストメッセージを受信する:

# Join channel and listen
JOIN_MESSAGE='{
  "topic": "realtime:chat-room-1",
  "event": "phx_join",
  "payload": {
    "config": {
      "broadcast": {
        "self": false
      }
    }
  },
  "ref": "1"
}'

echo "$JOIN_MESSAGE" | websocat "${WS_URL}/realtime/v1/websocket?apikey=${SUPABASE_KEY}&vsn=1.0.0"

プレゼンスの追跡

プレゼンスを追跡する

プレゼンスを有効にしてチャンネルに参加する:

PRESENCE_MESSAGE='{
  "topic": "realtime:lobby",
  "event": "phx_join",
  "payload": {
    "config": {
      "presence": {
        "key": "user-123"
      }
    }
  },
  "ref": "1"
}'

# Track presence state
TRACK_MESSAGE='{
  "topic": "realtime:lobby",
  "event": "presence",
  "payload": {
    "type": "presence",
    "event": "track",
    "payload": {
      "user_id": "123",
      "username": "Alice",
      "status": "online"
    }
  },
  "ref": "2"
}'
プレゼンスの追跡を停止する

プレゼンスから退出する:

UNTRACK_MESSAGE='{
  "topic": "realtime:lobby",
  "event": "presence",
  "payload": {
    "type": "presence",
    "event": "untrack"
  },
  "ref": "3"
}'

実用的なパターン

継続的なリスナースクリプト
#!/bin/bash
# listen-to-changes.sh

SUPABASE_URL="https://your-project.supabase.co"
SUPABASE_KEY="your-anon-key"
WS_URL=$(echo "$SUPABASE_URL" | sed 's/https:/wss:/')
TABLE="users"

echo "Listening for changes on $TABLE table..."

# Subscribe to changes
SUB_MESSAGE='{
  "topic": "realtime:public:'"$TABLE"'",
  "event": "phx_join",
  "payload": {
    "config": {
      "postgres_changes": [
        {
          "event": "*",
          "schema": "public",
          "table": "'"$TABLE"'"
        }
      ]
    }
  },
  "ref": "1"
}'

# Listen continuously
echo "$SUB_MESSAGE" | websocat "${WS_URL}/realtime/v1/websocket?apikey=${SUPABASE_KEY}&vsn=1.0.0" | \
while IFS= read -r line; do
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $line" | jq '.'
done
ハンドラーで変更を処理する
#!/bin/bash
# process-changes.sh

handle_insert() {
    local record="$1"
    echo "New record inserted:"
    echo "$record" | jq '.payload.record'

    # Your custom logic here
    # Example: Send notification, update cache, etc.
}

handle_update() {
    local old_record="$1"
    local new_record="$2"
    echo "Record updated:"
    echo "Old: $(echo "$old_record" | jq -c '.')"
    echo "New: $(echo "$new_record" | jq -c '.')"
}

handle_delete() {
    local record="$1"
    echo "Record deleted:"
    echo "$record" | jq '.payload.old_record'
}

# Listen and process
websocat "${WS_URL}/realtime/v1/websocket?apikey=${SUPABASE_KEY}&vsn=1.0.0" | \
while IFS= read -r line; do
    event_type=$(echo "$line" | jq -r '.payload.data.type // empty')

    case "$event_type" in
        "INSERT")
            handle_insert "$(echo "$line" | jq '.payload.data')"
            ;;
        "UPDATE")
            handle_update \
                "$(echo "$line" | jq '.payload.data.old_record')" \
                "$(echo "$line" | jq '.payload.data.record')"
            ;;
        "DELETE")
            handle_delete "$(echo "$line" | jq '.payload.data')"
            ;;
    esac
done
複数テーブルのリスナー
#!/bin/bash
# listen-multiple-tables.sh

TABLES=("users" "posts" "comments")

for table in "${TABLES[@]}"; do
    (
        echo "Starting listener for $table"
        SUB_MESSAGE='{
          "topic": "realtime:public:'"$table"'",
          "event": "phx_join",
          "payload": {
            "config": {
              "postgres_changes": [{"event": "*", "schema": "public", "table": "'"$table"'"}]
            }
          },
          "ref": "1"
        }'

        echo "$SUB_MESSAGE" | websocat "${WS_URL}/realtime/v1/websocket?apikey=${SUPABASE_KEY}&vsn=1.0.0" | \
        while IFS= read -r line; do
            echo "[$table] $line"
        done
    ) &
done

wait

メッセージ形式

サブスクリプションの確認
{
  "event": "phx_reply",
  "payload": {
    "response": {
      "postgres_changes": [
        {
          "id": "12345",
          "event": "*",
          "schema": "public",
          "table": "users"
        }
      ]
    },
    "status": "ok"
  },
  "ref": "1",
  "topic": "realtime:public:users"
}
INSERT イベント
{
  "event": "postgres_changes",
  "payload": {
    "data": {
      "commit_timestamp": "2023-01-01T12:00:00Z",
      "record": {
        "id": 123,
        "name": "John Doe",
        "email": "[email protected]"
      },
      "schema": "public",
      "table": "users",
      "type": "INSERT"
    },
    "ids": [12345]
  },
  "topic": "realtime:public:users"
}
UPDATE イベント
{
  "event": "postgres_changes",
  "payload": {
    "data": {
      "commit_timestamp": "2023-01-01T12:00:00Z",
      "old_record": {
        "id": 123,
        "name": "John Doe"
      },
      "record": {
        "id": 123,
        "name": "Jane Doe"
      },
      "schema": "public",
      "table": "users",
      "type": "UPDATE"
    }
  }
}
DELETE イベント
{
  "event": "postgres_changes",
  "payload": {
    "data": {
      "commit_timestamp": "2023-01-01T12:00:00Z",
      "old_record": {
        "id": 123,
        "name": "John Doe"
      },
      "schema": "public",
      "table": "users",
      "type": "DELETE"
    }
  }
}

代替方法:REST ポーリング

WebSocket の利用が現実的でない、よりシンプルなユースケースでは、ポーリングを検討してください。

#!/bin/bash
# poll-changes.sh

source "$(dirname "${BASH_SOURCE[0]}")/../../scripts/supabase-api.sh"

LAST_TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)

while true; do
    # Get records created/updated since last check
    new_records=$(supabase_get "/rest/v1/users?updated_at=gt.${LAST_TIMESTAMP}&order=updated_at.asc")

    if [[ "$new_records" != "[]" ]]; then
        echo "New changes detected:"
        echo "$new_records" | jq '.'

        # Update timestamp
        LAST_TIMESTAMP=$(echo "$new_records" | jq -r '.[-1].updated_at')
    fi

    # Poll every 5 seconds
    sleep 5
done

Realtime の設定

Supabase Dashboard で Realtime を有効にする:

  1. Database > Replication に移動します
  2. リッスンするテーブルのレプリケーションを有効にします
  3. パブリッシュするイベント(INSERT、UPDATE、DELETE)を選択します

行レベルセキュリティ: Realtime は RLS ポリシーに従います。ユーザーが受信するのは、アクセス権のある行の変更のみです。

制限事項

  • WebSocket 接続には、永続的な接続管理が必要です
  • WebSocket の処理に bash は適していません(本番環境では Node.js/Python を検討してください)
  • 接続が切断された場合は、再接続ロジックが必要です
  • Realtime には Supabase のプランに応じた接続数の制限があります

ユースケース

bash での Realtime に適している用途:

  • 開発/デバッグツール
  • シンプルな監視スクリプト
  • ログのストリーミング
  • リアルタイム機能のテスト

他の言語のほうが適している用途:

  • 本番環境のチャットアプリケーション
  • 複雑なプレゼンス追跡
  • 複数チャンネルの連携
  • 自動再接続が必要な場合

API ドキュメント

Supabase Realtime のドキュメント全文:https://supabase.com/docs/guides/realtime

コメント