Release Notes

Supabase.js v2 release notes.

Install the latest version of @supabase/supabase-js

1  npm install @supabase/supabase-js

Explicit constructor options#

All client specific options within the constructor are keyed to the library.

See PR:

  const supabase = createClient(apiURL, apiKey, {
    db: {
      schema: 'public',
    auth: {
      storage: AsyncStorage,
      autoRefreshToken: true,
      persistSession: true,
      detectSessionInUrl: true,
    realtime: {
    global: {
      fetch: customFetch,
      headers: DEFAULT_HEADERS,

Typescript support#

The libraries now support typescript.

  // previously definitions were injected in the `from()` method

  import type { Database } from './DatabaseDefinitions'

  // definitions are injected in `createClient()`
  const supabase = createClient<Database>(SUPABASE_URL, ANON_KEY)

  const { data } = await supabase.from('messages').select().match({ id: 1 })

Types can be generated via the CLI:

1supabase start
2supabase gen types typescript --local > DatabaseDefinitions.ts

Data operations return minimal#

.insert() / .upsert() / .update() / .delete() don't return rows by default: PR.

Previously, these methods return inserted/updated/deleted rows by default (which caused some confusion), and you can opt to not return it by specifying returning: 'minimal'. Now the default behavior is to not return rows. To return inserted/updated/deleted rows, add a .select() call at the end, e.g.:

const { data, error } = await supabase
    .eq('id', 1)

New ordering defaults#

.order() now defaults to Postgres’s default: PR.

Previously nullsFirst defaults to false , meaning nulls are ordered last. This is bad for performance if e.g. the column uses an index with NULLS FIRST (which is the default direction for indexes).

Cookies and localstorage namespace#

Storage key name in the Auth library has changed to include project reference which means that existing websites that had their JWT expiry set to a longer time could find their users logged out with this upgrade.

const defaultStorageKey = `sb-${new URL(this.authUrl).hostname.split('.')[0]}-auth-token`

New Auth Types#

Typescript typings have been reworked. Session interface now guarantees that it will always have an access_token, refresh_token and user

interface Session {
  provider_token?: string | null
  access_token: string
  expires_in?: number
  expires_at?: number
  refresh_token: string
  token_type: string
  user: User

New Auth methods#

We're removing the signIn() method in favor of more explicit function signatures: signInWithPassword(), signInWithOtp(), and signInWithOtp().

  const { data } = await supabase.auth.signIn({
    email: 'hello@example',
    password: 'pass',

  const { data } = await supabase.auth.signInWithPassword({
    email: 'hello@example',
    password: 'pass',

New Realtime methods#

There is a new channel() method in the Realtime library, which will be used for our Multiplayer updates.

We will deprecate the .from().on().subscribe() method previosuly used for listening to postgres changes.

  .on('presence', { event: 'track' }, (payload) => {

      event: 'INSERT',
      schema: 'public',
      table: 'movies',
    (payload) => {

Deprecated setAuth()#

Deprecated and removed setAuth() . To set a custom access_token jwt instead, pass the custom header into the createClient() method provided: (PR)

All changes#

  • supabase-js
    • shouldThrowOnError has been removed until all the client libraries support this option (PR).
  • postgrest-js
    • TypeScript typings have been reworked PR
    • Use undefined instead of null for function params, types, etc. (https://github.com/supabase/postgrest-js/pull/278)
    • Some features are now obsolete: (https://github.com/supabase/postgrest-js/pull/275)
      • filter shorthands (e.g. cs vs. contains)
      • body in response (vs. data)
      • upserting through the .insert() method
      • auth method on PostgrestClient
      • client-level throwOnError
  • gotrue-js
    • supabase-js client allows passing a storageKey param which will allow the user to set the key used in local storage for storing the session. By default, this will be namespace-d with the supabase project ref. (PR)
    • signIn method is now split into signInWithPassword , signInWithOtp , signInWithOAuth (PR)
    • Deprecated and removed session() , user() in favour of using getSession() instead. getSession() will always return a valid session if a user is already logged in, meaning no more random logouts. (PR)
    • Deprecated and removed setting for multitab support because getSession() and gotrue’s reuse interval setting takes care of session management across multiple tabs (PR)
    • No more throwing of random errors, gotrue-js v2 always returns a custom error type: (PR)
      • AuthSessionMissingError
        • Indicates that a session is expected but missing
      • AuthNoCookieError
        • Indicates that a cookie is expected but missing
      • AuthInvalidCredentialsError
        • Indicates that the incorrect credentials were passed
    • Renamed the api namespace to admin , the admin namespace will only contain methods that should only be used in a trusted server-side environment with the service role key
    • Moved resetPasswordForEmail , getUser and updateUser to the GoTrueClient which means they will be accessible from the supabase.auth namespace in supabase-js instead of having to do supabase.auth.api to access them
    • Removed sendMobileOTP , sendMagicLinkEmail in favor of signInWithOtp
    • Removed signInWithEmail, signInWithPhone in favor of signInWithPassword
    • Removed signUpWithEmail , signUpWithPhone in favor of signUp
    • Replaced update with updateUser
  • storage-js
    • Return types are more strict. Functions types used to indicate that the data returned could be null even if there was no error. We now make use of union types which only mark the data as null if there is an error and vice versa. (PR)
    • The upload and update function returns the path of the object uploaded as the path parameter. Previously the returned value had the bucket name prepended to the path which made it harder to pass the value on to other storage-js methods since all methods take the bucket name and path separately. We also chose to call the returned value path instead of Key (PR)
    • getPublicURL only returns the public URL inside the data object. This keeps it consistent with our other methods of returning only within the data object. No error is returned since this method cannot does not throw an error (PR)
    • signed urls are returned as signedUrl instead of signedURL in both createSignedUrl and createSignedUrls (PR)
    • Encodes URLs returned by createSignedUrl, createSignedUrls and getPublicUrl (PR)
    • createsignedUrl used to return a url directly and and within the data object. This was inconsistent. Now we always return values only inside the data object across all methods. (PR)
    • createBucket returns a data object instead of the name of the bucket directly. (PR)
    • Fixed types for metadata (PR)
    • Better error types make it easier to track down what went wrong quicker.
    • SupabaseStorageClient is no longer exported. Use StorageClient instead. (PR).
  • realtime-js
    • RealtimeSubscription class no longer exists and replaced by RealtimeChannel.
    • RealtimeClient's disconnect method now returns type of void . It used to return type of Promise<{ error: Error | null; data: boolean }.
    • Removed removeAllSubscriptions and removeSubscription methods from SupabaseClient class.
    • Removed SupabaseRealtimeClient class.
    • Removed SupabaseQueryBuilder class.
    • Removed SupabaseEventTypes type.
      • Thinking about renaming this to something like RealtimePostgresChangeEvents and moving it to realtime-js v2.
    • Removed .from(’table’).on(’INSERT’, () ⇒ {}).subscribe() in favor of new Realtime client API.
  • functions-js
    • supabase-js v1 only threw an error if the fetch call itself threw an error (network errors, etc) and not if the function returned HTTP errors like 400s or 500s. We have changed this behaviour to return an error if your function throws an error.
    • We have introduced new error types to distinguish between different kinds of errors. A FunctionsHttpError error is returned if your function throws an error, FunctionsRelayError if the Supabase Relay has an error processing your function and FunctionsFetchError if there is a network error in calling your function.
    • The correct content-type headers are automatically attached when sending the request if you don’t pass in a Content-Type header and pass in an argument to your function. We automatically attach the content type for Blob, ArrayBuffer, File, FormData ,String . If it doesn’t match any of these we assume the payload is json , we serialise the payload as JSON and attach the content type as application/json.
    • responseType does not need to be explicitly passed in. We parse the response based on the Content-Type response header sent by the function. We support parsing the responses as text, json, blob, form-data and are parsed as text by default.