Supabase Subscriptions Just Got Easier
Tags: supabase, firebase, webdev, database
Published: 2022-10-23 12:56:09

## Channels

For the moment, subscribing to realtime data in Supabase is very limited, and not easy to use. I personally believe the `channels` features is unnecessary and a waste of the developers time... for now. Let's not add new feature modules until the current features are adequate... capiche?

(Keep reading for package information...)

If you come from Firebase, you will be very disappointed in the way that you subscribe to realtime data. This is the same for `onAuthStateChange` and for `channels`. There are a few problems here.

1. You have to get the data first, as the Subscription does not return the current data beforehand.
2. You have to watch each type of change "INSERT, UPDATE, DELETE," in order to see the changes. You have to manually update accordingly in each case.
3. Only the current change is returned, not the whole data.
4. The UI is incredibly over-engineered and counterintuitive. Just figuring out how it works takes you at least an hour without examples.
5. There is a [few second delay](https://github.com/supabase/realtime/issues/282) when starting the subscriptions.
6. There is only one filter you can use: `eq`.
7. There is no way to limit the results.
8. Perhaps the most important, you cannot use Views with Supabase Channels.
9. When a group of data is inserted, it doesn't return in bulk, but individually.
10. There are no optimistic updates, nor persistent offline data capabilities.

## Problems 1 - 4 - Clean Code

I cannot help with the limitations of Supabase, but I did write a package that makes dealing with Subscriptions way easier. 

## Problems 5 - 9

These are the current limitations of Supabase. Don't get me wrong, **I LOVE SUPABASE**, and I am currently using it on this blog: [Code.Build](https://code.build). It just seems to me these are problems on the backburner and not at the top of the list to fix. Subscriptions to realtime data is incredibly important for a lot of people. Let's get this up-to-par please. I wrote a [list of issues](https://github.com/supabase/realtime-js/issues/185) a while back. I finally decided to fix what I could.

This is just not good enough:
```js
supabaseClient
  .channel('any_string_you_want')
  .on(
    'postgres_changes',
    {
      event: 'INSERT',
      schema: 'public',
      table: 'movies',
    },
    (payload) => {
      console.log(payload)
    }
  )
  .subscribe()
```

## Problem 10 - Offline & Optimistic


Okay, so that last one is doable, and someone is working on the caching right now with [supabase-cache-helpers](https://github.com/psteinroe/supabase-cache-helpers).

I also wrote an app to show you how you can do **optimistic updates**. Basically, you just create an array of your data, and change that array before the subscriptions returns. This is how Firebase's subscriptions are extremally fast. I may integrate this later into **j-supabase**.

You can also see an example **realtime todo** app I build with subscriptions and optimistic updates:

- [Demo](https://realtime-todos.vercel.app/)
- [Code](https://github.com/jdgamble555/realtime-todos/blob/master/src/lib/databases/supabase.ts)

## j-supabase

So, I created a simple tree-shakable package. I plan on adding more cool stuff to it later.

- [Source Code](https://github.com/jdgamble555/j-supabase/blob/master/src/index.ts)


## Authentication

First thing is first. Install the package:

```
npm i j-supabase
```
Make sure you have the **latest** version of Supabase SDK V2:

```
npm i @supabase/supabase-js
```

Authentication now works as expected like it does in Firebase:

```js
import { authUser, authSession, realtime } from 'j-supabase';

// user
const unsubscribe = authUser(supabase)
  .subscribe(user => console.log(user));

// session
const unsubscribe = authSession(supabase)
  .subscribe(session => console.log(session));
```
The current data is returned, and you can easily get to the variables without navigating a sub-tree of objects. You can see how it was done before in my [previous article](https://code.build/p/CSRkYyfYe7Fd1PyTc1Pe1Z/observing-supabase-auth-state-changes).

## Realtime Data

You can get the realtime data as you would expect, the Supabase way:

```js
// subscribe to a table
const unsubscribe = realtime<Todo>(supabase)
  .from('todos')
  .subscribe(snap => console.log(snap));

// use the one `eq` filter
const unsubscribe = realtime<Todo>(supabase)
  .from('todos')
  .eq('uid', uid)
  .subscribe(snap => console.log(snap));
```

I do have two optional inputs:

**idField**

Just in case your primary key is not `id`:

```js
const unsubscribe = realtime<Todo>(supabase, {
    idField: 'user_id'
  })
  .from('todos')
  .eq('uid', uid)
  .subscribe(snap => console.log(snap));
```

**schema**

You must set your async schema when you declare your use [createClient](https://supabase.com/docs/reference/javascript/initializing), but you can set your subscriptions schema this way:

```js
const unsubscribe = realtime<Todo>(supabase, {
    schema: 'marketing'
  })
  .from('todos')
  .eq('uid', uid)
  .subscribe(snap => console.log(snap));
```

This package is very easy, very clean (I do not use any dependencies), and very useful!

That is pretty much all Supabase can do... for the moment... but I hope to see new filters soon, and hopefully subscribable [Views](https://supabase.com/blog/postgresql-views) in the near future..

Possible todo list:
- **auto-resubscribe** - while Supabase does automatically re-subscribe, you lose your data. This would keep it.
- **optimistic updates** - Optimistic updates would be impossible for all situations, but I may add `upsert`, `insert`, `update`, and `delete` functions in this package to catch optimistic updates from the subscribed table. TBD.

Hope this helps someone,

J