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

Update Type Implementation (supabase-js side) #125

Closed
wants to merge 5 commits into from
Closed

Update Type Implementation (supabase-js side) #125

wants to merge 5 commits into from

Conversation

beeequeue
Copy link
Contributor

@beeequeue beeequeue commented Feb 1, 2021

What kind of change does this PR introduce?

A breaking type update, which allows easier and stricter type checking. This is a combined update for this package and postgrest-js.

supabase/postgrest-js#152

It also updates the next-ts example application!

What is the current behavior?

  • You have to pass the object you're working on into .from<definitions['user']>('users') every time you use it.
  • .select() does not have any intellisense help.

What is the new behavior?

You get intellisense suggestions in .select().


You now pass the schema into the SupabaseClient, and let the types handle the rest from there.

The schema type is based on what openapi-typescript generates, as recommended in the guide (which also has to be updated as the tool has renamed).

type User = {
  username: string
  data: object | null
  age_range: string | null
  status: 'ONLINE' | 'OFFLINE'
  catchphrase: 'string' | null
}

type Schema = {
  users: User
}

const supabase = new SupabaseClient<definitions>(REST_URL)

// Incorrect table, column names will result in type errors
typedClient.from('users').select('username').eq('username', 'supabot')

// Error
typedClient.from('uesrs').select('username').eq('username', 'wooo')
typedClient.from('users').select('username').eq('not_in_table', 'wooo')

Additional context

Not passing in a type still works as before, with any names working and returning any.

I tried very hard to not make this a breaking change, by still allowing .from<Object>(), but it's sadly impossible without some crazy workarounds. 😢

Comment on lines +1461 to +1462
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
"integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what happned here, I just installed a package with the latest npm@6 version...

@@ -5,7 +5,8 @@
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
"start": "next start",
"typegen": "openapi-typescript --output generated.ts https://[YOUR_SUPABASE_ID].supabase.co/rest/v1/?apikey=[YOUR_SUPABASE_ANON_KEY]"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added an example type generation script, along with the package to generate it with

@kiwicopple
Copy link
Member

kiwicopple commented Feb 2, 2021

I like the direction of this @beeequeue .

My first hesitation is on the open-api generated definitions. Although we added it to the docs, I have found them a bit limited. For example the swagger that it generates seems to have incorrect types (strings for dates), and it doesn't handle edge-cases like default fields not being required.

I started thinking that we can generate these ourselves by connecting directly to the database. I documented some of this in our CLI RFC here: supabase/cli#2

As soon as we decide what we will do for the Type generators I will loop back here - I think this ultimately is the correct way to handle types, rather than on every select()

@beeequeue
Copy link
Contributor Author

I would be very glad to help out with type generation!

A custom generator came to mind for me as well, especially since I've been thinking about how Supabase's API kind of resembles GraphQL a lot, with schemas and how you access them. It should be possible to create a client that uses a normalized object store like the Apollo Client or Urql's Graphcache.

{
  "queries": {
    "user.filter(username='supabot')": [
       "User:3126db5b-6371-430a-9342-3dd28997bc2a",
       "User:6b2f2d5b-2a61-4ceb-9258-1cf21e4f65c5",
    ]
  },
  "objects": {
    "User:6b2f2d5b-2a61-4ceb-9258-1cf21e4f65c5": {
      "id": "6b2f2d5b-2a61-4ceb-9258-1cf21e4f65c5",
      "username": "supabot",
    }
  }
}

I've been thinking that it could be fun to try to implement and would be a lot easier with more information about the schema than can be gotten from the Swagger documentation!

@sannajammeh
Copy link

What happens when you introduce advanced joins etc? There needs to be a way to override. Same with the .eq operator when joining another table. Where is this IntelliSense going to come from with the suggested type updates?

@beeequeue
Copy link
Contributor Author

Guess I can close these now.

@beeequeue beeequeue closed this Sep 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants