Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: update readme to v2 #647

Merged
merged 2 commits into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 47 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ void main() async {
final supabase = Supabase.instance.client;
```

> `authCallbackUrlHostname` is optional. It will be used to filter Supabase authentication redirect deeplink. You need to provide this param if you use deeplink for other features on the app.

> `debug` is optional. It's enabled by default if you're running the app in debug mode (`flutter run --debug`).

## Usage example
Expand Down Expand Up @@ -173,12 +171,12 @@ class MyWidget extends StatefulWidget {

class _MyWidgetState extends State<MyWidget> {
// Persisting the future as local variable to prevent refetching upon rebuilds.
final List<Map<String, dynamic>> _stream = supabase.from('countries').stream(primaryKey: ['id']);
final stream = supabase.from('countries').stream(primaryKey: ['id']);

@override
Widget build(BuildContext context) {
return StreamBuilder<List<Map<String, dynamic>>>(
stream: _stream,
stream: stream,
builder: (context, snapshot) {
// return your widget with the data from snapshot
},
Expand Down Expand Up @@ -213,11 +211,13 @@ Broadcast lets you send and receive low latency messages between connected clien
final myChannel = supabase.channel('my_channel');

// Subscribe to `cursor-pos` broadcast event
myChannel.on(RealtimeListenTypes.broadcast,
ChannelFilter(event: 'cursor-pos'), (payload, [ref]) {
// Do something fun or interesting when there is an change on the database
}).subscribe();

myChannel.on(
RealtimeListenTypes.broadcast,
ChannelFilter(event: 'cursor-pos'),
(payload, [ref]) {
// Do something fun or interesting when there is an change on the database
},
).subscribe();
// Send a broadcast message to other connected clients
await myChannel.send(
type: RealtimeListenTypes.broadcast,
Expand Down Expand Up @@ -245,13 +245,13 @@ myChannel.on(
}).on(RealtimeListenTypes.presence, ChannelFilter(event: 'leave'),
(payload, [ref]) {
// Users have left
}).subscribe(((status, [_]) async {
if (status == 'SUBSCRIBED') {
}).subscribe((status, error) async {
if (status == RealtimeSubscribeStatus.subscribed) {
// Send the current user's state upon subscribing
final status = await myChannel
.track({'online_at': DateTime.now().toIso8601String()});
}
}));
});
```

### [Storage](https://supabase.com/docs/guides/storage)
Expand Down Expand Up @@ -294,12 +294,12 @@ class MyWidget extends StatefulWidget {

class _MyWidgetState extends State<MyWidget> {
// Persisting the future as local variable to prevent refetching upon rebuilds.
final _future = client.functions.invoke('get_countries');
final future = client.functions.invoke('get_countries');

@override
Widget build(BuildContext context) {
return FutureBuilder(
future: _future,
future: future,
builder: (context, snapshot) {
// return your widget with the data from snapshot
},
Expand Down Expand Up @@ -338,45 +338,46 @@ supabase.auth.signInWithOAuth(

### Custom LocalStorage

As default, `supabase_flutter` uses [`hive`](https://pub.dev/packages/hive) to persist the user session. Encryption is disabled by default, since an unique encryption key is necessary, and we can not define it. To set an `encryptionKey`, do the following:
As default, `supabase_flutter` uses [`Shared preferences`](https://pub.dev/packages/shared_preferences) to persist the user session.

However, you can use any other methods by creating a `LocalStorage` implementation. For example, we can use [`flutter_secure_storage`](https://pub.dev/packages/flutter_secure_storage) plugin to store the user session in a secure storage.

```dart
Future<void> main() async {
// set it before initializing
HiveLocalStorage.encryptionKey = 'my_secure_key';
await Supabase.initialize(...);
}
```
// Define the custom LocalStorage implementation
class MockLocalStorage extends LocalStorage {

**Note** the key must be the same. There is no check if the encryption key is correct. If it isn't, there may be unexpected behavior. [Learn more](https://docs.hivedb.dev/#/advanced/encrypted_box) about encryption in hive.
final storage = FlutterSecureStorage();

@override
Future<void> initialize() async {}

However you can use any other methods by creating a `LocalStorage` implementation. For example, we can use [`flutter_secure_storage`](https://pub.dev/packages/flutter_secure_storage) plugin to store the user session in a secure storage.
@override
Future<String?> accessToken() async {
return storage.containsKey(key: supabasePersistSessionKey);
}

```dart
// Define the custom LocalStorage implementation
class SecureLocalStorage extends LocalStorage {
SecureLocalStorage() : super(
initialize: () async {},
hasAccessToken: () {
const storage = FlutterSecureStorage();
return storage.containsKey(key: supabasePersistSessionKey);
}, accessToken: () {
const storage = FlutterSecureStorage();
return storage.read(key: supabasePersistSessionKey);
}, removePersistedSession: () {
const storage = FlutterSecureStorage();
return storage.delete(key: supabasePersistSessionKey);
}, persistSession: (String value) {
const storage = FlutterSecureStorage();
return storage.write(key: supabasePersistSessionKey, value: value);
},
);
@override
Future<bool> hasAccessToken() async {
return storage.read(key: supabasePersistSessionKey);
}

@override
Future<void> persistSession(String persistSessionString) async {
return storage.write(key: supabasePersistSessionKey, value: persistSessionString);
}

@override
Future<void> removePersistedSession() async {
return storage.delete(key: supabasePersistSessionKey);
}
}

// use it when initializing
Supabase.initialize(
...
localStorage: SecureLocalStorage(),
authOptions: FlutterAuthClientOptions(
localStorage: const EmptyLocalStorage(),
),
);
```

Expand All @@ -385,7 +386,9 @@ You can also use `EmptyLocalStorage` to disable session persistence:
```dart
Supabase.initialize(
// ...
localStorage: const EmptyLocalStorage(),
authOptions: FlutterAuthClientOptions(
localStorage: const EmptyLocalStorage(),
),
);
```

Expand Down
7 changes: 3 additions & 4 deletions packages/postgrest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import 'package:postgrest/postgrest.dart';

final url = 'https://example.com/postgrest/endpoint';
final client = PostgrestClient(url);
final response = await client.from<PostgrestList>('users').select();
final response = await client.from('users').select();
```

#### Reading your data and converting it to an object
Expand All @@ -34,7 +34,7 @@ final url = 'https://example.com/postgrest/endpoint';
final client = PostgrestClient(url);
final response = await client
.from('users')
.select<PostgrestList>()
.select()
.withConverter((data) => data.map(User.fromJson).toList());
```

Expand Down Expand Up @@ -90,8 +90,7 @@ import 'package:postgrest/postgrest.dart';

final url = 'https://example.com/postgrest/endpoint';
final client = PostgrestClient(url);
final response = await client.from('countries')
.select<PostgrestResponse>('*', FetchOptions(count: CountOption.exact));
final response = await client.from('countries').select('*').count(CountOption.exact);
final data = response.data;
final count = response.count;
```
Expand Down
24 changes: 14 additions & 10 deletions packages/supabase/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,20 @@ main() {
import 'package:supabase/supabase.dart';

main() {
final supabase = SupabaseClient('supabaseUrl', 'supabaseKey');

// Set up a listener to listen to changes in `countries` table
supabase.channel('my_channel').on(RealtimeListenTypes.postgresChanges, ChannelFilter(
event: '*',
schema: 'public',
table: 'countries'
), (payload, [ref]) {
// Do something when there is an update
}).subscribe();
final supabase = SupabaseClient('supabaseUrl', 'supabaseKey');

// Set up a listener to listen to changes in `countries` table
supabase.channel('my_channel').on(
RealtimeListenTypes.postgresChanges,
ChannelFilter(
event: '*',
schema: 'public',
table: 'countries',
),
(payload, [ref]) {
// Do something when there is an update
},
).subscribe();

// remember to remove the channels when you're done
supabase.removeAllChannels();
Expand Down
80 changes: 43 additions & 37 deletions packages/supabase_flutter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ Use the `redirectTo` parameter to redirect the user to a deep link to bring the
```dart
// Perform web based OAuth login
await supabase.auth.signInWithOAuth(
Provider.github,
OAuthProvider.github,
redirectTo: kIsWeb ? null : 'io.supabase.flutter://callback',
);

Expand Down Expand Up @@ -240,12 +240,12 @@ class MyWidget extends StatefulWidget {

class _MyWidgetState extends State<MyWidget> {
// Persisting the future as local variable to prevent refetching upon rebuilds.
final List<Map<String, dynamic>> _stream = supabase.from('countries').stream(primaryKey: ['id']);
final stream = supabase.from('countries').stream(primaryKey: ['id']);

@override
Widget build(BuildContext context) {
return StreamBuilder<List<Map<String, dynamic>>>(
stream: _stream,
stream: stream,
builder: (context, snapshot) {
// return your widget with the data from snapshot
},
Expand Down Expand Up @@ -280,10 +280,13 @@ Broadcast lets you send and receive low latency messages between connected clien
final myChannel = supabase.channel('my_channel');

// Subscribe to `cursor-pos` broadcast event
myChannel.on(RealtimeListenTypes.broadcast,
ChannelFilter(event: 'cursor-pos'), (payload, [ref]) {
// Do something fun or interesting when there is an change on the database
}).subscribe();
myChannel.on(
RealtimeListenTypes.broadcast,
ChannelFilter(event: 'cursor-pos'),
(payload, [ref]) {
// Do something fun or interesting when there is an change on the database
},
).subscribe();

// Send a broadcast message to other connected clients
await myChannel.send(
Expand Down Expand Up @@ -556,45 +559,46 @@ Add this XML chapter in your macos/Runner/Info.plist inside <plist version="1.0"

### Custom LocalStorage

As default, `supabase_flutter` uses [`hive`](https://pub.dev/packages/hive) to persist the user session. Encryption is disabled by default, since an unique encryption key is necessary, and we can not define it. To set an `encryptionKey`, do the following:
As default, `supabase_flutter` uses [`Shared preferences`](https://pub.dev/packages/shared_preferences) to persist the user session.

However, you can use any other methods by creating a `LocalStorage` implementation. For example, we can use [`flutter_secure_storage`](https://pub.dev/packages/flutter_secure_storage) plugin to store the user session in a secure storage.

```dart
Future<void> main() async {
// set it before initializing
HiveLocalStorage.encryptionKey = 'my_secure_key';
await Supabase.initialize(...);
}
```
// Define the custom LocalStorage implementation
class MockLocalStorage extends LocalStorage {

final storage = FlutterSecureStorage();

@override
Future<void> initialize() async {}

@override
Future<String?> accessToken() async {
return storage.containsKey(key: supabasePersistSessionKey);
}

**Note** the key must be the same. There is no check if the encryption key is correct. If it isn't, there may be unexpected behavior. [Learn more](https://docs.hivedb.dev/#/advanced/encrypted_box) about encryption in hive.
@override
Future<bool> hasAccessToken() async {
return storage.read(key: supabasePersistSessionKey);
}

However you can use any other methods by creating a `LocalStorage` implementation. For example, we can use [`flutter_secure_storage`](https://pub.dev/packages/flutter_secure_storage) plugin to store the user session in a secure storage.
@override
Future<void> persistSession(String persistSessionString) async {
return storage.write(key: supabasePersistSessionKey, value: persistSessionString);
}

```dart
// Define the custom LocalStorage implementation
class SecureLocalStorage extends LocalStorage {
SecureLocalStorage() : super(
initialize: () async {},
hasAccessToken: () {
const storage = FlutterSecureStorage();
return storage.containsKey(key: supabasePersistSessionKey);
}, accessToken: () {
const storage = FlutterSecureStorage();
return storage.read(key: supabasePersistSessionKey);
}, removePersistedSession: () {
const storage = FlutterSecureStorage();
return storage.delete(key: supabasePersistSessionKey);
}, persistSession: (String value) {
const storage = FlutterSecureStorage();
return storage.write(key: supabasePersistSessionKey, value: value);
},
);
@override
Future<void> removePersistedSession() async {
return storage.delete(key: supabasePersistSessionKey);
}
}

// use it when initializing
Supabase.initialize(
...
localStorage: SecureLocalStorage(),
authOptions: FlutterAuthClientOptions(
localStorage: const EmptyLocalStorage(),
),
);
```

Expand All @@ -603,7 +607,9 @@ You can also use `EmptyLocalStorage` to disable session persistence:
```dart
Supabase.initialize(
// ...
localStorage: const EmptyLocalStorage(),
authOptions: FlutterAuthClientOptions(
localStorage: const EmptyLocalStorage(),
),
);
```

Expand Down