supabase-realtime
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSupabase Realtime
Supabase Realtime
Overview
概述
This skill provides guidance for working with Supabase Realtime features. Realtime allows you to listen to database changes, broadcast messages, and track presence using WebSocket connections.
Note: Realtime operations require WebSocket support, which is more complex in bash. This skill focuses on practical patterns and examples using available tools.
本技能提供了使用Supabase Realtime功能的指导。Realtime允许你通过WebSocket连接监听数据库变更、广播消息以及追踪在线状态。
注意: Realtime操作需要WebSocket支持,这在bash中实现起来较为复杂。本技能聚焦于使用现有工具的实用模式和示例。
Prerequisites
前提条件
Required environment variables:
bash
export SUPABASE_URL="https://your-project.supabase.co"
export SUPABASE_KEY="your-anon-or-service-role-key"Additional tools:
- or
websocatfor WebSocket connectionswscat - for JSON processing
jq
Install websocat:
bash
undefined所需环境变量:
bash
export SUPABASE_URL="https://your-project.supabase.co"
export SUPABASE_KEY="your-anon-or-service-role-key"额外工具:
- 或
websocat用于WebSocket连接wscat - 用于JSON处理
jq
安装websocat:
bash
undefinedmacOS
macOS
brew install websocat
brew install websocat
Linux
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
undefinedwget 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
undefinedWebSocket Connection
WebSocket连接
Connect to Supabase Realtime:
bash
SUPABASE_URL="https://your-project.supabase.co"
SUPABASE_KEY="your-anon-key"连接到Supabase Realtime:
bash
SUPABASE_URL="https://your-project.supabase.co"
SUPABASE_KEY="your-anon-key"Extract WebSocket URL (replace https:// with wss://)
提取WebSocket URL(将https://替换为wss://)
WS_URL=$(echo "$SUPABASE_URL" | sed 's/https:/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"
undefinedwebsocat "${WS_URL}/realtime/v1/websocket?apikey=${SUPABASE_KEY}&vsn=1.0.0"
undefinedDatabase Change Subscriptions
数据库变更订阅
Subscribe to Table Changes
订阅表变更
Listen to all changes on a table:
bash
#!/bin/bash
SUPABASE_URL="https://your-project.supabase.co"
SUPABASE_KEY="your-anon-key"
WS_URL=$(echo "$SUPABASE_URL" | sed 's/https:/wss:/')监听某个表的所有变更:
bash
#!/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"
}'
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"
**Subscribe to specific events:**
```bashecho "$SUB_MESSAGE" | websocat "${WS_URL}/realtime/v1/websocket?apikey=${SUPABASE_KEY}&vsn=1.0.0"
**订阅特定事件:**
```bashListen for INSERT events only
仅监听INSERT事件
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"
**Subscribe to UPDATE events:**
```bash
SUB_MESSAGE='{
"topic": "realtime:public:products",
"event": "phx_join",
"payload": {
"config": {
"postgres_changes": [
{
"event": "UPDATE",
"schema": "public",
"table": "products"
}
]
}
},
"ref": "1"
}'Subscribe to DELETE events:
bash
SUB_MESSAGE='{
"topic": "realtime:public:posts",
"event": "phx_join",
"payload": {
"config": {
"postgres_changes": [
{
"event": "DELETE",
"schema": "public",
"table": "posts"
}
]
}
},
"ref": "1"
}'Subscribe to all events (*, INSERT, UPDATE, DELETE):
bash
SUB_MESSAGE='{
"topic": "realtime:public:orders",
"event": "phx_join",
"payload": {
"config": {
"postgres_changes": [
{
"event": "*",
"schema": "public",
"table": "orders"
}
]
}
},
"ref": "1"
}'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事件:**
```bash
SUB_MESSAGE='{
"topic": "realtime:public:products",
"event": "phx_join",
"payload": {
"config": {
"postgres_changes": [
{
"event": "UPDATE",
"schema": "public",
"table": "products"
}
]
}
},
"ref": "1"
}'订阅DELETE事件:
bash
SUB_MESSAGE='{
"topic": "realtime:public:posts",
"event": "phx_join",
"payload": {
"config": {
"postgres_changes": [
{
"event": "DELETE",
"schema": "public",
"table": "posts"
}
]
}
},
"ref": "1"
}'订阅所有事件(*, INSERT, UPDATE, DELETE):
bash
SUB_MESSAGE='{
"topic": "realtime:public:orders",
"event": "phx_join",
"payload": {
"config": {
"postgres_changes": [
{
"event": "*",
"schema": "public",
"table": "orders"
}
]
}
},
"ref": "1"
}'Filter Subscriptions
过滤订阅
Listen to changes matching a filter:
bash
undefined监听符合过滤条件的变更:
bash
undefinedOnly listen to changes where status = 'active'
仅监听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"
}'
undefinedSUB_MESSAGE='{
"topic": "realtime:public:users",
"event": "phx_join",
"payload": {
"config": {
"postgres_changes": [
{
"event": "*",
"schema": "public",
"table": "users",
"filter": "status=eq.active"
}
]
}
},
"ref": "1"
}'
undefinedBroadcast Messaging
广播消息
Send Broadcast Message
发送广播消息
Broadcast a message to a channel:
bash
#!/bin/bash
SUPABASE_URL="https://your-project.supabase.co"
SUPABASE_KEY="your-anon-key"
WS_URL=$(echo "$SUPABASE_URL" | sed 's/https:/wss:/')向频道广播消息:
bash
#!/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"
}'
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"
}'
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"
undefined{
echo "$JOIN_MESSAGE"
sleep 1
echo "$BROADCAST_MESSAGE"
} | websocat "${WS_URL}/realtime/v1/websocket?apikey=${SUPABASE_KEY}&vsn=1.0.0"
undefinedListen to Broadcast Messages
监听广播消息
Receive broadcast messages:
bash
undefined接收广播消息:
bash
undefinedJoin 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"
undefinedJOIN_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"
undefinedPresence Tracking
在线状态追踪
Track Presence
追踪在线状态
Join channel with presence:
bash
PRESENCE_MESSAGE='{
"topic": "realtime:lobby",
"event": "phx_join",
"payload": {
"config": {
"presence": {
"key": "user-123"
}
}
},
"ref": "1"
}'加入带在线状态追踪的频道:
bash
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"
}'
undefinedTRACK_MESSAGE='{
"topic": "realtime:lobby",
"event": "presence",
"payload": {
"type": "presence",
"event": "track",
"payload": {
"user_id": "123",
"username": "Alice",
"status": "online"
}
},
"ref": "2"
}'
undefinedUntrack Presence
取消在线状态追踪
Leave presence:
bash
UNTRACK_MESSAGE='{
"topic": "realtime:lobby",
"event": "presence",
"payload": {
"type": "presence",
"event": "untrack"
},
"ref": "3"
}'退出在线状态追踪:
bash
UNTRACK_MESSAGE='{
"topic": "realtime:lobby",
"event": "presence",
"payload": {
"type": "presence",
"event": "untrack"
},
"ref": "3"
}'Practical Patterns
实用模式
Continuous Listener Script
持续监听脚本
bash
#!/bin/bashbash
#!/bin/bashlisten-to-changes.sh
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..."
SUPABASE_URL="https://your-project.supabase.co"
SUPABASE_KEY="your-anon-key"
WS_URL=$(echo "$SUPABASE_URL" | sed 's/https:/wss:/')
TABLE="users"
echo "正在监听$TABLE表的变更..."
Subscribe to changes
订阅变更
SUB_MESSAGE='{
"topic": "realtime:public:'"$TABLE"'",
"event": "phx_join",
"payload": {
"config": {
"postgres_changes": [
{
"event": "*",
"schema": "public",
"table": "'"$TABLE"'"
}
]
}
},
"ref": "1"
}'
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
while IFS= read -r line; do echo "[$(date '+%Y-%m-%d %H:%M:%S')] $line" | jq '.' done
undefinedecho "$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
while IFS= read -r line; do echo "[$(date '+%Y-%m-%d %H:%M:%S')] $line" | jq '.' done
undefinedProcess Changes with Handler
使用处理器处理变更
bash
#!/bin/bashbash
#!/bin/bashprocess-changes.sh
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'
}
handle_insert() {
local record="$1"
echo "插入新记录:"
echo "$record" | jq '.payload.record'
# 此处添加自定义逻辑
# 示例:发送通知、更新缓存等}
handle_update() {
local old_record="$1"
local new_record="$2"
echo "记录已更新:"
echo "旧记录:$(echo "$old_record" | jq -c '.')"
echo "新记录:$(echo "$new_record" | jq -c '.')"
}
handle_delete() {
local record="$1"
echo "记录已删除:"
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')
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')"
;;
esacdone
undefinedwebsocat "${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')
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')"
;;
esacdone
undefinedMulti-Table Listener
多表监听脚本
bash
#!/bin/bashbash
#!/bin/bashlisten-multiple-tables.sh
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
undefinedTABLES=("users" "posts" "comments")
for table in "${TABLES[@]}"; do
(
echo "开始监听$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
undefinedMessage Format
消息格式
Subscription Confirmation
订阅确认
json
{
"event": "phx_reply",
"payload": {
"response": {
"postgres_changes": [
{
"id": "12345",
"event": "*",
"schema": "public",
"table": "users"
}
]
},
"status": "ok"
},
"ref": "1",
"topic": "realtime:public:users"
}json
{
"event": "phx_reply",
"payload": {
"response": {
"postgres_changes": [
{
"id": "12345",
"event": "*",
"schema": "public",
"table": "users"
}
]
},
"status": "ok"
},
"ref": "1",
"topic": "realtime:public:users"
}INSERT Event
INSERT事件
json
{
"event": "postgres_changes",
"payload": {
"data": {
"commit_timestamp": "2023-01-01T12:00:00Z",
"record": {
"id": 123,
"name": "John Doe",
"email": "john@example.com"
},
"schema": "public",
"table": "users",
"type": "INSERT"
},
"ids": [12345]
},
"topic": "realtime:public:users"
}json
{
"event": "postgres_changes",
"payload": {
"data": {
"commit_timestamp": "2023-01-01T12:00:00Z",
"record": {
"id": 123,
"name": "John Doe",
"email": "john@example.com"
},
"schema": "public",
"table": "users",
"type": "INSERT"
},
"ids": [12345]
},
"topic": "realtime:public:users"
}UPDATE Event
UPDATE事件
json
{
"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"
}
}
}json
{
"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
DELETE事件
json
{
"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"
}
}
}json
{
"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"
}
}
}Alternative: REST Polling
替代方案:REST轮询
For simpler use cases where WebSockets are impractical, consider polling:
bash
#!/bin/bash对于WebSocket不适用的简单场景,可以考虑轮询:
bash
#!/bin/bashpoll-changes.sh
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 5done
undefinedsource "$(dirname "${BASH_SOURCE[0]}")/../../scripts/supabase-api.sh"
LAST_TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
while true; do
# 获取自上次检查以来创建/更新的记录
new_records=$(supabase_get "/rest/v1/users?updated_at=gt.${LAST_TIMESTAMP}&order=updated_at.asc")
if [[ "$new_records" != "[]" ]]; then
echo "检测到新变更:"
echo "$new_records" | jq '.'
# 更新时间戳
LAST_TIMESTAMP=$(echo "$new_records" | jq -r '.[-1].updated_at')
fi
# 每5秒轮询一次
sleep 5done
undefinedRealtime Configuration
Realtime配置
Enable Realtime in Supabase Dashboard:
- Go to Database > Replication
- Enable replication for tables you want to listen to
- Choose which events to publish (INSERT, UPDATE, DELETE)
Row Level Security:
Realtime respects RLS policies. Users only receive changes for rows they have access to.
在Supabase控制台中启用Realtime:
- 进入数据库 > 复制
- 为需要监听的表启用复制功能
- 选择要发布的事件(INSERT、UPDATE、DELETE)
行级安全性:
Realtime会遵循RLS策略。用户只会收到他们有权访问的行的变更。
Limitations
限制
- WebSocket connections require persistent connection management
- Bash is not ideal for WebSocket handling (consider Node.js/Python for production)
- Connection drops require reconnection logic
- Realtime is subject to connection limits based on your Supabase plan
- WebSocket连接需要持久连接管理
- Bash并非处理WebSocket的理想选择(生产环境建议使用Node.js/Python)
- 连接断开需要重连逻辑
- Realtime的连接数量受限于你的Supabase套餐
Use Cases
使用场景
Good for Realtime in bash:
- Development/debugging tools
- Simple monitoring scripts
- Log streaming
- Testing realtime functionality
Better in other languages:
- Production chat applications
- Complex presence tracking
- Multi-channel coordination
- Auto-reconnection requirements
适合在bash中使用Realtime的场景:
- 开发/调试工具
- 简单监控脚本
- 日志流
- 测试实时功能
更适合其他语言的场景:
- 生产环境聊天应用
- 复杂在线状态追踪
- 多频道协调
- 自动重连需求
API Documentation
API文档
Full Supabase Realtime documentation: https://supabase.com/docs/guides/realtime
完整的Supabase Realtime文档:https://supabase.com/docs/guides/realtime