Supadart: Typesafe Supabase Queries in Flutter
Introduction
Building modern, data-driven Flutter applications often involves seamless integration with a backend database. Supabase, an open-source Firebase alternative, provides a robust and scalable solution for managing data and authentication. While Supabase offers a powerful API, interacting with it directly can lead to cumbersome code and potential runtime errors. This is where Supadart, a powerful Dart library, steps in to provide a typesafe and efficient way to query and manage Supabase data directly from your Flutter application.
Why Supadart?
Supadart offers several key advantages over traditional Supabase API interactions:
- Type Safety: Supadart leverages Dart's strong typing system, ensuring data integrity and preventing runtime errors.
- Code Generation: Supadart automatically generates Dart classes based on your Supabase database schema, eliminating the need for manual data mapping and ensuring consistency between your data model and the database.
- Simplified Queries: Supadart provides a clean and expressive syntax for constructing complex queries, making it easier to write and maintain your data access logic.
- Error Handling: Supadart handles common errors and exceptions encountered during database interactions, simplifying error handling and debugging.
- Built-in Functionality: Supadart includes built-in functionality for common tasks like pagination, filtering, and sorting, making data management more efficient. ### Setting Up Supadart
- Install Supadart:
flutter pub add supadart
- Create a Supabase Client:
import 'package:supadart/supadart.dart';
final supabaseUrl = 'your-supabase-url';
final supabaseKey = 'your-supabase-key';
final supabaseClient = SupabaseClient(supabaseUrl, supabaseKey);
- Initialize Database Tables:
import 'package:supadart/supadart.dart';
// Create a database table representation
final table = supabaseClient.database.table('your_table_name');
Defining Your Data Model
1. Create a Data Model Class:
import 'package:supadart/supadart.dart';
class User extends SupabaseModel {
final String? id;
final String username;
final String email;
User({
this.id,
required this.username,
required this.email,
});
}
2. Configure the Table with the Data Model:
import 'package:supadart/supadart.dart';
final table = supabaseClient.database.table('users').withModel(User);
Performing Queries
Supadart provides a range of methods for interacting with your database. Here are some examples:
1. Selecting Data:
final users = await table.select(); // Select all users
2. Filtering Data:
final users = await table.select().eq('email', 'user@example.com');
3. Sorting Data:
final users = await table.select().orderBy('username', ascending: true);
4. Inserting Data:
final newUser = User(username: 'new_user', email: 'newuser@example.com');
final insertedUser = await table.insert(newUser);
5. Updating Data:
final updatedUser = await table.update(
User(username: 'updated_username', email: 'updated@example.com'),
where: (user) => user.id.eq('user_id'),
);
6. Deleting Data:
await table.delete(where: (user) => user.id.eq('user_id'));
7. Counting Rows:
final count = await table.selectCount();
Handling Relationships
Supadart supports working with relationships between different database tables. You can define relationships in your models using annotations:
import 'package:supadart/supadart.dart';
class Post extends SupabaseModel {
final String? id;
final String title;
final String content;
@Rel('users') // Define a relationship with the User table
final User? author;
Post({
this.id,
required this.title,
required this.content,
this.author,
});
}
You can then use the relationship to access related data:
final post = await table.select().eq('id', 'post_id');
final author = post.author;
Real-Time Updates
Supadart seamlessly integrates with Supabase's real-time functionality. You can subscribe to changes in your database and receive live updates:
final subscription = table.on(
SupabaseEvent.all,
(event) {
print(event); // Handle the event
},
);
Example: Building a Simple Blog App
Let's see how Supadart simplifies building a basic blog application.
1. Create a Blog Post Model:
import 'package:supadart/supadart.dart';
class BlogPost extends SupabaseModel {
final String? id;
final String title;
final String content;
final DateTime createdAt;
BlogPost({
this.id,
required this.title,
required this.content,
required this.createdAt,
});
}
2. Define the Blog Post Table:
import 'package:supadart/supadart.dart';
final blogTable = supabaseClient.database
.table('blog_posts')
.withModel(BlogPost);
3. Retrieve Blog Posts:
Future
<list<blogpost>
> getBlogPosts() async {
final posts = await blogTable
.select()
.orderBy('createdAt', ascending: false);
return posts;
}
4. Create a New Blog Post:
Future
<blogpost?>
createBlogPost(
String title,
String content,
) async {
final newPost = BlogPost(
title: title,
content: content,
createdAt: DateTime.now(),
);
final insertedPost = await blogTable.insert(newPost);
return insertedPost;
}
5. Display Blog Posts in Flutter:
import 'package:flutter/material.dart';
class BlogListPage extends StatefulWidget {
@override
_BlogListPageState createState() => _BlogListPageState();
}
class _BlogListPageState extends State
<bloglistpage>
{
List
<blogpost>
posts = [];
@override
void initState() {
super.initState();
_fetchBlogPosts();
}
Future
<void>
_fetchBlogPosts() async {
final fetchedPosts = await getBlogPosts();
setState(() {
posts = fetchedPosts;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('My Blog'),
),
body: ListView.builder(
itemCount: posts.length,
itemBuilder: (context, index) {
final post = posts[index];
return ListTile(
title: Text(post.title),
subtitle: Text(post.createdAt.toString()),
);
},
),
);
}
}
<br/>
### Conclusion
Supadart offers a powerful and typesafe way to interact with Supabase databases from your Flutter applications. Its code generation, streamlined querying, and real-time capabilities streamline your data management, leading to cleaner, more efficient, and maintainable Flutter code. By embracing Supadart, you can significantly improve the development experience and build robust and scalable Flutter applications that leverage the power of Supabase.