Supadart Typesafe Supabase Flutter Queries

WHAT TO KNOW - Sep 7 - - Dev Community

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
  1. Install Supadart:
flutter pub add supadart
Enter fullscreen mode Exit fullscreen mode
  1. Create a Supabase Client:
import 'package:supadart/supadart.dart';

final supabaseUrl = 'your-supabase-url';
final supabaseKey = 'your-supabase-key';

final supabaseClient = SupabaseClient(supabaseUrl, supabaseKey);
Enter fullscreen mode Exit fullscreen mode
  1. Initialize Database Tables:
import 'package:supadart/supadart.dart';

// Create a database table representation
final table = supabaseClient.database.table('your_table_name'); 
Enter fullscreen mode Exit fullscreen mode

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,
  });
}
Enter fullscreen mode Exit fullscreen mode

2. Configure the Table with the Data Model:

import 'package:supadart/supadart.dart';

final table = supabaseClient.database.table('users').withModel(User); 
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

2. Filtering Data:

final users = await table.select().eq('email', 'user@example.com'); 
Enter fullscreen mode Exit fullscreen mode

3. Sorting Data:

final users = await table.select().orderBy('username', ascending: true); 
Enter fullscreen mode Exit fullscreen mode

4. Inserting Data:

final newUser = User(username: 'new_user', email: 'newuser@example.com');
final insertedUser = await table.insert(newUser);
Enter fullscreen mode Exit fullscreen mode

5. Updating Data:

final updatedUser = await table.update(
  User(username: 'updated_username', email: 'updated@example.com'), 
  where: (user) => user.id.eq('user_id'), 
);
Enter fullscreen mode Exit fullscreen mode

6. Deleting Data:

await table.delete(where: (user) => user.id.eq('user_id'));
Enter fullscreen mode Exit fullscreen mode

7. Counting Rows:

final count = await table.selectCount();
Enter fullscreen mode Exit fullscreen mode

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,
  });
}
Enter fullscreen mode Exit fullscreen mode

You can then use the relationship to access related data:

final post = await table.select().eq('id', 'post_id');
final author = post.author; 
Enter fullscreen mode Exit fullscreen mode

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
  },
);
Enter fullscreen mode Exit fullscreen mode

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,
  });
}
Enter fullscreen mode Exit fullscreen mode

2. Define the Blog Post Table:

import 'package:supadart/supadart.dart';

final blogTable = supabaseClient.database
  .table('blog_posts')
  .withModel(BlogPost);
Enter fullscreen mode Exit fullscreen mode

3. Retrieve Blog Posts:

Future
<list<blogpost>
 &gt; getBlogPosts() async {
  final posts = await blogTable
    .select()
    .orderBy('createdAt', ascending: false);
  return posts;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

5. Display Blog Posts in Flutter:

import 'package:flutter/material.dart';

class BlogListPage extends StatefulWidget {
  @override
  _BlogListPageState createState() =&gt; _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()),
          );
        },
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode
 <br/>
 ### Conclusion
Enter fullscreen mode Exit fullscreen mode

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.




. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player