Typesafe Supabase Flutter Queries
Tags: flutter, supabase, schema, mobile
Published: 2024-06-24 10:08:04

Supabase Flutter Types? In web development, supabase provide you with an API to generate typescript types to make typesafe queries. But what about for flutter? for dart? That's what this is all about

Yes we can generate dart classes directly from you supabase schema in order to achieve Typesafe Queries Flutter Supabase

Supabase Schema Dart Class Generator using this tool you can generate dart class via [WebApp](https://github.com/mmvergara/supadart) or [CLI](https://github.com/mmvergara/supadart)



### 1. Assuming the following table schema

```sql
create table
  public.books (
    id bigint generated by default as identity,
    name character varying not null,
    description text null,
    price integer not null,
    created_at timestamp with time zone not null default now(),
    constraint books_pkey primary key (id)
  ) tablespace pg_default;
```

### 2. Use the CLI or the Web App to [generate dart classes](https://github.com/mmvergara/supadart)

```dart
class Books {
  final BigInt id;
  final String name;
  final String? description;
  final int price;
  final DateTime created_at;

  const Books({
    required this.id,
    required this.name,
    this.description,
    required this.price,
    required this.created_at,
  });

  static String get table_name => 'books';
  static String get c_id => 'id';
  static String get c_name => 'name';
  static String get c_description => 'description';
  static String get c_price => 'price';
  static String get c_created_at => 'created_at';
  static Map<String, dynamic> insert({
    BigInt? id,
    required String name,
    String? description,
    required int price,
    DateTime? created_at,
  }) {
    return {
      if (id != null) 'id': id.toString(),
      'name': name.toString(),
      if (description != null) 'description': description.toString(),
      'price': price.toString(),
      if (created_at != null) 'created_at': created_at.toUtc().toString(),
    };
  }

  static Map<String, dynamic> update({
    BigInt? id,
    String? name,
    String? description,
    int? price,
    DateTime? created_at,
  }) {
    return {
      if (id != null) 'id': id.toString(),
      if (name != null) 'name': name.toString(),
      if (description != null) 'description': description.toString(),
      if (price != null) 'price': price.toString(),
      if (created_at != null) 'created_at': created_at.toUtc().toString(),
    };
  }

  factory Books.fromJson(Map<String, dynamic> json) {
    return Books(
      id: BigInt.parse(json['id'].toString()),
      name: json['name'] as String,
      description:
          json['description'] != null ? json['description'] as String : null,
      price: json['price'] as int,
      created_at: DateTime.parse(json['created_at'].toString()),
    );
  }
}
```

### 3. Using the generated class

we now have a typesafe'ish to interact with the database.

#### Getting Table Name

```dart
  Books.table_name // "books"
```

#### Fetch Data

```dart
// fetchedBooks is a typeof List<Books>
final books = await supabase
      .books
      .select("*")
      .withConverter((data) => data.map(Books.fromJson).toList());
```

#### Insert Data
yes, we know which ones is required and which ones are optional
```dart
final data = Books.insert(
  name: 'Learn Flutter',
  description: 'Endless brackets and braces',
  price: 2,
);
await supabase.books.insert(data);
```

#### Inset Many Data

```dart
final many_data = [
  Books.insert(
    name: 'Learn Minecraft',
    description: 'Endless blocks and bricks',
    price: 2,
  ),
  Books.insert(
    name: 'Description is optional',
    created_at: DateTime.now(),
    price: 2,
  ),
];
await supabase.books.insert(many_data);
```

#### Update Data

```dart
final newData = Books.update(
  name: 'New Book Name',
);
await supabase.books.update(newData).eq(Books.c_id, 1);
```

#### Delete Data

```dart
await supabase.books.delete().eq(Books.c_id, 1);
```

How it works is that it uses the rest api to fetch for your schemas and then constructs the dart classes for you. Is it safe? yes first of all the project is open source and they api is used by other tools like [this one](https://supabase-schema.vercel.app/) that visualizes your database.

Is this only for flutter? no you can use it in a normal Dart Project.

Im trying to make it better for the community i would really appreciate some help and suggestions to improve it. especially the process of parsing the data to dart types, but either way the generated classes are tested for runtime for most supabase / postgres types

{% embed https://github.com/mmvergara/supadart %}