From 07c79366602005c84a69f4fddbd95c7f05bb3717 Mon Sep 17 00:00:00 2001
From: Tyler <18113850+dshukertjr@users.noreply.github.com>
Date: Thu, 7 Dec 2023 12:36:17 +0900
Subject: [PATCH] guide: adds Dart code sample to realtime giudes (#19323)
* adds Dart code sample to broadcast docs
* adds Dart code sample to presence guide
* add Dart code sample to realtime postgres change guide
* run prettier
* add Dart code sample on client side throttling
* add dart code sample to realtime overview
* run prettier
* update presence methods
---
apps/docs/pages/guides/realtime.mdx | 49 ++-
apps/docs/pages/guides/realtime/broadcast.mdx | 112 ++++++-
.../guides/client-side-throttling.mdx | 32 ++
.../guides/realtime/postgres-changes.mdx | 300 ++++++++++++++++++
apps/docs/pages/guides/realtime/presence.mdx | 79 ++++-
5 files changed, 565 insertions(+), 7 deletions(-)
diff --git a/apps/docs/pages/guides/realtime.mdx b/apps/docs/pages/guides/realtime.mdx
index ba3a79314d4..ba44847800a 100644
--- a/apps/docs/pages/guides/realtime.mdx
+++ b/apps/docs/pages/guides/realtime.mdx
@@ -53,7 +53,16 @@ alter
From the client, we can listen to any new data that is inserted into the `todos` table:
-```javascript
+
+
+
+```js
// Initialize the JS client
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY)
@@ -70,6 +79,44 @@ supabase
.subscribe()
```
+
+
+
+```dart
+import 'package:supabase_flutter/supabase_flutter.dart';
+
+void main() async {
+ // Initialize the Flutter client
+ Supabase.initialize(
+ url: 'https://.supabase.co',
+ anonKey: '',
+ realtimeClientOptions: const RealtimeClientOptions(
+ eventsPerSecond: 2,
+ ),
+ );
+ runApp(const MyApp());
+}
+
+final supabase = Supabase.instance.client;
+
+void handleInserts(payload) {
+ print('Change received! $payload');
+}
+
+// Listen to inserts
+supabase
+ .channel('todos')
+ .onPostgresChanges(
+ event: PostgresChangeEvent.insert,
+ schema: 'public',
+ table: 'todos',
+ callback: handleInserts)
+ .subscribe();
+```
+
+
+
+
Use [subscribe()](/docs/reference/javascript/subscribe) to listen to database changes.
The Realtime API works through PostgreSQL's replication functionality. Postgres sends database changes to a [publication](/docs/guides/database/replication#publications)
called `supabase_realtime`, and by managing this publication you can control which data is broadcast.
diff --git a/apps/docs/pages/guides/realtime/broadcast.mdx b/apps/docs/pages/guides/realtime/broadcast.mdx
index 177ced85477..f1707ad7249 100644
--- a/apps/docs/pages/guides/realtime/broadcast.mdx
+++ b/apps/docs/pages/guides/realtime/broadcast.mdx
@@ -35,6 +35,23 @@ const SUPABASE_KEY = ''
const client = createClient(SUPABASE_URL, SUPABASE_KEY)
```
+
+
+
+```dart
+import 'package:supabase_flutter/supabase_flutter.dart';
+
+void main() async {
+ Supabase.initialize(
+ url: 'https://.supabase.co',
+ anonKey: '',
+ );
+ runApp(MyApp());
+}
+
+final supabase = Supabase.instance.client;
+```
+
@@ -82,6 +99,22 @@ channelA
.subscribe()
```
+
+
+
+```dart
+// Simple function to log any messages we receive
+void messageReceived(payload) {
+ print(payload);
+}
+
+// Subscribe to the Channel
+channelA
+ .onBroadcast(
+ event: 'test', callback: (payload) => messageReceived(payload))
+ .subscribe();
+```
+
@@ -135,6 +168,27 @@ channelB.subscribe((status) => {
})
```
+
+
+
+```dart
+// Join a room/topic. Can be anything except for 'realtime'.
+final channelB = supabase.channel('room-1');
+
+channelB.subscribe((status, error) {
+ // Wait for successful connection
+ if (status != RealtimeSubscribeStatus.subscribed) {
+ return;
+ }
+
+ // Send a message once the client is subscribed
+ channelB.sendBroadcastMessage(
+ event: 'test',
+ payload: {'message': 'hello, world'},
+ );
+});
+```
+
@@ -199,6 +253,32 @@ myChannel.subscribe((status) => {
})
```
+
+
+
+```dart
+final myChannel = supabase.channel(
+ 'room-2',
+ opts: const RealtimeChannelConfig(
+ self: true,
+ ),
+);
+
+myChannel.onBroadcast(
+ event: 'test-my-messages',
+ callback: (payload) => print(payload),
+);
+
+myChannel.subscribe((status, error) {
+ if (status != RealtimeSubscribeStatus.subscribed) return;
+ // channelC.send({
+ myChannel.sendBroadcastMessage(
+ event: 'test-my-messages',
+ payload: {'message': 'talking to myself'},
+ );
+});
+```
+
@@ -265,6 +345,29 @@ myChannel.subscribe(async (status) => {
})
```
+
+
+
+```dart
+final myChannel = supabase.channel('room-3',opts: const RealtimeChannelConfig(
+ ack: true,
+),
+
+);
+
+myChannel.subscribe( (status, error) async {
+ if (status != RealtimeSubscribeStatus.subscribed) return;
+
+ final serverResponse = await myChannel.sendBroadcastMessage(
+
+ event: 'acknowledge',
+ payload: {},
+ );
+
+ print('serverResponse: $serverResponse');
+});
+```
+
@@ -330,15 +433,14 @@ client.removeChannel(channel)
```dart
// No need to subscribe to channel
-channel = client.channel('test-channel');
-final resp = await channel.send(
- type: RealtimeListenTypes.broadcast,
+final channel = supabase.channel('test-channel');
+final res = await channel.sendBroadcastMessage(
+ event: "test",
payload: {
'message': 'Hi',
},
- event: "test"
);
-print(resp);
+print(res);
````
diff --git a/apps/docs/pages/guides/realtime/guides/client-side-throttling.mdx b/apps/docs/pages/guides/realtime/guides/client-side-throttling.mdx
index 55ff58726de..cc718c23a03 100644
--- a/apps/docs/pages/guides/realtime/guides/client-side-throttling.mdx
+++ b/apps/docs/pages/guides/realtime/guides/client-side-throttling.mdx
@@ -13,6 +13,15 @@ The Supabase clients include functionality for throttling messages.
You can customize the client-side throttling when creating the client:
+
+
+
```js
import { createClient } from '@supabase/supabase-js'
@@ -28,6 +37,29 @@ const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {
})
```
+
+
+
+```dart
+import 'package:supabase_flutter/supabase_flutter.dart';
+
+void main() async {
+ Supabase.initialize(
+ url: 'https://.supabase.co',
+ anonKey: '',
+ realtimeClientOptions: const RealtimeClientOptions(
+ eventsPerSecond: 2,
+ ),
+ );
+ runApp(const MyApp());
+}
+
+final supabase = Supabase.instance.client;
+```
+
+
+
+
## Default client throttling
By default the Supabase clients throttles messages to 10 messages per-second (1 message every 100 milliseconds). This is a soft-limit provided as a safe-guard when you're getting started. You'll rarely need to send more messages than this.
diff --git a/apps/docs/pages/guides/realtime/postgres-changes.mdx b/apps/docs/pages/guides/realtime/postgres-changes.mdx
index 681f5a0df8d..8d4d11e0dab 100644
--- a/apps/docs/pages/guides/realtime/postgres-changes.mdx
+++ b/apps/docs/pages/guides/realtime/postgres-changes.mdx
@@ -226,6 +226,20 @@ const changes = client
.subscribe()
```
+
+
+
+```dart
+supabase
+ .channel('schema-db-changes')
+ .onPostgresChanges(
+ schema: 'public', // Subscribes to the "public" schema in Postgres
+ event: PostgresChangeEvent.all, // Listen to all changes
+
+ callback: (payload) => print(payload))
+ .subscribe();
+```
+
@@ -280,6 +294,19 @@ const changes = client
.subscribe()
```
+
+
+
+```dart
+final changes = supabase
+ .channel('schema-db-changes')
+ .onPostgresChanges(
+ event: PostgresChangeEvent.insert,
+ schema: 'public',
+ callback: (payload) => print(payload))
+ .subscribe();
+```
+
@@ -332,6 +359,19 @@ const changes = client
.subscribe()
```
+
+
+
+```dart
+supabase
+ .channel('schema-db-changes')
+ .onPostgresChanges(
+ event: PostgresChangeEvent.update, // Listen only to UPDATEs
+ schema: 'public',
+ callback: (payload) => print(payload))
+ .subscribe();
+```
+
@@ -384,6 +424,19 @@ const changes = client
.subscribe()
```
+
+
+
+```dart
+supabase
+ .channel('schema-db-changes')
+ .onPostgresChanges(
+ event: PostgresChangeEvent.delete, // Listen only to DELETEs
+ schema: 'public',
+ callback: (payload) => print(payload))
+ .subscribe();
+```
+
@@ -437,6 +490,20 @@ const changes = client
.subscribe()
```
+
+
+
+```dart
+supabase
+ .channel('table-db-changes')
+ .onPostgresChanges(
+ event: PostgresChangeEvent.all,
+ schema: 'public',
+ table: 'todos',
+ callback: (payload) => print(payload))
+ .subscribe();
+```
+
@@ -499,6 +566,25 @@ const channel = supabase
.subscribe()
```
+
+
+
+```dart
+supabase
+ .channel('db-changes')
+ .onPostgresChanges(
+ event: PostgresChangeEvent.all,
+ schema: 'public',
+ table: 'messages',
+ callback: (payload) => print(payload))
+ .onPostgresChanges(
+ event: PostgresChangeEvent.insert,
+ schema: 'public',
+ table: 'users',
+ callback: (payload) => print(payload))
+ .subscribe();
+```
+
@@ -546,6 +632,25 @@ const changes = client
.subscribe()
```
+
+
+
+```dart
+ supabase
+ .channel('table-filter-changes')
+ .onPostgresChanges(
+ event: PostgresChangeEvent.insert,
+ schema: 'public',
+ table: 'todos',
+ filter: PostgresChangeFilter(
+ type: PostgresChangeFilterType.eq,
+ column: 'id',
+ value: 1,
+ ),
+ callback: (payload) => print(payload))
+ .subscribe();
+```
+
@@ -603,6 +708,25 @@ const channel = supabase
.subscribe()
```
+
+
+
+```dart
+supabase
+ .channel('changes')
+ .onPostgresChanges(
+ event: PostgresChangeEvent.update,
+ schema: 'public',
+ table: 'messages',
+ filter: PostgresChangeFilter(
+ type: PostgresChangeFilterType.eq,
+ column: 'body',
+ value: 'hey',
+ ),
+ callback: (payload) => print(payload))
+ .subscribe();
+```
+
@@ -633,6 +757,15 @@ This filter uses Postgres's `=` filter.
To listen to changes when a column's value in a table does not equal a client-specified value:
+
+
+
```js
const channel = supabase
.channel('changes')
@@ -649,6 +782,49 @@ const channel = supabase
.subscribe()
```
+
+
+
+```dart
+supabase
+ .channel('changes')
+ .onPostgresChanges(
+ event: PostgresChangeEvent.insert,
+ schema: 'public',
+ table: 'messages',
+ filter: PostgresChangeFilter(
+ type: PostgresChangeFilterType.neq,
+ column: 'body',
+ value: 'bye',
+ ),
+ callback: (payload) => print(payload))
+ .subscribe();
+```
+
+
+
+
+```kotlin
+val myChannel = supabase.realtime.createChannel("db-changes")
+
+val changes = myChannel.postgresChangeFlow(schema = "public") {
+ table = "messages"
+ filter = "body=neq.bye"
+}
+
+changes
+ .onEach {
+ println(it.record)
+ }
+ .launchIn(yourCoroutineScope)
+
+supabase.realtime.connect()
+myChannel.join()
+```
+
+
+
+
This filter uses Postgres's `!=` filter.
### Less than (lt)
@@ -680,6 +856,25 @@ const channel = supabase
.subscribe()
```
+
+
+
+```dart
+supabase
+ .channel('changes')
+ .onPostgresChanges(
+ event: PostgresChangeEvent.insert,
+ schema: 'public',
+ table: 'profiles',
+ filter: PostgresChangeFilter(
+ type: PostgresChangeFilterType.lt,
+ column: 'age',
+ value: 65,
+ ),
+ callback: (payload) => print(payload))
+ .subscribe();
+```
+
@@ -735,6 +930,25 @@ const channel = supabase
.subscribe()
```
+
+
+
+```dart
+supabase
+ .channel('changes')
+ .onPostgresChanges(
+ event: PostgresChangeEvent.insert,
+ schema: 'public',
+ table: 'profiles',
+ filter: PostgresChangeFilter(
+ type: PostgresChangeFilterType.lte,
+ column: 'age',
+ value: 65,
+ ),
+ callback: (payload) => print(payload))
+ .subscribe();
+```
+
@@ -790,6 +1004,25 @@ const channel = supabase
.subscribe()
```
+
+
+
+```dart
+supabase
+ .channel('changes')
+ .onPostgresChanges(
+ event: PostgresChangeEvent.insert,
+ schema: 'public',
+ table: 'products',
+ filter: PostgresChangeFilter(
+ type: PostgresChangeFilterType.gt,
+ column: 'quantity',
+ value: 10,
+ ),
+ callback: (payload) => print(payload))
+ .subscribe();
+```
+
@@ -845,6 +1078,25 @@ const channel = supabase
.subscribe()
```
+
+
+
+```dart
+supabase
+ .channel('changes')
+ .onPostgresChanges(
+ event: PostgresChangeEvent.insert,
+ schema: 'public',
+ table: 'products',
+ filter: PostgresChangeFilter(
+ type: PostgresChangeFilterType.gte,
+ column: 'quantity',
+ value: 10,
+ ),
+ callback: (payload) => print(payload))
+ .subscribe();
+```
+
@@ -900,6 +1152,25 @@ const channel = supabase
.subscribe()
```
+
+
+
+```dart
+supabase
+ .channel('changes')
+ .onPostgresChanges(
+ event: PostgresChangeEvent.insert,
+ schema: 'public',
+ table: 'colors',
+ filter: PostgresChangeFilter(
+ type: PostgresChangeFilterType.lte,
+ column: 'name',
+ value: ['red', 'blue', 'yellow'],
+ ),
+ callback: (payload) => print(payload))
+ .subscribe();
+```
+
@@ -1001,6 +1272,28 @@ const channel = supabase
.subscribe()
```
+
+
+
+```dart
+supabase.realtime.setAuth('your-custom-jwt');
+
+supabase
+ .channel('db-changes')
+ .onPostgresChanges(
+ event: PostgresChangeEvent.all,
+ schema: 'public',
+ table: 'messages',
+ filter: PostgresChangeFilter(
+ type: PostgresChangeFilterType.eq,
+ column: 'body',
+ value: 'bye',
+ ),
+ callback: (payload) => print(payload),
+ )
+ .subscribe();
+```
+
@@ -1051,6 +1344,13 @@ For example, if you're using the `supabase-js` `v2` client then you can pass you
supabase.realtime.setAuth('fresh-token')
```
+
+
+
+```dart
+supabase.realtime.setAuth('fresh-token');
+```
+
diff --git a/apps/docs/pages/guides/realtime/presence.mdx b/apps/docs/pages/guides/realtime/presence.mdx
index 8d25c48ec6b..dbf8751a0dc 100644
--- a/apps/docs/pages/guides/realtime/presence.mdx
+++ b/apps/docs/pages/guides/realtime/presence.mdx
@@ -33,7 +33,23 @@ import { createClient } from '@supabase/supabase-js'
const SUPABASE_URL = 'https://.supabase.co'
const SUPABASE_KEY = ''
-const client = createClient(SUPABASE_URL, SUPABASE_KEY)
+const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
+```
+
+
+
+
+```dart
+void main() {
+ Supabase.initialize(
+ url: 'https://.supabase.co',
+ anonKey: '',
+ );
+
+ runApp(MyApp());
+}
+
+final supabase = Supabase.instance.client;
```
@@ -80,6 +96,24 @@ roomOne
.subscribe()
```
+
+
+
+```dart
+final supabase = Supabase.instance.client;
+
+final roomOne = supabase.channel('room_01');
+
+roomOne.onPresenceSync((_) {
+ final newState = roomOne.presenceState();
+ print('sync: $newState');
+}).onPresenceJoin((payload) {
+ print('join: $payload');
+}).onPresenceLeave((payload) {
+ print('leave: $payload');
+}).subscribe();
+```
+
@@ -131,6 +165,25 @@ roomOne.subscribe(async (status) => {
})
```
+
+
+
+```dart
+final roomOne = supabase.channel('room_01');
+
+final userStatus = {
+ 'user': 'user-1',
+ 'online_at': DateTime.now().toIso8601String(),
+};
+
+roomOne.subscribe((status, error) async {
+ if (status != RealtimeSubscribeStatus.subscribed) return;
+
+ final presenceTrackStatus = await roomOne.track(userStatus);
+ print(presenceTrackStatus);
+});
+```
+
@@ -175,6 +228,20 @@ const untrackPresence = async () => {
untrackPresence()
```
+
+
+
+```dart
+final roomOne = supabase.channel('room_01');
+
+untrackPresence() async {
+ final presenceUntrackStatus = await roomOne.untrack();
+ print(presenceUntrackStatus);
+}
+
+untrackPresence();
+```
+
@@ -218,6 +285,16 @@ const channelC = supabase.channel('test', {
})
```
+
+
+
+```dart
+final channelC = supabase.channel(
+ 'test',
+ opts: const RealtimeChannelConfig(key: 'userId-123'),
+);
+```
+