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

Announcing the Supabase Integration #445

Closed
tshedor opened this issue Sep 20, 2024 · 3 comments
Closed

Announcing the Supabase Integration #445

tshedor opened this issue Sep 20, 2024 · 3 comments

Comments

@tshedor
Copy link
Collaborator

tshedor commented Sep 20, 2024

Brick has a first-party integration with Supabase, the open-source Firebase alternative with exponential momentum. After being heavily requested in #359 , the first stable release has finally landed on pub.dev.

Quick Start

Adding a Supabase provider to your repository is almost identical to adding a REST or GraphQL provider. You'll need just a little extra sauce to integrate an offline queue that will retry requests made while your app was offline:

final (client, queue) = OfflineFirstWithSupabaseRepository.clientQueue(
  // For Flutter, use import 'package:sqflite/sqflite.dart' show databaseFactory;
  databaseFactory: databaseFactory,
);

final provider = SupabaseProvider(
  SupabaseClient(supabaseUrl, supabaseAnonKey, httpClient: client),
  modelDictionary: supabaseModelDictionary,
);

// For Flutter, initialize with this created client:
// final (client, queue) = OfflineFirstWithSupabaseRepository.clientQueue(databaseFactory: databaseFactory);
// await Supabase.initialize(httpClient: client)
// final provider = SupabaseProvider(Supabase.instance.client, modelDictionary: supabaseModelDictionary)

_singleton = MyRepository._(
  supabaseProvider: provider,
  sqliteProvider: SqliteProvider(
    'my_repository.sqlite',
    databaseFactory: databaseFactory,
    modelDictionary: sqliteModelDictionary,
  ),
  migrations: migrations,
  offlineRequestQueue: queue,
  memoryCacheProvider: MemoryCacheProvider(),
);

Associations

Brick will generate all the necessary code for retrieving and upserting associations as well as other fields:

class Customer extends BrickOfflineFirstWithSupabaseModel {
  @Supabase(unique: true)
  final String id;
}

class Pizza extends BrickOfflineFirstWithSupabaseModel {
  @Supabase(unique: true)
  final String id;

  final Customer customer;
}

Querying

Association querying with Supabase is automatically handled, even for nested queries:

await repository.get<Customer>(query: Where.exact('id', 'abcd-1234'));
await repository.get<Customer>(query: Query.where('pizza', Where.exact('frozen', true));

Note that not all of Supabase's extensive PostgREST operators are handled.

Creating

All associations of a model are upserted behind the scenes. You only need to upsert the parent model to ensure its dependencies also reach Supabase:

// Upserts each customer.pizzas first
await repository.upsert<Customer>(customer);

Testing

Quickly mock your Supabase endpoints to add uncluttered unit testing:

final mock = SupabaseMockServer(modelDictionary: supabaseModelDictionary);

group('MyClass', () {
  setUp(mock.setUp);

  tearDown(mock.tearDown);

  test('#myMethod', () async {
    final req = SupabaseRequest<MyModel>();
    final resp = SupabaseResponse([
      await mock.serialize(MyModel(name: 'Demo 1', id: '1')),
      await mock.serialize(MyModel(name: 'Demo 2', id: '2')),
    ]);
    mock.handle({req: resp});
    final provider = SupabaseProvider(mock.client, modelDictionary: supabaseModelDictionary);
    final retrieved = await provider.get<MyModel>();
    expect(retrieved, hasLength(2));
  });
});

Like the rest of Brick's domains, the Supabase integration brings straightforward offline capability to your app. Give it a spin and let us know how it works for you.

Finally, many thanks to @devj3ns for the extremely patient and thorough testing of the beta and alpha releases. We had a lot of back and forth on every issue and PR in #401 , so there will definitely never be a production bug.

@devj3ns
Copy link
Contributor

devj3ns commented Sep 20, 2024

Awesome 🎉 Thanks for all the work you put into this @tshedor! I enjoyed the collaboration. This is a big win for the Flutter developer community.

@ivanburlakov
Copy link

ivanburlakov commented Nov 5, 2024

@tshedor hello! Thank you very much for your work. I am trying to use this technology stack in a Flutter app. As I understand, that could be used instead of Riverpod\Bloc for requests and persistence.

My question is, what is the best practice to still use Supabase auth / edge functions along side it? I only see direct db usage, like .get in official examples and no ability to get Supabase client directly (as I understand it is a good practice to use a single client to be in sync with all Brick operations). Looking for the best way to implement Supabase sign in, store user session and clear all user specific data on logout with Brick.

What would you recommend? Maybe you could show a quick code snippet for it? Thank you once again!

@tshedor
Copy link
Collaborator Author

tshedor commented Nov 5, 2024

@ivanburlakov thanks for the comment.

As I understand, that could be used instead of Riverpod\Bloc for requests and persistence.

Real quick, I want to clarify that Brick is not inherently stateful - you should still use a state manager like Riverpod or Bloc. These state managers should call out to Brick to populate their data.

My question is, what is the best practice to still use Supabase auth / edge functions along side it?

Use Supabase.instance.client.auth or Supabase.instance.client.functions as normal.

By default, Brick will retry function requests, but it will not retry auth or storage requests (this default behavior can be configured). When you initialize Brick using the offline client, it attaches the offline client to the Supabase.instance.client, but Supabase.instance.client is still available for use throughout your Flutter app.

@tshedor tshedor closed this as completed Nov 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

3 participants