Files
supabase/apps/reference/_supabase_js/usage/usage.mdx
2022-08-11 13:48:42 +02:00

3900 lines
53 KiB
Plaintext

---
id: usage
title: Usage
toc_max_heading_level: 2
---
<!-- AUTOGENERATED: DO NOT EDIT DIRECTLY IF THIS IS VERSION "next" -->
Supabase JavaScript.
<!-- AUTOGENERATED: DO NOT EDIT DIRECTLY IF THIS IS VERSION "next" -->
## Initializing
```js
import { createClient } from '@supabase/supabase-js'
const supabase = createClient('<SUPABASE_URL>', '<SUPABASE_ANON_KEY>')
```
### Notes
You can initialize a new Supabase client using the `createClient()` method.
The Supabase client is your entrypoint to the rest of the Supabase functionality
and is the easiest way to interact with everything we offer within the Supabase ecosystem.
### Examples
#### Create a Supabase client.
```js
import { createClient } from '@supabase/supabase-js'
// Create a single supabase client for interacting with your database
const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key')
```
#### With additional parameters
```js
import { createClient } from '@supabase/supabase-js'
const options = {
schema: 'public',
headers: { 'x-my-custom-header': 'my-app-name' },
autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: true
}
const supabase = createClient("https://xyzcompany.supabase.co", "public-anon-key", options)
```
#### API schemas
```js
import { createClient } from '@supabase/supabase-js'
// Provide a custom schema. Defaults to "public".
const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key', {
schema: 'other_schema'
})
```
#### Custom `fetch` implementation
```js
import { createClient } from '@supabase/supabase-js'
const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key', {
fetch: fetch.bind(globalThis)
})
```
## Sign up
```js
const { user, session, error } = await supabase.auth.signUp(options)
```
### Notes
- By default, the user will need to verify their email address before logging in. If you would like to change this, you can disable "Email Confirmations" by going to Authentication -> Settings on [app.supabase.com](https://app.supabase.com)
- If "Email Confirmations" is turned on, a `user` is returned but `session` will be null
- If "Email Confirmations" is turned off, both a `user` and a `session` will be returned
- When the user confirms their email address, they will be redirected to localhost:3000 by default. To change this, you can go to Authentication -> Settings on [app.supabase.com](https://app.supabase.com)
- If signUp() is called for an existing confirmed user:
- If "Enable email confirmations" is enabled on the "Authentication" -> "Settings" page, an obfuscated / fake user object will be returned.
- If "Enable email confirmations" is disabled, an error with a message "User already registered" will be returned.
- To check if a user already exists, refer to getUser().
### Examples
#### With email and password.
```js
const { user, session, error } = await supabase.auth.signUp({
email: 'example@email.com',
password: 'example-password',
})
```
#### With additional user meta data.
```js
const { user, session, error } = await supabase.auth.signUp(
{
email: 'example@email.com',
password: 'example-password',
},
{
data: {
first_name: 'John',
age: 27,
}
}
)
```
#### Sign up with Phone.
```js
const { user, session, error } = await supabase.auth.signIn({
phone: '+13334445555',
password: 'some-password',
})
// After receiving an SMS with One Time Password.
let { session, error } = await supabase.auth.verifyOTP({
phone: '+13334445555',
token: '123456',
})
```
## Sign in
### Notes
- A user can sign up either via email or OAuth.
- If you provide `email` without a `password`, the user will be sent a magic link.
- The magic link's destination URL is determined by the SITE_URL config variable. To change this, you can go to Authentication -> Settings on [app.supabase.com](https://app.supabase.com)
- Specifying a `provider` will open the browser to the relevant login page.
### Examples
#### Sign in with email.
```js
const { user, session, error } = await supabase.auth.signIn({
email: 'example@email.com',
password: 'example-password',
})
```
#### Sign in with magic link.
```js
const { user, session, error } = await supabase.auth.signIn({
email: 'example@email.com'
})
```
#### Sign in using third-party providers.
```js
const { user, session, error } = await supabase.auth.signIn({
// provider can be 'github', 'google', 'gitlab', and more
provider: 'github'
})
```
#### Sign in with Phone.
```js
const { user, session, error } = await supabase.auth.signIn({
phone: '+13334445555',
password: 'some-password',
})
```
#### Sign in with redirect.
```js
const { user, session, error } = await supabase.auth.signIn({
provider: 'github'
}, {
redirectTo: 'https://example.com/welcome'
})
```
#### Sign in with scopes.
```js
const { user, session, error } = await supabase.auth.signIn({
provider: 'github'
}, {
scopes: 'repo gist notifications'
})
const oAuthToken = session.provider_token // use to access provider API
```
#### Sign in using a refresh token (e.g. in React Native).
```js
// An example using Expo's `AuthSession`
const redirectUri = AuthSession.makeRedirectUri({ useProxy: false });
const provider = 'google';
AuthSession.startAsync({
authUrl: `https://MYSUPABASEAPP.supabase.co/auth/v1/authorize?provider=${provider}&redirect_to=${redirectUri}`,
returnUrl: redirectUri,
}).then(async (response: any) => {
if (!response) return;
const { user, session, error } = await supabase.auth.signIn({
refreshToken: response.params?.refresh_token,
});
});
```
## Sign out
### Notes
### Examples
#### Sign out
```js
const { error } = await supabase.auth.signOut()
```
## Get user session
### Notes
### Examples
#### Get the session data
```js
const session = supabase.auth.session()
```
## Get user data
### Notes
This method gets the user object from memory.
### Examples
#### Get the logged in user
```js
const user = supabase.auth.user()
```
## Update user metadata
### Notes
User email: Email updates will send an email to both the user's current and new email with a confirmation link by default.
To toggle this behavior off and only send a single confirmation link to the new email, toggle "Double confirm email changes" under "Authentication" -> "Settings" off.
User metadata: It's generally better to store user data in a table inside your public schema (i.e. `public.users`).
Use the `update()` method if you have data which rarely changes or is specific only to the logged in user.
### Examples
#### Update email for authenticated user.
```js
const { user, error } = await supabase.auth.update({email: 'new@email.com'})
```
#### Update password for authenticated user.
```js
const { user, error } = await supabase.auth.update({password: 'new password'})
```
#### Update a user's metadata.
```js
const { user, error } = await supabase.auth.update({
data: { hello: 'world' }
})
```
## Set the authenticated users
### Notes
This is most useful on server-side functions where you cannot log the user in, but have access to the user's access token.
### Examples
#### Basic example
```js
function apiFunction(req, res) {
// Assuming the access token was sent as a header "X-Supabase-Auth"
const { access_token } = req.get('X-Supabase-Auth')
// You can now use it within a Supabase Client
const supabase = createClient("https://xyzcompany.supabase.co", "public-anon-key")
const { user, error } = supabase.auth.setAuth(access_token)
// This client will now send requests as this user
const { data } = await supabase.from('your_table').select()
}
```
#### With Express.
```js
/**
* Make a request from the client to your server function
*/
async function makeApiRequest() {
const token = newClient.session()?.access_token
await fetch('https://example.com/withAuth', {
method: 'GET',
withCredentials: true,
credentials: 'include',
headers: {
'Content-Type': 'application/json',
'Authorization': bearer, // Your own auth
'X-Supabase-Auth': token, // Set the Supabase user
}
})
}
/**
* Use the Auth token in your server-side function.
*/
async function apiFunction(req, res) {
const { access_token } = req.get('X-Supabase-Auth')
// You can now use it within a Supabase Client
const supabase = createClient("https://xyzcompany.supabase.co", "public-anon-key")
const { user, error } = supabase.auth.setAuth(access_token)
// This client will now send requests as this user
const { data } = await supabase.from('your_table').select()
}
```
## Listen to auth events
### Notes
### Examples
#### Listen to auth changes
```js
supabase.auth.onAuthStateChange((event, session) => {
console.log(event, session)
})
```
#### Listen to sign in
```js
supabase.auth.onAuthStateChange((event, session) => {
if (event == 'SIGNED_IN') console.log('SIGNED_IN', session)
})
```
#### Listen to sign out
```js
supabase.auth.onAuthStateChange((event, session) => {
if (event == 'SIGNED_OUT') console.log('SIGNED_OUT', session)
})
```
#### Listen to token refresh
```js
supabase.auth.onAuthStateChange((event, session) => {
if (event == 'TOKEN_REFRESHED') console.log('TOKEN_REFRESHED', session)
})
```
#### Listen to user updates
```js
supabase.auth.onAuthStateChange((event, session) => {
if (event == 'USER_UPDATED') console.log('USER_UPDATED', session)
})
```
#### Listen to user deleted
```js
supabase.auth.onAuthStateChange((event, session) => {
if (event == 'USER_DELETED') console.log('USER_DELETED', session)
})
```
#### Listen to password recovery events
```js
supabase.auth.onAuthStateChange((event, session) => {
if (event == 'PASSWORD_RECOVERY') console.log('PASSWORD_RECOVERY', session)
})
```
## Get User
### Notes
- Fetches the user object from the database instead of local storage.
- Note that user() fetches the user object from local storage which might not be the most updated.
- Requires the user's access_token.
### Examples
#### Fetch the user object using the access_token jwt.
```js
const { user, error } = await supabase.auth.api.getUser(
'ACCESS_TOKEN_JWT',
)
```
## List all users
### Notes
- Requires a `service_role` key.
- This function should be called on a server. Never expose your `service_role` key in the browser.
### Examples
#### Get a full list of users.
```js
const { data: user, error } = await supabase.auth.api.listUsers()
```
## Create user
### Notes
- Requires a `service_role` key.
- This function should be called on a server. Never expose your `service_role` key in the browser.
- If you do not provide the `email_confirm` and `phone_confirm` options to this function, both will default to false.
### Examples
#### Create a new user.
```js
const { data: user, error } = await supabase.auth.api.createUser({
email: 'user@email.com',
password: 'password',
user_metadata: { name: 'Yoda' }
})
```
#### Auto-confirm email.
```js
const { data: user, error } = await supabase.auth.api.createUser({
email: 'user@email.com',
email_confirm: true
})
```
#### Auto-confirm phone.
```js
const { data: user, error } = await supabase.auth.api.createUser({
phone: '1234567890',
phone_confirm: true
})
```
## Delete user
### Notes
- Requires a `service_role` key.
- This function should be called on a server. Never expose your `service_role` key in the browser.
### Examples
#### Remove a user completely.
```js
const { data: user, error } = await supabase.auth.api.deleteUser(
'715ed5db-f090-4b8c-a067-640ecee36aa0'
)
```
## Invite user by email
### Notes
- Requires a `service_role` key.
- This function should only be called on a server. Never expose your `service_role` key in the browser.
### Examples
#### Basic example.
```js
const { data: user, error } = await supabase.auth
.api
.inviteUserByEmail('email@example.com')
```
## Send mobile OTP
### Notes
- Requires a `service_role` key.
- This function should only be called on a server. Never expose your `service_role` key in the browser.
### Examples
#### Basic example.
```js
const { data: user, error } = await supabase.auth
.api
.sendMobileOTP('12345879')
```
## Reset passwprd for email address
### Notes
Sends a reset request to an email address.
When the user clicks the reset link in the email they will be forwarded to:
`<SITE_URL>#access_token=x&refresh_token=y&expires_in=z&token_type=bearer&type=recovery`
Your app must detect `type=recovery` in the fragment and display a password reset form to the user.
You should then use the access_token in the url and new password to update the user as follows:
```js
const { error, data } = await supabase.auth.api
.updateUser(access_token, { password : new_password })
```
### Examples
#### Reset password
```js
const { data, error } = await supabase.auth.api
.resetPasswordForEmail('user@email.com')
```
## Generate Auth Link
### Notes
- Requires a `service_role` key.
- This function should only be called on a server. Never expose your `service_role` key in the browser.
### Examples
#### Generate invite link.
```js
const { data: user, error } = await supabase.auth.api.generateLink(
'invite',
'email@example.com'
)
```
## Update user by ID
### Notes
- Requires a `service_role` key.
- This function should only be called on a server. Never expose your `service_role` key in the browser.
### Examples
#### Updates a user's email.
```js
const { data: user, error } = await supabase.auth.api.updateUserById(
'6aa5d0d4-2a9f-4483-b6c8-0cf4c6c98ac4',
{ email: 'new@email.com' }
)
```
#### Updates a user's password.
```js
const { data: user, error } = await supabase.auth.api.updateUserById(
'6aa5d0d4-2a9f-4483-b6c8-0cf4c6c98ac4',
{ password: 'new_password' }
)
```
#### Updates a user's metadata.
```js
const { data: user, error } = await supabase.auth.api.updateUserById(
'6aa5d0d4-2a9f-4483-b6c8-0cf4c6c98ac4',
{ user_metadata: { hello: 'world' } }
)
```
#### Updates a user's app_metadata.
```js
const { data: user, error } = await supabase.auth.api.updateUserById(
'6aa5d0d4-2a9f-4483-b6c8-0cf4c6c98ac4',
{ app_metadata: { plan: 'trial' } }
)
```
#### Confirms a user's email address.
```js
const { data: user, error } = await supabase.auth.api.updateUserById(
'6aa5d0d4-2a9f-4483-b6c8-0cf4c6c98ac4',
{ email_confirm: true }
)
```
#### Confirms a user's phone number.
```js
const { data: user, error } = await supabase.auth.api.updateUserById(
'6aa5d0d4-2a9f-4483-b6c8-0cf4c6c98ac4',
{ phone_confirm: true }
)
```
## Invoke an Edge Function
### Notes
Invokes a Supabase Function.
:::caution
Edge Functions are Experimental until 1 August 2022. There will breaking changes. Do not use them in Production.
:::
We have released Supabase Functions to gather feedback. You're welcome to try them out and send us feedback but we strongly advise against using them for anything in production.
There will be breaking changes with no notice.
- Requires an Authorization header.
- Invoke params generally match the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) spec.
### Examples
#### Basic invocation.
```js
const { data: user, error } = await supabase.functions.invoke('hello', {
body: JSON.stringify({ foo: 'bar' })
})
```
#### Specifying response type.
```js
const { data: user, error } = await supabase.functions.invoke('hello', {
responseType: 'text',
body: JSON.stringify({ foo: 'bar' })
})
```
#### Parsing custom headers.
```js
const { data: user, error } = await supabase.functions.invoke('hello', {
headers: {
"my-custom-header": 'my-custom-header-value'
},
body: JSON.stringify({ foo: 'bar' })
})
```
## Fetch data from database
### Notes
- By default, Supabase projects will return a maximum of 1,000 rows. This setting can be changed in Project API Settings. It's recommended that you keep it low to limit the payload size of accidental or malicious requests. You can use `range()` queries to paginate through your data.
- `select()` can be combined with [Modifiers](https://supabase.com/docs/reference/javascript/using-modifiers)
- `select()` can be combined with [Filters](https://supabase.com/docs/reference/javascript/using-filters)
- If using the Supabase hosted platform `apikey` is technically a reserved keyword, since the API gateway will pluck it out for authentication. [It should be avoided as a column name](https://github.com/supabase/supabase/issues/5465).
### Examples
#### Getting your data
```js
const { data, error } = await supabase
.from('cities')
.select()
```
#### Selecting specific columns
```js
const { data, error } = await supabase
.from('cities')
.select('name')
```
#### Query foreign tables
```js
const { data, error } = await supabase
.from('countries')
.select(`
name,
cities (
name
)
`)
```
#### Query the same foreign table multiple times
```js
const { data, error } = await supabase
.from('products')
.select(`
id,
supplier:supplier_id ( name ),
purchaser:purchaser_id ( name )
`)
```
#### Filtering with inner joins
```js
const { data, error } = await supabase
.from('messages')
.select('*, users!inner(*)')
.eq('users.username', 'Jane')
```
#### Querying with count option
```js
const { data, error, count } = await supabase
.from('cities')
.select('name', { count: 'exact' }) // if you don't want to return any rows, you can use { count: 'exact', head: true }
```
#### Querying JSON data
```js
const { data, error } = await supabase
.from('users')
.select(`
id, name,
address->street
`)
.eq('address->postcode', 90210)
```
#### Return data as CSV
```js
const { data, error } = await supabase
.from('users')
.select()
.csv()
```
#### Aborting requests in-flight
```js
const ac = new AbortController()
supabase
.from('very_big_table')
.select()
.abortSignal(ac.signal)
.then(console.log)
ac.abort()
// {
// error: {
// message: 'FetchError: The user aborted a request.',
// details: '',
// hint: '',
// code: ''
// },
// data: null,
// body: null,
// count: null,
// status: 400,
// statusText: 'Bad Request'
// }
```
## Insert data into database
### Notes
- By default, every time you run `insert()`, the client library will make a `select` to return the full record.
This is convenient, but it can also cause problems if your Policies are not configured to allow the `select` operation.
If you are using Row Level Security and you are encountering problems, try setting the `returning` param to `minimal`.
### Examples
#### Create a record
```js
const { data, error } = await supabase
.from('cities')
.insert([
{ name: 'The Shire', country_id: 554 }
])
```
#### Bulk create
```js
const { data, error } = await supabase
.from('cities')
.insert([
{ name: 'The Shire', country_id: 554 },
{ name: 'Rohan', country_id: 555 },
])
```
#### Upsert
```js
const { data, error } = await supabase
.from('cities')
.insert(
[
{ name: 'The Shire', country_id: 554 },
{ name: 'Rohan', country_id: 555 },
{ name: 'City by the Bay', country_id:840}
],
{ upsert: true })
```
## Update data in database
### Notes
- `update()` should always be combined with [Filters](https://supabase.com/docs/reference/javascript/using-filters) to target the item(s) you wish to update.
### Examples
#### Updating your data
```js
const { data, error } = await supabase
.from('cities')
.update({ name: 'Middle Earth' })
.match({ name: 'Auckland' })
```
#### Updating JSON data
```js
const { data, error } = await supabase
.from('users')
.update(`
address: {
street: 'Melrose Place',
postcode: 90210
}
`)
.eq('address->postcode', 90210)
```
## Upsert data into database
### Notes
- Primary keys should be included in the data payload in order for an update to work correctly.
- Primary keys must be natural, not surrogate. There are however, [workarounds](https://github.com/PostgREST/postgrest/issues/1118) for surrogate primary keys.
### Examples
#### Upsert your data
```js
const { data, error } = await supabase
.from('messages')
.upsert({ id: 3, message: 'foo', username: 'supabot' })
```
#### Bulk Upsert your data
```js
const { data, error } = await supabase
.from('messages')
.upsert([
{ id: 3, message: 'foo', username: 'supabot' },
{ id: 4, message: 'bar', username: 'supabot' }
])
```
#### Upserting into tables with constraints
```js
const { data, error } = await supabase
.from('users')
.upsert({ username: 'supabot' }, { onConflict: 'username' })
```
#### Return the exact number of rows
```js
const { data, error, count } = await supabase
.from('users')
.upsert({
id: 3, message: 'foo',
username: 'supabot'
}, {
count: 'exact'
})
```
## Delete data from database
### Notes
- `delete()` should always be combined with [filters](https://supabase.com/docs/reference/javascript/using-filters) to target the item(s) you wish to delete.
- If you use `delete()` with filters and you have
[RLS](https://supabase.com/docs/learn/auth-deep-dive/auth-row-level-security) enabled, only
rows visible through `SELECT` policies are deleted. Note that by default
no rows are visible, so you need at least one `SELECT`/`ALL` policy that
makes the rows visible.
### Examples
#### Delete records
```js
const { data, error } = await supabase
.from('cities')
.delete()
.match({ id: 666 })
```
## Execute Postgres functions
### Notes
You can call Postgres functions as a "Remote Procedure Call".
That's a fancy way of saying that you can put some logic into your database then call it from anywhere.
It's especially useful when the logic rarely changes - like password resets and updates.
```sql
create or replace function hello_world() returns text as $$
select 'Hello world';
$$ language sql;
```
### Examples
#### Call a Postgres function
```js
const { data, error } = await supabase
.rpc('hello_world')
```
#### With Parameters
```js
const { data, error } = await supabase
.rpc('echo_city', { name: 'The Shire' })
```
#### Bulk processing
```js
const { data, error } = await postgrest
.rpc('echo_cities', { names: ['The Shire', 'Mordor'] })
```
#### With filters
```js
const { data, error } = await supabase
.rpc('echo_all_cities')
.select('name, population')
.eq('name', 'The Shire')
```
#### With count option
```js
const { data, error, count } = await supabase
.rpc('hello_world', {}, { count: 'exact' })
```
## Subscribe to database changes
### Notes
- Realtime is disabled by default for new Projects for better database performance and security. You can turn it on by [managing replication](https://supabase.com/docs/guides/api#managing-realtime).
- If you want to receive the "previous" data for updates and deletes, you will need to set `REPLICA IDENTITY` to `FULL`, like this: `ALTER TABLE your_table REPLICA IDENTITY FULL;`
### Examples
#### Listen to all database changes
```js
const mySubscription = supabase
.from('*')
.on('*', payload => {
console.log('Change received!', payload)
})
.subscribe()
```
#### Listening to a specific table
```js
const mySubscription = supabase
.from('countries')
.on('*', payload => {
console.log('Change received!', payload)
})
.subscribe()
```
#### Listening to inserts
```js
const mySubscription = supabase
.from('countries')
.on('INSERT', payload => {
console.log('Change received!', payload)
})
.subscribe()
```
#### Listening to updates
```js
const mySubscription = supabase
.from('countries')
.on('UPDATE', payload => {
console.log('Change received!', payload)
})
.subscribe()
```
#### Listening to deletes
```js
const mySubscription = supabase
.from('countries')
.on('DELETE', payload => {
console.log('Change received!', payload)
})
.subscribe()
```
#### Listening to multiple events
```js
const mySubscription = supabase
.from('countries')
.on('INSERT', handleRecordInserted)
.on('DELETE', handleRecordDeleted)
.subscribe()
```
#### Listening to row level changes
```js
const mySubscription = supabase
.from('countries:id=eq.200')
.on('UPDATE', handleRecordUpdated)
.subscribe()
```
## Remove database subscription
### Notes
- Removing subscriptions is a great way to maintain the performance of your project's database. Supabase will automatically handle cleanup 30 seconds after a user is disconnected, but unused subscriptions may cause degradation as more users are simultaneously subscribed.
### Examples
#### Remove a subscription
```js
supabase.removeSubscription(mySubscription)
```
## Remove all subscriptions
### Notes
- Removing subscriptions is a great way to maintain the performance of your project's database. Supabase will automatically handle cleanup 30 seconds after a user is disconnected, but unused subscriptions may cause degradation as more users are simultaneously subscribed.
### Examples
#### Removes all subscriptions
```js
supabase.removeAllSubscriptions()
```
## Get all subcscriptions
### Notes
### Examples
#### Get all subscriptions
```js
const subscriptions = supabase.getSubscriptions()
```
## List all buckets
### Notes
- Policy permissions required:
- `buckets` permissions: `select`
- `objects` permissions: none
### Examples
#### List buckets
```js
const { data, error } = await supabase
.storage
.listBuckets()
```
## Get a single bucket
### Notes
- Policy permissions required:
- `buckets` permissions: `select`
- `objects` permissions: none
### Examples
#### Get bucket
```js
const { data, error } = await supabase
.storage
.getBucket('avatars')
```
## Create a new bucket
### Notes
- Policy permissions required:
- `buckets` permissions: `insert`
- `objects` permissions: none
### Examples
#### Create bucket
```js
const { data, error } = await supabase
.storage
.createBucket('avatars', { public: false })
```
## Empty a bucket
### Notes
- Policy permissions required:
- `buckets` permissions: `select`
- `objects` permissions: `select` and `delete`
### Examples
#### Empty bucket
```js
const { data, error } = await supabase
.storage
.emptyBucket('avatars')
```
## updateBucket()
### Notes
- Policy permissions required:
- `buckets` permissions: `update`
- `objects` permissions: none
### Examples
#### Update bucket
```js
const { data, error } = await supabase
.storage
.updateBucket('avatars', { public: false })
```
## deleteBucket()
### Notes
- Policy permissions required:
- `buckets` permissions: `select` and `delete`
- `objects` permissions: none
### Examples
#### Delete bucket
```js
const { data, error } = await supabase
.storage
.deleteBucket('avatars')
```
## Upload a file
### Notes
- Policy permissions required:
- `buckets` permissions: none
- `objects` permissions: `insert`
- For React Native, using either `Blob`, `File` or `FormData` does not work as intended. Upload file using `ArrayBuffer` from base64 file data instead, see example below.
### Examples
#### Upload file
```js
const avatarFile = event.target.files[0]
const { data, error } = await supabase
.storage
.from('avatars')
.upload('public/avatar1.png', avatarFile, {
cacheControl: '3600',
upsert: false
})
```
#### Upload file using `ArrayBuffer` from base64 file data
```js
import { decode } from 'base64-arraybuffer'
const { data, error } = await supabase
.storage
.from('avatars')
.upload('public/avatar1.png', decode('base64FileData'), {
contentType: 'image/png'
})
```
## Update a file
### Notes
- Policy permissions required:
- `buckets` permissions: none
- `objects` permissions: `update` and `select`
- For React Native, using either `Blob`, `File` or `FormData` does not work as intended. Update file using `ArrayBuffer` from base64 file data instead, see example below.
### Examples
#### Update file
```js
const avatarFile = event.target.files[0]
const { data, error } = await supabase
.storage
.from('avatars')
.update('public/avatar1.png', avatarFile, {
cacheControl: '3600',
upsert: false
})
```
#### Update file using `ArrayBuffer` from base64 file data
```js
import {decode} from 'base64-arraybuffer'
const { data, error } = await supabase
.storage
.from('avatars')
.update('public/avatar1.png', decode('base64FileData'), {
contentType: 'image/png'
})
```
## Move a file
### Notes
- Policy permissions required:
- `buckets` permissions: none
- `objects` permissions: `update` and `select`
### Examples
#### Move file
```js
const { data, error } = await supabase
.storage
.from('avatars')
.move('public/avatar1.png', 'private/avatar2.png')
```
## Copy a file
### Notes
- Policy permissions required:
- `buckets` permissions: none
- `objects` permissions: `update` and `select`
### Examples
#### Copy file
```js
const { data, error } = await supabase
.storage
.from('avatars')
.copy('public/avatar1.png', 'private/avatar2.png')
```
## Create a signed URL
### Notes
- Policy permissions required:
- `buckets` permissions: none
- `objects` permissions: `select`
### Examples
#### Create Signed URL
```js
const { signedURL, error } = await supabase
.storage
.from('avatars')
.createSignedUrl('folder/avatar1.png', 60)
```
## Sign multiple URLs
### Notes
- Policy permissions required:
- `buckets` permissions: none
- `objects` permissions: `select`
### Examples
#### Create Signed URLs
```js
const { data, error } = await supabase
.storage
.from('avatars')
.createSignedUrls(['folder/avatar1.png', 'folder/avatar2.png'], 60)
```
## Get public URL
### Notes
- The bucket needs to be set to public, either via [updateBucket()](https://supabase.com/docs/reference/javascript/storage-updatebucket) or by going to Storage on [app.supabase.com](https://app.supabase.com), clicking the overflow menu on a bucket and choosing "Make public"
- Policy permissions required:
- `buckets` permissions: none
- `objects` permissions: none
### Examples
#### Returns the URL for an asset in a public bucket
```js
const { publicURL, error } = supabase
.storage
.from('public-bucket')
.getPublicUrl('folder/avatar1.png')
```
## Download a file
### Notes
- Policy permissions required:
- `buckets` permissions: none
- `objects` permissions: `select`
### Examples
#### Download file
```js
const { data, error } = await supabase
.storage
.from('avatars')
.download('folder/avatar1.png')
```
## from.remove()
### Notes
- Policy permissions required:
- `buckets` permissions: none
- `objects` permissions: `delete` and `select`
### Examples
#### Delete file
```js
const { data, error } = await supabase
.storage
.from('avatars')
.remove(['folder/avatar1.png'])
```
## List files
### Notes
- Policy permissions required:
- `buckets` permissions: none
- `objects` permissions: `select`
### Examples
#### List files in a bucket
```js
const { data, error } = await supabase
.storage
.from('avatars')
.list('folder', {
limit: 100,
offset: 0,
sortBy: { column: 'name', order: 'asc' },
})
```
#### Search files in a bucket
```js
const { data, error } = await supabase
.storage
.from('avatars')
.list('folder', {
limit: 100,
offset: 0,
sortBy: { column: 'name', order: 'asc' },
search: 'jon'
})
```
## Limit rows returned
### Notes
Modifiers can be used on `select()` queries.
If a Postgres function returns a table response, you can also apply modifiers to the `rpc()` function.
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('cities')
.select('name, country_id')
.limit(1)
```
#### With embedded resources
```js
const { data, error } = await supabase
.from('countries')
.select('name, cities(name)')
.eq('name', 'United States')
.limit(1, { foreignTable: 'cities' })
```
## Order results
### Notes
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('cities')
.select('name', 'country_id')
.order('id', { ascending: false })
```
#### With embedded resources
```js
const { data, error } = await supabase
.from('countries')
.select('name, cities(name)')
.eq('name', 'United States')
.order('name', {foreignTable: 'cities'})
```
## Select a range of data
### Notes
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('cities')
.select('name, country_id')
.range(0,3)
```
## Get a single row of data
### Notes
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('cities')
.select('name, country_id')
.limit(1)
.single()
```
## Return a single row if it exists
### Notes
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('cities')
.select('name, country_id')
.eq('name', 'Singapore')
.maybeSingle()
```
## Apply multiple filters with OR conditional
### Notes
- `.or()` expects you to use the raw [PostgREST syntax](https://postgrest.org/en/stable/api.html#horizontal-filtering-rows) for the filter names and values.
```js
.or('id.in.(6,7), arraycol.cs.{"a","b"}') // Use Postgres list () for in filter. Array {} for array column and 'cs' for contains.
.or(`id.in.(${arrList}),arraycol.cs.{${arr}}`) // You can insert a javascipt array for list or array on array column.
.or(`id.in.(${arrList}),rangecol.cs.[${arrRange})`) // You can insert a javascipt array for list or range on a range column.
```
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('cities')
.select('name, country_id')
.or('id.eq.20,id.eq.30')
```
#### Use `or` with `and`
```js
const { data, error } = await supabase
.from('cities')
.select('name, country_id')
.or('id.gt.20,and(name.eq.New Zealand,name.eq.France)')
```
#### Use `or` on foreign tables
```js
const { data, error } = await supabase
.from('countries')
.select('id, cities(*)')
.or('name.eq.Wellington,name.eq.Paris', { foreignTable: "cities" })
```
## Apply a "not" filter
### Notes
- `.not()` expects you to use the raw [PostgREST syntax](https://postgrest.org/en/stable/api.html#horizontal-filtering-rows) for the filter names and values.
```js
.not('name','eq','Paris')
.not('arraycol','cs','{"a","b"}') // Use Postgres array {} for array column and 'cs' for contains.
.not('rangecol','cs','(1,2]') // Use Postgres range syntax for range column.
.not('id','in','(6,7)') // Use Postgres list () for in filter.
.not('id','in',`(${arr})`) // You can insert a javascript array.
```
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('cities')
.select('name, country_id')
.not('name', 'eq', 'Paris')
```
#### With `update()`
```js
const { data, error } = await supabase
.from('cities')
.update({ name: 'Mordor' })
.not('name', 'eq', 'Paris')
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('cities')
.delete()
.not('name', 'eq', 'Paris')
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_cities')
.not('name', 'eq', 'Paris')
```
## Match on several criteria
### Notes
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('cities')
.select('name, country_id')
.match({name: 'Beijing', country_id: 156})
```
#### With `update()`
```js
const { data, error } = await supabase
.from('cities')
.update({ name: 'Mordor' })
.match({name: 'Beijing', country_id: 156})
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('cities')
.delete()
.match({name: 'Beijing', country_id: 156})
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_cities')
.match({name: 'Beijing', country_id: 156})
```
## Filter by exact equality
### Notes
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('cities')
.select('name, country_id')
.eq('name', 'The shire')
```
#### With `update()`
```js
const { data, error } = await supabase
.from('cities')
.update({ name: 'Mordor' })
.eq('name', 'San Francisco')
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('cities')
.delete()
.eq('name', 'Mordor')
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_cities')
.eq('name', 'San Francisco')
```
## Filter by not equal
### Notes
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('cities')
.select('name, country_id')
.neq('name', 'The shire')
```
#### With `update()`
```js
const { data, error } = await supabase
.from('cities')
.update({ name: 'Mordor' })
.neq('name', 'San Francisco')
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('cities')
.delete()
.neq('name', 'Mordor')
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_cities')
.neq('name', 'Lagos')
```
## Filter by greater than
### Notes
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('cities')
.select('name, country_id')
.gt('country_id', 250)
```
#### With `update()`
```js
const { data, error } = await supabase
.from('cities')
.update({ name: 'Mordor' })
.gt('country_id', 250)
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('cities')
.delete()
.gt('country_id', 250)
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_cities')
.gt('country_id', 250)
```
## Filter by greater than or equal
### Notes
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('cities')
.select('name, country_id')
.gte('country_id', 250)
```
#### With `update()`
```js
const { data, error } = await supabase
.from('cities')
.update({ name: 'Mordor' })
.gte('country_id', 250)
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('cities')
.delete()
.gte('country_id', 250)
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_cities')
.gte('country_id', 250)
```
## Filter by less than
### Notes
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('cities')
.select('name, country_id')
.lt('country_id', 250)
```
#### With `update()`
```js
const { data, error } = await supabase
.from('cities')
.update({ name: 'Mordor' })
.lt('country_id', 250)
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('cities')
.delete()
.lt('country_id', 250)
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_cities')
.lt('country_id', 250)
```
## Filter by TBD
### Notes
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('cities')
.select('name, country_id')
.lte('country_id', 250)
```
#### With `update()`
```js
const { data, error } = await supabase
.from('cities')
.update({ name: 'Mordor' })
.lte('country_id', 250)
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('cities')
.delete()
.lte('country_id', 250)
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_cities')
.lte('country_id', 250)
```
## Filter by string equality
### Notes
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('cities')
.select('name, country_id')
.like('name', '%la%')
```
#### With `update()`
```js
const { data, error } = await supabase
.from('cities')
.update({ name: 'Mordor' })
.like('name', '%la%')
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('cities')
.delete()
.like('name', '%la%')
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_cities')
.like('name', '%la%')
```
## Filter by string equality (case insensitive)
### Notes
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('cities')
.select('name, country_id')
.ilike('name', '%la%')
```
#### With `update()`
```js
const { data, error } = await supabase
.from('cities')
.update({ name: 'Mordor' })
.ilike('name', '%la%')
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('cities')
.delete()
.ilike('name', '%la%')
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_cities')
.ilike('name', '%la%')
```
## Filter by null values
### Notes
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('cities')
.select('name, country_id')
.is('name', null)
```
#### With `update()`
```js
const { data, error } = await supabase
.from('cities')
.update({ name: 'Mordor' })
.is('name', null)
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('cities')
.delete()
.is('name', null)
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_cities')
.is('name', null)
```
## Filter if in array
### Notes
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('cities')
.select('name, country_id')
.in('name', ['Rio de Janeiro', 'San Francisco'])
```
#### With `update()`
```js
const { data, error } = await supabase
.from('cities')
.update({ name: 'Mordor' })
.in('name', ['Rio de Janeiro', 'San Francisco'])
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('cities')
.delete()
.in('name', ['Rio de Janeiro', 'San Francisco'])
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_cities')
.in('name', ['Rio de Janeiro', 'San Francisco'])
```
## Filter if TBD
### Notes
- `.contains()` can work on array columns or range columns.
It is very useful for finding rows where a tag array contains all the values in the filter array.
```js
.contains('arraycol',["a","b"]) // You can use a javascript array for an array column
.contains('arraycol','{"a","b"}') // You can use a string with Postgres array {} for array column.
.contains('rangecol','(1,2]') // Use Postgres range syntax for range column.
.contains('rangecol',`(${arr}]`) // You can insert an array into a string.
```
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('countries')
.select('name, id, main_exports')
.contains('main_exports', ['oil'])
```
#### With `update()`
```js
const { data, error } = await supabase
.from('countries')
.update({ name: 'Mordor' })
.contains('main_exports', ['oil'])
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('countries')
.delete()
.contains('main_exports', ['oil'])
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_countries')
.contains('main_exports', ['oil'])
```
## Filter by TBD
### Notes
- `.containedBy()` can work on array columns or range columns.
```js
.containedBy('arraycol',["a","b"]) // You can use a javascript array for an array column
.containedBy('arraycol','{"a","b"}') // You can use a string with Postgres array {} for array column.
.containedBy('rangecol','(1,2]') // Use Postgres range syntax for range column.
.containedBy('rangecol',`(${arr}]`) // You can insert an array into a string.
```
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('countries')
.select('name, id, main_exports')
.containedBy('main_exports', ['cars', 'food', 'machine'])
```
#### With `update()`
```js
const { data, error } = await supabase
.from('countries')
.update({ name: 'Mordor' })
.containedBy('main_exports', ['orks', 'surveillance', 'evil'])
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('countries')
.delete()
.containedBy('main_exports', ['cars', 'food', 'machine'])
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_countries')
.containedBy('main_exports', ['cars', 'food', 'machine'])
```
## Filter by TBD
### Notes
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('countries')
.select('name, id, population_range_millions')
.rangeLt('population_range_millions', '[150, 250]')
```
#### With `update()`
```js
const { data, error } = await supabase
.from('countries')
.update({ name: 'Mordor' })
.rangeLt('population_range_millions', '[150, 250]')
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('countries')
.delete()
.rangeLt('population_range_millions', '[150, 250]')
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_countries')
.rangeLt('population_range_millions', '[150, 250]')
```
## Filter by TBD
### Notes
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('countries')
.select('name, id, population_range_millions')
.rangeGt('population_range_millions', '[150, 250]')
```
#### With `update()`
```js
const { data, error } = await supabase
.from('countries')
.update({ name: 'Mordor' })
.rangeGt('population_range_millions', '[150, 250]')
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('countries')
.delete()
.rangeGt('population_range_millions', '[150, 250]')
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_countries')
.rangeGt('population_range_millions', '[150, 250]')
```
## Filter by TBD
### Notes
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('countries')
.select('name, id, population_range_millions')
.rangeGte('population_range_millions', '[150, 250]')
```
#### With `update()`
```js
const { data, error } = await supabase
.from('countries')
.update({ name: 'Mordor' })
.rangeGte('population_range_millions', '[150, 250]')
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('countries')
.delete()
.rangeGte('population_range_millions', '[150, 250]')
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_countries')
.rangeGte('population_range_millions', '[150, 250]')
```
## Filter by TBD
### Notes
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('countries')
.select('name, id, population_range_millions')
.rangeLte('population_range_millions', '[150, 250]')
```
#### With `update()`
```js
const { data, error } = await supabase
.from('countries')
.update({ name: 'Mordor' })
.rangeLte('population_range_millions', '[150, 250]')
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('countries')
.delete()
.rangeLte('population_range_millions', '[150, 250]')
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_countries')
.rangeLte('population_range_millions', '[150, 250]')
```
## Filter by TBD
### Notes
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('countries')
.select('name, id, population_range_millions')
.rangeAdjacent('population_range_millions', '[70, 185]')
```
#### With `update()`
```js
const { data, error } = await supabase
.from('countries')
.update({ name: 'Mordor' })
.rangeAdjacent('population_range_millions', '[70, 185]')
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('countries')
.delete()
.rangeAdjacent('population_range_millions', '[70, 185]')
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_countries')
.rangeAdjacent('population_range_millions', '[70, 185]')
```
## Filter by TBD
### Notes
- `.overlaps()` can work on array columns or range columns.
```js
.overlaps('arraycol',["a","b"]) // You can use a javascript array for an array column
.overlaps('arraycol','{"a","b"}') // You can use a string with Postgres array {} for array column.
.overlaps('rangecol','(1,2]') // Use Postgres range syntax for range column.
.overlaps('rangecol',`(${arr}]`) // You can insert an array into a string.
```
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('countries')
.select('name, id, main_exports')
.overlaps('main_exports', ['computers', 'minerals'])
```
#### With `update()`
```js
let countries = await supabase
.from('countries')
.update({ name: 'Mordor' })
.overlaps('main_exports', ['computers', 'minerals'])
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('countries')
.delete()
.overlaps('main_exports', ['computers', 'minerals'])
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_countries')
.overlaps('main_exports', ['computers', 'minerals'])
```
## Filter by TBD
### Notes
### Examples
#### Text search
```js
const { data, error } = await supabase
.from('quotes')
.select('catchphrase')
.textSearch('catchphrase', `'fat' & 'cat'`, {
config: 'english'
})
```
#### Basic normalization
```js
const { data, error } = await supabase
.from('quotes')
.select('catchphrase')
.textSearch('catchphrase', `'fat' & 'cat'`, {
type: 'plain',
config: 'english'
})
```
#### Full normalization
```js
const { data, error } = await supabase
.from('quotes')
.select('catchphrase')
.textSearch('catchphrase', `'fat' & 'cat'`, {
type: 'phrase',
config: 'english'
})
```
#### Websearch
```js
const { data, error } = await supabase
.from('quotes')
.select('catchphrase')
.textSearch('catchphrase', `'fat or cat'`, {
type: 'websearch',
config: 'english'
})
```
## Filter by TBD
### Notes
- `.filter()` expects you to use the raw [PostgREST syntax](https://postgrest.org/en/stable/api.html#horizontal-filtering-rows) for the filter names and values, so it should only be used as an escape hatch in case other filters don't work.
```js
.filter('arraycol','cs','{"a","b"}') // Use Postgres array {} for array column and 'cs' for contains.
.filter('rangecol','cs','(1,2]') // Use Postgres range syntax for range column.
.filter('id','in','(6,7)') // Use Postgres list () for in filter.
.filter('id','in',`(${arr})`) // You can insert a javascript array.
```
### Examples
#### With `select()`
```js
const { data, error } = await supabase
.from('cities')
.select('name, country_id')
.filter('name', 'in', '("Paris","Tokyo")')
```
#### With `update()`
```js
const { data, error } = await supabase
.from('cities')
.update({ name: 'Mordor' })
.filter('name', 'in', '("Paris","Tokyo")')
```
#### With `delete()`
```js
const { data, error } = await supabase
.from('cities')
.delete()
.filter('name', 'in', '("Paris","Tokyo")')
```
#### With `rpc()`
```js
// Only valid if the Postgres function returns a table type.
const { data, error } = await supabase
.rpc('echo_all_cities')
.filter('name', 'in', '("Paris","Tokyo")')
```
#### Filter embedded resources
```js
const { data, error } = await supabase
.from('cities')
.select('name, countries ( name )')
.filter('countries.name', 'in', '("France","Japan")')
```