Merge branch 'master' into joshen/spike/rls-tester

This commit is contained in:
Joshen Lim committed 2026-04-21 14:02:09 +08:00
commit bb2eb4caa7
301 files changed
+25680 -17497

No files matched your search

+1 -1
View File
@@ -1,5 +1,5 @@
import '@/styles/globals.css'
import '../../studio/styles/typography.scss'
import '../../studio/styles/typography.css'
import type { Metadata, Viewport } from 'next'
+1 -5
View File
@@ -1,5 +1 @@
module.exports = {
plugins: {
tailwindcss: {},
},
}
module.exports = require('config/postcss.config')
+4 -4
View File
@@ -1,9 +1,9 @@
import '@code-hike/mdx/styles.css'
import 'config/code-hike.scss'
import 'config/code-hike.css'
import 'ui-patterns/ShimmeringLoader/index.css'
import '../styles/main.scss'
import '../styles/new-docs.scss'
import '../styles/prism-okaidia.scss'
import '../styles/main.css'
import '../styles/new-docs.css'
import '../styles/prism-okaidia.css'
import { GlobalProviders } from '~/features/app.providers'
import { TopNavSkeleton } from '~/layouts/MainSkeleton'
@@ -1040,6 +1040,10 @@ export const database: NavMenuConstant = {
name: 'Implementing cascade deletes',
url: '/guides/database/postgres/cascade-deletes' as `/${string}`,
},
{
name: 'Deleting data and dropping objects safely',
url: '/guides/database/postgres/data-deletion' as `/${string}`,
},
{ name: 'Managing enums', url: '/guides/database/postgres/enums' },
{
name: 'Managing database functions',
@@ -1490,7 +1494,7 @@ export const api: NavMenuConstant = {
items: [
{ name: 'How API Keys work', url: '/guides/api/api-keys' },
{ name: 'Securing your API', url: '/guides/api/securing-your-api' },
{ name: 'Hardening the Data API', url: '/guides/api/hardening-data-api' },
{ name: 'Data API', url: '/guides/database/data-api' },
{
name: 'Custom Claims & RBAC',
url: '/guides/api/custom-claims-and-role-based-access-control-rbac',
@@ -2481,7 +2485,7 @@ export const security: NavMenuConstant = {
url: '/guides/deployment/shared-responsibility-model' as `/${string}`,
},
{ name: 'Row Level Security', url: '/guides/database/postgres/row-level-security' },
{ name: 'Hardening the Data API', url: '/guides/api/hardening-data-api' },
{ name: 'Data API', url: '/guides/database/data-api' },
],
},
],
@@ -2584,12 +2588,28 @@ export const platform: NavMenuConstant = {
enabled: fullPlatformEnabled,
items: [
{ name: 'Overview', url: '/guides/platform/sso' as `/${string}` },
{
name: 'Understanding Login Flows',
url: '/guides/platform/sso/login-flows' as `/${string}`,
},
{
name: 'Choosing a Login Flow',
url: '/guides/platform/sso/choosing-login-flow' as `/${string}`,
},
{ name: 'SSO with Azure AD', url: '/guides/platform/sso/azure' },
{
name: 'SSO with Google Workspace',
url: '/guides/platform/sso/gsuite' as `/${string}`,
},
{ name: 'SSO with Okta', url: '/guides/platform/sso/okta' },
{
name: 'Multiple SSO Providers',
url: '/guides/platform/sso/multiple-providers' as `/${string}`,
},
{
name: 'Testing and Best Practices',
url: '/guides/platform/sso/testing-best-practices' as `/${string}`,
},
],
},
],
@@ -32,7 +32,7 @@ curl -X POST https://api.supabase.com/v1/projects \
<StepHikeCompact.Details>
When your project is up and running, go to the [Table Editor](/dashboard/project/_/editor), create a new table and insert some data.
When your project is up and running, go to the [**Table Editor**](/dashboard/project/_/editor) section of the Dashboard, create a new table and insert some data. Then in the [**Integrations > Data API**](/dashboard/project/_/integrations/data_api/settings) section of the Dashboard, expose the specific tables or functions you want to access. To automatically grant access for new tables and functions in `public`, enable **Default privileges for new entities**.
Alternatively, you can run the following snippet in your project's [SQL Editor](/dashboard/project/_/sql/new). This will create an `instruments` table with some sample data.
@@ -54,6 +54,9 @@ Alternatively, you can run the following snippet in your project's [SQL Editor](
('cello');
alter table instruments enable row level security;
-- Enable read access for the Data API
grant select on public.instruments to anon;
```
</StepHikeCompact.Code>
@@ -108,7 +108,7 @@ const fetchWithRetry = fetchRetry(fetch, {
attempt < 3
&& response
&& response.status == 520 // Cloudflare errors
&& response.url.includes('rpc/your_stored_procedure')
&& response.url.includes('rpc/your_database_function')
if (shouldRetry(attempt, error, response)) {
console.log(`Retrying request... Attempt #${attempt}`, response)
@@ -119,9 +119,9 @@ const fetchWithRetry = fetchRetry(fetch, {
}
})
async function yourStoredProcedure() {
async function yourDatabaseFunction() {
const { data, error } = await supabase
.rpc('your_stored_procedure', { param1: 'value1' });
.rpc('your_database_function', { param1: 'value1' });
if (error) {
console.log('Error executing RPC:', error);
@@ -130,10 +130,10 @@ async function yourStoredProcedure() {
}
}
yourStoredProcedure();
yourDatabaseFunction();
```
By using `retryOn` with a custom function, you can define specific conditions for retrying requests. In this example, the retry logic is applied only to requests targeting a specific stored procedure.
By using `retryOn` with a custom function, you can define specific conditions for retrying requests. In this example, the retry logic is applied only to requests targeting a specific database function.
## Conclusion
@@ -25,29 +25,39 @@ This creates a corresponding route `todos` which can accept `GET`, `POST`, `PATC
1. Click **Save**.
1. Click **New Column** and create a column with the name `task` and type `text`.
1. Click **Save**.
<video width="99%" muted playsInline controls={true}>
<source
src="https://xguihxuzqibwxjnimxev.supabase.co/storage/v1/object/public/videos/docs/api/api-create-table-sm.mp4"
type="video/mp4"
/>
</video>
1. In the [**Integrations > Data API**](/dashboard/project/_/integrations/data_api/settings) section of the Dashboard, expose specific tables like `todos` or the functions you want to access. To automatically grant access for new tables and functions in `public`, enable **Default privileges for new entities**.
</TabPanel>
<TabPanel id="sql" label="SQL">
```sql
-- Create a table called "todos" with a column to store tasks.
-- Create a table called "todos" with a column to store tasks.
create table
todos (
id bigint generated by default as identity primary key,
task text check (char_length(task) > 3)
);
-- Enable Data API access with least-privilege grants
-- Allow read-only access for anonymous clients
grant select on public.todos to anon;
-- Allow full CRUD for authenticated clients
grant select, insert, update, delete on public.todos to authenticated;
-- Allow full CRUD for the server-side service role
grant select, insert, update, delete on public.todos to service_role;
-- Important: enable Row Level Security and create appropriate policies
-- before granting write access to client roles (see RLS guide)
```
</TabPanel>
</Tabs>
<Admonition type="note" title="What it means to expose tables or functions via the API">
Granting privileges (like `select` or `execute`) to roles such as `anon` or `authenticated` makes those tables or functions accessible through the Data API. Behind the scenes, the API checks your Postgres permissions—only objects with explicit grants are exposed, and all other access is denied by default.
</Admonition>
## API URL and keys
Every Supabase project has a unique API URL. Your API is secured behind an API gateway which requires an API Key for every request.
@@ -92,6 +102,7 @@ using the API URL (`SUPABASE_URL`) and Key (`SUPABASE_PUBLISHABLE_KEY`) we provi
```javascript
// Initialize the JS client
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(SUPABASE_URL, SUPABASE_PUBLISHABLE_KEY)
// Make a request
@@ -1,137 +0,0 @@
---
title: 'Hardening the Data API'
---
Your database's auto-generated Data API exposes the `public` schema by default. You can change this to any schema in your database, or even disable the Data API completely.
Any tables that are accessible through the Data API _must_ have [Row Level Security](/docs/guides/database/postgres/row-level-security) enabled. Row Level Security (RLS) is enabled by default when you create tables from the Supabase Dashboard. If you create a table using the SQL editor or your own SQL client or migration runner, you*must* enable RLS yourself.
## Shared responsibility
Your application's security is your responsibility as a developer. This includes RLS, falling under the [Shared Responsibility](/docs/guides/deployment/shared-responsibility-model) model. To help you:
- Supabase sends daily emails warning of any tables that are exposed to the Data API which do not have RLS enabled.
- Supabase provides a Security Advisor and other tools in the Supabase Dashboard to fix any issues.
## Private schemas
We highly recommend creating a `private` schema for storing tables that you do not want to expose via the Data API. These tables can be accessed via Supabase Edge Functions or any other serverside tool. In this model, you should implement your security model in your serverside code. Although it's not required, we _still_ recommend enabling RLS for private tables and then connecting to your database using a Postgres role with `bypassrls` privileges.
## Managing the public schema
If your `public` schema is used by other tools as a default space, you might want to lock down this schema. This helps prevent accidental exposure of data that's automatically added to `public`.
There are several levels of security hardening for the Data API:
- [Disabling the Data API entirely](#disabling-the-data-api). This is recommended if you _never_ need to access your database via Supabase client libraries or the REST and GraphQL endpoints.
- [Exposing a custom schema](#exposing-a-custom-schema-instead-of-public) instead of `public`, giving you explicit control over what is accessible.
- [Automatically enabling RLS on new tables](#automatically-enabling-rls-on-new-tables) using an event trigger.
- [Adjusting table-level grants](#table-level-grants) to control which roles can access specific tables.
## Disabling the Data API
You can disable the Data API entirely if you never intend to use the Supabase client libraries or the REST and GraphQL data endpoints. For example, if you only access your database via a direct connection on the server, disabling the Data API gives you the greatest layer of protection.
1. Go to [API Settings](/dashboard/project/_/settings/api) in the Supabase Dashboard.
1. Under **Data API Settings**, toggle **Enable Data API** off.
## Exposing a custom schema instead of `public`
If you want to use the Data API but with increased security, you can expose a custom schema instead of `public`. By not using `public`, which is often used as a default space and has laxer default permissions, you get more conscious control over your exposed data.
Any data, views, or functions that should be exposed need to be deliberately put within your custom schema (which we will call `api`), rather than ending up there by default.
### Step 1: Remove `public` from exposed schemas
1. Go to [**API Settings**](/dashboard/project/_/settings/api) in the Supabase Dashboard.
1. Under **Data API Settings**, remove `public` from **Exposed schemas**. Also remove `public` from **Extra search path**.
1. Click **Save**.
1. Go to [**Database Extensions**](/dashboard/project/_/database/extensions) and disable the `pg_graphql` extension.
### Step 2: Create an `api` schema and expose it
1. Connect to your database. You can use `psql`, the [Supabase SQL Editor](/dashboard/project/_/sql), or the Postgres client of your choice.
1. Create a new schema named `api`:
```sql
create schema if not exists api;
```
1. Grant the `anon` and `authenticated` roles usage on this schema.
```sql
grant usage on schema api to anon, authenticated;
```
1. Go to [API Settings](/dashboard/project/_/settings/api) in the Supabase Dashboard.
1. Under **Data API Settings**, add `api` to **Exposed schemas**. Make sure it is the first schema in the list, so that it will be searched first by default.
1. Under these new settings, `anon` and `authenticated` can execute functions defined in the `api` schema, but they have no automatic permissions on any tables. On a table-by-table basis, you can grant them permissions. For example:
```sql
grant select on table api.<your_table> to anon;
grant select, insert, update, delete on table api.<your_table> to authenticated;
```
## Automatically enabling RLS on new tables
Tables created via the Supabase Dashboard have RLS enabled by default. However, if you or your team create tables using the SQL editor, migrations, or an external tool, RLS will not be enabled automatically.
You can use an [event trigger](/docs/guides/database/postgres/event-triggers#example-trigger-function---auto-enable-row-level-security) to automatically enable RLS whenever a new table is created in the `public` schema. This ensures that no table is accidentally left exposed without RLS protection.
## Table-level grants
By default, tables in the `public` schema are granted full access (`SELECT`, `INSERT`, `UPDATE`, `DELETE`) to the `anon` and `authenticated` roles. This allows the Data API to query those tables on behalf of users.
You can adjust these privileges on a per-table basis to restrict which operations each role can perform. For example, you might want to:
- Allow `anon` users to only `SELECT` from a table, preventing anonymous writes.
- Prevent `anon` users from accessing a table entirely, making it available only to authenticated users.
- Restrict `authenticated` users to `SELECT` and `INSERT` only, preventing updates and deletes.
<Admonition type="tip">
Table-level privileges work alongside [Row Level Security](/docs/guides/database/postgres/row-level-security). Privileges control _which operations_ are possible, while RLS policies control _which rows_ are accessible. For full protection, use both: restrict privileges to limit operation types, and use RLS policies to control row-level access.
</Admonition>
### Adjusting table-level grants via the Dashboard
<Admonition type="note">
Adjusting table-level privileges via the Dashboard is currently in beta and will be available via gradual roll-out.
</Admonition>
1. Go to [**Table Editor**](/dashboard/project/_/editor) in the Supabase Dashboard.
2. Select the table you want to configure.
3. Click the vertical dots icon to open the table menu and select "Edit table".
4. Under **Data API Access**, click the settings icon to open **Adjust API privileges per role**.
5. For each role (`anon` and `authenticated`), select or deselect the privileges you want to grant.
6. Click **Save**.
### Adjusting table-level grants via SQL
You can also adjust privileges using SQL. For example, to allow only `SELECT` access for `anon` on a table:
```sql
-- Revoke all existing privileges
revoke all on table public.your_table from anon;
-- Grant only SELECT
grant select on table public.your_table to anon;
```
To remove all access for `anon` from a table:
```sql
revoke all on table public.your_table from anon;
```
To restore full access:
```sql
grant select, insert, update, delete on table public.your_table to anon;
```
+23 -7
View File
@@ -38,17 +38,21 @@ We'll create a database table called `todos` for storing tasks. This creates a c
id serial primary key,
task text
);
-- Enable Data API access
-- Allow read-only access for anonymous clients
grant select on public.todos to anon;
```
</TabPanel>
<TabPanel id="dashboard" label="Dashboard">
<video width="99%" muted playsInline controls={true}>
<source
src="https://xguihxuzqibwxjnimxev.supabase.co/storage/v1/object/public/videos/docs/api/api-create-table-sm.mp4"
type="video/mp4"
/>
</video>
1. Go to the [**Table editor**](/dashboard/project/_/editor) section in the Dashboard.
2. Click **New Table** and create a table with the name `todos`.
3. Click **Save**.
4. Click **New Column** and create a column with the name `task` and type `text`.
5. Click **Save**.
6. In the [**Integrations > Data API**](/dashboard/project/_/integrations/data_api/settings) section of the Dashboard, expose the `todos` table. To automatically grant access for new tables and functions in `public`, enable **Default privileges for new entities**.
</TabPanel>
</Tabs>
@@ -61,7 +65,7 @@ We'll create a database table called `todos` for storing tasks. This creates a c
<StepHikeCompact.Details title="Allow public access">
Let's turn on Row Level Security for this table and allow public access.
Let's turn on Row Level Security for this table, create the required policies, and then grant any write access.
</StepHikeCompact.Details>
@@ -78,6 +82,18 @@ We'll create a database table called `todos` for storing tasks. This creates a c
for select
to anon
using (true);
-- Allow authenticated users to read and modify todos
create policy "Allow authenticated users to manage todos"
on todos
for all
to authenticated
using (true)
with check (true);
-- Grant write access only after RLS and policies are in place
grant select, insert, update, delete on public.todos to authenticated;
grant select, insert, update, delete on public.todos to service_role;
```
</StepHikeCompact.Code>
@@ -8,15 +8,15 @@ The data APIs are designed to work with Postgres Row Level Security (RLS). If yo
To control access to your data, you can use [Policies](/docs/guides/auth#policies).
## Enabling row level security
## Add RLS policies
Any table you create in the `public` schema will be accessible via the Supabase Data API.
Enable Row Level Security (RLS) on all tables and views you have exposed via the Data API. You can then write RLS policies to grant users access to specific database rows based on their authentication token.
To restrict access, enable Row Level Security (RLS) on all tables, views, and functions in the `public` schema. You can then write RLS policies to grant users access to specific database rows or functions based on their authentication token.
For functions, RLS does not apply. Instead, control access by granting `EXECUTE` privileges only to the roles that should be able to call the function, and review any `SECURITY DEFINER` functions carefully.
<Admonition type="danger">
Always enable Row Level Security on tables, views, and functions in the `public` schema to protect your data.
Always enable Row Level Security on tables and views you expose via the Data API to protect your data. For functions, restrict access by granting `EXECUTE` only to appropriate roles.
</Admonition>
@@ -49,14 +49,10 @@ With RLS enabled, you can create Policies that allow or disallow users to access
<Admonition type="danger">
Any table **without RLS enabled** in the `public` schema will be accessible to the public, using the `anon` role. Always make sure that RLS is enabled or that you've got other security measures in place to avoid unauthorized access to your project's data!
Any exposed table **without RLS enabled** can be accessed by roles with matching Data API grants (for example, `anon`). Always make sure RLS is enabled, or that you've got other controls in place to avoid unauthorized access to your project's data.
</Admonition>
## Disable the API or restrict to custom schema
If you don't use the Data API, or if you don't want to expose the `public` schema, you can either disable it entirely or change the automatically exposed schema to one of your choice. See **[Hardening the Data API](/docs/guides/api/hardening-data-api)** for instructions.
## Enforce additional rules on each request
Using Row Level Security policies may not always be adequate or sufficient to protect APIs.
@@ -66,7 +62,7 @@ Here are some common situations where additional protections are necessary:
- Enforcing per-IP or per-user rate limits.
- Checking custom or additional API keys before allowing further access.
- Rejecting requests after exceeding a quota or requiring payment.
- Disallowing direct access to certain tables, views or functions in the `public` schema.
- Disallowing direct access to certain tables, views, or functions in exposed schemas.
You can build these cases in your application by creating a Postgres function that will read information from the request and perform additional checks, such as counting the number of requests received or checking that an API key is already registered in your database before serving the response.
@@ -0,0 +1,47 @@
---
title: 'Data API'
description: 'Quick options for managing Data API exposure and access.'
---
The Supabase Data API is a standalone server that sits between your application client code and your database. It automatically generates a fully RESTful API based on your database structure, allowing you to interact with your database through HTTP endpoints.
With the Data API, you have granular control over exposure: expose specific tables and functions by granting Data API roles the access they need, or enable **Default privileges for new entities** to automatically grant access to new tables and functions in `public`.
<Admonition type="caution">
Any table that is exposed through the Data API should have [Row Level Security (RLS) enabled](/docs/guides/database/postgres/row-level-security) to prevent unauthorized data access.
</Admonition>
## Expose specific tables and functions (recommended)
In [Data API integrations settings](/dashboard/project/_/integrations/data_api/settings), expose specific tables and functions and grant only the privileges each role needs.
```sql
grant select on table public.your_table to anon;
grant select, insert, update, delete on table public.your_table to authenticated;
grant execute on function public.your_function to anon, authenticated;
```
## Use default privileges for new entities in `public`
If you want new entities in `public` to be accessible automatically, enable **Default privileges for new entities** in the [**Integrations > Data API**](/dashboard/project/_/integrations/data_api/settings) section of the Dashboard. This applies only to new tables and functions in `public`.
```sql
alter default privileges for role postgres in schema public
grant select, insert, update, delete on tables to anon, authenticated, service_role;
alter default privileges for role postgres in schema public
grant execute on functions to anon, authenticated, service_role;
```
## Disable the Data API completely
If your app never uses Supabase client libraries, REST, or GraphQL data endpoints:
1. In the [**Integrations > Data API**](/dashboard/project/_/integrations/data_api/overview) section of the Dashboard.
1. Turn **Enable Data API** off.
## Learn more
To learn more about the Data API, see the [full guide](/docs/guides/api).
@@ -665,7 +665,7 @@ select title from books where to_tsvector(title) @@ to_tsquery('Lit:*');
### Extending functionality with RPC
To make the partial search functionality accessible through the API, you can wrap the search logic in a stored procedure.
To make the partial search functionality accessible through the API, you can wrap the search logic in a database function.
After creating this function, you can invoke it from your application using the SDK for your platform. Here's an example:
@@ -0,0 +1,205 @@
---
id: 'data-deletion'
title: 'Deleting data and dropping objects safely'
description: 'Strategies for removing data and schema objects while minimising impact.'
footerHelpType: 'postgres'
---
Deleting rows and dropping database objects are routine operations, but on a live database they can lock tables, block queries, and cause downtime. This guide covers practical strategies for keeping these operations safe and fast.
## Preparing to delete
- Test in a staging environment
- Ensure you have a recent backup
- Confirm the table dependencies and foreign key constraints
- Drop dependent objects explicitly, use [CASCADE](/docs/guides/database/postgres/cascade-deletes) with caution
- Choose a low traffic time to run the operation
- Run operations inside a [migration](/docs/guides/deployment/database-migrations)
- Set timeouts, such as `lock_timeout` and `statement_timeout`
### Identifying dependencies
The system catalog tables `pg_class`, `pg_constraint`, and `pg_depend` can be used to identify dependencies:
```sql
-- Find tables that depend on a specific table
select
d.classid::regclass as dependent_object,
d.objid::regclass as dependent_object_id,
d.refclassid::regclass as referenced_object,
d.refobjid::regclass as referenced_object_id
from pg_depend d
where d.refobjid = 'public.logs'::regclass;
```
If the object you want to delete has dependencies, you'll need to drop those first or use `CASCADE` which will automatically drop all related objects.
## Data deletion strategies
There are several ways to delete data from a table and the approach you choose depends on how much you want to delete.
### Small deletes
For tables with less than a few thousand rows, a `DELETE` operation is fine:
```sql
delete from logs
where created_at < now() - interval '90 days';
```
This acquires a `ROW EXCLUSIVE` lock on the table, which still allows other `SELECT`, `INSERT`, `UPDATE`, and `DELETE` statements to run concurrently. For small row counts, the operation completes quickly and has minimal impact.
### Large deletes
Deleting millions of rows in a single statement can hold locks for a long time, generate WAL (Write-Ahead Log) traffic, and impact replication. Instead, delete in batches:
```sql
-- Delete 5,000 rows at a time
DELETE FROM logs
WHERE id IN (
SELECT id
FROM logs
WHERE created_at < now() - interval '90 days'
LIMIT 5000
);
```
This approach has the benefit of controlling when it runs, locking for a shorter period of time and minimising impact on other transactions.
If you know in advance that such large deletes will have to happen in the business cycle of your database, then you should seriously think about using (table parititioning)[/docs/guides/database/partitions] as a management tool.
### Soft deletes
If you need to "delete" data but want the option to recover it, consider a soft-delete pattern:
```sql
alter table orders
add column deleted_at timestamptz;
-- "Delete" a row
update orders
set deleted_at = now()
where id = 42;
```
Then exclude soft-deleted rows in your queries or views:
```sql
create view active_orders as
select * from orders where deleted_at is null;
```
<Admonition type="tip">
Combine soft deletes with a scheduled hard-delete job (using [pg_cron](/docs/guides/database/extensions/pg_cron)) to permanently remove old soft-deleted rows in batches during low-traffic periods.
</Admonition>
### Deleting all data
If you need to delete all data from a table, consider using `TRUNCATE` instead of `DELETE`:
```sql
truncate table logs;
```
`TRUNCATE` is much faster than `DELETE` because it doesn't generate individual row-level WAL entries and doesn't scan the table. It also resets any auto-incrementing sequences.
## Object deletion strategies
### Dropping tables
Dropping a table removes it and all its data permanently. Always use `IF EXISTS` to avoid errors in migrations:
```sql
drop table if exists old_analytics;
```
<Admonition type="caution">
`DROP TABLE` acquires an `ACCESS EXCLUSIVE` lock, which blocks **all** other operations on the table, including reads. On a busy table, this can queue up behind long-running queries. See [Monitoring locks](#monitoring-locks) below.
</Admonition>
### Dropping columns
Dropping a column is a metadata-only operation in Postgres — it doesn't rewrite the table. However, it still requires an `ACCESS EXCLUSIVE` lock:
```sql
alter table users
drop column if exists legacy_field;
```
Since the lock is brief (metadata-only), this is generally safe. But on a table with many concurrent transactions, even a brief `ACCESS EXCLUSIVE` lock can queue behind long-running queries. Use a lock timeout to avoid waiting indefinitely:
```sql
set local lock_timeout = '5s';
alter table users drop column if exists legacy_field;
```
If the statement times out, retry during a quieter period.
### Dropping indexes
Dropping a regular index takes an `ACCESS EXCLUSIVE` lock on the index but **not** on the table, so reads and writes to the table continue uninterrupted:
```sql
drop index if exists idx_users_legacy_field;
```
<Admonition type="tip">
The `inspect` command in the [Supabase CLI](/docs/reference/cli/supabase-inspect-db-index-stats) can help you identify unused indexes:
```bash
supabase inspect db index-stats
```
</Admonition>
## Monitoring
### Check for blocked queries
Query `pg_locks` and `pg_stat_activity` to see currently active queries and queries waiting for locks.
The [Supabase CLI](/docs/reference/cli/supabase-inspect-db-locks) provides commands to view these metrics:
```bash
supabase inspect db locks
supabase inspect db blocking
```
### Monitor table bloat after large deletes
When deleting a large number of rows, the space is not always reclaimed and available for use. In normal cases, the rows are marked as deleted but the space is not immediately freed. You can monitor table bloat to see if the space is being reclaimed:
```bash
supabase inspect db bloat
```
## Reclaiming disk space
To reclaim the disk space freed by deleted rows, Postgres' autovacuum process runs automatically to mark deleted rows as reusable, but it may not always keep up with large deletes.
If autovacuum is not keeping up, you can trigger a manual vacuum:
```sql
vacuum (verbose) logs;
```
For reclaiming disk space (not just marking tuples as reusable), use `VACUUM FULL` — but be aware this rewrites the entire table and takes an `ACCESS EXCLUSIVE` lock:
```sql
-- This locks the table for the duration — use during maintenance windows only
vacuum full logs;
```
The most efficient way to reclaim disk space, without locks, is to use [pg_repack](/docs/guides/database/extensions/pg_repack).
## Related links
- [Safe Cascading Deletes](/docs/guides/database/postgres/cascade-deletes)
- [Inspecting your Database](/docs/guides/database/inspect)
- [Understanding Database and Disk Size](/docs/guides/platform/database-size)
- [Bloat in Postgres](/docs/blog/postgres-bloat)
@@ -28,6 +28,6 @@ Supabase and Postgres provide you with multiple ways to manage security, includi
- [Row Level Security](/docs/guides/database/postgres/row-level-security)
- [Column Level Security](/docs/guides/database/postgres/column-level-security)
- [Hardening the Data API](/docs/guides/api/hardening-data-api)
- [Data API](/docs/guides/database/data-api)
- [Managing Postgres roles](/docs/guides/database/postgres/roles)
- [Managing secrets with Vault](/docs/guides/database/vault)
@@ -149,7 +149,7 @@ View the [complete code](https://github.com/supabase/supabase/tree/master/exampl
### Seeding data
Now that you are managing your database with migrations scripts, it would be great have some seed data to use every time you reset the database.
Now that you are managing your database with migrations, it would be great have some seed data to use every time you reset the database.
<StepHikeCompact>
@@ -200,6 +200,12 @@ You should now see the `employees` table, along with your seed data in the Dashb
This workflow is great if you know SQL and are comfortable creating tables and columns. If not, you can still use the Dashboard to create tables and columns, and then use the CLI to diff your changes and create migrations.
<Admonition type="caution">
Only use the Dashboard to make schema changes on your **local** database, then capture them with `supabase db diff`. Making schema changes directly on your **remote** database (via the SQL editor or Table Editor) bypasses the migration history and will cause `db push` to fail with sync errors. Once you're using migrations, all schema changes to your remote database should go through migration files only.
</Admonition>
<StepHikeCompact>
<StepHikeCompact.Step step={1}>
@@ -343,3 +349,146 @@ supabase db push --include-seed
</StepHikeCompact>
Visiting your live project on [Supabase](/dashboard/project/_), you'll see a new `employees` table, complete with the `department` column you added in the second migration above.
## Working with a team
When multiple developers share a Supabase project, a few rules keep migrations from getting out of sync.
**The golden rule: never change the remote database directly.** Once you're using migrations, all schema changes — even small ones — should go through migration files. Using the Dashboard's SQL editor or Table Editor on your remote database bypasses the migration history, and `db push` will start failing with sync errors.
**The team workflow:**
<StepHikeCompact>
<StepHikeCompact.Step step={1}>
<StepHikeCompact.Details title="Create a migration locally">
Each developer creates migration files on their own branch, never touching the remote database directly.
</StepHikeCompact.Details>
<StepHikeCompact.Code>
```bash name=Terminal
supabase migration new your_change_description
```
</StepHikeCompact.Code>
</StepHikeCompact.Step>
</StepHikeCompact>
<StepHikeCompact>
<StepHikeCompact.Step step={2}>
<StepHikeCompact.Details title="Test and commit">
Reset your local database to apply the migration, then commit the migration file to git.
</StepHikeCompact.Details>
<StepHikeCompact.Code>
```bash name=Terminal
supabase db reset
git add supabase/migrations
git commit -m "add migration: your_change_description"
```
</StepHikeCompact.Code>
</StepHikeCompact.Step>
</StepHikeCompact>
<StepHikeCompact>
<StepHikeCompact.Step step={3}>
<StepHikeCompact.Details title="Pull and reset when a teammate merges a migration">
After pulling new migration files from git, reset your local database to apply them.
</StepHikeCompact.Details>
<StepHikeCompact.Code>
```bash name=Terminal
git pull
supabase db reset
```
</StepHikeCompact.Code>
</StepHikeCompact.Step>
</StepHikeCompact>
<StepHikeCompact>
<StepHikeCompact.Step step={4}>
<StepHikeCompact.Details title="One person deploys to remote">
Coordinate so only one person runs `db push` at a time. Migration files are applied in timestamp order, so concurrent pushes from different machines can cause conflicts.
</StepHikeCompact.Details>
<StepHikeCompact.Code>
```bash name=Terminal
supabase db push
```
</StepHikeCompact.Code>
</StepHikeCompact.Step>
</StepHikeCompact>
<Admonition type="tip">
For a more automated deployment approach, consider using [Supabase Branching](/docs/guides/deployment/branching) or a CI/CD pipeline that runs `supabase db push` on merge to your main branch.
</Admonition>
## Diagnosing and fixing sync errors
If `db push` fails with errors suggesting you run `supabase migration repair`, your local migration files and the remote database's migration history are out of sync. Here's how to diagnose and fix it.
### How migration tracking works
Supabase tracks which migrations have been applied on each database in a table called `supabase_migrations.schema_migrations`. When you run `supabase db push`, it compares your local `supabase/migrations` folder against that table and runs only the ones not yet applied, in order.
Git tracks your migration _files_. Supabase tracks what's been _applied to each database_. These are two separate systems that need to stay in sync.
### Step 1: Check what's out of sync
Start by listing the migration status across local and remote:
```bash name=Terminal
supabase migration list
```
This shows which migrations are applied locally, which are applied on the remote, and where they diverge.
### Step 2: If you made changes on the remote database directly
Pull the current remote state into a migration file to get back in sync:
```bash name=Terminal
supabase db pull
```
This creates a new migration file capturing the current remote schema. Commit it to git, then follow the standard workflow going forward.
### Step 3: If the migration history table is wrong
If a migration shows as missing in the remote history table but the schema change is actually already there (for example, it was applied manually), you can mark it as applied without re-running it:
```bash name=Terminal
supabase migration repair --status applied <migration-timestamp>
```
Or if a migration is recorded as applied but was never actually run:
```bash name=Terminal
supabase migration repair --status reverted <migration-timestamp>
```
<Admonition type="caution">
`migration repair` updates the tracking table only — it does not apply or revert any SQL. Use it to correct the history record when you know the actual database state is correct.
</Admonition>
@@ -375,12 +375,6 @@ curl https://api.supabase.com/v1/projects/database/backups/restore-pitr \
Management API endpoint: [`GET /v1/oauth/authorize/project-claim`](https://api.supabase.com/api/v1#tag/oauth/get/v1/oauth/authorize/project-claim)
<Admonition type="note" title="Contact us for access to claim flow">
Only select customers have access to claim flow. Submit this [form](/solutions/ai-builders#talk-to-partnerships-team) to get access.
</Admonition>
Your users may want to claim the project that currently lives in your org so that they can have more control over it.
We've enabled transferring the project from your org to your user's org while you continue to retain access to interact with the project through an [OAuth integration](/docs/guides/integrations/build-a-supabase-oauth-integration).
+101 -12
View File
@@ -19,21 +19,64 @@ Supabase currently provides SAML SSO for [Team and Enterprise Plan customers](/p
## Supported providers
Supabase supports practically all identity providers that support the SAML 2.0 SSO protocol. We've prepared these guides for commonly used identity providers to help you get started. If you use a different provider, our support stands ready to support you.
Supabase supports practically all identity providers (IdP) that support the SAML 2.0 SSO protocol. These guides cover commonly used identity providers to help you get started. If you use a different provider, contact support.
- [Google Workspaces (formerly G Suite)](/docs/guides/platform/sso/gsuite)
- [Azure Active Directory](/docs/guides/platform/sso/azure)
- [Okta](/docs/guides/platform/sso/okta)
Once configured, you can update your settings anytime via the [SSO tab](/dashboard/org/_/sso) under **Organization Settings**.
Once configured, you can update your settings anytime from [the **SSO** section](/dashboard/org/_/sso) of the dashboard under **Organization Settings**.
![SSO Example](/docs/img/sso-dashboard-enabled.png)
![SSO Example](/docs/img/sso-dashboard-enabled-idp.png)
<Admonition type="tip" label="Testing your SSO configuration">
After configuring your SSO provider, thorough testing is essential. See our [SSO Testing and Best Practices](/docs/guides/platform/sso/testing-best-practices) guide for:
- Step-by-step testing instructions
- Troubleshooting common issues
- Security best practices
- Pre-launch checklist
</Admonition>
## Choosing your login flow
Supabase supports two SSO login flows: **IdP-initiated** and **SP-initiated**. You can enable one or both depending on your organization's needs.
### IdP-initiated login (recommended)
Users start their login from your identity provider (Okta, Azure AD, Google Workspace) by clicking an app tile or bookmark. This is the **simplest and most common configuration** - it requires no domain configuration and works automatically once SSO is enabled.
**Best for:**
- Organizations with established IdP workflows
- Multiple SAML apps per domain (Dev, Staging, Prod)
- Simplest user experience
### SP-initiated login
Users start their login at supabase.com by entering their email address, then are redirected to your identity provider. This flow requires configuring email domains to route users to the correct IdP.
**Best for:**
- Users who bookmark supabase.com directly
- Organizations migrating from password authentication
- Supporting domain-based automatic IdP routing
### Need help choosing?
- **Quick decision:** Start with IdP-initiated only (the default). It works for 90% of use cases.
- **Detailed guidance:** See [Choosing the Right Login Flow](/docs/guides/platform/sso/choosing-login-flow) for scenario-based recommendations.
- **Technical details:** Read [Understanding SSO Login Flows](/docs/guides/platform/sso/login-flows) for in-depth explanations.
## Key configuration options
- **Multiple domains** - You can associate one or more email domains with your SSO provider. Users with email addresses matching these domains are eligible to sign in via SSO.
- **Auto-join** - Optionally allow users with a matching domain to be added to your organization automatically when they first sign in, without an invitation.
- **Default role for auto-joined users** - Choose the role (e.g., `Read-only`, `Developer`, `Administrator`, `Owner`) that automatically joined users receive. Refer to [access control](/docs/guides/platform/access-control) for more information about roles.
- **Login flows** - Choose between IdP-initiated (users start from identity provider), SP-initiated (users start at supabase.com), or both. IdP-initiated is recommended for most organizations and requires no domain configuration. See [Choosing the Right Login Flow](/docs/guides/platform/sso/choosing-login-flow) for guidance.
- **Email domains** - Required only if you enable SP-initiated login. You can associate one or more email domains with your SSO provider. Users with matching email addresses can sign in via SSO at supabase.com. Not required for IdP-initiated flow.
- **Auto-join** - Optionally allow users with a matching domain to be added to your organization automatically when they sign in via SSO. Auto-join applies on every login, not just first signup, making it easy to test before enabling.
- **Default role for auto-joined users** - Choose the role (e.g., `Read-only`, `Developer`, `Administrator`, `Owner`) that automatically joined users receive. We recommend using `Developer` as the default (principle of least privilege) and promoting users individually as needed. Refer to [access control](/docs/guides/platform/access-control) for more information about roles.
- **Invitation types** - When inviting users to your organization, you can explicitly choose whether the invitation requires SSO authentication or allows non-SSO login (password/social). This enables mixed authentication organizations with both SSO and non-SSO users.
## How SSO works in Supabase
@@ -47,13 +90,25 @@ When SSO is enabled for an organization:
## Enabling SSO for an organization
- Review the steps above to configure your setup.
- Invite users to the organization and ensure they join with their SSO linked account.
- If a user is already a member of the organization under a non SSO account, they will need to be removed and invited again for them to join under their SSO account.
**Recommended workflow:**
<Admonition type="note">
1. Create or verify at least one non-SSO owner account exists (required for safety)
2. Configure your SSO provider following one of our [provider-specific guides](#supported-providers)
3. Start with auto-join **disabled** to test the configuration
4. Test SSO login with your own account
5. Once confirmed working, enable auto-join if desired
6. Thoroughly test using our [SSO Testing and Best Practices](/docs/guides/platform/sso/testing-best-practices) guide
7. Invite users to the organization or let them auto-join on login
**No automatic linking:** Each user account verified using a SSO identity provider will not be automatically linked to existing user accounts in the system. That is, if a user `valid.email@supabase.io` had signed up with a password, and then uses their company SSO login with your project, there will be two `valid.email@supabase.io` user accounts in the system.
<Admonition type="note" label="Account linking">
If a user is already a member of the organization under a non-SSO account, they will need to be removed and invited again with an SSO-required invitation to join under their SSO account. SSO and non-SSO accounts with the same email are treated as separate accounts.
</Admonition>
<Admonition type="note" label="No automatic linking">
Each user account verified using a SSO identity provider will not be automatically linked to existing user accounts in the system. That is, if a user `valid.email@supabase.io` had signed up with a password, and then uses their company SSO login with your project, there will be two `valid.email@supabase.io` user accounts in the system.
Users will need to ensure they are logged in with the correct account when accepting invites or accessing organizations/projects.
@@ -61,7 +116,19 @@ Users will need to ensure they are logged in with the correct account when accep
## Disabling SSO for an organization
If you disable the SSO provider for an organization, **all SSO users will immediately be unable to sign in**. Before disabling SSO, ensure you have at least one non-SSO owner account to prevent being locked out.
If you disable or delete the SSO provider for an organization, **all SSO users will immediately be unable to sign in**.
<Admonition type="caution" label="Safety requirement">
The system requires at least one non-SSO owner account before allowing SSO provider deletion. This prevents complete organization lockout. When you delete an SSO provider, all SSO members are automatically removed from the organization.
Before disabling or deleting SSO:
- Verify a non-SSO owner account exists and can log in
- Communicate to affected users in advance
- Consider whether disabling is better than deleting if the change is temporary
</Admonition>
## Removing an individual SSO user's access
@@ -69,3 +136,25 @@ To revoke access for a specific SSO user without disabling the provider entirely
- Remove or disable the user's account in your identity provider
- Downgrade or remove their permissions for any organizations in Supabase.
## Testing and best practices
Before rolling out SSO to your organization, we strongly recommend thorough testing and following security best practices. Our comprehensive guide covers:
- Step-by-step testing procedures for SSO login, auto-join, and invitations
- Troubleshooting common issues (many of which previously required support intervention)
- Security best practices including certificate monitoring and domain configuration
- Operational guidance for making SSO changes safely
- Pre-launch verification checklist
Visit the [SSO Testing and Best Practices](/docs/guides/platform/sso/testing-best-practices) guide for complete details.
## Advanced scenarios
Most organizations use a single SSO provider for all users. However, Supabase supports multiple SSO providers within an organization for advanced use cases such as:
- Separate providers for development, staging, and production environments
- Different providers for different teams or business units
- Gradual migration from one identity provider to another
If you need to configure multiple SSO providers, refer to the [Multiple SSO Providers](/docs/guides/platform/sso/multiple-providers) guide for detailed configuration steps, and contact your Supabase support representative if you need additional guidance.
@@ -110,6 +110,12 @@ We do not permit use of public domains like `gmail.com`, `yahoo.com`.
</Admonition>
<Admonition type="note">
You can configure each SSO provider with different email domains. For multi-environment setups (Dev/Staging/Prod), we recommend using IdP-initiated flow with multiple SAML apps under the same domain rather than domain-based routing. For more details, see the [Multiple SSO Providers guide](/docs/guides/platform/sso/multiple-providers).
</Admonition>
## Step 10: Configure metadata [#dashboard-configure-metadata]
Enter the metadata URL you obtained from [Step 7](#idp-metadata-url) into the Metadata URL field:
@@ -128,7 +134,7 @@ By default this setting is disabled, users logging in via SSO will not be added
![Auto-join disabled](/docs/img/sso-dashboard-configure-autojoin-disabled.png)
Toggle this on if you want SSO-authenticated users to be **automatically added to your organization** when they log in via SSO.
Toggle this on if you want SSO-authenticated users to be **automatically added to your organization** when they log in via SSO. Auto-join applies on **every login**, not just first signup - this makes it safe to test SSO before enabling this feature.
![Auto-join enable](/docs/img/sso-dashboard-configure-autojoin-enabled.png)
@@ -136,18 +142,30 @@ When auto-join is enabled, you can choose the **default role** for new users:
![Auto-join role selection](/docs/img/sso-dashboard-configure-autojoin-enabled-role.png)
Choose a role that fits the level of access you want to grant to new members.
We recommend choosing **Developer** as the default role (principle of least privilege) and promoting users individually as needed.
<Admonition type="note">
Visit [access-control](/docs/guides/platform/access-control) documentation for details about each role.
Read [the Access Control documentation](/docs/guides/platform/access-control) for details about each role.
</Admonition>
## Step 13: Save changes and test single sign-on [#dashboard-configure-save]
## Step 13: Save changes [#dashboard-configure-save]
When you click **Save changes**, your new SSO configuration is applied immediately. From that moment, any user with an email address matching one of your configured domains who visits your organization's sign-in URL will be routed through the SSO flow.
We recommend asking a few users to test signing in via their Azure AD account. They can do this by entering their email address on the [Sign in with SSO](/dashboard/sign-in-sso) page.
## Step 14: Test your SSO configuration
If SSO sign-in doesn't work as expected, contact your Supabase support representative for assistance.
Before rolling out SSO to your organization, we strongly recommend thorough testing. Read [the SSO Testing and Best Practices guide](/docs/guides/platform/sso/testing-best-practices) for:
- Step-by-step testing instructions
- How to verify auto-join works correctly
- Common issues and troubleshooting
- Security best practices
- Pre-launch checklist
<Admonition type="note" label="Testing in Azure sandbox">
If your organization has an Azure sandbox or test tenant, consider testing your SSO configuration there first before applying to production.
</Admonition>
@@ -0,0 +1,320 @@
---
title: 'Choosing the Right SSO Login Flow'
description: 'Quick reference guide to help you choose between IdP-initiated, SP-initiated, or both login flows based on your use case.'
---
Not sure which single sign-on (SSO) login flow to enable? This guide maps common enterprise scenarios to the recommended configuration.
<Admonition type="tip">
Start with identity provider (IdP)-initiated, the default behavior. It requires no domain configuration, and works for most enterprise use cases. You can enable SP-initiated later if needed.
</Admonition>
## Decision flowchart
```
Do users need to start login at supabase.com?
│
├─ No → Use IdP-initiated only (default) ✅
│ - No domain configuration needed
│ - Simplest setup
│ - Users access via IdP dashboard
│
└─ Yes → Do you need multiple SAML apps per domain?
│
├─ Yes → Use IdP-initiated only ✅
│ - Supports Dev/Staging/Prod under same domain
│ - Each environment is a separate IdP tile
│
└─ No → Enable both flows ✅
- SP-initiated for users who bookmark supabase.com
- IdP-initiated still works from IdP dashboard
- Configure email domains
```
## Common scenarios
### Scenario 1: Multiple environments (dev, staging, prod)
**Your situation:**
- You need separate Supabase organizations for Dev, Staging, and Production
- All employees use `company.com` email addresses
- You can't assign different email domains to different environments
**Recommended configuration:** IdP-initiated only ✅
**Why:**
- Create separate SAML apps in your IdP for each environment
- All apps use the same domain (`company.com`)
- Users click "Supabase Dev", "Supabase Staging", or "Supabase Prod" tiles
- No domain conflicts
**How to configure:**
1. In your IdP, create three SAML apps:
- "Supabase Dev" → Points to dev org ACS URL
- "Supabase Staging" → Points to staging org ACS URL
- "Supabase Production" → Points to prod org ACS URL
2. In each Supabase organization:
- Enable SSO
- Leave "Enable SP-initiated login" **OFF**
- Configure metadata from corresponding IdP app
3. Users access each environment via IdP tiles
**Result:** Clean separation of environments with single domain.
---
### Scenario 2: Single production organization
**Your situation:**
- One Supabase organization for your entire company
- All employees use company email domain
- Users are comfortable with IdP dashboard
**Recommended configuration:** IdP-initiated only ✅
**Why:**
- Simplest possible setup
- No domain configuration required
- Users access Supabase with one click from IdP
- Fewer potential failure points
**How to configure:**
1. Enable SSO in your Supabase organization
2. Leave "Enable SP-initiated login" **OFF**
3. Configure identity provider metadata
4. Create Supabase app tile in your IdP
**Result:** One-click SSO login for all users.
---
### Scenario 3: Users bookmark supabase.com
**Your situation:**
- Users frequently bookmark supabase.com directly
- You want to support starting login from Supabase
- Single domain, single organization
**Recommended configuration:** Enable both flows ✅
**Why:**
- Supports users who start at supabase.com (SP-initiated)
- Also supports users who prefer IdP tiles (IdP-initiated)
- Flexible for different user preferences
**How to configure:**
1. Enable SSO in your Supabase organization
2. Toggle "Enable SP-initiated login" **ON**
3. Add your email domain(s) (e.g., `company.com`)
4. Configure identity provider metadata
5. Create Supabase app tile in your IdP (optional but recommended)
**Result:** Users can start login from either Supabase or IdP.
---
### Scenario 4: Migrating from password authentication
**Your situation:**
- Currently using password-based login
- Transitioning to SSO
- Users are used to starting at supabase.com
**Recommended configuration:** Enable both flows ✅
**Why:**
- Familiar login starting point for existing users
- Gradual transition to IdP-based access
- Can promote IdP tiles after users adapt
**How to configure:**
1. Ensure at least one non-SSO owner account exists
2. Enable SSO and toggle "Enable SP-initiated login" **ON**
3. Add email domain(s)
4. Start with auto-join **disabled**
5. Test with small group
6. Enable auto-join once confirmed
7. Communicate new IdP tiles to users
8. Gradually encourage IdP-initiated usage
**Migration path:**
- **Week 1:** Enable both flows, announce SSO availability
- **Week 2-4:** Monitor usage, troubleshoot issues
- **Month 2+:** Promote IdP tiles, consider disabling SP-initiated if usage drops
---
### Scenario 5: Multiple subsidiaries with different domains
**Your situation:**
- Parent company (`parent.com`) and subsidiaries (`sub1.com`, `sub2.com`)
- All use the same Supabase organization
- Each domain maps to same identity provider
**Recommended configuration:** SP-initiated with multiple domains ✅
**Why:**
- Multiple domains supported in SP-initiated configuration
- Automatic routing based on email domain
- Centralized organization management
**How to configure:**
1. Enable SSO in your Supabase organization
2. Toggle "Enable SP-initiated login" **ON**
3. Add all domains: `parent.com`, `sub1.com`, `sub2.com`
4. Configure identity provider to accept all domains
5. Create Supabase app tiles in IdP (IdP-initiated also works)
**Result:** Users with any configured domain can access organization.
---
### Scenario 6: SaaS platform with customer-specific SSO
**Your situation:**
- You're building a SaaS product
- Each customer has their own organization
- Each customer uses their own identity provider
**Recommended configuration:** Per-customer decision (typically IdP-initiated)
**Why:**
- Each customer may have different preferences
- Default to IdP-initiated for simplicity
- Enable SP-initiated only if customer requests it
**How to configure:**
1. For each customer organization:
- Enable SSO with their IdP metadata
- Default: Leave SP-initiated **OFF**
- If customer requests SP-initiated: Toggle **ON** and add their domain
2. Document both options in customer onboarding
3. Let customers choose based on their workflow
**Result:** Flexible, customer-specific SSO configurations.
---
### Scenario 7: Mixed authentication (SSO + non-SSO users)
**Your situation:**
- Some users authenticate via SSO (employees)
- Some users use password/social auth (contractors, external partners)
- Single organization with mixed membership
**Recommended configuration:** Both flows with careful planning ⚠️
**Why:**
- SSO users can use either flow
- Non-SSO users use password/social login
- Separate invitation types for each group
**How to configure:**
1. Enable SSO with both flows (toggle SP-initiated **ON**)
2. Configure employee email domain(s)
3. Use **SSO-required invitations** for employees
4. Use **non-SSO invitations** for contractors
5. Consider disabling auto-join to control membership
<Admonition type="caution" label="Account linking caution">
SSO and non-SSO accounts with the same email are treated as separate accounts. An employee with `alice@company.com` will have two accounts if they:
1. Join via SSO (SSO account)
2. Previously joined via password (non-SSO account)
Communicate clearly which authentication method each user should use.
</Admonition>
**Result:** Mixed authentication with clear separation.
## Configuration quick reference
| Use Case | IdP-initiated | SP-initiated | Domains Required |
| ---------------------------------------- | ------------- | ------------ | ----------------- |
| Multiple environments (Dev/Staging/Prod) | ✅ Only | ❌ Off | No |
| Single production org | ✅ Only | ❌ Off | No |
| Users bookmark supabase.com | ✅ Yes | ✅ Yes | Yes |
| Migrating from passwords | ✅ Yes | ✅ Yes | Yes |
| Multiple email domains | ✅ Yes | ✅ Yes | Yes (all domains) |
| Customer-specific SSO (SaaS) | ✅ Default | Optional | Per customer |
| Mixed authentication | ✅ Yes | ✅ Yes | Yes |
## Testing your configuration
After choosing your login flow, thoroughly test:
1. **IdP-initiated:** Click app tile in IdP → Verify redirect to Supabase
2. **SP-initiated:** Go to supabase.com/sign-in-sso → Enter email → Verify IdP redirect
3. **Auto-join:** Test with new user accounts
4. **Domain restrictions:** Try non-matching domain (should fail for SP-initiated)
See our comprehensive [SSO Testing and Best Practices guide](/docs/guides/platform/sso/testing-best-practices) for detailed testing procedures.
## When to change configuration
You can safely change login flow configuration at any time:
### Adding SP-initiated to IdP-only
- Toggle "Enable SP-initiated login" ON
- Add required domains
- Test with existing users
- No disruption to IdP-initiated flow
### Removing SP-initiated
- Toggle "Enable SP-initiated login" OFF
- Domains are preserved (can re-enable later)
- IdP-initiated continues working
- Users who bookmarked supabase.com need to use IdP tiles instead
**No migration required** - Changes take effect immediately.
## Still not sure?
If you're uncertain which configuration to use:
1. Start with IdP-initiated only (simplest, works for most cases)
2. Test with a small group of users
3. Gather feedback on user experience
4. Enable SP-initiated if users request it
5. Monitor usage to see which flow is preferred
<Admonition type="tip" label="Support available">
If you need help choosing the right configuration for your organization, contact Supabase support with details about your use case. We're happy to provide personalized recommendations.
</Admonition>
## Next steps
- **Understand the technical details:** Read [Understanding SSO Login Flows](/docs/guides/platform/sso/login-flows)
- **Configure your provider:** Follow our [provider-specific guides](/docs/guides/platform/sso#supported-providers)
- **Test your setup:** Review [SSO Testing and Best Practices](/docs/guides/platform/sso/testing-best-practices)
- **Enable auto-join:** Configure [auto-join settings](/docs/guides/platform/sso#key-configuration-options)
@@ -39,7 +39,13 @@ This is a very important step. Click on _DOWNLOAD METADATA_ and save the file th
![Google Workspace: Web and mobile apps admin console, Add custom SAML, Google Identity Provider details screen](/docs/img/sso-gsuite-step-04.png)
**Important: Make sure the certificate as shown on screen has at least 1 year before it expires. Mark down this date in your calendar so you will be reminded that you need to update the certificate without any downtime for your users.**
**Important: Make sure the certificate as shown on screen has at least 1 year before it expires.**
<Admonition type="caution">
**Certificate expiration:** Set a calendar reminder 30 days before the certificate expiration date. When the certificate is renewed, you'll need to download the new metadata file and update it in your Supabase SSO settings. Expired certificates are a common cause of SSO sign-in failures.
</Admonition>
## Step 5: Add service provider details [#add-service-provider-details]
@@ -102,6 +108,12 @@ We do not permit use of public domains like `gmail.com`, `yahoo.com`.
</Admonition>
<Admonition type="note">
Each SSO provider can be configured with different email domains. For multi-environment setups (Dev/Staging/Prod), we recommend using IdP-initiated flow with multiple SAML apps under the same domain rather than domain-based routing. For more details, see the [Multiple SSO Providers guide](/docs/guides/platform/sso/multiple-providers).
</Admonition>
## Step 10: Configure metadata [#dashboard-configure-metadata]
Upload the metadata file you downloaded in [Step 6](#download-idp-metadata) into the Metadata Upload File field.
@@ -122,11 +134,17 @@ If you did not customize your settings you may save some time by clicking the **
## Step 12: Join organization on signup (optional) [#dashboard-configure-autojoin]
<Admonition type="tip">
**Recommended workflow:** Start with auto-join **disabled** to test your SSO configuration. Once SSO login is working correctly, enable auto-join if desired.
</Admonition>
By default this setting is disabled, users logging in via SSO will not be added to your organization automatically.
![Auto-join disabled](/docs/img/sso-dashboard-configure-autojoin-disabled.png)
Toggle this on if you want SSO-authenticated users to be **automatically added to your organization** when they log in via SSO.
Toggle this on if you want SSO-authenticated users to be **automatically added to your organization** when they log in via SSO. Auto-join applies on **every login**, not just first signup - this makes it safe to test SSO before enabling this feature.
![Auto-join enable](/docs/img/sso-dashboard-configure-autojoin-enabled.png)
@@ -134,7 +152,7 @@ When auto-join is enabled, you can choose the **default role** for new users:
![Auto-join role selection](/docs/img/sso-dashboard-configure-autojoin-enabled-role.png)
Choose a role that fits the level of access you want to grant to new members.
We recommend choosing **Developer** as the default role (principle of least privilege) and promoting users individually as needed.
<Admonition type="note">
@@ -142,10 +160,20 @@ Visit [access-control](/docs/guides/platform/access-control) documentation for d
</Admonition>
## Step 13: Save changes and test single sign-on [#dashboard-configure-save]
## Step 13: Save changes [#dashboard-configure-save]
When you click **Save changes**, your new SSO configuration is applied immediately. From that moment, any user with an email address matching one of your configured domains who visits your organization's sign-in URL will be routed through the SSO flow.
We recommend asking a few users to test signing in via their Google Workspace account. They can do this by entering their email address on the [Sign in with SSO](/dashboard/sign-in-sso) page.
<Admonition type="tip">
If SSO sign-in doesn't work as expected, contact your Supabase support representative for assistance.
**Next step: Test your SSO configuration**
Before rolling out SSO to your organization, we strongly recommend thorough testing. Visit our [SSO Testing and Best Practices](/docs/guides/platform/sso/testing-best-practices) guide for:
- Step-by-step testing instructions
- How to verify auto-join works correctly
- Common issues and troubleshooting
- Security best practices
- Pre-launch checklist
</Admonition>
@@ -0,0 +1,267 @@
---
title: 'Understanding SSO Login Flows'
description: 'Learn about IdP-initiated and SP-initiated SSO login flows and when to use each approach.'
---
When configuring SSO for your organization, you can choose between two different login flows: **identity provider (IdP)-initiated** and **service provider (SP)-initiated**. Understanding the difference helps you provide the best experience for your users.
<Admonition type="tip" label="Quick decision guide">
Most enterprises use IdP-initiated flow for its simplicity and better user experience. Enable SP-initiated only if you need users to start their login journey at supabase.com.
See our [Choosing the Right Login Flow guide](/docs/guides/platform/sso/choosing-login-flow) for use case examples.
</Admonition>
## Overview of login flows
### IdP-initiated (Identity Provider Initiated)
With IdP-initiated flow, users start their login journey from your identity provider (Okta, Azure AD, Google Workspace, etc.) and are directly authenticated into Supabase.
**User experience:**
1. User opens their identity provider dashboard (e.g., Okta homepage, Azure MyApps)
2. User clicks the Supabase app tile or bookmark
3. User is immediately logged into Supabase (if already authenticated with IdP)
**Key characteristics:**
- ✅ Simpler user experience - one click from IdP
- ✅ No domain configuration required
- ✅ Works automatically once SSO is enabled
- ✅ Better for intranet portals and employee app catalogs
- ✅ Default behavior in Supabase
### SP-initiated (Service Provider Initiated)
With SP-initiated flow, users start at supabase.com, enter their email address, and are redirected to your identity provider for authentication.
**User experience:**
1. User visits supabase.com and clicks "Sign in with SSO"
2. User enters their email address
3. User is redirected to their identity provider
4. After authenticating, user is redirected back to Supabase
**Key characteristics:**
- ✅ Familiar flow for users who bookmark supabase.com
- ✅ Supports domain-based automatic IdP routing
- ⚠️ Requires configuring email domains
- ⚠️ More steps in the login process
## Choosing between flows
### When to use IdP-initiated (recommended)
**Best for:**
- Organizations with established identity provider workflows
- Users who primarily access apps through their IdP dashboard
- Multiple SAML apps per domain (Dev, Staging, Prod environments)
- Simplifying user onboarding
**Common scenarios:**
- "Our team accesses all tools through Okta tiles"
- "We want the simplest possible login experience"
- "We need separate Dev and Prod SAML apps under the same domain"
- "Users should never need to remember supabase.com"
### When to use SP-initiated
**Best for:**
- Organizations where users bookmark supabase.com directly
- Migrating from password-based authentication
- Users unfamiliar with identity provider dashboards
**Common scenarios:**
- "Some users bookmark supabase.com and expect to start there"
- "We're transitioning from password auth to SSO"
- "Users need a consistent login page across all tools"
- "We want domain-based automatic IdP selection"
### When to enable both flows
You can enable both flows simultaneously to support different user preferences.
**Best for:**
- Large organizations with diverse user needs
- Gradual SSO migration with mixed authentication
- Supporting both technical and non-technical users
## Configuring login flows
### Enabling IdP-initiated flow (default)
IdP-initiated flow is automatically enabled when you configure SSO. No additional steps required.
1. Navigate to [the **SSO** settings](/dashboard/org/_/sso) section of the dashboard
2. Enable "Single Sign-On"
3. Configure your identity provider metadata and attribute mapping
4. Save your configuration
Users can now access Supabase through your IdP's app catalog.
<Admonition type="note" label="Domain configuration optional">
With IdP-initiated flow, you don't need to configure email domains. Your identity provider handles all authentication routing.
</Admonition>
### Enabling SP-initiated flow
To enable SP-initiated flow, you need to configure email domains:
1. Navigate to [the **SSO** settings](/dashboard/org/_/sso) section of the dashboard
2. Enable "Single Sign-On"
3. Toggle **Enable SP-initiated login** to "ON"
4. Add one or more email domains (e.g., `yourcompany.com`)
5. Configure your identity provider metadata and attribute mapping
6. Save your configuration
#### Email domain requirements
- At least one domain required when SP-initiated is enabled
- Domains must be verified through your identity provider
- Multiple domains supported (e.g., `company.com`, `subsidiary.com`)
- Users with matching email domains will be routed to your IdP
<Admonition type="caution" label="Domain restrictions apply">
Only users with email addresses matching your configured domains can use SP-initiated login. Users with other domains cannot sign in via SSO at supabase.com (but can still use IdP-initiated flow if you configure it in your IdP).
</Admonition>
### Switching between flows
You can change login flow configuration at any time:
#### To switch from SP-initiated to IdP-only
1. Navigate to [the **SSO** settings](/dashboard/org/_/sso) section of the dashboard
2. Toggle **Enable SP-initiated login** to "OFF"
3. Save changes
Existing users can continue signing in via IdP-initiated flow.
#### To switch from IdP-only to SP-initiated
1. Navigate to [the **SSO** settings](/dashboard/org/_/sso) section of the dashboard
2. Toggle **Enable SP-initiated login** to "ON"
3. Add required email domains
4. Save changes
## Technical details
### How IdP-initiated flow works
1. User clicks app tile in identity provider
2. IdP generates SAML assertion and POSTs to Supabase ACS URL
3. Supabase validates assertion and creates session
4. User is redirected to Supabase dashboard
**No domain lookup required** - The IdP assertion contains all necessary user information.
### How SP-initiated flow works
1. User enters email at supabase.com/sign-in-sso
2. Supabase matches email domain to configured SSO provider
3. Supabase generates SAML request and redirects to IdP
4. IdP authenticates user and generates SAML assertion
5. IdP POSTs assertion to Supabase ACS URL
6. Supabase validates assertion and creates session
**Domain matching is critical** - Without matching domains, users cannot complete SP-initiated flow.
## Multiple SAML apps per domain
One of the key advantages of IdP-initiated flow is supporting multiple SAML applications under the same domain.
### The problem with SP-initiated only
Many enterprises need separate SAML apps for different environments:
- Development SAML app
- Staging SAML app
- Production SAML app
**With SP-initiated flow only:** Each SAML app requires a unique domain. You'd need:
- `dev.company.com`
- `staging.company.com`
- `prod.company.com`
This is often impractical since all employees use `company.com` email addresses.
### The solution with IdP-initiated flow
**With IdP-initiated flow:** All SAML apps can use the same domain (`company.com`) because:
- Users access each app through different IdP tiles/bookmarks
- No domain-based routing is needed
- Each SAML app has its own unique ACS URL and metadata
#### Configuration in your IdP
- Create "Supabase Dev" SAML app → Points to dev org's ACS URL
- Create "Supabase Staging" SAML app → Points to staging org's ACS URL
- Create "Supabase Production" SAML app → Points to prod org's ACS URL
Users click the appropriate tile for the environment they need.
<Admonition type="tip">
This is the recommended approach for enterprises with multiple environments. Configure each environment as IdP-initiated only (no domains needed).
</Admonition>
## Common questions
### Can you use both flows simultaneously?
Yes! Enable SP-initiated login and configure domains. IdP-initiated flow continues to work automatically.
### What happens when you don't configure domains?
Without domains, only IdP-initiated flow is available. Users cannot start their login at supabase.com.
### Does the IdP require configuration?
For **IdP-initiated flow:** Configure the Supabase ACS URL and entity ID in your IdP. See our provider-specific guides:
- [Google Workspace](/docs/guides/platform/sso/gsuite)
- [Azure Active Directory](/docs/guides/platform/sso/azure)
- [Okta](/docs/guides/platform/sso/okta)
For **SP-initiated flow:** Same configuration, but also ensure your IdP accepts SAML requests from Supabase.
### What happens if a user tries SP-initiated with no matching domain?
They receive an error message indicating no SSO provider found for their email domain. They can still sign in using password or social auth (if they have a non-SSO account).
### Can you disable SP-initiated flow after enabling it?
Yes, toggle it off at any time. Existing users can continue using IdP-initiated flow.
### Which flow is more secure?
Both flows are equally secure when properly configured. Security depends on:
- Strong identity provider authentication policies
- Certificate management and rotation
- Attribute mapping configuration
- Regular security audits
See our [SSO Testing and Best Practices](/docs/guides/platform/sso/testing-best-practices) guide for security recommendations.
## Next steps
- **Choose your login flow:** See [Choosing the Right Login Flow](/docs/guides/platform/sso/choosing-login-flow)
- **Configure your provider:** Follow our [provider-specific guides](/docs/guides/platform/sso#supported-providers)
- **Test thoroughly:** Review [SSO Testing and Best Practices](/docs/guides/platform/sso/testing-best-practices)
- **Enable auto-join:** Configure [auto-join settings](/docs/guides/platform/sso#key-configuration-options) for seamless onboarding
@@ -0,0 +1,546 @@
---
title: 'Multiple SSO Providers'
description: 'Configure multiple SSO providers for different environments, teams, or use cases'
---
Many enterprises need multiple single sign-on (SSO) providers configured within Supabase to support different environments, teams, or organizational structures. This guide explains when and how to set up multiple providers effectively.
## Why multiple SSO providers?
Common scenarios requiring multiple SSO providers include:
- **Multiple environments**: Separate Dev, Staging, and Production organizations
- **Team separation**: Different business units or departments
- **Migration**: Transitioning from one identity provider to another
- **Acquisitions**: Integrating subsidiaries with different identity systems
- **Testing**: Isolated test environments alongside production
## Key concept: IDP-initiated enables unlimited providers per domain
The traditional challenge with multiple SAML apps is domain conflicts. With SP-initiated flow only, each SAML app requires a unique email domain. Since all your employees use the same domain (e.g., `company.com`), this creates a problem.
**Solution:** Use identity provider (IdP)-initiated flow, which doesn't require domain configuration. You can create unlimited SAML apps under the same domain.
<Admonition type="tip" label="Recommended pattern">
Configure each environment as IdP-initiated only (no domains). Users access each environment through different app tiles in your identity provider.
For technical details, see [the Understanding SSO Login Flows guide](/docs/guides/platform/sso/login-flows#multiple-saml-apps-per-domain).
</Admonition>
## Use case 1: Multiple environments (dev/staging/prod)
This is the most common enterprise pattern and the primary use case for IDP-initiated flow.
### The challenge
You have three Supabase organizations:
- Development (`dev-org`)
- Staging (`staging-org`)
- Production (`prod-org`)
All employees use `company.com` email addresses. You need separate SSO configurations for each environment.
### The solution
Create three separate SAML apps in your identity provider, each pointing to a different Supabase organization.
#### In your identity provider (Okta, Azure AD, Google Workspace)
1. **Create "Supabase Dev" SAML app**
- Configure with Dev organization's ACS URL
- Assign developers and testers
- Deploy app tile labeled "Supabase Dev"
2. **Create "Supabase Staging" SAML app**
- Configure with Staging organization's ACS URL
- Assign QA team and release managers
- Deploy app tile labeled "Supabase Staging"
3. **Create "Supabase Production" SAML app**
- Configure with Production organization's ACS URL
- Assign production users only
- Deploy app tile labeled "Supabase Production"
#### In each Supabase organization
1. Navigate to [the **SSO** settings](/dashboard/org/_/sso) section of the dashboard
2. Enable **Single Sign-On**
3. Leave **Enable SP-initiated login** "OFF", this is critical
4. Configure metadata from the corresponding IDP app
5. Set up attribute mappings
6. Configure auto-join if desired
### Result
- Users click the appropriate app tile for the environment they need
- No domain conflicts (all apps use `company.com`)
- Clean isolation between environments
- Each environment can have different user assignments and roles
### Configuration example
Here's how the three configurations differ:
| Environment | Organization | IDP App Name | ACS URL |
| ----------- | ------------ | ------------------ | ------------------------------------ |
| Dev | `dev` | "Supabase Dev" | `https://...dev-org.../saml/acs` |
| Staging | `staging` | "Supabase Staging" | `https://...staging-org.../saml/acs` |
| Production | `prod` | "Supabase Prod" | `https://...prod-org.../saml/acs` |
#### Each organization
- SP-initiated: **OFF** (no domains configured)
- IDP-initiated: **ON** (automatic, no configuration needed)
- Auto-join: Your preference (typically enabled for dev, disabled for prod)
## Use case 2: Different teams or business units
Some organizations need to isolate teams within separate Supabase organizations.
### Example scenario
- Engineering team uses `engineering-org`
- Data team uses `data-org`
- Both teams have `company.com` emails
### Configuration approach
#### Option A: IDP-initiated with different app tiles
Create separate SAML apps in your IDP:
- "Supabase Engineering" → Points to `engineering-org`
- "Supabase Data" → Points to `data-org`
Assign appropriate users to each app. Users only see the tiles they're assigned to.
#### Option B: Both IDP and SP-initiated with role-based routing
Configure both organizations with SP-initiated enabled using the same domain:
- Both organizations add `company.com` as a domain
- Users can log in via SP-initiated at supabase.com
- System routes based on org membership (first match wins)
- Also provide IDP tiles for explicit routing
<Admonition type="caution" label="SP-initiated routing with multiple providers">
When multiple organizations use SP-initiated with the same domain, the first provider where the user is a member will be used. This can cause confusion. **IDP-initiated is recommended** for clarity.
</Admonition>
## Use case 3: Migration from one IDP to another
When migrating from one identity provider to another, multiple providers help ensure a smooth transition.
### Migration workflow
#### Phase 1: Dual configuration
1. Configure new IDP as additional SSO provider
2. Keep existing IDP active
3. Test new IDP with small group
4. Both providers operational simultaneously
#### Phase 2: Gradual rollout
1. Migrate users in batches to new IDP
2. Update app tile assignments
3. Monitor for issues
4. Keep old IDP as fallback
#### Phase 3: Cutover
1. Move all users to new IDP
2. Verify no users depend on old IDP
3. Disable (don't delete) old IDP provider
4. Monitor for any issues
#### Phase 4: Cleanup
1. After verification period (1-2 weeks)
2. Delete old IDP provider
3. Update documentation
<Admonition type="caution">
Always maintain at least one non-SSO owner account during migrations to ensure you never lose access to the organization.
</Admonition>
## Use case 4: Acquisitions and subsidiaries
Organizations with multiple email domains need provider configurations for each domain.
### Example scenario
- Parent company: `parent.com`
- Subsidiary 1: `subsidiary1.com`
- Subsidiary 2: `subsidiary2.com`
All authenticate through the same central IDP but use different email domains.
### Configuration approach
#### Option A: Single provider with multiple domains (SP-initiated)
1. Enable SSO with SP-initiated flow
2. Add all domains: `parent.com`, `subsidiary1.com`, `subsidiary2.com`
3. Configure single IDP metadata
4. Users with any matching domain can log in via supabase.com
#### Option B: Separate providers per subsidiary (IDP-initiated)
1. Create separate SAML apps for each entity
2. Configure as IDP-initiated only
3. Assign users based on their subsidiary
4. More isolation, clearer organization boundaries
## Step-by-step setup guide
### For IDP-initiated multi-environment pattern
This is the recommended pattern for most enterprises.
#### Step 1: Plan your environments
Document:
- Organization names and slugs
- Environment purposes (dev, staging, prod)
- Which users need access to which environments
- Default roles for each environment
#### Step 2: Create SAML apps in your IDP
For each environment, follow your provider-specific guide to create a SAML app:
- [Okta setup guide](/docs/guides/platform/sso/okta)
- [Azure AD setup guide](/docs/guides/platform/sso/azure)
- [Google Workspace setup guide](/docs/guides/platform/sso/gsuite)
#### Naming convention example
- "Supabase - Production"
- "Supabase - Staging"
- "Supabase - Development"
Use consistent naming to help users identify the right environment.
#### Step 3: Configure each Supabase organization
For **each** organization:
1. Navigate to [the **SSO** settings](/dashboard/org/_/sso) section of the dashboard
2. Enable **Single Sign-On**
3. Verify **Enable SP-initiated login** is "OFF"
4. Upload or paste metadata from the corresponding IDP app
5. Configure attribute mappings:
- Email (required): Map to `email`
- Name (optional): Map to `name` or `displayName`
6. Configure auto-join settings:
- Dev: Usually enabled with "Developer" role
- Staging: Usually enabled with "Developer" role
- Prod: Usually disabled (explicit invitations only)
7. Save configuration
#### Step 4: Test each environment separately
For each environment:
1. Open your IDP dashboard (Okta, Azure, Google)
2. Click the corresponding app tile
3. Verify redirect to correct Supabase organization
4. Check that user information is populated correctly
5. Verify auto-join behavior (if enabled)
See [the SSO Testing and Best Practices guide](/docs/guides/platform/sso/testing-best-practices) for comprehensive testing procedures.
#### Step 5: Assign users in your IDP
Configure app assignments in your IDP:
- **Production**: Only production users (restrictive)
- **Staging**: QA team, release managers, senior engineers
- **Development**: All engineers and testers (permissive)
Users only see app tiles they're assigned to.
#### Step 6: Document and communicate
Create documentation for your team:
- Which app tile corresponds to which environment
- Access request process for each environment
- Naming conventions and organization structure
- Emergency access procedures (non-SSO owner account)
## User access management
### IDP app assignment strategies
#### Per-environment access control
Control who can access each environment by managing app assignments in your IDP:
```
Engineering Team:
├─ Supabase Dev (assigned) ✅
├─ Supabase Staging (assigned) ✅
└─ Supabase Prod (assigned) ✅
QA Team:
├─ Supabase Dev (assigned) ✅
├─ Supabase Staging (assigned) ✅
└─ Supabase Prod (NOT assigned) ❌
Contractors:
├─ Supabase Dev (assigned) ✅
├─ Supabase Staging (NOT assigned) ❌
└─ Supabase Prod (NOT assigned) ❌
```
### Role assignment patterns
#### Option 1: Different default roles per environment
- Dev: Auto-join with "Administrator" role (developers need full control)
- Staging: Auto-join with "Developer" role
- Prod: No auto-join, explicit invitations with "Read-only" or "Developer"
#### Option 2: Consistent roles, manual promotion
- All environments: Auto-join with "Developer" role
- Promote to "Administrator" or "Owner" manually as needed
- Provides consistent baseline, explicit elevation
#### Option 3: No auto-join, explicit control
- All environments: Auto-join disabled
- Send explicit invitations with appropriate roles
- Maximum control, more management overhead
Choose based on your organization's security posture and operational preferences.
## Best practices
### Naming conventions
#### IDP app names
Use consistent, descriptive names that clearly indicate the environment:
- ✅ "Supabase - Production"
- ✅ "Supabase Prod"
- ❌ "Supabase" (ambiguous)
- ❌ "SUPA_PROD" (unclear abbreviation)
#### Supabase organization names
Match your IDP app names when possible:
- IDP app: "Supabase - Production" → Org: `acme-production`
- IDP app: "Supabase - Staging" → Org: `acme-staging`
- IDP app: "Supabase - Dev" → Org: `acme-development`
### Configuration synchronization
Keep critical settings synchronized across environments:
- **Attribute mappings**: Should be identical across all providers
- **Certificate settings**: Coordinate renewals across all environments
- **Safety accounts**: Each org needs a non-SSO owner account
#### Configuration drift checklist
- [ ] Attribute mappings match across environments
- [ ] Certificate expiration dates documented for all providers
- [ ] Non-SSO owner accounts exist in all organizations
- [ ] Auto-join settings are intentional (not accidental)
- [ ] Default roles appropriate for each environment
### Testing in lower environments first
Always test SSO changes in non-production environments:
1. **Make change in Dev environment**
2. **Test thoroughly** (see [testing guide](/docs/guides/platform/sso/testing-best-practices))
3. **Deploy to Staging** and verify
4. **Monitor for issues** (1-2 days)
5. **Deploy to Production** during low-usage period
6. **Monitor closely** after production deployment
### Security considerations
#### Environment isolation
- Never reuse metadata between environments (security risk)
- Each environment should have unique ACS URLs
- Verify IDP app assignments are correct (don't give prod access accidentally)
#### Access reviews
- Quarterly review of who has access to production
- Verify IDP app assignments are up to date
- Remove access for users who have changed roles
- Audit auto-join configurations (still appropriate?)
#### Break-glass access
Each organization must have at least one non-SSO owner account:
- Create dedicated "break-glass" accounts
- Store credentials in secure password manager
- Test these accounts regularly (quarterly)
- Document emergency access procedures
## Troubleshooting
### Users accessing the wrong environment
#### Symptom
User clicks "Supabase Prod" tile but sees the dev environment.
#### Causes
- Metadata configured incorrectly (swapped between environments)
- ACS URL points to wrong organization
- User has bookmarked the wrong organization
#### Solution
1. Verify ACS URL in IDP app configuration
2. Compare metadata in Supabase SSO settings
3. Check that organization slug matches expected environment
4. Have user clear browser cookies and try again
5. Verify user is clicking correct app tile
### Configuration drift between environments
#### Symptom
SSO works in dev but fails in staging or production.
#### Causes
- Attribute mappings differ between providers
- Certificate expired in one environment but not others
- Domain configuration inconsistent (if using SP-initiated)
#### Solution
1. Compare SSO configurations side-by-side
2. Check attribute mappings are identical
3. Verify certificate expiration dates
4. Test with same user account across all environments
5. Review IDP audit logs for authentication failures
### Users don't see expected app tiles
#### Symptom
User cannot find "Supabase Staging" tile in IDP dashboard.
#### Causes
- User not assigned to the app in IDP
- App not deployed/published in IDP
- User looking in wrong place (different IDP portal)
#### Solution
1. Verify app assignment in IDP admin console
2. Check app is published/active
3. Confirm user has logged out and back into IDP
4. Verify user is checking correct IDP portal (some organizations have multiple)
### Auto-join adding users to wrong organization
#### Symptom
User joins dev environment when they should join production.
#### Cause
User clicked wrong app tile, auto-join is enabled.
#### Prevention
- Disable auto-join in production (explicit invitations only)
- Use clear app tile naming
- Document which tile corresponds to which environment
- Consider using different IDP groups for different environments
#### Remediation
1. Remove user from incorrect organization
2. Send explicit invitation to correct organization
3. Educate user on correct app tile to use
4. Consider disabling auto-join to prevent recurrence
### Multiple organizations with same domain (SP-initiated confusion)
#### Symptom
With SP-initiated enabled and same domain in multiple organizations, users get routed to unexpected organization.
#### Cause
SP-initiated routing uses first matching provider.
#### Solution
- **Recommended:** Switch to IDP-initiated only (disable SP-initiated)
- Remove domain configuration from all but one organization
- Provide clear IDP app tiles for explicit routing
- Document which organization users should access via SP-initiated
## Migration from single to multiple providers
If you currently have a single SSO provider and need to add more:
### Phase 1: Planning
1. Decide which pattern to use (environments, teams, etc.)
2. Document new organization structure
3. Identify users for each environment
4. Plan user communication strategy
### Phase 2: Create new organizations
1. Create additional Supabase organizations
2. Configure projects within each organization
3. Migrate data if needed (see [project transfer](/docs/guides/platform/project-transfer))
### Phase 3: Configure SSO providers
1. Create additional SAML apps in your IDP
2. Configure SSO in each new organization
3. Start with auto-join disabled
4. Test with small group
### Phase 4: Migrate users
1. Communicate changes to users
2. Assign users to appropriate IDP apps
3. Test that users can access correct environments
4. Enable auto-join if desired
### Phase 5: Decommission old configuration (if applicable)
1. Migrate all users to new structure
2. Verify no one depends on old configuration
3. Disable old SSO provider
4. Monitor for issues
5. Delete after verification period
## Next steps
- **Configure your IDP:** Follow your [provider-specific guide](/docs/guides/platform/sso#supported-providers)
- **Test thoroughly:** Review [SSO Testing and Best Practices](/docs/guides/platform/sso/testing-best-practices)
- **Understand login flows:** Read [Understanding SSO Login Flows](/docs/guides/platform/sso/login-flows)
- **Choose the right flow:** See [Choosing the Right Login Flow](/docs/guides/platform/sso/choosing-login-flow)
+33 -5
View File
@@ -94,6 +94,12 @@ We do not permit use of public domains like `gmail.com`, `yahoo.com`.
</Admonition>
<Admonition type="note">
Each SSO provider can be configured with different email domains. For multi-environment setups (Dev/Staging/Prod), we recommend using IdP-initiated flow with multiple SAML apps under the same domain rather than domain-based routing. For more details, see the [Multiple SSO Providers guide](/docs/guides/platform/sso/multiple-providers).
</Admonition>
## Step 9: Configure metadata [#dashboard-configure-metadata]
Enter the metadata URL you obtained from [Step 6](#idp-metadata-url) into the Metadata URL field:
@@ -114,11 +120,17 @@ If you did not customize your settings you may save some time by clicking the **
## Step 11: Join organization on signup (optional) [#dashboard-configure-autojoin]
<Admonition type="tip">
**Recommended workflow:** Start with auto-join **disabled** to test your SSO configuration. Once SSO login is working correctly, enable auto-join if desired.
</Admonition>
By default this setting is disabled, users logging in via SSO will not be added to your organization automatically.
![Auto-join disabled](/docs/img/sso-dashboard-configure-autojoin-disabled.png)
Toggle this on if you want SSO-authenticated users to be **automatically added to your organization** when they log in via SSO.
Toggle this on if you want SSO-authenticated users to be **automatically added to your organization** when they log in via SSO. Auto-join applies on **every login**, not just first signup - this makes it safe to test SSO before enabling this feature.
![Auto-join enable](/docs/img/sso-dashboard-configure-autojoin-enabled.png)
@@ -126,7 +138,7 @@ When auto-join is enabled, you can choose the **default role** for new users:
![Auto-join role selection](/docs/img/sso-dashboard-configure-autojoin-enabled-role.png)
Choose a role that fits the level of access you want to grant to new members.
We recommend choosing **Developer** as the default role (principle of least privilege) and promoting users individually as needed.
<Admonition type="note">
@@ -134,10 +146,26 @@ Visit [access-control](/docs/guides/platform/access-control) documentation for d
</Admonition>
## Step 12: Save changes and test single sign-on [#dashboard-configure-save]
## Step 12: Save changes [#dashboard-configure-save]
When you click **Save changes**, your new SSO configuration is applied immediately. From that moment, any user with an email address matching one of your configured domains who visits your organization's sign-in URL will be routed through the SSO flow.
We recommend asking a few users to test signing in via their Okta account. They can do this by entering their email address on the [Sign in with SSO](/dashboard/sign-in-sso) page.
<Admonition type="tip">
If SSO sign-in doesn't work as expected, contact your Supabase support representative for assistance.
**Next step: Test your SSO configuration**
Before rolling out SSO to your organization, we strongly recommend thorough testing. Visit our [SSO Testing and Best Practices](/docs/guides/platform/sso/testing-best-practices) guide for:
- Step-by-step testing instructions
- How to verify auto-join works correctly
- Common issues and troubleshooting
- Security best practices
- Pre-launch checklist
</Admonition>
<Admonition type="note">
**Testing in Okta sandbox:** If your organization has an Okta sandbox environment, consider testing your SSO configuration there first before applying to production.
</Admonition>
@@ -0,0 +1,844 @@
---
title: 'SSO Testing and Best Practices'
description: 'Comprehensive guide to testing SSO configuration and best practices for secure, reliable single sign-on.'
---
After configuring your SSO provider, thorough testing is essential before rolling out to your organization. This guide covers testing procedures, troubleshooting common issues, and best practices for maintaining a secure SSO setup.
## Pre-configuration checklist
Before you begin testing, verify:
- [ ] Organization has Team or Enterprise plan
- [ ] Login flow type decided (IdP-initiated, SP-initiated, or both) - see [Choosing a Login Flow](/docs/guides/platform/sso/choosing-login-flow)
- [ ] Email domains identified (only required if using SP-initiated)
- [ ] Auto-join settings and default role are decided
- [ ] **At least one non-SSO owner account exists** (critical safety requirement)
- [ ] Certificate expiration dates are documented (especially for Google Workspace)
## Testing login flows
Before testing auto-join and other features, verify which login flows work for your SSO configuration. See [Understanding SSO Login Flows](/docs/guides/platform/sso/login-flows) for technical details.
### Testing IdP-initiated login
IdP-initiated login is always available and doesn't require domain configuration. This should be your primary test.
**Test procedure:**
1. **Access from identity provider:**
- Open your IdP dashboard (Okta, Azure AD, Google Workspace)
- Locate your Supabase app tile or bookmark
- Click the app tile
2. **Verify authentication:**
- If already authenticated with IdP: Immediate redirect to Supabase
- If not authenticated: Complete IdP login flow, then redirect
- Check you're logged into the correct organization
- Verify user profile information is populated correctly
3. **Confirm success:**
- No error messages appear
- Organization dashboard loads properly
- User attributes (name, email) mapped correctly
**Expected results:**
- ✅ Direct login from IdP with no intermediate steps
- ✅ Works regardless of domain configuration
- ✅ User information properly mapped from IdP
### Testing SP-initiated login
SP-initiated login requires domain configuration. Only test this if you've enabled SP-initiated flow.
<Admonition type="note">
If you haven't configured domains or have "Enable SP-initiated login" disabled, skip this test. SP-initiated will not work without domain configuration.
</Admonition>
**Prerequisites:**
- "Enable SP-initiated login" toggle is **ON**
- At least one email domain configured
**Test procedure:**
1. **Start at Supabase:**
- Visit [Sign in with SSO](/dashboard/sign-in-sso)
- Or click "Sign in with SSO" from main sign-in page
2. **Enter email:**
- Use email with matching configured domain
- Click "Continue"
3. **Verify redirect chain:**
- Should redirect to your identity provider
- Complete authentication if needed
- Should redirect back to Supabase
- Check you're in correct organization
4. **Test domain matching:**
- Try email with non-matching domain
- Should receive error: "No SSO provider found"
- Confirms domain-based routing works
**Expected results:**
- ✅ Users with matching domains redirected to IdP
- ✅ Non-matching domains show clear error message
- ✅ Successful authentication redirects back to Supabase
### Testing without domains (IdP-initiated only)
This is a critical test for domainless providers, which enable multiple SAML apps per domain.
**Test scenario:**
You've configured SSO with:
- "Enable SP-initiated login" **OFF** (or no domains configured)
- IdP metadata configured
- Attribute mappings configured
**Test procedure:**
1. **Verify SP-initiated is unavailable:**
- Visit [Sign in with SSO](/dashboard/sign-in-sso)
- Enter your email address
- Expected: Error message "No SSO provider found"
- This is correct behavior (no domains = no SP-initiated)
2. **Verify IdP-initiated works:**
- Open IdP dashboard
- Click Supabase app tile
- Should successfully log in
- Verify correct organization access
3. **Confirm multi-environment pattern works (if applicable):**
- If you have multiple environments (Dev/Staging/Prod)
- Each should have separate app tile in IdP
- Click each tile individually
- Verify each routes to correct organization
**Expected results:**
- ✅ IdP-initiated login works perfectly
- ❌ SP-initiated login unavailable (expected)
- ✅ Multiple environments accessible via different tiles
- ✅ No domain conflicts between environments
<Admonition type="tip">
**Multiple environments:** If you're setting up Dev/Staging/Prod, this domainless pattern is recommended. See [Multiple SSO Providers](/docs/guides/platform/sso/multiple-providers) for detailed configuration guidance.
</Admonition>
### Login flow verification checklist
- [ ] IdP-initiated login works from IdP dashboard
- [ ] SP-initiated login works (if domains configured)
- [ ] SP-initiated properly blocked if no domains configured
- [ ] Domain matching works correctly for SP-initiated
- [ ] Non-matching domains show appropriate errors
- [ ] Multiple environments route correctly (if using multiple providers)
- [ ] Both flows work simultaneously (if both enabled)
## Testing SSO login flow
### Basic login test
1. **Navigate to the SSO sign-in page**:
- Visit [Sign in with SSO](/dashboard/sign-in-sso)
- Or click "Sign in with SSO" from the main Supabase sign-in page
2. **Enter your email address**:
- Use an email with a domain configured in your SSO settings
- Click "Continue"
3. **Verify redirect to identity provider**:
- You should be redirected to your identity provider (Okta, Azure AD, Google Workspace)
- If already signed in to your IdP, you may be automatically redirected back
- If not signed in, complete the IdP login flow
4. **Confirm successful sign-in**:
- You should be redirected back to Supabase dashboard
- Your profile should show your SSO identity
- Check that your user information is populated correctly
### Multi-user testing
Test with 2-3 additional users to verify:
- Users with matching email domains can sign in via SSO
- User attributes (name, email) are mapped correctly
- Users receive appropriate access to organization (if using auto-join)
- Users without matching domains cannot use SSO for this organization
## Testing auto-join
<Admonition type="caution">
**Recent improvement:** Auto-join now applies on EVERY login, not just first signup. This resolves a common issue where org owners would test with auto-join disabled, enable it, then log in again expecting to auto-join.
</Admonition>
### Recommended testing workflow
1. **Start with auto-join disabled**:
- Navigate to [SSO settings](/dashboard/org/_/sso)
- Ensure "Join organization on signup" is **disabled**
- Configure your SSO provider
- Test basic SSO login (see above)
2. **Enable auto-join after successful test**:
- Return to [SSO settings](/dashboard/org/_/sso)
- Toggle "Join organization on signup" to **enabled**
- Select default role (recommended: **Developer**)
- Click "Save changes"
3. **Test auto-join with your account**:
- **Log out completely** from Supabase
- Sign in again via SSO
- Verify you were automatically added to the organization
- Check you received the correct default role
4. **Test with additional users**:
- Have colleagues with matching email domains sign in via SSO
- They should automatically join the organization
- Verify they received the correct default role
- Check organization members list at `/dashboard/org/_/team`
5. **Test domain restrictions (if using SP-initiated)**:
- Try signing in with an email from a non-configured domain
- User should be able to sign in but will NOT see the organization
- This confirms domain-based access control is working
- Note: With IdP-initiated only, domain matching doesn't apply
6. **Test idempotency (prevents duplicate memberships)**:
- Log in again with an account that's already a member
- Verify no error occurs
- Check members list - should be no duplicate entry
- Confirm role hasn't changed unexpectedly
- Expected: Auto-join gracefully handles existing members
7. **Test with domainless (IdP-initiated only) configuration**:
<Admonition type="note">
This test is critical if you're using multiple environments under the same domain. See [Multiple SSO Providers](/docs/guides/platform/sso/multiple-providers) for details.
</Admonition>
- If you configured SSO without domains (IdP-initiated only):
- Enable auto-join
- New user accesses via IdP app tile
- Verify auto-join works without domain check
- User automatically added to organization
- Correct role assigned
- Expected: Auto-join works for IdP-initiated regardless of email domain
8. **Test auto-join re-enablement**:
- Disable auto-join
- Have new user sign in via SSO
- Verify they are NOT added to organization
- Re-enable auto-join
- Same user logs out and logs in again
- Verify they ARE now added to organization
- Expected: Existing SSO users auto-join when feature is enabled
### Auto-join verification checklist
- [ ] Auto-join works when enabled
- [ ] Users receive correct default role
- [ ] Non-matching domains are excluded (if using SP-initiated with domains)
- [ ] Existing users auto-join on their next login (not just new signups)
- [ ] Auto-join can be disabled and re-enabled as needed
- [ ] Auto-join is idempotent (no duplicate memberships)
- [ ] Auto-join works with IdP-initiated only (no domains)
- [ ] Auto-join works with both IdP and SP-initiated flows
## Testing invitations
<Admonition type="caution">
**Recent improvement:** You can now explicitly choose whether an invitation requires SSO or non-SSO authentication. Previously, this was inherited from the inviter's account type, which caused confusion.
</Admonition>
### Creating and testing invitations
1. **Create SSO-required invitation**:
- Navigate to [organization team settings](/dashboard/org/_/team)
- Click "Invite" to create a new invitation
- Select **"Require SSO"** option
- Enter recipient email and select role
- Send invitation
- Recipient must log in via SSO to accept
2. **Create non-SSO invitation**:
- Create a new invitation
- Select **"Non-SSO"** option
- Send invitation
- Recipient can use password or social login to accept
3. **Test SSO mismatch scenario**:
- Create an SSO-required invitation
- Have recipient try to accept while logged in with a non-SSO account
- Error should display: "Invite token SSO provider does not match the one you are logged in with"
- Recipient should log out and sign in via SSO
- Can then successfully accept the invitation
### Common invitation scenarios
- **All-SSO organization**: Always select "Require SSO" for invitations
- **Mixed organization**: Choose based on recipient's authentication method
- **Transitioning to SSO**: Start with non-SSO users, gradually add SSO users, maintain non-SSO owner before removing old authentication methods
### Invitation verification checklist
- [ ] SSO-required invitations work correctly
- [ ] Non-SSO invitations work correctly
- [ ] SSO mismatch error message is clear
- [ ] Mixed authentication organization functions properly
- [ ] Invitations can be resent if needed
<Admonition type="note">
If you're configuring multiple SSO providers for different environments (dev/staging/prod), the testing steps outlined here apply to each provider individually. For advanced multi-provider configuration strategies, see the [Multiple SSO Providers guide](/docs/guides/platform/sso/multiple-providers).
</Admonition>
## Testing SSO account restrictions
SSO accounts have specific restrictions to prevent accidental organization lockouts.
<Admonition type="caution">
**Safety mechanism:** SSO accounts cannot delete SSO providers. This prevents scenarios where an SSO user could accidentally lock out the entire organization by deleting the SSO provider they use to authenticate.
</Admonition>
### Testing SSO account deletion restrictions
1. **Log in with SSO account:**
- Authenticate via SSO (IdP or SP-initiated)
- Navigate to [SSO settings](/dashboard/org/_/sso)
- Verify you are an organization owner
2. **Attempt to delete SSO provider:**
- Try to delete the SSO provider
- **Expected:** Error message preventing deletion
- Error: "Only a non-SSO account may delete an SSO Provider"
- Deletion should be blocked
3. **Verify other SSO operations work:**
- SSO accounts CAN read SSO configuration
- SSO accounts CAN update SSO settings
- SSO accounts CAN disable (but not delete) SSO provider
- Only deletion is restricted
**Expected results:**
- ❌ SSO accounts cannot delete SSO providers
- ✅ Clear error message explains the restriction
- ✅ Other SSO management operations still work
### Testing with non-SSO owner account
1. **Log in with non-SSO owner:**
- Use password or social auth account
- Must be organization owner
- Navigate to [SSO settings](/dashboard/org/_/sso)
2. **Verify deletion capability:**
- Non-SSO owners CAN delete SSO providers
- Deletion subject to additional safety checks (see next section)
- System allows proceeding to deletion flow
**Expected results:**
- ✅ Non-SSO owners CAN access deletion functionality
- ✅ Safety checks still apply (non-SSO account requirement)
### SSO account restrictions checklist
- [ ] SSO accounts cannot delete SSO providers
- [ ] SSO accounts CAN update SSO settings
- [ ] SSO accounts CAN disable SSO providers
- [ ] Non-SSO owners CAN delete SSO providers
- [ ] Error messages clearly explain the restriction
- [ ] Restriction applies to all SSO accounts (not just certain roles)
## Common issues and troubleshooting
Based on customer pain points that previously required support intervention:
### Critical issues
#### "Enabled auto-join but users aren't automatically joining"
**Common workflow that causes this:**
1. Org owner tests SSO with auto-join disabled
2. Enables auto-join after testing
3. Logs in again expecting to auto-join but nothing happens
**Solution:**
- Auto-join now applies on **every login**, not just first signup
- To test: Enable auto-join, log out completely, log back in via SSO
- If still not working, verify domain configuration matches user email exactly
#### "Can't invite users with the right authentication type"
**Previous limitation:**
- Invitation type was inherited from inviter's account type
- Non-SSO owners couldn't send SSO invitations
- SSO owners couldn't send non-SSO invitations
**Solution:**
- When creating invitations, explicitly choose "Require SSO" or "Non-SSO"
- Mixed organizations are now fully supported
- Both SSO and non-SSO users can coexist in the same organization
#### "Invitation acceptance shows 'SSO provider mismatch' error"
**Cause:** User is logged in with wrong authentication method for the invitation
**Solution:**
1. Check if invitation requires SSO or non-SSO login
2. Log out completely
3. Sign in with the correct method (SSO or password/social)
4. Accept the invitation
5. Contact the person who sent the invitation if unsure about the type
#### "Deleted the SSO provider and now members can't log in"
**Recent safety improvements:**
- System now automatically removes all SSO members before deletion
- Must have at least one non-SSO owner before deletion is allowed
**Best practice:**
- Add a non-SSO owner account **before** deleting SSO provider
- Communicate to affected users before deletion
- Consider disabling rather than deleting if change is temporary
## Testing safe provider deletion
<Admonition type="danger">
**Critical safety checks:** Deleting an SSO provider automatically removes ALL SSO members from the organization. The system enforces multiple safety checks to prevent complete organization lockout.
**Only test deletion in non-production environments or test organizations.** Do not test this in your actual production organization unless you fully understand the consequences.
</Admonition>
### Understanding deletion behavior
When an SSO provider is deleted:
1. System verifies at least one non-SSO owner account exists
2. **All SSO members are automatically removed** from the organization
3. SSO provider configuration is deleted
4. Organization continues operating with remaining non-SSO members
This behavior prevents "orphaned" SSO accounts that can no longer authenticate.
### Test 1: Deletion without non-SSO accounts (should fail)
**Setup:**
- Organization with only SSO accounts
- All owners authenticate via SSO
- No password or social auth owners exist
**Test procedure:**
1. **Verify current state:**
- Check [team settings](/dashboard/org/_/team)
- Confirm all owners are SSO accounts
- No non-SSO owner exists
2. **Attempt deletion:**
- Navigate to [SSO settings](/dashboard/org/_/sso)
- Try to delete SSO provider
- **Expected:** Error preventing deletion
- Error message: "At least one non-SSO account is required to maintain organization access"
3. **Verify organization state:**
- SSO provider still exists
- All SSO members still have access
- No partial deletion occurred
**Expected result:** ❌ Deletion blocked with clear error message
### Test 2: Add non-SSO owner and retry deletion (should succeed)
<Admonition type="caution">
**Warning:** This test WILL remove all SSO members. Only perform in test organizations.
</Admonition>
**Setup:**
1. **Add non-SSO owner:**
- Create or invite a non-SSO user (password or social login)
- Promote to owner role
- **Critical:** Verify non-SSO owner can log in BEFORE deletion
- Store credentials securely
2. **Document SSO members:**
- Note current SSO member count
- Document SSO member email addresses (for verification)
**Test procedure:**
1. **Attempt deletion as non-SSO owner:**
- Log in with non-SSO owner account
- Navigate to [SSO settings](/dashboard/org/_/sso)
- Delete SSO provider
- Confirm deletion
2. **Verify deletion results:**
- All SSO members removed from organization
- Check [team settings](/dashboard/org/_/team)
- Only non-SSO members should remain
- SSO configuration completely removed
3. **Verify non-SSO access:**
- Non-SSO owner retains full access
- Organization remains functional
- Can invite new members (non-SSO invitations)
**Expected result:** ✅ Deletion succeeds, SSO members removed, non-SSO access preserved
### Test 3: Member removal during deletion
**Test in isolated environment with test accounts.**
**Setup:**
1. Create test organization
2. Enable SSO
3. Add multiple SSO members (3-5 test users)
4. Add at least one non-SSO owner
5. Document member list before deletion
**Test procedure:**
1. **Track members before deletion:**
- Note SSO member count (e.g., 5 SSO members)
- Note SSO member email addresses
- Document their roles
2. **Delete SSO provider:**
- Log in as non-SSO owner
- Delete SSO provider
- System may show member count being removed
3. **Verify member removal:**
- Check organization members list
- All SSO members should be gone
- Only non-SSO members remain
- Previous SSO users cannot access org
**Expected result:** All SSO members cleanly removed, no orphaned accounts
### Test 4: Mixed authentication scenario
**Setup:**
- Organization with both SSO and non-SSO members
- SSO members: employees (via SSO)
- Non-SSO members: contractors (password auth)
- Mixed owner types
**Test procedure:**
1. **Ensure non-SSO owner exists:**
- Verify at least one non-SSO owner
- Test their login before deletion
2. **Delete SSO provider:**
- System allows deletion (non-SSO owner exists)
- Confirm deletion
3. **Verify selective removal:**
- SSO members removed (employees)
- Non-SSO members retained (contractors)
- Organization still functional
- Non-SSO owners can manage organization
**Expected result:** ✅ Selective removal - only SSO members affected
### Safe deletion verification checklist
- [ ] Cannot delete without non-SSO owner account
- [ ] Error message clearly explains requirement
- [ ] Adding non-SSO owner enables deletion
- [ ] All SSO members removed upon deletion
- [ ] Non-SSO members unaffected by SSO provider deletion
- [ ] Organization remains accessible via non-SSO accounts
- [ ] SSO configuration completely removed after deletion
- [ ] Non-SSO owner account tested BEFORE deletion
### Best practices for safe deletion
**Before deleting SSO provider:**
1. **Create dedicated non-SSO owner account**
- Use password authentication
- **Test that this account can log in**
- Store credentials in secure password manager
- Verify owner permissions
2. **Communication plan:**
- Notify all SSO members before deletion
- Explain they will lose organization access
- Provide timeline for deletion
- Offer alternative access if needed (re-invite as non-SSO)
3. **Documentation:**
- Document which members will be removed
- Plan for re-adding users if needed
- Have rollback plan (reconfigure SSO if needed)
**After deletion:**
1. **Verify organization function:**
- Test non-SSO owner access
- Verify critical functionality works
- Check that SSO members removed
2. **User communication:**
- Confirm to users that deletion complete
- Provide instructions for alternative access
- Answer questions about regaining access
### Configuration issues
#### "SSO sign-in doesn't work at all"
Common causes:
- Metadata URL/file incorrect or expired
- Certificate expired (especially Google Workspace - check during setup)
- Attribute mapping misconfigured
- User not assigned to Supabase app in identity provider
- Email domain not configured in Supabase SSO settings
- User email domain doesn't match configured domains
**Troubleshooting steps:**
1. Verify metadata URL/file is accessible and current
2. Check certificate expiration date
3. Verify attribute mappings (email mapping is required)
4. Confirm user is assigned to app in IdP
5. Check domain configuration in Supabase matches user email
6. Review IdP logs for authentication errors
#### "Attribute mapping errors or missing user data"
**Requirements:**
- Email mapping to `email` is **required**
- Attribute keys must be spelled exactly as shown in provider
- Use provider presets (Okta, Azure, G Suite) to avoid errors
**Troubleshooting:**
1. Verify email attribute is mapped correctly
2. Check attribute names match your IdP configuration exactly
3. Test that mappings return expected user data
4. Use IdP test tools to see what attributes are being sent
#### "Cannot delete SSO provider"
**Error:** "At least one non-SSO account is required"
**Solution:**
1. Create or convert an existing member to a non-SSO owner account
2. Verify the non-SSO owner can log in
3. Then proceed with SSO provider deletion
**Why this is required:** Prevents complete organization lockout if SSO becomes unavailable
## Best practices
### Security and safety
#### CRITICAL: Maintain at least one non-SSO owner account
- **Required** to prevent complete organization lockout
- System enforces this when deleting SSO provider
- Create dedicated non-SSO owner **before** enabling SSO
- Store credentials securely in a password manager
- Verify this account can log in before critical changes
#### Monitor certificate expiration
- Set calendar reminders **30 days before** certificate expiration
- Especially important for Google Workspace (certificates shown during setup)
- Test SSO after certificate renewal
- Update metadata in Supabase after IdP certificate renewal
- Communicate planned renewal to team
#### Configure domains carefully
- Use specific corporate email domains only
- Public domains (gmail.com, yahoo.com, etc.) are automatically blocked
- Be cautious with domains you don't fully control
- Multiple domains supported for contractors/acquisitions
- Document which domains are configured and why
#### Regular access reviews
- Periodically review organization member list
- Verify auto-join role is still appropriate
- Check for orphaned or inactive accounts
- Coordinate with IT team on user access reviews
- Remove members who no longer need access
### Configuration and testing
#### Recommended SSO setup workflow
1. Create or verify non-SSO owner account exists
2. Configure SSO provider with auto-join **DISABLED**
3. Test SSO login with your own account
4. Verify attribute mappings are correct
5. Test with 2-3 additional users
6. Enable auto-join if desired
7. Test auto-join functionality thoroughly
8. Communicate SSO availability to team
#### Role selection for auto-join
- Default to **"Developer"** role (principle of least privilege)
- Avoid "Owner" or "Administrator" for auto-join
- Promote users individually as needed
- Review and document your access control strategy
- See [access control documentation](/docs/guides/platform/access-control) for role details
#### Attribute mapping
- Email mapping is **REQUIRED**
- Use provider presets (Okta, Azure, G Suite) when available
- Document custom mappings for future reference
- Test mappings return expected user data
- Keep mappings consistent across environments
#### Multi-environment strategy
- Consider separate providers for dev/staging/prod
- Test configuration changes in non-production first
- Keep provider configurations synchronized
- Document differences between environments
- See [Multiple SSO Providers guide](/docs/guides/platform/sso/multiple-providers) for details
### Operations and maintenance
#### Before making SSO changes
- Notify team members in advance
- Schedule during low-usage period if possible
- Have rollback plan ready
- Keep Supabase support contact information handy
- Document what you're changing and why
#### After SSO configuration changes
- Test login immediately
- Verify auto-join still works (if enabled)
- Check that invitations are working
- Confirm no users are locked out
- Monitor for support requests from team
#### Before deleting SSO provider
- Verify at least one non-SSO owner exists (system enforces)
- Understand that **all SSO members will be removed automatically**
- Communicate to affected users **before** deletion
- Consider disabling rather than deleting if temporary
- Have plan for users to regain access if needed
#### Coordinating with IT/Security team
- SSO changes may affect compliance requirements
- Certificate renewals require coordination
- User access reviews should include Supabase
- Incident response plans should consider SSO dependencies
- Document SSO configuration in your organization's runbook
## Final verification checklist
Before rolling out SSO to your organization:
**Authentication & Login Flows:**
- [ ] IdP-initiated login works from IdP dashboard
- [ ] SP-initiated login works (if domains configured)
- [ ] Appropriate login flow chosen for your use case
- [ ] Domain configuration correct (or intentionally empty for IdP-only)
- [ ] Multiple environments route correctly (if using multiple providers)
**Auto-Join Functionality:**
- [ ] Auto-join adds users to correct organization (if enabled)
- [ ] Auto-joined users receive correct default role
- [ ] Auto-join works on first login (not just signup)
- [ ] Existing users auto-join when feature enabled
- [ ] Auto-join is idempotent (no duplicate memberships)
- [ ] Auto-join works with IdP-initiated (no domains required)
- [ ] Non-matching domains excluded (if using SP-initiated)
**Invitations:**
- [ ] SSO-required invitations work correctly
- [ ] Non-SSO invitations work correctly
- [ ] Invitation types can be explicitly chosen
- [ ] SSO mismatch errors are clear
**Safety & Access Controls:**
- [ ] At least one non-SSO owner account exists
- [ ] Non-SSO owner account can log in successfully
- [ ] Non-SSO credentials stored securely
- [ ] SSO account deletion restrictions understood and tested
- [ ] Safe deletion behavior verified (if tested)
**Configuration:**
- [ ] Certificate expiration date documented with calendar reminders
- [ ] Team notified of SSO availability
- [ ] Login instructions provided (IdP tile and/or supabase.com)
- [ ] Rollback plan documented
- [ ] Support contact information available
**Testing Completed:**
- [ ] Tested with multiple user accounts
- [ ] Both login flows tested (if both enabled)
- [ ] Auto-join behavior verified
- [ ] SSO account restrictions confirmed
- [ ] Domain restrictions validated (if applicable)
- [ ] Multi-environment isolation verified (if using multiple providers)
## Need help?
If you encounter issues not covered in this guide, contact your Supabase support representative for assistance. When reaching out, include:
- Organization name and URL
- SSO provider type (Okta, Azure AD, Google Workspace, etc.)
- Specific error messages
- Steps you've already tried
- Whether the issue affects all users or specific individuals
@@ -19,7 +19,7 @@ Various products at Supabase have their own hardening and configuration guides,
- [Row Level Security](/docs/guides/database/postgres/row-level-security)
- [Column Level Security](/docs/guides/database/postgres/column-level-security)
- [Hardening the Data API](/docs/guides/api/hardening-data-api)
- [Data API](/docs/guides/database/data-api)
- [Additional security controls for the Data API](/docs/guides/api/securing-your-api)
- [Custom claims and role based access control](/docs/guides/api/custom-claims-and-role-based-access-control-rbac)
- [Managing Postgres roles](/docs/guides/database/postgres/roles)
+12 -8
View File
@@ -7,7 +7,7 @@ hideToc: true
## Get started
The fastest and recommended way to self-host Supabase is using Docker.
The fastest and recommended way to self-host Supabase is to use Docker.
<div className="grid md:grid-cols-12 gap-4 not-prose">
<div className="md:col-span-6 xl:col-span-4 relative" key="/guides/self-hosting/docker">
@@ -55,7 +55,7 @@ There are several other options to deploy Supabase. If you're interested in help
## About self-hosting
Self-hosting is a good fit if you need full control over your data, have compliance requirements that prevent using managed services, or want to run Supabase in an isolated environment.
Self-hosting is a good fit if you need full control over your data, have compliance requirements that prevent you from using managed services, or want to run Supabase in an isolated environment.
### How self-hosted Supabase differs
@@ -64,11 +64,7 @@ Self-hosted Supabase is different from:
- **Supabase CLI** (local development), which is intended for development and testing only.
- **Managed Supabase** platform, which is fully hosted and operated by Supabase.
### Telemetry
Self-hosted Supabase (Docker) does not phone home or collect any telemetry.
The **Supabase CLI** is a [separate tool](/docs/guides/local-development/cli/getting-started) from self-hosted Supabase and collects usage telemetry to help improve the developer experience. You can opt out by running `supabase telemetry disable` or setting `SUPABASE_TELEMETRY_DISABLED=1`. See [CLI telemetry](/docs/guides/local-development/cli/getting-started#telemetry) for other opt-out methods.
Self-hosted Supabase mimics a single project. Studio doesn't support multiple organizations or projects. Platform-only [features](/features) such as branching, advanced metrics beyond logs, managed backups and PITR, analytics and vector buckets, ETL, and the platform management API are **unavailable** in self-hosted configuration. Most settings are configured through [environment variables](https://github.com/supabase/supabase/blob/master/docker/.env.example).
### Your responsibilities when self-hosting
@@ -76,10 +72,18 @@ When you self-host, **you are responsible for**:
- Server provisioning and maintenance
- Security hardening and keeping OS and services updated
- Maintaining the Postgres database
- Service configuration and management
- Postgres database maintenance
- High availability and scalability
- Backups and disaster recovery
- Monitoring and uptime
### Telemetry
Self-hosted Supabase (run via Docker Compose) **does not phone home or collect any telemetry**.
The **Supabase CLI** is a [separate tool](/docs/guides/local-development/cli/getting-started) and collects usage telemetry to help improve the developer experience. See [CLI telemetry](/docs/guides/local-development/cli/getting-started#telemetry) for opt-out methods.
## Support and community
Self-hosted Supabase is community-supported.
@@ -39,7 +39,7 @@ For better performance with large files, use the direct storage hostname: `https
## Step 2: Create buckets on self-hosted
Buckets must exist on the destination before you can copy objects into them. You can create them through dashboard UI, or with **SQL Editor**.
Buckets must exist on the destination before you can copy objects into them. You can create them through the dashboard UI, or with the **SQL Editor**.
<Admonition type="tip">
@@ -93,7 +93,7 @@ Replace the credentials with your actual values. For self-hosted, use the `REGIO
Verify both remotes connect:
```bash
```sh
rclone lsd platform:
rclone lsd self-hosted:
```
@@ -104,13 +104,13 @@ Both commands should list your buckets.
Copy a single bucket:
```bash
```sh
rclone copy platform:your-storage-bucket self-hosted:your-storage-bucket --progress
```
To copy all buckets:
```bash
```sh
for bucket in $(rclone lsf platform: | tr -d '/'); do
echo "Copying bucket: $bucket"
rclone copy "platform:$bucket" "self-hosted:$bucket" --progress
@@ -127,7 +127,7 @@ For large migrations, consider adding `--transfers 4` to increase parallelism, o
Compare object counts between source and destination:
```bash
```sh
rclone size platform:your-storage-bucket && \
rclone size self-hosted:your-storage-bucket
```
@@ -154,7 +154,7 @@ If rclone reports that a bucket doesn't exist on the self-hosted side, create it
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
For very large files, increase rclone's timeout:
```bash
```sh
rclone copy platform:your-storage-bucket self-hosted:your-storage-bucket --timeout 30m
```
@@ -69,7 +69,7 @@ volumes/
Update the `auth` service to depend on `templates-server`, and pass the email template environment variables. Then add a `templates-server` service to serve the templates from `./volumes/templates`.
```yml
```yml name=docker-compose.yml
services:
auth:
depends_on:
@@ -90,7 +90,7 @@ services:
#### What this configuration does
- Adds a `templates-server`service that runs alongside the Supabase services in the same docker network.
- Adds a `templates-server` service that runs alongside the Supabase services in the same docker network.
- Serves your custom email template files from the `./volumes/templates` directory.
- Keeps the templates-server private to the Docker network (no published ports), so it is not accessible from outside.
- Allows the `auth` service to fetch templates via `http://templates-server/<template>.html`.
@@ -148,7 +148,7 @@ volumes/
Update the `auth` service in `docker-compose.yml` to enable password changed notification
```yml
```yml name=docker-compose.yml
services:
auth:
depends_on:
+149 -122
View File
@@ -14,7 +14,7 @@ Docker is the easiest way to get started with self-hosted Supabase. It should ta
3. [Installing Supabase](#installing-supabase)
4. [Configuring and securing Supabase](#configuring-and-securing-supabase)
5. [Starting and stopping](#starting-and-stopping)
6. [Accessing Supabase services](#accessing-supabase-services)
6. [Accessing Supabase services](#accessing-supabase-studio-dashboard)
7. [Updating](#updating)
8. [Uninstalling](#uninstalling)
9. [Advanced topics](#advanced-topics)
@@ -27,7 +27,7 @@ This guide assumes you're comfortable with:
- Docker and Docker Compose
- Networking fundamentals (ports, DNS, firewalls)
If you're new to these topics, consider starting with managed [Supabase platform](/dashboard) for free.
If you're new to these topics, consider starting with the managed [Supabase platform](/dashboard) for free.
You need the following installed on your system:
@@ -37,6 +37,9 @@ You need the following installed on your system:
- **Linux desktop**: Install [Docker Desktop](https://docs.docker.com/desktop/setup/install/linux/)
- **macOS**: Install [Docker Desktop](https://docs.docker.com/desktop/install/mac-install/)
- **Windows**: Install [Docker Desktop](https://docs.docker.com/desktop/install/windows-install/)
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
- OpenSSL and Node.js 16+ (when switching to the [new API keys](/docs/guides/self-hosting/self-hosted-auth-keys) and new auth)
## System requirements
@@ -133,105 +136,89 @@ While we provided example placeholder passwords and keys in the `.env.example` f
<Admonition type="danger">
Review the configuration options below and ensure you set all secrets before starting the services.
Review the configuration steps below and ensure you set all secrets properly before starting the services.
</Admonition>
### Quick setup (experimental)
### Quick setup
To generate and apply all secrets at once you can run:
To generate secure passwords and secrets, run:
```sh
sh ./utils/generate-keys.sh
sh utils/generate-keys.sh
```
Review the output before proceeding and also check `.env` after it's updated by the script. Alternatively, configure all secrets manually as follows.
As the **next step**, use the following script to add the new API keys and asymmetric key pair:
### Configure database password
```sh
sh utils/add-new-auth-keys.sh
```
Change the placeholder password in the `.env` file **before** starting Supabase for the first time.
Review the output of both scripts and check the `.env` file **before proceeding** to configure [Supabase URLs](#configure-supabase-urls).
- `POSTGRES_PASSWORD`: the password for the `postgres` and `supabase_admin` database roles
For a description of all secrets refer to the [related section](#configuring-secrets) in the "Advanced topics" below. If you'd like to learn more about how the new API keys and asymmetric JWT signing work in a self-hosted Supabase setup, make sure to read the detailed [how-to guide](/docs/guides/self-hosting/self-hosted-auth-keys).
Follow the [password guidelines](/docs/guides/database/postgres/roles#passwords) for choosing a secure password. For easier configuration, **use only letters and numbers** to avoid URL encoding issues in connection strings.
### Configure Supabase URLs
### Generate and configure API keys
Review and change URL configuration variables:
Use the key generator below to obtain and configure the following secure keys in `.env`:
- `JWT_SECRET`: Used by Auth, PostgREST, and other services to sign and verify JWTs.
- `ANON_KEY`: Client-side API key with limited permissions (`anon` role). Use this in your frontend applications.
- `SERVICE_ROLE_KEY`: Server-side API key with full database access (`service_role` role). **Never expose this in client code.**
<JwtGeneratorSimple />
1. Copy the generated value and update `JWT_SECRET` in the `.env` file. Do not share this secret publicly or commit it to version control.
2. Copy the generated value and update `ANON_KEY` in the `.env` file.
3. Copy the generated value and update `SERVICE_ROLE_KEY` in the `.env` file.
The generated keys expire in 5 years. You can verify them at [jwt.io](https://jwt.io) using the saved value of `JWT_SECRET`.
### Configure other keys, and important URLs
Edit the following settings in the `.env` file:
- `SECRET_KEY_BASE`: encryption key for securing Realtime and Supavisor communications. (Must be at least 64 characters; generate with `openssl rand -base64 48`)
- `VAULT_ENC_KEY`: encryption key used by Supavisor for storing encrypted configuration. (Must be exactly 32 characters; generate with `openssl rand -hex 16`)
- `PG_META_CRYPTO_KEY`: encryption key for securing connection strings used by Studio against postgres-meta. (Must be at least 32 characters; generate with `openssl rand -base64 24`)
- `LOGFLARE_PUBLIC_ACCESS_TOKEN`: API token for log ingestion and querying. Used by Vector and Studio to send and query logs. (Must be at least 32 characters; generate with `openssl rand -base64 24`)
- `LOGFLARE_PRIVATE_ACCESS_TOKEN`: API token for Logflare management operations. Used by Studio for administrative tasks. Never expose client-side. (Must be at least 32 characters; generate with `openssl rand -base64 24`)
- `S3_PROTOCOL_ACCESS_KEY_ID`: Access key ID (username-like) for [accessing](/docs/guides/self-hosting/self-hosted-s3) the S3 protocol endpoint in Storage. (Generate with `openssl rand -hex 16`)
- `S3_PROTOCOL_ACCESS_KEY_SECRET`: Secret key (password-like) used with S3_PROTOCOL_ACCESS_KEY_ID. (Generate with `openssl rand -hex 32`)
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
- `MINIO_ROOT_PASSWORD`: Root administrator password for the [MinIO server](/docs/guides/self-hosting/self-hosted-s3#using-minio). (Must be 8+ characters; generate with `openssl rand -hex 16`)
Review and change URL environment variables:
- `SUPABASE_PUBLIC_URL`: base URL for accessing Supabase from the Internet (Dashboard, API, Storage, etc.), e.g, `http://example.com:8000`
- `API_EXTERNAL_URL`: base URL of the Auth service as seen externally, e.g., `http://example.com:8000`
- `SUPABASE_PUBLIC_URL`: base URL for accessing Supabase from the Internet (Dashboard, API, Storage, etc.), e.g., `http://example.com:8000`
- `API_EXTERNAL_URL`: used by the Auth service to configure callback URLs, e.g., `http://example.com:8000`
- `SITE_URL`: default [redirect URL](/docs/guides/auth/redirect-urls) for Auth, e.g., `http://example.com:3000`
<Admonition type="tip">
<Admonition type="note" label="What your-domain means in the docs">
If you are only using self-hosted Supabase locally, you can use `localhost`.
Throughout the self-hosting guides, `<your-domain>` stands for the host where your Supabase instance is reachable: your domain name, your server's IP, or `localhost`, depending on your setup.
- **Default setup:** Kong listens on port `8000`, so the full URL is `http://<your-domain>:8000`.
- **Behind a [reverse proxy](/docs/guides/self-hosting/self-hosted-proxy-https):** the proxy terminates TLS on port `443`, so the URL becomes `https://<your-domain>`.
</Admonition>
### Where to find your credentials
The generated secrets and password are written to the `.env` file. The ones you are most likely to need when connecting your application to self-hosted Supabase are:
- `POSTGRES_PASSWORD`: database password used in Postgres connection strings and by `psql`
- `SUPABASE_PUBLISHABLE_KEY`: publishable API key for client-side use (e.g., in your frontend)
- `SUPABASE_SECRET_KEY`: secret API key for server-side use. Never expose this in client code
- `SUPABASE_PUBLIC_URL`: base URL you pass as `supabaseUrl` to the client libraries
If you are still using the [legacy API keys](#configuring-legacy-api-keys), look for `ANON_KEY` and `SERVICE_ROLE_KEY` instead of the new publishable and secret API keys above.
### Studio authentication
Access to Studio dashboard and internal API is protected with **HTTP basic authentication**.
Access to Studio (Dashboard) is protected with **HTTP basic authentication**.
<Admonition type="danger">
The default password MUST be changed before starting Supabase.
A secure password MUST be set before starting Supabase. The password must include at least one letter - do not use numbers only or any special characters.
</Admonition>
The password must include at least one letter: do not use numbers only and do not use any special characters.
Change the password in the `.env` file:
- `DASHBOARD_PASSWORD`: password for Studio / dashboard
Optionally change the user:
- `DASHBOARD_USERNAME`: username for Studio / dashboard
In the `.env` file, edit `DASHBOARD_PASSWORD` to change the password, and optionally `DASHBOARD_USERNAME` to change the username.
## Starting and stopping
You can start all services by using the following command in the same directory as your `docker-compose.yml` file:
You can start Supabase by using the following command in the same directory as your `docker-compose.yml` file:
```sh
# Start the services (in detached mode)
docker compose up -d
```
After all the services have started you can see them running in the background:
Check the status of the services:
```sh
docker compose ps
```
After a minute or less, all services should have a status `Up [...] (healthy)`. If you see a status such as `created` but not `Up`, try inspecting the Docker logs for a specific container, e.g.,
After a minute or less, all services should have a status `Up [...] (healthy)`. If you see a status such as `created` but not `Up`, run the test script to determine what the problem might be:
```sh
sh tests/test-container-logs.sh
```
Then try inspecting the Docker logs for a specific container, e.g.,
```sh
docker compose logs analytics
@@ -243,21 +230,17 @@ To stop Supabase, use:
docker compose down
```
## Accessing Supabase services
## Accessing Supabase Studio (Dashboard)
After the Supabase services are configured and running, you can access the dashboard, connect to the database, and use edge functions.
By default, you can access the dashboard through the API gateway on port `8000`.
### Accessing Supabase Studio
For example: `http://<your-domain>:8000`, or `http://<your-ip>:8000` (or `localhost:8000` if you are running Docker Compose locally).
You can access Supabase Studio through the API gateway on port `8000`.
You will be prompted for a username and password. See the [Studio authentication](#studio-authentication) section for details.
For example: `http://example.com:8000`, or `http://<your-ip>:8000` (or `localhost:8000` if you are running Docker Compose locally).
## Accessing Postgres
You will be prompted for a username and password. Use the credentials that you set up earlier in [Studio authentication](#studio-authentication).
### Accessing Postgres
By default, the Supabase stack provides the [Supavisor](https://supabase.github.io/supavisor/development/docs/) connection pooler for accessing Postgres and managing database connections.
The self-hosted Supabase stack provides the [Supavisor](https://supabase.github.io/supavisor/development/docs/) connection pooler for accessing Postgres and managing database connections.
You can connect to the Postgres database via Supavisor using the methods described below. Use your domain name, your server IP, or `localhost` depending on whether you are running self-hosted Supabase on a VPS, or locally.
@@ -281,13 +264,23 @@ If you need to configure Postgres to be directly accessible from the Internet, r
To change the database password, read [Changing database password](#changing-database-password).
### Accessing Edge Functions
## Accessing Edge Functions
Edge Functions are stored in `volumes/functions`. The default setup has a `hello` function that you can invoke on `http://<your-domain>:8000/functions/v1/hello`.
Edge Functions live in `volumes/functions`. The default setup includes a `hello` function you can invoke with `curl`:
You can add new Functions as `volumes/functions/<FUNCTION_NAME>/index.ts`. Restart the `functions` service to pick up the changes: `docker compose restart functions --no-deps`
```sh
curl http://<your-domain>:8000/functions/v1/hello
```
### Accessing the APIs
Add new functions at `volumes/functions/<FUNCTION_NAME>/index.ts`, then restart the service to pick them up:
```sh
docker compose restart functions --no-deps
```
See the [self-hosted Edge Functions guide](/docs/guides/self-hosting/self-hosted-functions) for more details.
## Accessing APIs
Each of the APIs is available through the same API gateway:
@@ -296,9 +289,15 @@ Each of the APIs is available through the same API gateway:
- Storage: `http://<your-domain>:8000/storage/v1/`
- Realtime: `http://<your-domain>:8000/realtime/v1/`
## Configuring HTTPS
By default, Supabase is accessible over HTTP. For production deployments, especially when using OAuth providers, you need HTTPS with a valid TLS certificate. The recommended approach is to place a reverse proxy (such as Caddy or Nginx) in front of Kong.
See the [Configure HTTPS](/docs/guides/self-hosting/self-hosted-proxy-https) guide for detailed setup instructions.
## Updating
We publish stable releases of the Docker Compose setup approximately once a month. To update, apply the latest changes from the repository and restart the services. If you want to run different versions of individual services, you can change the image tags in the Docker Compose file, but compatibility is not guaranteed. All Supabase images are available on [Docker Hub](https://hub.docker.com/u/supabase).
We publish stable releases of the Docker Compose setup approximately once a month. The versions in each release are tested together, so they may lag behind the latest images on Docker Hub. To update, apply the latest changes from the repository and restart the services. If you want to run different versions of individual services, you can change the image tags in the Docker Compose file, but compatibility is **not guaranteed**. All Supabase images are available on [Docker Hub](https://hub.docker.com/u/supabase).
To follow the changes and updates, refer to the self-hosted Supabase [changelog](https://github.com/supabase/supabase/blob/master/docker/CHANGELOG.md).
@@ -320,10 +319,11 @@ You'd like to update or rollback the Studio image. Follow the steps below:
</Admonition>
To uninstall, stop Supabase (while in the same directory as your `docker-compose.yml` file):
To uninstall, stop Supabase (while in the same directory as your `docker-compose.yml` file).
Stop the containers and remove volumes:
```sh
# Stop docker and remove volumes:
docker compose down -v
```
@@ -345,9 +345,10 @@ Everything beyond this point in the guide helps you understand how the system wo
### Architecture
Supabase is a combination of open source tools specifically developed for enterprise-readiness.
Supabase is built from open source tools, each chosen or developed for production use.
If the tools and communities already exist, with an MIT, Apache 2, or equivalent open source license, we will use and support that tool. If the tool doesn't exist, we build and open source it ourselves.
{/* supa-mdx-lint-disable-next-line Rule004ExcludeWords */}
If the tools and communities already exist, with an MIT, Apache 2, PostgreSQL, or equivalent open source license, we will use and support that tool. If the tool doesn't exist, we build and open source it ourselves.
<Image
alt="Diagram showing the architecture of Supabase. The Kong API gateway sits in front of 7 services: GoTrue, PostgREST, Realtime, Storage, pg_meta, Functions, and pg_graphql. All the services talk to a single Postgres instance."
@@ -369,7 +370,6 @@ If the tools and communities already exist, with an MIT, Apache 2, or equivalent
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
- **[imgproxy](https://github.com/imgproxy/imgproxy)** - Fast and secure image processing server
- **[postgres-meta](https://github.com/supabase/postgres-meta)** - RESTful API for managing Postgres (fetch tables, add roles, run queries)
{/* supa-mdx-lint-disable-next-line Rule004ExcludeWords */}
- **[Postgres](https://github.com/supabase/postgres)** - Object-relational database with over 30 years of active development
- **[Edge Runtime](https://github.com/supabase/edge-runtime)** - Web server based on Deno runtime for running JavaScript, TypeScript, and WASM services
- **[Logflare](https://github.com/Logflare/logflare)** - Log management and event analytics platform
@@ -378,9 +378,55 @@ If the tools and communities already exist, with an MIT, Apache 2, or equivalent
Multiple services require specific configuration within the Postgres database. Refer to the documentation describing the [default roles](/docs/guides/database/postgres/roles#supabase-roles) to learn more.
You can find all the default extensions inside the [schema migration scripts repo](https://github.com/supabase/postgres/tree/develop/migrations). These scripts are mounted at `/docker-entrypoint-initdb.d` to run automatically when starting the database container.
You can find all the default extensions inside the [schema migration scripts repo](https://github.com/supabase/postgres/tree/develop/migrations). These scripts are mounted at `/docker-entrypoint-initdb.d` to run automatically when starting the Postgres container.
### Configuring services
### Setting database password
The `generate-keys.sh` script creates a secure random database password. If you want to use your own, you can change `POSTGRES_PASSWORD` in the `.env` file **before** starting Supabase for the first time.
Follow the [password guidelines](/docs/guides/database/postgres/roles#passwords) for choosing a secure password. For easier configuration, **use only letters and numbers** to avoid URL encoding issues in connection strings.
### Changing database password
To change the database password after the initial setup, run:
```sh
sh utils/db-passwd.sh
```
The script generates a new password, updates all database roles, and modifies your `.env` file. After running it, restart the services with `docker compose up -d --force-recreate`.
### Configuring legacy API keys
Use the key generator below to obtain and configure the following secure keys in `.env`:
- `JWT_SECRET`: Used by Auth, PostgREST, and other services to sign and verify JWTs.
- `ANON_KEY`: Client-side API key with limited permissions (`anon` role). Use this in your frontend applications.
- `SERVICE_ROLE_KEY`: Server-side API key with full database access (`service_role` role). **Never expose this in client code.**
<JwtGeneratorSimple />
1. Copy the generated value and update `JWT_SECRET` in the `.env` file. Do not share this secret publicly or commit it to version control.
2. Copy the generated value and update `ANON_KEY` in the `.env` file.
3. Copy the generated value and update `SERVICE_ROLE_KEY` in the `.env` file.
The generated keys expire in 5 years. You can verify them at [jwt.io](https://jwt.io) using the saved value of `JWT_SECRET`.
### Configuring secrets
The `generate-keys.sh` script sets the following secrets automatically. You can also configure them manually in the `.env` file if needed:
- `SECRET_KEY_BASE`: encryption key for securing Realtime and Supavisor communications. (Must be at least 64 characters; generate with `openssl rand -base64 48`)
- `VAULT_ENC_KEY`: encryption key used by Supavisor for storing encrypted configuration. (Must be exactly 32 characters; generate with `openssl rand -hex 16`)
- `PG_META_CRYPTO_KEY`: encryption key for securing connection strings used by Studio against postgres-meta. (Must be at least 32 characters; generate with `openssl rand -base64 24`)
- `LOGFLARE_PUBLIC_ACCESS_TOKEN`: API token for log ingestion and querying. Used by Vector and Studio to send and query logs. (Must be at least 32 characters; generate with `openssl rand -base64 24`)
- `LOGFLARE_PRIVATE_ACCESS_TOKEN`: API token for Logflare management operations. Used by Studio for administrative tasks. Never expose client-side. (Must be at least 32 characters; generate with `openssl rand -base64 24`)
- `S3_PROTOCOL_ACCESS_KEY_ID`: Access key ID (username-like) for [accessing](/docs/guides/self-hosting/self-hosted-s3) the S3 protocol endpoint in Storage. (Generate with `openssl rand -hex 16`)
- `S3_PROTOCOL_ACCESS_KEY_SECRET`: Secret key (password-like) used with S3_PROTOCOL_ACCESS_KEY_ID. (Generate with `openssl rand -hex 32`)
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
- `MINIO_ROOT_PASSWORD`: Root administrator password for the [MinIO server](/docs/guides/self-hosting/self-hosted-s3#using-minio). (Must be 8+ characters; generate with `openssl rand -hex 16`)
### Configuring Supabase services
Each service has a number of configuration options you can find in the related documentation.
@@ -396,22 +442,26 @@ services:
PGRST_JWT_SECRET: ${JWT_SECRET}
```
```bash name=.env
```sh name=.env
## Never check your secrets into version control
JWT_SECRET=${JWT_SECRET}
```
</$CodeTabs>
### Common configuration tasks
### Configuring social login (OAuth) providers
You can configure each Supabase service separately through environment variables and configuration files. Below are the most common configuration options.
See the [Configure Social Login (OAuth) Providers](/docs/guides/self-hosting/self-hosted-oauth) guide for setup instructions.
#### Configuring an email server
### Configuring phone login, SMS, and MFA
See the [Configure Phone Login & MFA](/docs/guides/self-hosting/self-hosted-phone-mfa) guide for SMS provider setup, OTP settings, and multi-factor authentication configuration.
### Configuring an email server
You will need to use a production-ready SMTP server for sending emails. You can configure the SMTP server by updating the following environment variables in the `.env` file:
```sh .env
```sh name=.env
SMTP_ADMIN_EMAIL=
SMTP_HOST=
SMTP_PORT=
@@ -422,35 +472,17 @@ SMTP_SENDER_NAME=
We recommend using [AWS SES](https://aws.amazon.com/ses/). It's affordable and reliable. Restart all services to pick up the new configuration.
#### Configuring S3 Storage
### Configuring S3 Storage
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
By default all files are stored locally on the server. You can connect Storage to an S3-compatible backend (AWS S3, MinIO, Cloudflare R2), enable the S3 protocol endpoint for tools like `rclone`, or both. These are independent features.
By default, all files are stored locally on the server. You can connect Storage to an S3-compatible backend (AWS S3, RustFS, MinIO, Cloudflare R2), enable the S3 protocol endpoint for tools like `rclone`, or both. These are independent features.
See the [Configure S3 Storage](/docs/guides/self-hosting/self-hosted-s3) guide for detailed setup instructions.
#### Configuring HTTPS
By default, Supabase is accessible over HTTP. For production deployments, especially when using OAuth providers, you need HTTPS with a valid TLS certificate. The recommended approach is to place a reverse proxy (such as Caddy or Nginx) in front of Kong.
See the [Configure HTTPS](/docs/guides/self-hosting/self-hosted-proxy-https) guide for setup instructions.
#### Configuring social login (OAuth) providers
See the [Configure Social Login (OAuth) Providers](/docs/guides/self-hosting/self-hosted-oauth) guide for setup instructions.
#### Configuring phone login, SMS, and MFA
See the [Configure Phone Login & MFA](/docs/guides/self-hosting/self-hosted-phone-mfa) guide for SMS provider setup, OTP settings, and multi-factor authentication configuration.
#### Configuring Supabase AI Assistant
### Configuring Supabase AI Assistant
Configuring the Supabase AI Assistant is optional. By adding **your own** `OPENAI_API_KEY` to `.env` you can enable AI services, which help with writing SQL queries, statements, and policies.
#### Setting log_min_messages in Postgres
By default, the database's `log_min_messages` configuration is set to `fatal` in [docker-compose.yml](https://github.com/supabase/supabase/blob/df8729a82b1847e2989c14ede27965612761d503/docker/docker-compose.yml#L466) to prevent redundant logs generated by Realtime. You can configure `log_min_messages` using any of the Postgres [Severity Levels](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-SEVERITY-LEVELS).
#### Accessing Postgres through Supavisor
### Accessing Postgres through Supavisor
By default, Postgres connections go through the Supavisor connection pooler for efficient connection management. Two ports are available:
@@ -459,7 +491,7 @@ By default, Postgres connections go through the Supavisor connection pooler for
For more information on configuring and using Supavisor, see the [Supavisor documentation](https://supabase.github.io/supavisor/).
#### Exposing your Postgres database
### Exposing your Postgres database
By default, Postgres is only accessible through Supavisor. If you need direct access to the database (bypassing the connection pooler), you need to disable Supavisor and expose the Postgres port.
@@ -474,7 +506,7 @@ Edit `docker-compose.yml`:
1. **Disable Supavisor** - Comment out or remove the entire `supavisor` service section
2. **Expose Postgres port** - Add the port mapping to the `db` service, it should look like the example below:
```yaml docker-compose.yml
```yaml name=docker-compose.yml
db:
ports:
- ${POSTGRES_PORT}:${POSTGRES_PORT}
@@ -487,23 +519,18 @@ After restarting, you can connect to the database directly using a standard Post
postgres://postgres:[POSTGRES_PASSWORD]@[your-server-ip]:5432/[POSTGRES_DB]
```
### Changing database password
### Setting log_min_messages in Postgres
To change the database password after initial setup, run:
By default, the database's `log_min_messages` configuration is set to `fatal` in [docker-compose.yml](https://github.com/supabase/supabase/blob/df8729a82b1847e2989c14ede27965612761d503/docker/docker-compose.yml#L466) to prevent redundant logs generated by Realtime. You can configure `log_min_messages` using any of the Postgres [Severity Levels](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-SEVERITY-LEVELS).
```sh
sh ./utils/db-passwd.sh
```
### Using file backend in Storage on macOS
The script generates a new password, updates all database roles, and modifies your `.env` file. After running it, restart the services with `docker compose up -d --force-recreate`.
#### File storage backend on macOS
By default, Storage backend is set to `file`, which is to use local files as the storage backend. If using Docker Desktop on a Mac, choose `VirtioFS` as the Docker container file sharing implementation (in **Preferences** > **General**).
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
By default, the Storage backend uses local files via a bind mount. On macOS, Docker Desktop bind mounts have known limitations (missing xattr support, permission issues) that can prevent Storage from working correctly. Change the [bind mount](https://github.com/supabase/supabase/blob/a5f4a59e0e262394b345600e8d8a2241d6ac3b64/docker/docker-compose.yml#L391) to a named Docker volume instead.
## Managing your secrets
Many components inside Supabase use secure secrets and passwords. These are kept in the `.env` file, but we strongly recommend using a secrets manager when deploying to production.
Many components inside Supabase rely on secrets and passwords being kept securely. By default, all secrets are in the `.env` file, but we strongly recommend using a secrets manager when deploying to production.
Some suggested systems include:
@@ -27,7 +27,7 @@ When connecting via an SSH tunnel to the Studio Docker container, the source IP
Determine the Docker bridge gateway IP on the host running your Supabase containers:
```bash
```sh
docker inspect supabase-kong \
--format '{{range .NetworkSettings.Networks}}{{println .Gateway}}{{end}}'
```
@@ -43,7 +43,7 @@ Add the IP address you discovered to the Kong configuration by editing the follo
3. Add your local IP to the 'allow' list.
4. Your edited configuration should look like the example below.
```yaml
```yaml name=volumes/api/kong.yml
## MCP endpoint - local access
- name: mcp
_comment: 'MCP: /mcp -> http://studio:3000/api/mcp (local access)'
@@ -79,7 +79,7 @@ Add the IP address you discovered to the Kong configuration by editing the follo
After you've added the local IP address as above, restart the Kong container:
```bash
```sh
docker compose restart kong
```
@@ -87,7 +87,7 @@ docker compose restart kong
From your local machine, create an SSH tunnel to your Supabase host:
```bash
```sh
ssh -L localhost:8080:localhost:8000 you@your-supabase-host
```
@@ -111,7 +111,7 @@ Edit the settings for your MCP client and add the following to `"mcpServers": {}
From your local machine, check that the MCP server is reachable:
```bash
```sh
curl http://localhost:8080/mcp \
-X POST \
-H "Content-Type: application/json" \
@@ -12,7 +12,7 @@ Self-hosted Supabase ships with Postgres 15 by default. This guide covers two sc
## Before you begin
- Complete the [Self-Hosting with Docker](/docs/guides/self-hosting/docker) setup
- Your current database image should be `supabase/postgres:15.x` (check with `docker inspect supabase-db --format '{{.Config.Image}}'`)
- Your current database image should be `supabase/postgres:15.x`
## New deployment with Postgres 17
@@ -24,7 +24,7 @@ docker compose -f docker-compose.yml -f docker-compose.pg17.yml up -d
This uses the `docker-compose.pg17.yml` override file which swaps the database image:
```yaml
```yaml name=docker-compose.pg17.yml
services:
db:
image: supabase/postgres:17.6.1.084
@@ -32,11 +32,11 @@ services:
<Admonition type="tip">
Always include both compose files when running commands. If you omit the override, Docker Compose falls back to the Postgres 15 image defined in `docker-compose.yml`.
If you use the override file, remember to include both compose files when running commands. Alternatively, you can update the image tag directly in `docker-compose.yml` instead of using an override.
</Admonition>
The rest of the setup is the same as the standard Docker guide. All init scripts (`roles.sql`, `jwt.sql`, `webhooks.sql`, etc.) are compatible with Postgres 17.
The rest of the setup is the same as for Postgres 15 (see the Docker install [guide](/docs/guides/self-hosting/docker)).
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
If the new Postgres 17 container fails to start, make sure to check for an old `db-config` Docker volume. See [Postgres 17 fails to start with a leftover db-config volume](#postgres-17-fails-to-start-with-a-leftover-db-config-volume) for details.
@@ -136,7 +136,9 @@ docker compose -f docker-compose.yml -f docker-compose.pg17.yml exec db psql -U
The original Postgres 15 data is preserved at `./volumes/db/data.bak.pg15`. The pgsodium root key is saved as `./volumes/db/pgsodium_root.key.bak.pg15`. The upgrade binaries tarball is cached at `./volumes/db/pg17_upgrade_bin_*.tar.gz`. Once you have verified that everything works, you can reclaim disk space:
```sh
rm -rf ./volumes/db/data.bak.pg15 ./volumes/db/pgsodium_root.key.bak.pg15 ./volumes/db/pg17_upgrade_bin_*.tar.gz
rm -rf ./volumes/db/data.bak.pg15 \
./volumes/db/pgsodium_root.key.bak.pg15 \
./volumes/db/pg17_upgrade_bin_*.tar.gz
```
<Admonition type="caution">
@@ -274,7 +276,7 @@ If you run out of space mid-upgrade, the safest path is to roll back and free up
### Postgres 17 fails to start with a leftover db-config volume
If you are starting a **fresh** Postgres 17 deployment (not upgrading from Postgres 15) and the container fails to start, the most likely cause is a leftover `db-config` volume from a previous Postgres 15 installation. Try to start the containers without the `-d` option and/or check the logs for errors about `postgresql.conf` or other configuration mismatch.
If you are starting a **fresh** Postgres 17 deployment (not using the upgrade script) and the container fails to start, the most likely cause is a leftover `db-config` volume from a previous Postgres 15 installation. Start the containers without the `-d` option or check the logs for errors about `postgresql.conf` or other configuration mismatch.
To fix, remove the old volume and let Postgres 17 initialize a clean configuration:
@@ -4,7 +4,7 @@ description: 'Restore your database from the Supabase platform to a self-hosted
subtitle: 'Restore your database from the Supabase platform to a self-hosted instance.'
---
This guide walks you through restoring your database from a Supabase platform project to a [self-hosted Docker instance](/docs/guides/self-hosting/docker). Storage objects transfer or redeploying edge functions is not covered here.
This guide walks you through restoring your database from a Supabase platform project to a [self-hosted Docker instance](/docs/guides/self-hosting/docker). Transferring storage objects or redeploying edge functions is not covered here.
## Before you begin
@@ -24,15 +24,15 @@ On your managed Supabase project dashboard, click [**Connect**](/dashboard/proje
Export roles, schema, and data as three separate SQL files:
```bash
```sh
supabase db dump --db-url "[CONNECTION_STRING]" -f roles.sql --role-only
```
```bash
```sh
supabase db dump --db-url "[CONNECTION_STRING]" -f schema.sql
```
```bash
```sh
supabase db dump --db-url "[CONNECTION_STRING]" -f data.sql --use-copy --data-only
```
@@ -64,7 +64,7 @@ Use your domain name, your server IP, or localhost for `[your-domain]` depending
Run `psql` to restore:
```bash
```sh
psql \
--single-transaction \
--variable ON_ERROR_STOP=1 \
@@ -81,7 +81,7 @@ Setting `session_replication_role` to `replica` disables triggers during the dat
Connect to your self-hosted database and run a few checks:
```bash
```sh
psql "postgres://postgres.your-tenant-id:[POSTGRES_PASSWORD]@[your-domain]:5432/postgres"
```
@@ -119,7 +119,13 @@ Your `auth.users` table and related data are included in the database dump, so u
## Postgres version compatibility
Managed Supabase may run a newer Postgres version (Postgres 17) than the self-hosted Docker image (currently Postgres 15). The `supabase db dump` command produces plain SQL files that work across major Postgres versions.
Managed Supabase may run a newer Postgres version (Postgres 17) than the self-hosted Docker image (currently it's Postgres 15 by default). The `supabase db dump` command produces plain SQL files that work across major Postgres versions.
<Admonition type="tip">
If your managed project runs Postgres 17, consider starting your self-hosted deployment with Postgres 17 as well. See the [Postgres 17 guide](/docs/guides/self-hosting/postgres-upgrade-17) for setup instructions.
</Admonition>
Keep in mind:
@@ -141,7 +147,7 @@ The platform may run a newer Postgres version (17 vs 15) and newer Auth service
**Workaround:** Edit `data.sql` before restoring:
```bash
```sh
# Comment out PG17-only transaction_timeout
sed -i 's/^SET transaction_timeout/-- &/' data.sql
```
@@ -8,8 +8,10 @@ You can configure self-hosted Supabase to use the [new API keys](/docs/guides/ap
## Before you begin
- Complete the [Docker setup guide](/docs/guides/self-hosting/docker), including running `generate-keys.sh` so that `JWT_SECRET`, `ANON_KEY`, and `SERVICE_ROLE_KEY` are set in your `.env` file.
- Ensure `openssl` and `node` version 16 or newer are available on the machine where you will generate new keys.
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
- Ensure OpenSSL and Node.js 16+ are available on the machine where you will generate new keys
- Complete the [Docker setup guide](/docs/guides/self-hosting/docker), including running `generate-keys.sh` so that `JWT_SECRET`, `ANON_KEY`, and `SERVICE_ROLE_KEY` are set in your `.env` file
- If you are upgrading an existing self-hosted Supabase environment, make sure to check the [changelog](https://github.com/supabase/supabase/blob/master/docker/CHANGELOG.md) and add/update the following files:
- `.env.example` (merge new sections into your `.env` file)
- `docker-compose.yml`
@@ -36,7 +38,7 @@ The script reads `JWT_SECRET` from `.env` and includes it as a symmetric key ins
After updating `.env`, enable new authentication by uncommenting these lines in `docker-compose.yml`:
```yaml
```yaml name=docker-compose.yml
auth:
environment:
# JSON array of signing JWKs (EC private + legacy symmetric)
@@ -55,7 +57,13 @@ storage:
PostgREST does not need uncommenting - it already uses `PGRST_JWT_SECRET: ${JWT_JWKS:-${JWT_SECRET}}` which automatically picks up `JWT_JWKS` when set.
Then restart all services:
<Admonition type="caution">
Podman does not support nested variable interpolation (`${A:-${B}}`). If you are using Podman, replace each nested expression with the required variable directly - see the inline comments in `docker-compose.yml` for the exact substitutions.
</Admonition>
Restart all services:
```sh
docker compose down && docker compose up -d
@@ -74,14 +82,14 @@ sb_secret_<22-char-random>_<8-char-checksum>
Test with the new publishable key:
```
```sh
curl http://<your-domain>/rest/v1/ \
-H "apikey: your-supabase-publishable-key"
```
You should receive a valid response from PostgREST. Then verify that the legacy key still works:
```
```sh
curl http://<your-domain>/rest/v1/ \
-H "apikey: your-anon-key"
```
@@ -90,7 +98,7 @@ Both should work and return the same result.
You can also verify the public JWKS endpoint:
```
```sh
curl http://<your-domain>/auth/v1/.well-known/jwks.json
```
@@ -119,10 +127,8 @@ New variables default to empty values in `.env.example`. When empty, the API gat
The new authentication configuration is fully backward compatible:
- **All new variables are optional.** If left with empty values, the API gateway (Kong) and all services behave exactly as before.
- **Kong accepts both key types simultaneously.** You can migrate clients incrementally - some using legacy API keys, others using the new ones.
- **JWKS includes the symmetric key.** `JWT_JWKS` contains both the EC public key (for verifying new ES256 tokens) and the legacy `JWT_SECRET` as a symmetric JWK (for verifying old HS256 tokens). Services that receive `JWT_JWKS` can verify both token types.
- **Services fall back gracefully.** PostgREST uses `${JWT_JWKS:-${JWT_SECRET}}` - if `JWT_JWKS` is empty, it uses `JWT_SECRET` directly.
- **No database changes required.** The asymmetric key system operates entirely at the API gateway and service configuration layer.
<Admonition type="caution">
@@ -190,7 +196,7 @@ For **Realtime WebSocket** connections, the API key is sent as a `?apikey=` quer
Kong is configured with two consumers that each accept both the legacy and new API keys:
```yaml
```yaml name=volumes/api/kong.yml
consumers:
- username: anon
keyauth_credentials:
@@ -16,8 +16,8 @@ On managed Supabase platform, Edge Functions are deployed across multiple region
The default `hello` function is located at `volumes/functions/hello/index.ts`. You can invoke it immediately after starting your stack:
```bash
curl http://<your-domain>:8000/functions/v1/hello
```sh
curl http://<your-domain>/functions/v1/hello
```
This returns `"Hello from Edge Functions!"`.
@@ -26,12 +26,12 @@ This returns `"Hello from Edge Functions!"`.
### Step 1: Add a new function directory and the function code
```
```sh
mkdir -p volumes/functions/my-function &&
touch volumes/functions/my-function/index.ts
```
add the following code to `index.ts`:
Add the following code to `index.ts`:
```typescript
Deno.serve(async (req: Request) => {
@@ -46,22 +46,22 @@ Deno.serve(async (req: Request) => {
### Step 2: Restart the functions service to pick up the new function
```bash
```sh
docker compose restart functions --no-deps
```
### Step 3: Invoke your function
```bash
curl -X POST http://<your-domain>:8000/functions/v1/my-function \
```sh
curl -X POST http://<your-domain>/functions/v1/my-function \
-H 'Content-Type: application/json' \
-d '{"name": "World"}'
```
You should be able to see the response from `my-function`:
```
{"message":"Hello, World!"}
```json
{ "message": "Hello, World!" }
```
## Custom environment variables
@@ -70,13 +70,13 @@ You should be able to see the response from `my-function`:
For multiple variables or secrets, create a separate env file, e.g., `.env.functions` in your `docker/` directory:
```bash
```
MY_CUSTOM_VAR=some-value
```
Add `env_file` to the `functions` service in `docker-compose.yml` (variables in `env_file` load first, then `environment` values take precedence):
```yaml
```yaml name=docker-compose.yml
functions:
env_file:
- .env.functions
@@ -93,7 +93,7 @@ Don't commit `.env.functions` to version control if it contains secrets. Add it
Restart the functions service:
```bash
```sh
docker compose up -d --force-recreate --no-deps functions
```
@@ -101,7 +101,7 @@ docker compose up -d --force-recreate --no-deps functions
For one or two variables, you can add them directly under `environment` in `docker-compose.yml`:
```yaml
```yaml name=docker-compose.yml
functions:
environment:
# Custom variables
@@ -115,7 +115,7 @@ Then define `MY_CUSTOM_VAR` in your main `.env` file, or specify the value direc
### Accessing variables in functions
All container environment variables are forwarded to function workers by `main/index.ts`. Access them with:
All container environment variables are forwarded to the function workers by `main/index.ts`. Access them with:
```typescript
const customVar = Deno.env.get('MY_CUSTOM_VAR')
@@ -125,14 +125,16 @@ const customVar = Deno.env.get('MY_CUSTOM_VAR')
The functions service is pre-configured with the following environment variables:
| Variable | Value | Purpose |
| --------------------------- | --------------------------- | ------------------------------------------------------------------- |
| `SUPABASE_URL` | `http://kong:8000` | Internal API gateway URL |
| `SUPABASE_PUBLIC_URL` | `http://<your-domain>:8000` | Base URL for accessing Supabase from the Internet |
| `JWT_SECRET` | Your secret key | Legacy symmetric encryption key used to sign and verify JWTs |
| `SUPABASE_ANON_KEY` | Your anon key | Client-side API key with limited permissions (`anon` role). |
| `SUPABASE_SERVICE_ROLE_KEY` | Your service role key | Server-side API key with full database access (`service_role` role) |
| `SUPABASE_DB_URL` | Postgres connection string | Can be used for direct database access |
| Variable | Value | Purpose |
| --------------------------- | --------------------------------- | ------------------------------------------------- |
| `SUPABASE_URL` | `http://kong:8000` | Internal API gateway URL |
| `SUPABASE_PUBLIC_URL` | `http(s)://<your-domain>` | Base URL for accessing Supabase from the Internet |
| `JWT_SECRET` | `your-jwt-secret` | Legacy symmetric encryption key for JWTs |
| `SUPABASE_ANON_KEY` | `your-anon-key` | Client-side API key (`anon` role). |
| `SUPABASE_SERVICE_ROLE_KEY` | `your-service-role-key` | Server-side API key (`service_role` role) |
| `SUPABASE_DB_URL` | `postgresql://...` | Postgres connection string |
| `SUPABASE_PUBLISHABLE_KEYS` | `{"default":"sb_publishable_...}` | New publishable API key |
| `SUPABASE_SECRET_KEYS` | `{"default":"sb_secret_...}` | New secret API key |
Here's an example function that queries a table using `@supabase/supabase-js`:
@@ -159,7 +161,7 @@ This is a key distinction that affects how you build URLs in your functions:
- **`SUPABASE_URL`** contains an internal Docker network hostname. Use it for server-side calls from your functions to other Supabase services (Auth, Storage, database via PostgREST). This is what the Supabase JS client should use inside functions.
- **`SUPABASE_PUBLIC_URL`** is the externally-reachable URL of your Supabase instance (e.g., `<your-domain>:8000`). Use it if your function needs to build URLs that HTTP clients can reach from the outside.
- **`SUPABASE_PUBLIC_URL`** is the externally-reachable URL of your Supabase instance. Use it if your function needs to build URLs that HTTP clients can reach from the outside.
## Managing functions via dashboard
@@ -169,13 +171,13 @@ Self-hosted Studio [mounts](https://github.com/supabase/supabase/blob/df8729a82b
To deploy a function to a remote server running self-hosted Supabase, copy the function directory with `scp`:
```bash
```sh
scp -r ./my-function user@<your-domain>:/path/to/self-hosted/volumes/functions/
```
Then restart the functions service on the remote host:
```bash
```sh
ssh user@<your-domain> 'cd /path/to/self-hosted && docker compose restart functions --no-deps'
```
@@ -203,7 +205,7 @@ The request URL must include the function name after `/functions/v1/`. For examp
Check the functions service logs:
```bash
```sh
docker compose logs functions
```
@@ -218,7 +220,7 @@ Common causes: syntax errors in your function code, invalid imports, or missing
Restart the functions service:
```bash
```sh
docker compose restart functions --no-deps
```
@@ -230,7 +232,7 @@ docker compose restart functions --no-deps
Use the following command to recreate the container, not just `restart`:
```bash
```sh
docker compose up -d --force-recreate --no-deps functions
```
@@ -15,11 +15,11 @@ You need:
<Admonition type="danger">
HTTPS is strongly recommended in production. Most OAuth providers reject `http://` callback URLs (except `localhost`).
HTTPS is required by most OAuth providers - `http://` callback URLs are rejected (except `localhost`). See the HTTPS [how-to guide](/docs/guides/self-hosting/self-hosted-proxy-https) for setup instructions.
</Admonition>
Your **OAuth callback URL** is built from `API_EXTERNAL_URL`. For example, if `API_EXTERNAL_URL` is `https://<your-domain>`, the callback URL will become:
Your **OAuth callback URL** should look like the following:
```
https://<your-domain>/auth/v1/callback
@@ -60,7 +60,7 @@ The default `.env.example` and `docker-compose.yml` include commented-out placeh
Uncomment the lines for your provider in `.env` and add your client ID and secret, e.g., for Google:
```
```sh
GOOGLE_ENABLED=true
GOOGLE_CLIENT_ID=your-client-id
GOOGLE_SECRET=your-client-secret
@@ -72,7 +72,7 @@ GOOGLE_SECRET=your-client-secret
Uncomment the corresponding `GOTRUE_EXTERNAL_` lines in the `auth` service's `environment`:
```yaml
```yaml name=docker-compose.yml
auth:
environment:
# ... existing variables ...
@@ -104,7 +104,7 @@ curl -H 'apikey: your-anon-key' https://<your-domain>/auth/v1/settings
The response should include your provider under `external`:
```
```json
{
"external": {
"google": true
@@ -136,17 +136,13 @@ The response should include your provider under `external`:
9. Under **Authorized redirect URIs**, add: `https://<your-domain>/auth/v1/callback`
10. Click **Create** and copy the client ID and client secret
**`.env`:**
```
```sh name=.env
GOOGLE_ENABLED=true
GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
GOOGLE_SECRET=your-google-client-secret
```
**`docker-compose.yml`:**
```yaml
```yaml name=docker-compose.yml
auth:
environment:
# ... existing variables ...
@@ -169,17 +165,13 @@ auth:
5. Click **Register application**
6. Copy the client ID, generate and copy a client secret
**`.env`:**
```
```sh name=.env
GITHUB_ENABLED=true
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_SECRET=your-github-client-secret
```
**`docker-compose.yml`:**
```yaml
```yaml name=docker-compose.yml
auth:
environment:
# ... existing variables ...
@@ -206,9 +198,7 @@ auth:
9. Click on **New client secret** and add a client secret
10. Copy the secret value (not "secret ID")
**`.env`:**
```
```sh name=.env
AZURE_ENABLED=true
AZURE_CLIENT_ID=your-azure-application-client-id
AZURE_SECRET=your-azure-client-secret
@@ -216,9 +206,7 @@ AZURE_SECRET=your-azure-client-secret
# AZURE_URL=https://login.microsoftonline.com/your-tenant-id
```
**`docker-compose.yml`:**
```yaml
```yaml name=docker-compose.yml
auth:
environment:
# ... existing variables ...
@@ -240,17 +228,13 @@ auth:
2. Create a private key for sign in with Apple
3. Generate a client secret JWT from your private key. See [Apple Developer documentation](https://developer.apple.com/documentation/accountorganizationaldatasharing/creating-a-client-secret) for details.
**`.env`:**
```
```sh name=.env
APPLE_ENABLED=true
APPLE_CLIENT_ID=com.example.your-services-id
APPLE_SECRET=your-generated-jwt-client-secret
```
**`docker-compose.yml`:**
```yaml
```yaml name=docker-compose.yml
auth:
environment:
# ... existing variables ...
@@ -281,9 +265,7 @@ Apple uses `response_mode=form_post` for its OAuth flow. The Auth service handle
7. Under **Valid redirect URIs**, add: `https://<your-domain>/auth/v1/callback`
8. Save, then go to the **Credentials** tab and copy the **Client secret**
**`.env` variables:**
```
```sh name=.env
KEYCLOAK_ENABLED=true
KEYCLOAK_CLIENT_ID=supabase
KEYCLOAK_SECRET=your-keycloak-client-secret
@@ -291,9 +273,7 @@ KEYCLOAK_SECRET=your-keycloak-client-secret
KEYCLOAK_URL=https://keycloak.example.com/realms/myrealm
```
**`docker-compose.yml` passthrough:**
```yaml
```yaml name=docker-compose.yml
auth:
environment:
# ... existing variables ...
@@ -411,8 +391,11 @@ For detailed client-side integration, see [Social Login](/docs/guides/auth/socia
Configuration variables from `.env` are **not** automatically available inside the container unless there's a matching passthrough definition in `docker-compose.yml`. Check, e.g., for:
```
GOTRUE_EXTERNAL_GOOGLE_ENABLED: ${GOOGLE_ENABLED}
```yaml name=docker-compose.yml
auth:
environment:
# ... existing variables ...
GOTRUE_EXTERNAL_GOOGLE_ENABLED: ${GOOGLE_ENABLED}
```
Run `docker compose exec auth env | grep GOTRUE_EXTERNAL` to verify the variables are reaching the container.
@@ -442,8 +425,11 @@ When using Google Sign In on mobile with ID tokens, nonce verification may fail
To enable it, uncomment the following line in `docker-compose.yml`:
```
GOTRUE_EXTERNAL_SKIP_NONCE_CHECK: true
```yaml name=docker-compose.yml
auth:
environment:
# ... existing variables ...
GOTRUE_EXTERNAL_SKIP_NONCE_CHECK: 'true'
```
### Auth service fails to start
@@ -25,7 +25,9 @@ To enable SMS delivery:
### Step 1: Uncomment and configure the environment variables
```
Edit the `.env` file as follows:
```sh name=.env
SMS_PROVIDER=twilio
SMS_OTP_EXP=60
SMS_OTP_LENGTH=6
@@ -44,7 +46,7 @@ SMS_TWILIO_MESSAGE_SERVICE_SID=your-message-service-sid
Uncomment the `GOTRUE_SMS_*` lines in the `auth` service's `environment` block:
```yaml
```yaml name=docker-compose.yml
auth:
environment:
# ... existing variables ...
@@ -90,7 +92,7 @@ The default OTP expiration is **60 seconds**. This is often too short for produc
Set `SMS_OTP_EXP` in `.env` (value is in seconds):
```
```sh name=.env
# Set expiration to 5 minutes
SMS_OTP_EXP=300
```
@@ -101,7 +103,7 @@ And ensure `GOTRUE_SMS_OTP_EXP: ${SMS_OTP_EXP}` is uncommented in `docker-compos
The default OTP length is 6 digits. You can set it to any value between 6 and 10:
```
```sh name=.env
SMS_OTP_LENGTH=8
```
@@ -109,7 +111,7 @@ SMS_OTP_LENGTH=8
`SMS_MAX_FREQUENCY` controls the minimum interval between SMS sends to the same phone number. The default is 60 seconds:
```
```sh name=.env
## Allow one SMS every 30 seconds
SMS_MAX_FREQUENCY=30s
```
@@ -118,11 +120,11 @@ SMS_MAX_FREQUENCY=30s
To avoid sending real SMS during development, use `SMS_TEST_OTP` to map phone numbers to fixed OTP codes:
```
```sh name=.env
SMS_TEST_OTP=16505551234:123456,16505555678:654321
```
And uncomment `GOTRUE_SMS_TEST_OTP: ${SMS_TEST_OTP}` in `docker-compose.yml`.
Make sure to also uncomment `GOTRUE_SMS_TEST_OTP: ${SMS_TEST_OTP}` in `docker-compose.yml`.
When a test phone number requests an OTP, the Auth service skips SMS delivery and accepts only the mapped code. Other phone numbers continue to use the real SMS provider.
@@ -142,7 +144,7 @@ TOTP is **enabled by default** - users can enroll with apps like Google Authenti
To disable TOTP:
```
```sh name=.env
MFA_TOTP_ENROLL_ENABLED=false
MFA_TOTP_VERIFY_ENABLED=false
```
@@ -153,7 +155,7 @@ Phone MFA is **disabled by default** (opt-in). It uses the same SMS provider con
To enable:
```
```sh name=.env
MFA_PHONE_ENROLL_ENABLED=true
MFA_PHONE_VERIFY_ENABLED=true
```
@@ -162,7 +164,7 @@ MFA_PHONE_VERIFY_ENABLED=true
By default, a user can enroll up to 10 MFA factors. To change this:
```
```sh name=.env
MFA_MAX_ENROLLED_FACTORS=5
```
@@ -172,7 +174,7 @@ MFA_MAX_ENROLLED_FACTORS=5
The default `SMS_OTP_EXP` is 60 seconds. Increase it in `.env`:
```
```sh name=.env
SMS_OTP_EXP=300
```
@@ -10,9 +10,9 @@ HTTPS is required for production self-hosted Supabase deployments. This guide co
You need:
- A working self-hosted Supabase installation. See [Self-Hosting with Docker](/docs/guides/self-hosting/docker).
- A domain name with DNS pointing to your server's public IP address (to obtain Let's Encrypt certificate).
- Ports 80 and 443 open.
- A working self-hosted Supabase installation. See [Self-Hosting with Docker](/docs/guides/self-hosting/docker)
- A domain name with DNS pointing to your server's public IP address (to obtain Let's Encrypt certificate)
- Ports 80 and 443 open
## Set up HTTPS
@@ -24,10 +24,10 @@ If you already run [HAProxy](https://www.haproxy.com/), [Traefik](https://traefi
- Proxy to Kong on port `8000` (or `<your-ip>:8000` if the proxy runs outside the Docker network)
- Enable WebSocket support (required for Realtime)
- Proxy traffic to Storage directly to the container, bypassing Kong
- Add `X-Forwarded` headers to all requests
- Comment out Kong's host port bindings in `docker-compose.yml` if the proxy runs in the same Docker network
- Update `SUPABASE_PUBLIC_URL`, `API_EXTERNAL_URL`, and `SITE_URL` in `.env` to your HTTPS URL
- See `volumes/proxy` for example proxy configuration files
</Admonition>
@@ -35,15 +35,15 @@ If you already run [HAProxy](https://www.haproxy.com/), [Traefik](https://traefi
Update the URL configuration in your `.env` file to use your HTTPS domain:
```
```sh name=.env
SUPABASE_PUBLIC_URL=https://<your-domain>
API_EXTERNAL_URL=https://<your-domain>
SITE_URL=https://<your-domain>
```
Change the following to your domain name and a **valid** email address:
For Nginx, change the following to your domain name and a **valid** email address:
```
```sh name=.env
PROXY_DOMAIN=your-domain.example.com
CERTBOT_EMAIL=admin@your-domain.example.com
```
@@ -73,7 +73,7 @@ Caddy configuration is in `volumes/proxy/caddy/Caddyfile`.
</TabPanel>
<TabPanel id="nginx" label="Nginx + Let's Encrypt">
This option uses a 3rd party Nginx Docker image ([`jonasal/nginx-certbot`](https://github.com/JonasAlfredsson/docker-nginx-certbot)), which includes Certbot for automatic Let's Encrypt certificate issuance and renewal in a single container.
This option uses a third-party Nginx Docker image ([`jonasal/nginx-certbot`](https://github.com/JonasAlfredsson/docker-nginx-certbot)), which includes Certbot for automatic Let's Encrypt certificate issuance and renewal in a single container.
Start Nginx by using the pre-configured `docker-compose.nginx.yml` overlay:
@@ -90,11 +90,17 @@ HTTP-to-HTTPS redirects are handled automatically by the `jonasal/nginx-certbot`
### Step 3: Verify HTTPS connection
Test the HTTPS connection - you should get a `401` response confirming you could connect to Auth:
```sh
curl -I https://<your-domain>/auth/v1/
```
You should receive a `401` response confirming you could connect to Auth.
Check container logs if needed (use `supabase-nginx` for Nginx):
```sh
docker logs supabase-caddy
```
## Self-signed certificates (development only)
@@ -125,7 +131,7 @@ openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
Comment out Kong's **HTTP** port mapping in `docker-compose.yml`:
```yaml
```yaml name=docker-compose.yml
kong:
# ...
ports:
@@ -134,7 +140,7 @@ kong:
Uncomment the certificate volume mounts and SSL environment variables in `docker-compose.yml`:
```yaml
```yaml name=docker-compose.yml
kong:
# ... existing configuration ...
volumes:
@@ -151,7 +157,7 @@ kong:
Edit your `.env` file to use HTTPS with the Kong HTTPS port:
```
```sh name=.env
SUPABASE_PUBLIC_URL=https://<your-domain>:8443
API_EXTERNAL_URL=https://<your-domain>:8443
SITE_URL=https://<your-domain>:8443
@@ -17,9 +17,9 @@ You can configure either feature independently. For example, you can enable the
The S3 protocol endpoint at `/storage/v1/s3` allows standard S3 clients to interact with your self-hosted Storage instance. It works with any storage backend, including the default file-based storage - you do not need to configure an S3 backend first. The Supabase REST API and SDK do not use the S3 protocol.
Make sure to check that `REGION`, `S3_PROTOCOL_ACCESS_KEY_ID` and `S3_PROTOCOL_ACCESS_KEY_SECRET` are properly configured in you `.env` file. Read more about the secrets and passwords in [Configuring and securing Supabase](/docs/guides/self-hosting/docker#configuring-and-securing-supabase).
Make sure to check that `REGION`, `S3_PROTOCOL_ACCESS_KEY_ID` and `S3_PROTOCOL_ACCESS_KEY_SECRET` are properly configured in your `.env` file. Read more about the secrets and passwords in [Configuring and securing Supabase](/docs/guides/self-hosting/docker#configuring-and-securing-supabase).
```yaml
```yaml name=docker-compose.yml
storage:
environment:
# ... existing variables ...
@@ -30,7 +30,7 @@ storage:
### Test with the AWS CLI
```bash
```sh
( set -a && \
source .env > /dev/null 2>&1 && \
echo "" && \
@@ -46,7 +46,7 @@ s3://your-storage-bucket )
### Test with rclone
```bash
```sh
( set -a && \
source .env > /dev/null 2>&1 && \
echo "" && \
@@ -65,7 +65,7 @@ Use `aws login` and `rclone config` for persistent configuration.
In general, the following configuration variables define S3 backend configuration for Storage in `docker-compose.yml`:
```yaml
```yaml name=docker-compose.yml
storage:
environment:
# ... existing variables ...
@@ -80,17 +80,38 @@ storage:
```
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
Depending on your setup, you may need to adjust these values - for example, to use a local S3-compatible service like MinIO or a cloud provider like AWS.
Depending on your setup, you may need to adjust these values - for example, to use a local S3-compatible service like RustFS, MinIO or a cloud provider like AWS.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
### Using RustFS
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
An overlay `docker-compose.rustfs.yml` configuration can be added to enable RustFS container and provide an S3-compatible API for Storage backend:
```sh
docker compose -f docker-compose.yml -f docker-compose.rustfs.yml up -d
```
Make sure to review the Storage section in your `.env` file for related configuration options.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
### Using MinIO
<Admonition type="note">
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
MinIO no longer publishes open source Docker images or maintains their open source repository. The MinIO configuration is provided for backward compatibility and uses images built by [Chainguard](https://images.chainguard.dev/directory/image/minio/overview) (`cgr.dev/chainguard/minio`). For new deployments, consider using [RustFS](#using-rustfs) instead.
</Admonition>
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
An overlay `docker-compose.s3.yml` configuration can be added to enable MinIO container and provide an S3-compatible API for Storage backend:
```bash
```sh
docker compose -f docker-compose.yml -f docker-compose.s3.yml up -d
```
@@ -100,7 +121,7 @@ Make sure to review the Storage section in your `.env` file for related configur
Create an S3 bucket and an IAM user with access to it. Then configure the storage service:
```yaml docker-compose.yml
```yaml name=docker-compose.yml
storage:
environment:
# ... existing variables ...
@@ -118,7 +139,7 @@ For AWS S3, you do not need `GLOBAL_S3_ENDPOINT` or `GLOBAL_S3_FORCE_PATH_STYLE`
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
Use the same configuration as MinIO, but point to your provider's endpoint, e.g.:
```yaml
```yaml name=docker-compose.yml
storage:
environment:
# ... existing variables ...
@@ -174,6 +195,8 @@ const client = new S3Client({
S3 clients sign requests using the access key ID and secret. If you see `SignatureDoesNotMatch`, verify that the `REGION`, `S3_PROTOCOL_ACCESS_KEY_ID` and `S3_PROTOCOL_ACCESS_KEY_SECRET` in your `.env` file match what your S3 client is using.
**If you use a custom reverse proxy**: with the [new API keys and auth](/docs/guides/self-hosting/self-hosted-auth-keys) configuration, requests to Storage should be forwarded to the API gateway (Kong) for proper handling. If you are still using legacy API keys and proxy directly to Storage, make sure your proxy sets the `X-Forwarded-Prefix` header to `/storage/v1` so that signed URLs are generated correctly. In both cases, `STORAGE_PUBLIC_URL` must be [set properly](https://github.com/supabase/supabase/blob/a5f4a59e0e262394b345600e8d8a2241d6ac3b64/docker/docker-compose.yml#L369) in `docker-compose.yml`.
### TUS upload errors on Cloudflare R2
If resumable (TUS) uploads fail with HTTP 500 and a message about `x-amz-tagging`, add `TUS_ALLOW_S3_TAGS: "false"` to the storage service environment. Cloudflare R2 does not implement this S3 feature.
@@ -75,7 +75,7 @@ For a production deployment, consider using a 4096-bit key by adding `-pkeyopt r
Add the following to your `.env` file:
```sh
```sh name=.env
############
# SAML SSO
############
@@ -101,7 +101,7 @@ SAML_PRIVATE_KEY=<your-base64-encoded-private-key>
In `docker-compose.yml`, add the SAML environment variables to the `auth` service. Auth expects the `GOTRUE_` prefix for all of its configuration variables:
```yaml
```yaml name=docker-compose.yml
auth:
environment:
# ... existing variables ...
@@ -20,7 +20,7 @@ message = "invalid claim: missing sub"
The missing sub claim error is returned when `supabase.auth.getUser()` is called with an invalid JWT in the session or when the user attempts to register/sign in but hasn't completed the sign in when the `getUser` call is made.
A common pitfall, is inadvertently using a Supabase API key (such as the anon or service_role keys) instead of the Supabase Auth access token.
A common pitfall, is inadvertently using a Supabase API key (such as the publishable or secret keys) instead of the Supabase Auth access token.
**Why Does This Happen?**
@@ -53,4 +53,4 @@ supabase.rpc("get_my_complex_query", { parameter: 1 })
**Further Resources:**
For more information on Postgres database functions, refer to the following resource:
[Supabase Stored Procedures](/docs/guides/database/functions#quick-demo)
[Supabase Functions](/docs/guides/database/functions#quick-demo)
@@ -49,7 +49,7 @@ If you created a custom schema, you will have to give the Database API permissio
If you see an error like `permission denied for table your_table`, the querying role may not have the required privilege for the operation.
By default, tables in the `public` schema are granted `SELECT`, `INSERT`, `UPDATE`, and `DELETE` to the `anon` and `authenticated` roles. However, these privileges can be adjusted via the [Dashboard Table Editor](/dashboard/project/_/editor) or via SQL.
By default, tables in the `public` schema are granted `SELECT`, `INSERT`, `UPDATE`, and `DELETE` to the `anon` and `authenticated` roles. However, you can change these privileges in the [**Integrations > Data API**](/dashboard/project/_/integrations/data_api/settings) section of the Dashboard or via SQL.
To check the current privileges on a table:
@@ -75,7 +75,7 @@ grant select, insert, update, delete on table public.your_table to anon, authent
Granting privileges allows access to your table through the Data API, so you should ensure you [enable RLS](/docs/guides/database/postgres/row-level-security) and write appropriate policies to protect your data.
For more information, see [Adjusting table-level privileges](/docs/guides/api/hardening-data-api#adjusting-table-level-privileges).
For more information, see [Data API](/docs/guides/database/data-api).
</Admonition>
@@ -0,0 +1,9 @@
---
title = "'Disk size not shrinking after deleting data'"
topics = [ "database", "storage" ]
keywords = []
---
If you've deleted a significant amount of data (e.g., by dropping large tables), you may observe that your project's disk size does not automatically shrink. This is expected behavior as Postgres reclaims freed space for internal reuse but does not return it to the operating system. Furthermore, cloud storage volumes (such as AWS EBS) do not support in-place shrinking, which means the disk size cannot be directly reduced via the dashboard UI.
To reclaim disk space and reduce your project's disk allocation, you will need to initiate a Postgres version upgrade. This process provisions a new instance with a smaller disk attached, migrates your data, and involves brief downtime during the upgrade and switchover. You can start this process from the [Supabase Dashboard](/dashboard/project/_/settings/database).
@@ -14,7 +14,7 @@ This guide is for identifying configuration mistakes in [self-hosted Supabase Gr
Use the below cURL command to make sure your metrics endpoint returns data:
```sh
curl https://<YOUR_PROJECT_REF>.supabase.co/customer/v1/privileged/metrics --user 'service_role:<SECRET_API_KEY>'
curl https://<YOUR_PROJECT_REF>.supabase.co/customer/v1/privileged/metrics --user 'user:<SECRET_API_KEY>'
```
## Step 2: Set your Grafana Dashboard to auto-refresh in the top right corner
@@ -58,7 +58,7 @@ docker exec -it <container id> bash
Run the following in the docker container:
```sh
printenv | egrep 'GRAFANA_PASSWORD|SUPABASE_PROJECT_REF|SUPABASE_SERVICE_ROLE_KEY'
printenv | egrep 'GRAFANA_PASSWORD|SUPABASE_PROJECT_REF|SUPABASE_SECRET_KEY'
```
Ensure the values are correct by comparing them with those in the Dashboard. Users have previously encountered issues by accidentally omitting the last character of their strings, so a thorough check is essential.
@@ -79,7 +79,7 @@ def psycop_call(): #user_ids: list[str]):
def supabase_call():
supabase: Client = create_client("SUPABASE_URL", "SUPBASE_SERVICE_ROLE_KEY")
supabase: Client = create_client("SUPABASE_URL", "SUPABASE_SECRET_KEY")
start = time.time()
result = supabase.table("your_table_name").select("*").execute()
stop = time.time()
@@ -9,7 +9,7 @@ database_id = "74972531-f2fc-4d68-a745-21f9c75761e6"
Make a `GET` request to the health check endpoint to retrieve this information. Below is an example using `curl`:
```
curl -X GET 'https://project-ref.supabase.co/auth/v1/health' -H 'apikey: ANON_KEY'
curl -X GET 'https://project-ref.supabase.co/auth/v1/health' -H 'apikey: PUBLISHABLE_KEY'
{
"version": "v2.60.7",
@@ -1,22 +1,22 @@
---
title = "Performing administration tasks on the server side with the service_role secret"
title = "Performing administration tasks on the server side with a secret key"
github_url = "https://github.com/orgs/supabase/discussions/15860"
date_created = "2023-07-18T12:25:03+00:00"
topics = [ "auth", "platform" ]
keywords = [ "service_role", "server", "security" ]
keywords = [ "secret-key", "server", "security" ]
database_id = "0d3389c0-5e75-473c-a18b-0699d0911fb2"
---
By default, the auth-helpers/ssr do not permit the use of the `service_role` `secret`. This restriction is in place to prevent the accidental exposure of your `service_role` `secret` to the public. Since the auth-helpers/ssr function on both the server and client side, it becomes challenging to separate the key specifically for client-side usage.
By default, server side rendering (SSR) does not permit the use of a `secret` key. This restriction is in place to prevent the accidental exposure of your `secret` key to the public. Since SSR runs on both the server and client side, it becomes challenging to separate the key specifically for client-side usage.
However, there is a solution. You can create a separate Supabase client using the `createClient` method from `@supabase/supabase-js` and provide it with the `service_role` `secret`. In a server environment, you will also need to disable certain properties to ensure proper functionality. See the example code below for the required settings.
However, there is a solution. You can create a separate Supabase client using the `createClient` method from `@supabase/supabase-js` and provide it with the `secret` key. In a server environment, you will also need to disable certain properties to ensure proper functionality. See the example code below for the required settings.
By implementing this approach, you can safely utilize the `service_role` `secret` without compromising security or exposing sensitive information to the public.
By implementing this approach, you can safely utilize the `secret` key without compromising security or exposing sensitive information to the public.
```ts
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(supabaseUrl, serviceRoleSecret, {
const supabase = createClient(supabaseUrl, secretKey, {
auth: {
persistSession: false,
autoRefreshToken: false,
@@ -0,0 +1,74 @@
---
title = "Resolving 'cannot execute UPDATE in a read-only transaction' on transaction pooler connections"
topics = [ "database", "supavisor" ]
keywords = []
---
### Key technical terms
**Transaction Pooling**
A connection management method used by tools like Supavisor or PgBouncer. Instead of giving every client a dedicated, permanent connection to the database, the pooler maintains a small set of "backend connections." It lends one of these connections to a client for the duration of a single transaction, then immediately takes it back to give to another client.
**Backend Connection**
The actual physical process on the Postgres server that executes your queries. In pooling environments, one backend connection will serve many different database clients over its lifetime.
**Session-Level State**
That backend connection has _state_. Postgres connections carry settings like timezone, memory limits, search path, read-only mode etc. In a normal setup where each client has its own connection, this doesn't matter. When the client disconnects, the connection and all its state go away. In a pooled environment, the connection doesn't go away. It goes back into the pool, settings and all, and the next client who gets it inherits whatever was left behind.
---
### Understanding the problem: The "sticky" state
When you encounter the error `cannot execute UPDATE in a read-only transaction` while using a transaction pooler (typically on port 6543), even when you have verified that the connection is made to the primary database and the database itself is not in read-only mode (check with `SHOW default_transaction_read_only;` or `SELECT pg_is_in_recovery();` using a direct connection on port 5432), it signifies that a backend connection has been unintentionally locked into a read-only state.
**Note:** If your database is in read-only mode (for example, due to exceeding disk space limits), you can review this guide: [Database Size and Read-Only Mode](/docs/guides/platform/database-size#read-only-mode). The remainder of this guide addresses a different issue specific to transaction pooling.
#### The cause: Connection contamination
In transaction pooling mode, reset behavior is intentionally limited for performance, so session state can persist unless explicitly reset. If a client, script, or automated task changes a session-level setting, that setting "sticks" to the backend connection.
When that backend connection is returned to the pool, the next client to use it inherits that exact state. If a previous script set the connection to "read-only" for safety and failed to reset it, any subsequent application attempt to perform an `UPDATE` or `INSERT` using that same backend will fail.
#### Why is the error sporadic?
The error appears intermittent because it only occurs when your application is randomly assigned a "contaminated" backend connection from the pool. Other connections in the same pool may still be in the default read-write state, leading to a confusing mix of successful and failed requests.
---
### Step-by-step resolution
To resolve this issue, you must identify and remove any commands that modify the session state globally rather than locally.
#### 1. Audit application and scripts
Search your application code, migration scripts, and maintenance tasks for the following session-level commands:
- `SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY;`
- `SET default_transaction_read_only = on;`
Even if these commands are used in secondary scripts (like data exports or safety-first maintenance tasks) and not the main application, they can still contaminate the pool used by the main application.
#### 2. Implement "safe" settings
If you need to execute a read-only transaction for safety, use transaction-level commands that only affect the current transaction and do not persist on the backend connection.
- **Avoid:** `SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY;` or `SET default_transaction_read_only = on;` (these contaminate the connection pool)
- **Use:** `BEGIN TRANSACTION READ ONLY;` or `BEGIN; SET TRANSACTION READ ONLY;` (these only affect the current transaction)
If you have existing scripts that use session-level settings and cannot be immediately refactored:
- **Temporary workaround:** Ensure they explicitly reset the state before closing the connection with `SET default_transaction_read_only = off;`
- **Best approach:** Connect directly to port 5432 (bypassing the pooler) for scripts requiring special session states
#### 3. Connection string verification
Ensure your application is using the intended pooler.
- **Shared Transaction Pooler (Supavisor):** `postgresql://postgres.PROJECT_REF:[YOUR-PASSWORD]@aws-X-REGION.pooler.supabase.com:6543/postgres`
- **Dedicated Transaction Pooler (PgBouncer):** `postgresql://postgres:[YOUR-PASSWORD]@db.PROJECT_REF.supabase.co:6543/postgres`
---
### Best practices for transaction pooling
- **Use Dedicated Connections for Maintenance:** If a script requires a specific session state (like a long-running read-only export), connect directly to the database (port 5432) rather than using the transaction pooler (port 6543). This prevents maintenance settings from leaking into the application's connection pool.%
@@ -17,7 +17,7 @@ See the last section for ways to measure the performance of your queries as you
### Is RLS causing performance issues (on a single table query)?
For very slow queries, or if using the tools at end of article, run a query with RLS enabled on the table and then with it disabled (this should only be done in a non production environment). If the results are similar then your query itself is likely the performance issue. Although, remember any join tables in RLS will also need to run their RLS unless a security definer function is used to bypass them. You can also create a service_role client to run the query bypassing RLS if in a secure environment.
For very slow queries, or if using the tools at end of article, run a query with RLS enabled on the table and then with it disabled (this should only be done in a non production environment). If the results are similar then your query itself is likely the performance issue. Although, remember any join tables in RLS will also need to run their RLS unless a security definer function is used to bypass them. You can also create a client using a secret key to run the query bypassing RLS if in a secure environment.
### How to improve RLS performance.
@@ -0,0 +1,134 @@
---
title = "Identifying Dashboard SQL Editor Activity by User"
topics = [ "database" ]
keywords = []
---
When team members run SQL queries from the Dashboard SQL Editor, and if that query is logged in the Postgres Logs, it's not immediately clear who executed which query. This guide shows you how to track queries back to the specific team member who ran them.
### **Understanding Dashboard query execution**
First, it helps to understand how Dashboard queries are executed. When someone runs a query from the SQL editor, it's routed through the `postgres` role at the database level. The Supabase Dashboard automatically appends metadata comments to queries, specifically `-- user: [UUID]`, `-- source: dashboard`, and `-- date`.
By default, that role has `log_statement` set to `ddl`, which means Postgres logs only schema-level changes such as `CREATE`, `ALTER`, and `DROP`. It does not log data-modifying statements such as `INSERT`, `UPDATE`, `DELETE` or `TRUNCATE`.
So, if someone truncates a table, and you're relying on the default logging, you won't see it.
### **Enabling data modification logging**
To make those operations visible, you can increase the logging level for the `postgres` role:
```sql
ALTER ROLE postgres SET log_statement='mod';
```
**Note:** This step is only necessary if you need to track data-modifying statements like `INSERT`, `UPDATE`, `DELETE`, or `TRUNCATE`. If you're only looking to track DDL statements (such as `CREATE`, `ALTER`, `DROP`), the default `log_statement='ddl'` setting is already sufficient.
Setting it to `mod` tells Postgres to log all data-modifying statements. Once that's in place, try running something like a `TRUNCATE` from the Dashboard. In the logs, you'll see an entry similar to:
```
statement: TRUNCATE TABLE public.data;
-- source: dashboard
-- user: f8c2e1a9-3b4d-4f7e-8c9a-1d2e3f4a5b6c
-- date: 2026-04-02T11:41:22.158Z
```
Notice that the log includes:
- The full statement
- The timestamp
- A `user` field, which is actually the Supabase user UUID
- The source (dashboard)
That UUID corresponds to the team member who logged in via the Supabase Dashboard and executed queries in the [SQL Editor](/dashboard/project/_/sql/new). But at this point, it's just an ID - not yet a name or email.
### **Mapping UUIDs to team members**
To map the UUID, you'll need to query the Management API. The process looks like this:
**1. Create a Personal Access Token (PAT)**
Generate a token from your [account settings](/dashboard/account/tokens).
**2. Call the Organization Members Endpoint**
```bash
curl -X GET "https://api.supabase.com/v1/organizations/your-org-slug/members" \
-H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN"
```
**3. Match the UUID**
The response will include entries like:
```json
{
"user_id": "f8c2e1a9-3b4d-4f7e-8c9a-1d2e3f4a5b6c",
"user_name": "john@supabase.io",
"email": "john@supabase.io",
"role_name": "Administrator"
}
```
Now you can directly match `user_id` values from the Postgres logs to the corresponding team members.
### **Querying logs for specific operations**
Navigate to the [Logs Explorer](/dashboard/project/_/logs/explorer) and query `postgres_logs`. Here's an example query that searches for data-modifying operations and maps user IDs to team members:
```sql
SELECT
DATETIME(postgres_logs.timestamp) AS time,
parsed.session_id,
postgres_logs.identifier,
parsed.user_name AS db_role,
CASE
WHEN REGEXP_CONTAINS(postgres_logs.event_message, 'f8c2e1a9-3b4d-4f7e-8c9a-1d2e3f4a5b6c')
THEN 'john@example.com'
WHEN REGEXP_CONTAINS(postgres_logs.event_message, 'insert another-uuid-here')
THEN 'jane@example.io'
ELSE 'unknown'
END AS detected_user,
parsed.error_severity,
postgres_logs.event_message
FROM postgres_logs
CROSS JOIN UNNEST(metadata) AS metadata
CROSS JOIN UNNEST(parsed) AS parsed
WHERE postgres_logs.timestamp > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
AND (
REGEXP_CONTAINS(postgres_logs.event_message, '(?i)DELETE|TRUNCATE|UPDATE|ALTER|DROP')
OR REGEXP_CONTAINS(parsed.query, '(?i)DELETE|TRUNCATE|UPDATE|ALTER|DROP')
)
ORDER BY postgres_logs.timestamp DESC
LIMIT 500;
```
This query:
- Searches the last 7 days of logs
- Filters for common data-modifying operations (`DELETE`, `TRUNCATE`, `UPDATE`, `ALTER`, `DROP`)
- Uses a `CASE` statement to map known UUIDs to team member emails
- Returns results ordered by timestamp (most recent first)
**Example Output:**
| db_role | detected_user | error_severity | event_message | identifier |
| -------- | ------------- | -------------- | -------------------------------------------------------------------------------- | ---------- |
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
| postgres | support | LOG | statement: TRUNCATE TABLE public.data; -- source: dashboard -- user: f8c2e1a9... | ... |
You can further refine your search by filtering for specific commands like `TRUNCATE` or `DELETE` where `parsed.user_name = 'postgres'`.
### **Tracking external tools**
For external tools like n8n or other applications connecting to your database, you can identify the source of database changes by appending `?application_name=example_app_name` to your connection string. This ensures the source is clearly identified in the logs, making it easier to distinguish between Dashboard operations and external tool operations.
### **Additional logging levels**
Postgres supports these `log_statement` values:
- `none`: No statements are logged
- `ddl`: Log data definition statements (`CREATE`, `ALTER`, `DROP`) - this is the default for the `postgres` role
- `mod`: Log data modification statements plus all DDL (includes `INSERT`, `UPDATE`, `DELETE`, `TRUNCATE`)
- `all`: Log all statements (including `SELECT` queries)
**Note:** Setting to `all` can generate very large log volumes. Use it only when necessary and for limited periods. Test the performance impact of `log_statement='mod'` in your specific environment, as the impact depends on your query volume and workload.
@@ -0,0 +1,17 @@
---
title = "`Unexpected behavior with 'auth.updateUser({ phone })': Phone linked to incorrect user ID`"
topics = [ "auth" ]
keywords = []
---
When using `auth.updateUser({ phone: '...' })`, you might observe that a phone number is unexpectedly linked to a different `auth.users` record than the currently authenticated user during the phone verification process, even if `auth.getUser()` reports the correct user ID beforehand.
**Why does this happen?**
Supabase phone verification identifies the user by searching for the provided phone number in the `phone_change` column, rather than relying solely on the active session. Unlike the `phone` column, the `phone_change` column does not enforce uniqueness. If multiple `auth.users` records contain the same phone number in `phone_change` due to uncompleted or abandoned verification attempts, the system may update an unintended user's `phone` field upon successful OTP verification. This occurs because the system finds and updates the first matching record in `phone_change`, which might not belong to the currently authenticated user.
**How to prevent/resolve this:**
To prevent ambiguous lookups from abandoned verification attempts, implement application-level cleanup to remove stale `phone_change` values from your `auth.users` records.
1. **Define a grace period:** Establish a reasonable time frame after which an unconfirmed phone verification attempt is considered stale.
2. **Identify stale records:** Periodically query `auth.users` to find accounts where `phone_verified` is `false` and the `phone_change` value has been present beyond your defined grace period.
3. **Clear `phone_change`:** For identified stale records, clear their `phone_change` value. This ensures that only active and unique `phone_change` entries are considered during verification.
@@ -0,0 +1,25 @@
---
title = "Vercel Integration: Environment variables explained"
topics = [ "platform" ]
keywords = []
---
Vercel has three environments, which map to different stages of the deployment lifecycle:
- **Production** is used for the branch configured as the production branch (usually main). Deployments from that branch go to the live site.
- **Preview** is used for all other Git branches, including pull requests, feature branches, and persistent branches like staging. If you deploy a staging branch, it still runs under the Preview environment unless you explicitly create a separate environment in Vercel and map that branch to it.
- **Development** is only used for local development via the Vercel CLI (`vercel dev`). It allows your local environment to pull env vars from Vercel, but it does not apply to Git branches or deployments on the platform.
### Creating a staging environment
On the Hobby plan, staging is implemented by scoping Preview environment variables to a branch. On the Pro plan, staging can be configured as a dedicated environment with its own settings.
You can create a dedicated environment (Vercel Pro):
1. Go to `Project` → `Settings` → `Environments`
2. Click `Create Environment`
3. Name it `staging`
4. Enable `Branch Tracking` and select the `staging` branch
5. Add environment variables scoped to this environment
With this setup, the staging branch deploys to its own environment and is fully separate from Preview and Production.
@@ -7,7 +7,14 @@ keywords = [ "rls", "service_role", "authorization", "session", "apikey" ]
database_id = "677f0a69-e454-4718-ad92-91053d40c085"
---
A Supabase client with the Authorization header set to the service role API key will ALWAYS bypass RLS. By default the Authorization header is the `apikey` used in `createClient`. If you are getting an RLS error then you have a user session getting into the client or you initialized with the anon key. RLS in enforced based on the `Authorization` header and not the `apikey` header.
<Admonition type="deprecation">
This troubleshooting guide is about rotating **Legacy anon, service_role API keys**. We are deprecating the Legacy API keys, and recommend migrating to New API keys. To learn more about API
keys, refer to [the API documentation](/docs/guides/api/api-keys).
</Admonition>
A Supabase client with the Authorization header set to the service role API key will ALWAYS bypass RLS. By default the Authorization header is the `apikey` used in `createClient`. If you are getting an RLS error then you have a user session getting into the client or you initialized with the publishable key. RLS in enforced based on the `Authorization` header and not the `apikey` header.
Three common cases of the `createClient` `apikey` being replaced by a user session/token:
+33
View File
@@ -33,3 +33,36 @@ custom_edit_url: https://github.com/supabase/supabase/edit/master/web/spec/supab
</RefSubLayout.Examples>
</RefSubLayout.EducationRow>
### Enable Data API access
<RefSubLayout.EducationRow>
<RefSubLayout.Details>
supabase-csharp uses the Data API to query and mutate your Postgres data. You first need to grant Data API roles permissions to access your tables and functions.
In the [**Integrations > Data API**](/dashboard/project/_/integrations/data_api/settings) section of the Dashboard, expose the specific tables and functions you want to access. To automatically grant access for new tables and functions in `public`, enable **Default privileges for new entities**.
Alternatively, use SQL to grant the required permissions:
</RefSubLayout.Details>
<RefSubLayout.Examples>
```sql
-- Before granting access to client roles, make sure RLS is enabled
-- and create the policies required for each role's allowed operations.
alter table public.your_table enable row level security;
-- create policy ... on public.your_table ...;
-- Grant least-privilege access to tables after RLS and policies are in place
grant select on public.your_table to anon;
grant select, insert, update, delete on public.your_table to authenticated;
grant all on public.your_table to service_role;
-- Grant execute on functions after verifying any table access they rely on
grant execute on function public.your_function to authenticated, service_role;
```
</RefSubLayout.Examples>
</RefSubLayout.EducationRow>
+33
View File
@@ -40,3 +40,36 @@ custom_edit_url: https://github.com/supabase/supabase/edit/master/web/spec/supab
</RefSubLayout.Examples>
</RefSubLayout.EducationRow>
### Enable Data API access
<RefSubLayout.EducationRow>
<RefSubLayout.Details>
supabase_flutter uses the Data API to query and mutate your Postgres data. You first need to grant Data API roles permissions to access your tables and functions.
In [Data API integrations settings](/dashboard/project/_/integrations/data_api/settings), expose the specific tables and functions you want to access. To automatically grant access for new tables and functions in `public`, enable **Default privileges for new entities**.
Alternatively, use SQL to grant the required permissions:
</RefSubLayout.Details>
<RefSubLayout.Examples>
```sql
-- Before granting access to client roles, make sure RLS is enabled
-- and create the policies required for each role's allowed operations.
alter table public.your_table enable row level security;
-- create policy ... on public.your_table ...;
-- Grant least-privilege access to tables after RLS and policies are in place
grant select on public.your_table to anon;
grant select, insert, update, delete on public.your_table to authenticated;
grant all on public.your_table to service_role;
-- Grant execute on functions after verifying any table access they rely on
grant execute on function public.your_function to authenticated, service_role;
```
</RefSubLayout.Examples>
</RefSubLayout.EducationRow>
@@ -85,3 +85,36 @@ custom_edit_url: https://github.com/supabase/supabase/edit/master/web/spec/supab
</RefSubLayout.Examples>
</RefSubLayout.EducationRow>
### Enable Data API access
<RefSubLayout.EducationRow>
<RefSubLayout.Details>
supabase-js uses the Data API to query and mutate your Postgres data. You first need to grant Data API roles permissions to access your tables and functions.
In [Data API integrations settings](/dashboard/project/_/integrations/data_api/settings), expose the specific tables and functions you want to access. To automatically grant access for new tables and functions in `public`, enable **Default privileges for new entities**.
Alternatively, use SQL to grant the required permissions:
</RefSubLayout.Details>
<RefSubLayout.Examples>
```sql
-- Before granting access to client roles, make sure RLS is enabled
-- and create the policies required for each role's allowed operations.
alter table public.your_table enable row level security;
-- create policy ... on public.your_table ...;
-- Grant least-privilege access to tables after RLS and policies are in place
grant select on public.your_table to anon;
grant select, insert, update, delete on public.your_table to authenticated;
grant all on public.your_table to service_role;
-- Grant execute on functions after verifying any table access they rely on
grant execute on function public.your_function to authenticated, service_role;
```
</RefSubLayout.Examples>
</RefSubLayout.EducationRow>
+34
View File
@@ -397,3 +397,37 @@ By default, [KotlinX Serialization](https://github.com/Kotlin/kotlinx.serializat
</RefSubLayout.Examples>
</RefSubLayout.EducationRow>
### Enable Data API access
<RefSubLayout.EducationRow>
<RefSubLayout.Details>
supabase-kt uses the Data API to query and mutate your Postgres data. You first need to grant Data API roles permissions to access your tables and functions.
In [Data API integrations settings](/dashboard/project/_/integrations/data_api/settings), expose the specific tables and functions you want to access. To automatically grant access for new tables and functions in `public`, enable **Default privileges for new entities**.
Alternatively, use SQL to grant the required permissions:
</RefSubLayout.Details>
<RefSubLayout.Examples>
```sql
-- Before granting access to client roles, make sure RLS is enabled
-- and create the policies required for each role's allowed operations.
alter table public.your_table enable row level security;
-- create policy ... on public.your_table ...;
-- Grant least-privilege access to tables after RLS and policies are in place
grant select on public.your_table to anon;
grant select, insert, update, delete on public.your_table to authenticated;
grant all on public.your_table to service_role;
-- Grant execute on functions after verifying any table access they rely on
grant execute on function public.your_function to authenticated, service_role;
```
</RefSubLayout.Examples>
</RefSubLayout.EducationRow>
+33
View File
@@ -40,3 +40,36 @@ custom_edit_url: https://github.com/supabase/supabase/edit/master/apps/docs/spec
</RefSubLayout.Examples>
</RefSubLayout.EducationRow>
### Enable Data API access
<RefSubLayout.EducationRow>
<RefSubLayout.Details>
supabase-py uses the Data API to query and mutate your Postgres data. You first need to grant Data API roles permissions to access your tables and functions.
In [Data API integrations settings](/dashboard/project/_/integrations/data_api/settings), expose the specific tables and functions you want to access. To automatically grant access for new tables and functions in `public`, enable **Default privileges for new entities**.
Alternatively, use SQL to grant the required permissions:
</RefSubLayout.Details>
<RefSubLayout.Examples>
```sql
-- Before granting access to client roles, make sure RLS is enabled
-- and create the policies required for each role's allowed operations.
alter table public.your_table enable row level security;
-- create policy ... on public.your_table ...;
-- Grant least-privilege access to tables after RLS and policies are in place
grant select on public.your_table to anon;
grant select, insert, update, delete on public.your_table to authenticated;
grant all on public.your_table to service_role;
-- Grant execute on functions after verifying any table access they rely on
grant execute on function public.your_function to authenticated, service_role;
```
</RefSubLayout.Examples>
</RefSubLayout.EducationRow>
+33
View File
@@ -65,3 +65,36 @@ custom_edit_url: https://github.com/supabase/supabase/edit/master/web/spec/supab
</RefSubLayout.Examples>
</RefSubLayout.EducationRow>
### Enable Data API access
<RefSubLayout.EducationRow>
<RefSubLayout.Details>
supabase-swift uses the Data API to query and mutate your Postgres data. You first need to grant Data API roles permissions to access your tables and functions.
In [Data API integrations settings](/dashboard/project/_/integrations/data_api/settings), expose the specific tables and functions you want to access. To automatically grant access for new tables and functions in `public`, enable **Default privileges for new entities**.
Alternatively, use SQL to grant the required permissions:
</RefSubLayout.Details>
<RefSubLayout.Examples>
```sql
-- Before granting access to client roles, make sure RLS is enabled
-- and create the policies required for each role's allowed operations.
alter table public.your_table enable row level security;
-- create policy ... on public.your_table ...;
-- Grant least-privilege access to tables after RLS and policies are in place
grant select on public.your_table to anon;
grant select, insert, update, delete on public.your_table to authenticated;
grant all on public.your_table to service_role;
-- Grant execute on functions after verifying any table access they rely on
grant execute on function public.your_function to authenticated, service_role;
```
</RefSubLayout.Examples>
</RefSubLayout.EducationRow>
@@ -1536,8 +1536,13 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"shortText": "Creates an admin API client that can be used to manage users and OAuth clients.",
"examples": [
{
"id": "example-1",
"name": "Example 1",
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'secret-or-service-role-key')\\nconst { data, error } = await supabase.auth.admin.listUsers()\\n\`\`\`"
},
{
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`ts\\nimport { GoTrueAdminApi } from '@supabase/auth-js'\\n\\nconst admin = new GoTrueAdminApi({\\n url: 'https://xyzcompany.supabase.co/auth/v1',\\n headers: { Authorization: \`Bearer \${process.env.SUPABASE_SERVICE_ROLE_KEY}\` },\\n})\\n\`\`\`"
}
]
@@ -10302,9 +10307,14 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"shortText": "Create a new client for use in the browser.",
"examples": [
{
"id": "example-1",
"name": "Example 1",
"code": "\`\`\`ts\\nimport { GoTrueClient } from '@supabase/auth-js'\\n\\nconst auth = new GoTrueClient({\\n url: 'https://xyzcompany.supabase.co/auth/v1',\\n headers: { apikey: 'public-anon-key' },\\n storageKey: 'supabase-auth',\\n})\\n\`\`\`"
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\\nconst { data, error } = await supabase.auth.getUser()\\n\`\`\`"
},
{
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`ts\\nimport { GoTrueClient } from '@supabase/auth-js'\\n\\nconst auth = new GoTrueClient({\\n url: 'https://xyzcompany.supabase.co/auth/v1',\\n headers: { apikey: 'publishable-or-anon-key' },\\n storageKey: 'supabase-auth',\\n})\\n\`\`\`"
}
]
}
@@ -40221,14 +40231,14 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"shortText": "Creates a builder configured for a specific PostgREST request.",
"examples": [
{
"id": "example-1",
"name": "Example 1",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst builder = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: new Headers({ apikey: 'public-anon-key' }) }\\n)\\n\`\`\`"
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\\nconst { data, error } = await supabase.from('users').select('*')\\n\`\`\`"
},
{
"id": "creating-a-postgrest-query-builder",
"name": "Creating a Postgrest query builder",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst builder = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: new Headers({ apikey: 'public-anon-key' }) }\\n)\\n\`\`\`"
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst builder = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: new Headers({ apikey: 'publishable-or-anon-key' }) }\\n)\\n\`\`\`"
}
]
}
@@ -40758,14 +40768,14 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"shortText": "Creates a builder configured for a specific PostgREST request.",
"examples": [
{
"id": "example-1",
"name": "Example 1",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst builder = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: new Headers({ apikey: 'public-anon-key' }) }\\n)\\n\`\`\`"
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\\nconst { data, error } = await supabase.from('users').select('*')\\n\`\`\`"
},
{
"id": "creating-a-postgrest-query-builder",
"name": "Creating a Postgrest query builder",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst builder = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: new Headers({ apikey: 'public-anon-key' }) }\\n)\\n\`\`\`"
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst builder = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: new Headers({ apikey: 'publishable-or-anon-key' }) }\\n)\\n\`\`\`"
}
]
}
@@ -43770,9 +43780,14 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"shortText": "Creates a query builder scoped to a Postgres table or view.",
"examples": [
{
"id": "creating-a-postgrest-query-builder",
"name": "Creating a Postgrest query builder",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst query = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: { apikey: 'public-anon-key' }, retry: true }\\n)\\n\`\`\`"
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\\nconst { data, error } = await supabase.from('users').select('*')\\n\`\`\`"
},
{
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst query = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: { apikey: 'publishable-or-anon-key' }, retry: true }\\n)\\n\`\`\`"
}
]
}
@@ -44562,14 +44577,14 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"shortText": "Creates a builder configured for a specific PostgREST request.",
"examples": [
{
"id": "example-1",
"name": "Example 1",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst builder = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: new Headers({ apikey: 'public-anon-key' }) }\\n)\\n\`\`\`"
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\\nconst { data, error } = await supabase.from('users').select('*')\\n\`\`\`"
},
{
"id": "creating-a-postgrest-query-builder",
"name": "Creating a Postgrest query builder",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst builder = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: new Headers({ apikey: 'public-anon-key' }) }\\n)\\n\`\`\`"
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst builder = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: new Headers({ apikey: 'publishable-or-anon-key' }) }\\n)\\n\`\`\`"
}
]
}
@@ -45674,9 +45689,14 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"shortText": "Creates a channel that can broadcast messages, sync presence, and listen to Postgres changes.\\n\\nThe topic determines which realtime stream you are subscribing to. Config options let you\\nenable acknowledgement for broadcasts, presence tracking, or private channels.",
"examples": [
{
"id": "example-for-a-public-channel",
"name": "Example for a public channel",
"code": "\`\`\`ts\\nimport RealtimeClient from '@supabase/realtime-js'\\n\\nconst client = new RealtimeClient('https://xyzcompany.supabase.co/realtime/v1', {\\n params: { apikey: 'public-anon-key' },\\n})\\nconst channel = new RealtimeChannel('realtime:public:messages', { config: {} }, client)\\n\`\`\`"
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\\nconst channel = supabase.channel('room1')\\nchannel\\n .on('broadcast', { event: 'cursor-pos' }, (payload) => console.log(payload))\\n .subscribe()\\n\`\`\`"
},
{
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`ts\\nimport RealtimeClient from '@supabase/realtime-js'\\n\\nconst client = new RealtimeClient('https://xyzcompany.supabase.co/realtime/v1', {\\n params: { apikey: 'publishable-or-anon-key' },\\n})\\nconst channel = new RealtimeChannel('realtime:public:messages', { config: {} }, client)\\n\`\`\`"
}
]
}
@@ -45992,9 +46012,14 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"shortText": "Initializes the Socket.",
"examples": [
{
"id": "example-for-a-public-channel",
"name": "Example for a public channel",
"code": "\`\`\`ts\\nimport RealtimeClient from '@supabase/realtime-js'\\n\\nconst client = new RealtimeClient('https://xyzcompany.supabase.co/realtime/v1', {\\n params: { apikey: 'public-anon-key' },\\n})\\nclient.connect()\\n\`\`\`"
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\\nconst channel = supabase.channel('room1')\\nchannel\\n .on('broadcast', { event: 'cursor-pos' }, (payload) => console.log(payload))\\n .subscribe()\\n\`\`\`"
},
{
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`ts\\nimport RealtimeClient from '@supabase/realtime-js'\\n\\nconst client = new RealtimeClient('https://xyzcompany.supabase.co/realtime/v1', {\\n params: { apikey: 'publishable-or-anon-key' },\\n})\\nclient.connect()\\n\`\`\`"
}
]
}
@@ -49180,7 +49205,7 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
{
"id": "with-a-database-query",
"name": "With a database query",
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key')\\n\\nconst { data } = await supabase.from('profiles').select('*')\\n\`\`\`"
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\\n\\nconst { data } = await supabase.from('profiles').select('*')\\n\`\`\`"
}
]
}
@@ -51390,8 +51415,13 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"shortText": "Creates an admin API client that can be used to manage users and OAuth clients.",
"examples": [
{
"id": "example-1",
"name": "Example 1",
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'secret-or-service-role-key')\\nconst { data, error } = await supabase.auth.admin.listUsers()\\n\`\`\`"
},
{
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`ts\\nimport { GoTrueAdminApi } from '@supabase/auth-js'\\n\\nconst admin = new GoTrueAdminApi({\\n url: 'https://xyzcompany.supabase.co/auth/v1',\\n headers: { Authorization: \`Bearer \${process.env.SUPABASE_SERVICE_ROLE_KEY}\` },\\n})\\n\`\`\`"
}
]
@@ -60153,9 +60183,14 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"shortText": "Create a new client for use in the browser.",
"examples": [
{
"id": "example-1",
"name": "Example 1",
"code": "\`\`\`ts\\nimport { GoTrueClient } from '@supabase/auth-js'\\n\\nconst auth = new GoTrueClient({\\n url: 'https://xyzcompany.supabase.co/auth/v1',\\n headers: { apikey: 'public-anon-key' },\\n storageKey: 'supabase-auth',\\n})\\n\`\`\`"
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\\nconst { data, error } = await supabase.auth.getUser()\\n\`\`\`"
},
{
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`ts\\nimport { GoTrueClient } from '@supabase/auth-js'\\n\\nconst auth = new GoTrueClient({\\n url: 'https://xyzcompany.supabase.co/auth/v1',\\n headers: { apikey: 'publishable-or-anon-key' },\\n storageKey: 'supabase-auth',\\n})\\n\`\`\`"
}
]
}
@@ -86962,14 +86997,14 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"shortText": "Creates a builder configured for a specific PostgREST request.",
"examples": [
{
"id": "example-1",
"name": "Example 1",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst builder = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: new Headers({ apikey: 'public-anon-key' }) }\\n)\\n\`\`\`"
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\\nconst { data, error } = await supabase.from('users').select('*')\\n\`\`\`"
},
{
"id": "creating-a-postgrest-query-builder",
"name": "Creating a Postgrest query builder",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst builder = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: new Headers({ apikey: 'public-anon-key' }) }\\n)\\n\`\`\`"
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst builder = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: new Headers({ apikey: 'publishable-or-anon-key' }) }\\n)\\n\`\`\`"
}
]
}
@@ -87362,19 +87397,14 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"text": "- A \`timeout\` option (in milliseconds) can be set to automatically abort requests that take too long.\\n- A \`urlLengthLimit\` option (default: 8000) can be set to control when URL length warnings are included in error messages for aborted requests.",
"examples": [
{
"id": "example-1",
"name": "Example 1",
"code": "\`\`\`ts\\nimport { PostgrestClient } from '@supabase/postgrest-js'\\n\\nconst postgrest = new PostgrestClient('https://xyzcompany.supabase.co/rest/v1', {\\n headers: { apikey: 'public-anon-key' },\\n schema: 'public',\\n timeout: 30000, // 30 second timeout\\n})\\n\`\`\`"
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\\nconst { data, error } = await supabase.from('profiles').select('*')\\n\`\`\`"
},
{
"id": "creating-a-postgrest-client",
"name": "Creating a Postgrest client",
"code": "\`\`\`ts\\nimport { PostgrestClient } from '@supabase/postgrest-js'\\n\\nconst postgrest = new PostgrestClient('https://xyzcompany.supabase.co/rest/v1', {\\n headers: { apikey: 'public-anon-key' },\\n schema: 'public',\\n})\\n\`\`\`"
},
{
"id": "with-timeout",
"name": "With timeout",
"code": "\`\`\`ts\\nimport { PostgrestClient } from '@supabase/postgrest-js'\\n\\nconst postgrest = new PostgrestClient('https://xyzcompany.supabase.co/rest/v1', {\\n headers: { apikey: 'public-anon-key' },\\n schema: 'public',\\n timeout: 30000, // 30 second timeout\\n retry: false, // Disable automatic retries\\n})\\n\`\`\`"
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`ts\\nimport { PostgrestClient } from '@supabase/postgrest-js'\\n\\nconst postgrest = new PostgrestClient('https://xyzcompany.supabase.co/rest/v1', {\\n headers: { apikey: 'publishable-or-anon-key' },\\n schema: 'public',\\n timeout: 30000, // 30 second timeout\\n})\\n\`\`\`"
}
]
}
@@ -87865,14 +87895,14 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"shortText": "Creates a builder configured for a specific PostgREST request.",
"examples": [
{
"id": "example-1",
"name": "Example 1",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst builder = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: new Headers({ apikey: 'public-anon-key' }) }\\n)\\n\`\`\`"
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\\nconst { data, error } = await supabase.from('users').select('*')\\n\`\`\`"
},
{
"id": "creating-a-postgrest-query-builder",
"name": "Creating a Postgrest query builder",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst builder = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: new Headers({ apikey: 'public-anon-key' }) }\\n)\\n\`\`\`"
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst builder = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: new Headers({ apikey: 'publishable-or-anon-key' }) }\\n)\\n\`\`\`"
}
]
}
@@ -91373,9 +91403,14 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"shortText": "Creates a query builder scoped to a Postgres table or view.",
"examples": [
{
"id": "creating-a-postgrest-query-builder",
"name": "Creating a Postgrest query builder",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst query = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: { apikey: 'public-anon-key' }, retry: true }\\n)\\n\`\`\`"
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\\nconst { data, error } = await supabase.from('users').select('*')\\n\`\`\`"
},
{
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst query = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: { apikey: 'publishable-or-anon-key' }, retry: true }\\n)\\n\`\`\`"
}
]
}
@@ -92240,14 +92275,14 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"shortText": "Creates a builder configured for a specific PostgREST request.",
"examples": [
{
"id": "example-1",
"name": "Example 1",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst builder = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: new Headers({ apikey: 'public-anon-key' }) }\\n)\\n\`\`\`"
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\\nconst { data, error } = await supabase.from('users').select('*')\\n\`\`\`"
},
{
"id": "creating-a-postgrest-query-builder",
"name": "Creating a Postgrest query builder",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst builder = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: new Headers({ apikey: 'public-anon-key' }) }\\n)\\n\`\`\`"
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`ts\\nimport { PostgrestQueryBuilder } from '@supabase/postgrest-js'\\n\\nconst builder = new PostgrestQueryBuilder(\\n new URL('https://xyzcompany.supabase.co/rest/v1/users'),\\n { headers: new Headers({ apikey: 'publishable-or-anon-key' }) }\\n)\\n\`\`\`"
}
]
}
@@ -93477,9 +93512,14 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"shortText": "Creates a channel that can broadcast messages, sync presence, and listen to Postgres changes.\\n\\nThe topic determines which realtime stream you are subscribing to. Config options let you\\nenable acknowledgement for broadcasts, presence tracking, or private channels.",
"examples": [
{
"id": "example-for-a-public-channel",
"name": "Example for a public channel",
"code": "\`\`\`ts\\nimport RealtimeClient from '@supabase/realtime-js'\\n\\nconst client = new RealtimeClient('https://xyzcompany.supabase.co/realtime/v1', {\\n params: { apikey: 'public-anon-key' },\\n})\\nconst channel = new RealtimeChannel('realtime:public:messages', { config: {} }, client)\\n\`\`\`"
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\\nconst channel = supabase.channel('room1')\\nchannel\\n .on('broadcast', { event: 'cursor-pos' }, (payload) => console.log(payload))\\n .subscribe()\\n\`\`\`"
},
{
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`ts\\nimport RealtimeClient from '@supabase/realtime-js'\\n\\nconst client = new RealtimeClient('https://xyzcompany.supabase.co/realtime/v1', {\\n params: { apikey: 'publishable-or-anon-key' },\\n})\\nconst channel = new RealtimeChannel('realtime:public:messages', { config: {} }, client)\\n\`\`\`"
}
]
}
@@ -93795,9 +93835,14 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"shortText": "Initializes the Socket.",
"examples": [
{
"id": "example-for-a-public-channel",
"name": "Example for a public channel",
"code": "\`\`\`ts\\nimport RealtimeClient from '@supabase/realtime-js'\\n\\nconst client = new RealtimeClient('https://xyzcompany.supabase.co/realtime/v1', {\\n params: { apikey: 'public-anon-key' },\\n})\\nclient.connect()\\n\`\`\`"
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\\nconst channel = supabase.channel('room1')\\nchannel\\n .on('broadcast', { event: 'cursor-pos' }, (payload) => console.log(payload))\\n .subscribe()\\n\`\`\`"
},
{
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`ts\\nimport RealtimeClient from '@supabase/realtime-js'\\n\\nconst client = new RealtimeClient('https://xyzcompany.supabase.co/realtime/v1', {\\n params: { apikey: 'publishable-or-anon-key' },\\n})\\nclient.connect()\\n\`\`\`"
}
]
}
@@ -97009,9 +97054,14 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"shortText": "Creates a client for Storage buckets, files, analytics, and vectors.",
"examples": [
{
"id": "creating-a-storage-client",
"name": "Creating a Storage client",
"code": "\`\`\`ts\\nimport { StorageClient } from '@supabase/storage-js'\\n\\nconst storage = new StorageClient('https://xyzcompany.supabase.co/storage/v1', {\\n apikey: 'public-anon-key',\\n})\\nconst avatars = storage.from('avatars')\\n\`\`\`"
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\\nconst avatars = supabase.storage.from('avatars')\\n\`\`\`"
},
{
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`ts\\nimport { StorageClient } from '@supabase/storage-js'\\n\\nconst storage = new StorageClient('https://xyzcompany.supabase.co/storage/v1', {\\n apikey: 'publishable-or-anon-key',\\n})\\nconst avatars = storage.from('avatars')\\n\`\`\`"
}
]
}
@@ -98900,9 +98950,14 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
],
"examples": [
{
"id": "creating-a-storageanalyticsclient-instance",
"name": "Creating a StorageAnalyticsClient instance",
"code": "\`\`\`typescript\\nconst client = new StorageAnalyticsClient(url, headers)\\n\`\`\`"
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`typescript\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\\nconst { data, error } = await supabase.storage.analytics.listBuckets()\\n\`\`\`"
},
{
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`typescript\\nimport { StorageAnalyticsClient } from '@supabase/storage-js'\\n\\nconst client = new StorageAnalyticsClient(url, headers)\\n\`\`\`"
}
]
}
@@ -103923,9 +103978,14 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
],
"examples": [
{
"id": "creating-a-storagevectorsclient-instance",
"name": "Creating a StorageVectorsClient instance",
"code": "\`\`\`typescript\\nconst client = new StorageVectorsClient(url, options)\\n\`\`\`"
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`typescript\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\\nconst bucket = supabase.storage.vectors.from('embeddings-prod')\\n\`\`\`"
},
{
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`typescript\\nimport { StorageVectorsClient } from '@supabase/storage-js'\\n\\nconst client = new StorageVectorsClient(url, options)\\n\`\`\`"
}
]
}
@@ -106483,14 +106543,14 @@ exports[`TS type spec parsing > matches snapshot 1`] = `
"shortText": "Creates a new Functions client bound to an Edge Functions URL.",
"examples": [
{
"id": "example-1",
"name": "Example 1",
"code": "\`\`\`ts\\nimport { FunctionsClient, FunctionRegion } from '@supabase/functions-js'\\n\\nconst functions = new FunctionsClient('https://xyzcompany.supabase.co/functions/v1', {\\n headers: { apikey: 'public-anon-key' },\\n region: FunctionRegion.UsEast1,\\n})\\n\`\`\`"
"id": "using-supabase-js-recommended",
"name": "Using supabase-js (recommended)",
"code": "\`\`\`ts\\nimport { createClient } from '@supabase/supabase-js'\\n\\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\\nconst { data, error } = await supabase.functions.invoke('hello-world')\\n\`\`\`"
},
{
"id": "creating-a-functions-client",
"name": "Creating a Functions client",
"code": "\`\`\`ts\\nimport { FunctionsClient, FunctionRegion } from '@supabase/functions-js'\\n\\nconst functions = new FunctionsClient('https://xyzcompany.supabase.co/functions/v1', {\\n headers: { apikey: 'public-anon-key' },\\n region: FunctionRegion.UsEast1,\\n})\\n\`\`\`"
"id": "standalone-import-for-bundle-sensitive-environments",
"name": "Standalone import for bundle-sensitive environments",
"code": "\`\`\`ts\\nimport { FunctionsClient, FunctionRegion } from '@supabase/functions-js'\\n\\nconst functions = new FunctionsClient('https://xyzcompany.supabase.co/functions/v1', {\\n headers: { apikey: 'publishable-or-anon-key' },\\n region: FunctionRegion.UsEast1,\\n})\\n\`\`\`"
}
]
}
+1
View File
@@ -56,6 +56,7 @@ Colin Murray
Colum Ferry
Craig Cannon
Cuong Do
Dane Harrigan
Daniel Velázquez Lara
Danny White
Dave Wilson
Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

+6 -7
View File
@@ -1912,10 +1912,10 @@
"401": { "description": "Unauthorized" },
"403": { "description": "Forbidden action" },
"429": { "description": "Rate limit exceeded" },
"500": { "description": "Failed to retrieve project's JIT access config" }
"500": { "description": "Failed to retrieve project's temporary access configuration." }
},
"security": [{ "bearer": [] }, { "fga_permissions": ["project_admin_read"] }],
"summary": "[Beta] Get project's just-in-time access configuration.",
"summary": "[Beta] Get project's temporary access configuration.",
"tags": ["Database"],
"x-badges": [{ "name": "OAuth scope: database:read", "position": "after" }],
"x-endpoint-owners": ["security", "management-api"],
@@ -1956,10 +1956,10 @@
"401": { "description": "Unauthorized" },
"403": { "description": "Forbidden action" },
"429": { "description": "Rate limit exceeded" },
"500": { "description": "Failed to update project's just-in-time access configuration." }
"500": { "description": "Failed to update project's temporary access configuration." }
},
"security": [{ "bearer": [] }, { "fga_permissions": ["project_admin_write"] }],
"summary": "[Beta] Update project's just-in-time access configuration.",
"summary": "[Beta] Update project's temporary access configuration.",
"tags": ["Database"],
"x-badges": [{ "name": "OAuth scope: database:write", "position": "after" }],
"x-endpoint-owners": ["security", "management-api"],
@@ -8416,9 +8416,7 @@
},
"JitAccessRequestRequest": {
"type": "object",
"properties": {
"state": { "type": "string", "enum": ["enabled", "disabled", "unavailable"] }
},
"properties": { "state": { "type": "string", "enum": ["enabled", "disabled"] } },
"required": ["state"],
"example": { "state": "enabled" }
},
@@ -12136,6 +12134,7 @@
"security.audit_logs_days",
"security.questionnaire",
"security.soc2_report",
"security.iso27001_certificate",
"security.private_link",
"security.enforce_mfa",
"log.retention_days",
+1 -1
View File
@@ -2391,7 +2391,7 @@ commands:
Automatically generates type definitions based on your Postgres database schema.
This command connects to your database (local or remote) and generates typed definitions that match your database tables, views, and stored procedures. By default, it generates TypeScript definitions, but also supports Go and Swift.
This command connects to your database (local or remote) and generates typed definitions that match your database tables, views, and functions. By default, it generates TypeScript definitions, but also supports Go and Swift.
Generated types give you type safety and autocompletion when working with your database in code, helping prevent runtime errors and improving developer experience.
+1 -1
View File
@@ -116,7 +116,7 @@ parameters:
required: false
default: '1000'
description: |
The maximum number of rows returned from a view, table, or stored procedure. Limits payload size for accidental or malicious requests.
The maximum number of rows returned from a view, table, or function. Limits payload size for accidental or malicious requests.
links:
- name: 'PostgREST configuration'
link: 'https://postgrest.org/en/stable/configuration.html'
@@ -368,6 +368,14 @@
"parent": "modifiers",
"type": "function"
},
{
"id": "strip-nulls",
"title": "Strip null values",
"slug": "db-strip-nulls",
"product": "database",
"parent": "modifiers",
"type": "function"
},
{
"id": "returns",
"title": "Override type of successful response",
@@ -893,6 +901,48 @@
"slug": "auth-admin-oauth-regenerateclientsecret",
"product": "auth-admin",
"type": "function"
},
{
"id": "admin-oauth-list-clients",
"title": "List OAuth clients",
"slug": "auth-admin-oauth-listclients",
"product": "auth-admin",
"type": "function"
},
{
"id": "admin-oauth-create-client",
"title": "Create OAuth client",
"slug": "auth-admin-oauth-createclient",
"product": "auth-admin",
"type": "function"
},
{
"id": "admin-oauth-get-client",
"title": "Get OAuth client",
"slug": "auth-admin-oauth-getclient",
"product": "auth-admin",
"type": "function"
},
{
"id": "admin-oauth-update-client",
"title": "Update OAuth client",
"slug": "auth-admin-oauth-updateclient",
"product": "auth-admin",
"type": "function"
},
{
"id": "admin-oauth-delete-client",
"title": "Delete OAuth client",
"slug": "auth-admin-oauth-deleteclient",
"product": "auth-admin",
"type": "function"
},
{
"id": "admin-oauth-regenerate-client-secret",
"title": "Regenerate client secret",
"slug": "auth-admin-oauth-regenerateclientsecret",
"product": "auth-admin",
"type": "function"
}
]
}
File diff suppressed because it is too large. Load diff
@@ -23,7 +23,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 96,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L96"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L96"
}
],
"type": {
@@ -42,7 +42,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 97,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L97"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L97"
}
],
"type": {
@@ -61,7 +61,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 98,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L98"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L98"
}
],
"type": {
@@ -80,7 +80,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 99,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L99"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L99"
}
],
"type": {
@@ -99,7 +99,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 100,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L100"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L100"
}
],
"type": {
@@ -118,7 +118,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 101,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L101"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L101"
}
],
"type": {
@@ -137,7 +137,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 102,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L102"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L102"
}
],
"type": {
@@ -156,7 +156,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 103,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L103"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L103"
}
],
"type": {
@@ -175,7 +175,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 104,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L104"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L104"
}
],
"type": {
@@ -194,7 +194,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 105,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L105"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L105"
}
],
"type": {
@@ -213,7 +213,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 106,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L106"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L106"
}
],
"type": {
@@ -232,7 +232,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 107,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L107"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L107"
}
],
"type": {
@@ -251,7 +251,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 108,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L108"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L108"
}
],
"type": {
@@ -270,7 +270,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 109,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L109"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L109"
}
],
"type": {
@@ -289,7 +289,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 110,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L110"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L110"
}
],
"type": {
@@ -309,7 +309,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 95,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L95"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L95"
}
]
},
@@ -337,9 +337,9 @@
"sources": [
{
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 46,
"line": 44,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L46"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L44"
}
],
"signatures": [
@@ -359,10 +359,11 @@
"blockTags": [
{
"tag": "@example",
"name": "Using supabase-js (recommended)",
"content": [
{
"kind": "code",
"text": "```ts\nimport { FunctionsClient, FunctionRegion } from '@supabase/functions-js'\n\nconst functions = new FunctionsClient('https://xyzcompany.supabase.co/functions/v1', {\n headers: { apikey: 'public-anon-key' },\n region: FunctionRegion.UsEast1,\n})\n```"
"text": "```ts\nimport { createClient } from '@supabase/supabase-js'\n\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\nconst { data, error } = await supabase.functions.invoke('hello-world')\n```"
}
]
},
@@ -377,11 +378,11 @@
},
{
"tag": "@example",
"name": "Creating a Functions client",
"name": "Standalone import for bundle-sensitive environments",
"content": [
{
"kind": "code",
"text": "```ts\nimport { FunctionsClient, FunctionRegion } from '@supabase/functions-js'\n\nconst functions = new FunctionsClient('https://xyzcompany.supabase.co/functions/v1', {\n headers: { apikey: 'public-anon-key' },\n region: FunctionRegion.UsEast1,\n})\n```"
"text": "```ts\nimport { FunctionsClient, FunctionRegion } from '@supabase/functions-js'\n\nconst functions = new FunctionsClient('https://xyzcompany.supabase.co/functions/v1', {\n headers: { apikey: 'publishable-or-anon-key' },\n region: FunctionRegion.UsEast1,\n})\n```"
}
]
}
@@ -390,9 +391,9 @@
"sources": [
{
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 46,
"line": 44,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L46"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L44"
}
],
"parameters": [
@@ -433,9 +434,9 @@
"sources": [
{
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 54,
"line": 52,
"character": 6,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L54"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L52"
}
],
"type": {
@@ -662,9 +663,9 @@
"sources": [
{
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 53,
"line": 51,
"character": 6,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L53"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L51"
}
],
"type": {
@@ -699,9 +700,9 @@
"sources": [
{
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 55,
"line": 53,
"character": 6,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L55"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L53"
}
],
"type": {
@@ -722,9 +723,9 @@
"sources": [
{
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 52,
"line": 50,
"character": 7,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L52"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L50"
}
]
}
@@ -754,7 +755,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 19,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L19"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L19"
}
],
"type": {
@@ -983,7 +984,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 17,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L17"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L17"
}
],
"type": {
@@ -1019,7 +1020,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 18,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L18"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L18"
}
],
"type": {
@@ -1042,7 +1043,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 16,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L16"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L16"
}
],
"type": {
@@ -1059,9 +1060,9 @@
"sources": [
{
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 204,
"line": 202,
"character": 8,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L204"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L202"
}
],
"signatures": [
@@ -1502,9 +1503,9 @@
"sources": [
{
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 204,
"line": 202,
"character": 8,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L204"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L202"
}
],
"typeParameters": [
@@ -1601,9 +1602,9 @@
"sources": [
{
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 75,
"line": 73,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L75"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L73"
}
],
"signatures": [
@@ -1645,9 +1646,9 @@
"sources": [
{
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 75,
"line": 73,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L75"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L73"
}
],
"parameters": [
@@ -1708,7 +1709,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 15,
"character": 13,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L15"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L15"
}
]
},
@@ -1749,7 +1750,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 32,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L32"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L32"
}
],
"signatures": [
@@ -1764,7 +1765,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 32,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L32"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L32"
}
],
"parameters": [
@@ -1835,7 +1836,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 31,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L31"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L31"
}
],
"type": {
@@ -1854,7 +1855,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"signatures": [
@@ -1869,7 +1870,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -1892,7 +1893,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 45,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -1911,7 +1912,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 28,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -1930,7 +1931,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 14,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -1950,7 +1951,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
]
}
@@ -1978,7 +1979,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 30,
"character": 13,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L30"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L30"
}
],
"extendedTypes": [
@@ -2047,7 +2048,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 58,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L58"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L58"
}
],
"signatures": [
@@ -2062,7 +2063,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 58,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L58"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L58"
}
],
"parameters": [
@@ -2110,7 +2111,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 31,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L31"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L31"
}
],
"type": {
@@ -2136,7 +2137,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"signatures": [
@@ -2153,7 +2154,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2176,7 +2177,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 45,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2195,7 +2196,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 28,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2214,7 +2215,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 14,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2234,7 +2235,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
]
}
@@ -2272,7 +2273,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 57,
"character": 13,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L57"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L57"
}
],
"extendedTypes": [
@@ -2321,7 +2322,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 90,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L90"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L90"
}
],
"signatures": [
@@ -2336,7 +2337,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 90,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L90"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L90"
}
],
"parameters": [
@@ -2384,7 +2385,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 31,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L31"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L31"
}
],
"type": {
@@ -2410,7 +2411,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"signatures": [
@@ -2427,7 +2428,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2450,7 +2451,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 45,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2469,7 +2470,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 28,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2488,7 +2489,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 14,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2508,7 +2509,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
]
}
@@ -2546,7 +2547,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 89,
"character": 13,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L89"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L89"
}
],
"extendedTypes": [
@@ -2595,7 +2596,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 74,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L74"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L74"
}
],
"signatures": [
@@ -2610,7 +2611,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 74,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L74"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L74"
}
],
"parameters": [
@@ -2658,7 +2659,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 31,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L31"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L31"
}
],
"type": {
@@ -2684,7 +2685,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"signatures": [
@@ -2701,7 +2702,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2724,7 +2725,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 45,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2743,7 +2744,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 28,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2762,7 +2763,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 14,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2782,7 +2783,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
]
}
@@ -2820,7 +2821,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 73,
"character": 13,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L73"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L73"
}
],
"extendedTypes": [
@@ -2843,7 +2844,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 113,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L113"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L113"
}
],
"type": {
@@ -2876,7 +2877,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 129,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L129"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L129"
}
],
"type": {
@@ -2985,7 +2986,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 117,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L117"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L117"
}
],
"type": {
@@ -3001,7 +3002,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 117,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L117"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L117"
}
],
"indexSignatures": [
@@ -3016,7 +3017,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 117,
"character": 14,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L117"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L117"
}
],
"parameters": [
@@ -3062,7 +3063,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 121,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L121"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L121"
}
],
"type": {
@@ -3112,7 +3113,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 125,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L125"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L125"
}
],
"type": {
@@ -3143,7 +3144,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 140,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L140"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L140"
}
],
"type": {
@@ -3177,7 +3178,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 145,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L145"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L145"
}
],
"type": {
@@ -3197,7 +3198,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 113,
"character": 36,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L113"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L113"
}
]
}
@@ -3214,7 +3215,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 16,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L16"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L16"
}
],
"typeParameters": [
@@ -23,7 +23,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 96,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L96"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L96"
}
],
"type": {
@@ -42,7 +42,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 97,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L97"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L97"
}
],
"type": {
@@ -61,7 +61,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 98,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L98"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L98"
}
],
"type": {
@@ -80,7 +80,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 99,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L99"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L99"
}
],
"type": {
@@ -99,7 +99,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 100,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L100"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L100"
}
],
"type": {
@@ -118,7 +118,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 101,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L101"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L101"
}
],
"type": {
@@ -137,7 +137,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 102,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L102"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L102"
}
],
"type": {
@@ -156,7 +156,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 103,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L103"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L103"
}
],
"type": {
@@ -175,7 +175,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 104,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L104"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L104"
}
],
"type": {
@@ -194,7 +194,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 105,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L105"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L105"
}
],
"type": {
@@ -213,7 +213,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 106,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L106"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L106"
}
],
"type": {
@@ -232,7 +232,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 107,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L107"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L107"
}
],
"type": {
@@ -251,7 +251,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 108,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L108"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L108"
}
],
"type": {
@@ -270,7 +270,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 109,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L109"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L109"
}
],
"type": {
@@ -289,7 +289,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 110,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L110"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L110"
}
],
"type": {
@@ -309,7 +309,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 95,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L95"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L95"
}
]
},
@@ -337,9 +337,9 @@
"sources": [
{
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 46,
"line": 44,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L46"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L44"
}
],
"signatures": [
@@ -359,10 +359,11 @@
"blockTags": [
{
"tag": "@example",
"name": "Using supabase-js (recommended)",
"content": [
{
"kind": "code",
"text": "```ts\nimport { FunctionsClient, FunctionRegion } from '@supabase/functions-js'\n\nconst functions = new FunctionsClient('https://xyzcompany.supabase.co/functions/v1', {\n headers: { apikey: 'public-anon-key' },\n region: FunctionRegion.UsEast1,\n})\n```"
"text": "```ts\nimport { createClient } from '@supabase/supabase-js'\n\nconst supabase = createClient('https://xyzcompany.supabase.co', 'publishable-or-anon-key')\nconst { data, error } = await supabase.functions.invoke('hello-world')\n```"
}
]
},
@@ -377,11 +378,11 @@
},
{
"tag": "@example",
"name": "Creating a Functions client",
"name": "Standalone import for bundle-sensitive environments",
"content": [
{
"kind": "code",
"text": "```ts\nimport { FunctionsClient, FunctionRegion } from '@supabase/functions-js'\n\nconst functions = new FunctionsClient('https://xyzcompany.supabase.co/functions/v1', {\n headers: { apikey: 'public-anon-key' },\n region: FunctionRegion.UsEast1,\n})\n```"
"text": "```ts\nimport { FunctionsClient, FunctionRegion } from '@supabase/functions-js'\n\nconst functions = new FunctionsClient('https://xyzcompany.supabase.co/functions/v1', {\n headers: { apikey: 'publishable-or-anon-key' },\n region: FunctionRegion.UsEast1,\n})\n```"
}
]
}
@@ -390,9 +391,9 @@
"sources": [
{
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 46,
"line": 44,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L46"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L44"
}
],
"parameters": [
@@ -433,9 +434,9 @@
"sources": [
{
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 54,
"line": 52,
"character": 6,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L54"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L52"
}
],
"type": {
@@ -662,9 +663,9 @@
"sources": [
{
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 53,
"line": 51,
"character": 6,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L53"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L51"
}
],
"type": {
@@ -699,9 +700,9 @@
"sources": [
{
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 55,
"line": 53,
"character": 6,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L55"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L53"
}
],
"type": {
@@ -722,9 +723,9 @@
"sources": [
{
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 52,
"line": 50,
"character": 7,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L52"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L50"
}
]
}
@@ -754,7 +755,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 19,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L19"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L19"
}
],
"type": {
@@ -983,7 +984,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 17,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L17"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L17"
}
],
"type": {
@@ -1019,7 +1020,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 18,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L18"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L18"
}
],
"type": {
@@ -1042,7 +1043,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 16,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L16"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L16"
}
],
"type": {
@@ -1059,9 +1060,9 @@
"sources": [
{
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 204,
"line": 202,
"character": 8,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L204"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L202"
}
],
"signatures": [
@@ -1502,9 +1503,9 @@
"sources": [
{
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 204,
"line": 202,
"character": 8,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L204"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L202"
}
],
"typeParameters": [
@@ -1601,9 +1602,9 @@
"sources": [
{
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 75,
"line": 73,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L75"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L73"
}
],
"signatures": [
@@ -1645,9 +1646,9 @@
"sources": [
{
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 75,
"line": 73,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L75"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L73"
}
],
"parameters": [
@@ -1708,7 +1709,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 15,
"character": 13,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/FunctionsClient.ts#L15"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/FunctionsClient.ts#L15"
}
]
},
@@ -1749,7 +1750,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 32,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L32"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L32"
}
],
"signatures": [
@@ -1764,7 +1765,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 32,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L32"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L32"
}
],
"parameters": [
@@ -1835,7 +1836,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 31,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L31"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L31"
}
],
"type": {
@@ -1854,7 +1855,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"signatures": [
@@ -1869,7 +1870,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -1892,7 +1893,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 45,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -1911,7 +1912,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 28,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -1930,7 +1931,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 14,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -1950,7 +1951,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
]
}
@@ -1978,7 +1979,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 30,
"character": 13,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L30"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L30"
}
],
"extendedTypes": [
@@ -2047,7 +2048,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 58,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L58"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L58"
}
],
"signatures": [
@@ -2062,7 +2063,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 58,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L58"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L58"
}
],
"parameters": [
@@ -2110,7 +2111,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 31,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L31"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L31"
}
],
"type": {
@@ -2136,7 +2137,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"signatures": [
@@ -2153,7 +2154,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2176,7 +2177,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 45,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2195,7 +2196,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 28,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2214,7 +2215,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 14,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2234,7 +2235,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
]
}
@@ -2272,7 +2273,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 57,
"character": 13,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L57"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L57"
}
],
"extendedTypes": [
@@ -2321,7 +2322,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 90,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L90"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L90"
}
],
"signatures": [
@@ -2336,7 +2337,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 90,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L90"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L90"
}
],
"parameters": [
@@ -2384,7 +2385,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 31,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L31"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L31"
}
],
"type": {
@@ -2410,7 +2411,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"signatures": [
@@ -2427,7 +2428,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2450,7 +2451,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 45,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2469,7 +2470,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 28,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2488,7 +2489,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 14,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2508,7 +2509,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
]
}
@@ -2546,7 +2547,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 89,
"character": 13,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L89"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L89"
}
],
"extendedTypes": [
@@ -2595,7 +2596,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 74,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L74"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L74"
}
],
"signatures": [
@@ -2610,7 +2611,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 74,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L74"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L74"
}
],
"parameters": [
@@ -2658,7 +2659,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 31,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L31"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L31"
}
],
"type": {
@@ -2684,7 +2685,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"signatures": [
@@ -2701,7 +2702,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2724,7 +2725,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 45,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2743,7 +2744,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 28,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2762,7 +2763,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 14,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2782,7 +2783,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L38"
}
]
}
@@ -2820,7 +2821,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 73,
"character": 13,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L73"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L73"
}
],
"extendedTypes": [
@@ -2843,7 +2844,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 113,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L113"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L113"
}
],
"type": {
@@ -2876,7 +2877,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 129,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L129"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L129"
}
],
"type": {
@@ -2985,7 +2986,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 117,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L117"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L117"
}
],
"type": {
@@ -3001,7 +3002,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 117,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L117"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L117"
}
],
"indexSignatures": [
@@ -3016,7 +3017,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 117,
"character": 14,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L117"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L117"
}
],
"parameters": [
@@ -3062,7 +3063,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 121,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L121"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L121"
}
],
"type": {
@@ -3112,7 +3113,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 125,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L125"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L125"
}
],
"type": {
@@ -3143,7 +3144,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 140,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L140"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L140"
}
],
"type": {
@@ -3177,7 +3178,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 145,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L145"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L145"
}
],
"type": {
@@ -3197,7 +3198,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 113,
"character": 36,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L113"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L113"
}
]
}
@@ -3214,7 +3215,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 16,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/4c16408238bcff28db41052107ffe286ab510f76/packages/core/functions-js/src/types.ts#L16"
"url": "https://github.com/supabase/supabase-js/blob/897fb8e9d288e74dd47e765b5d6ec647e765a3cb/packages/core/functions-js/src/types.ts#L16"
}
],
"typeParameters": [
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+13 -13
View File
@@ -991,7 +991,7 @@
"required": false
},
{
"schema": { "type": "string", "enum": ["origin", "avif"] },
"schema": { "type": "string", "enum": ["origin", "avif", "webp"] },
"in": "query",
"name": "format",
"required": false
@@ -1278,7 +1278,7 @@
"required": false
},
{
"schema": { "type": "string", "enum": ["origin", "avif"] },
"schema": { "type": "string", "enum": ["origin", "avif", "webp"] },
"in": "query",
"name": "format",
"required": false
@@ -1445,7 +1445,7 @@
"height": { "type": "integer", "minimum": 0, "example": 100 },
"width": { "type": "integer", "minimum": 0, "example": 100 },
"resize": { "type": "string", "enum": ["cover", "contain", "fill"] },
"format": { "type": "string", "enum": ["origin", "avif"] },
"format": { "type": "string", "enum": ["origin", "avif", "webp"] },
"quality": { "type": "integer", "minimum": 20, "maximum": 100 }
}
}
@@ -1918,7 +1918,7 @@
"required": false
},
{
"schema": { "type": "string", "enum": ["origin", "avif"] },
"schema": { "type": "string", "enum": ["origin", "avif", "webp"] },
"in": "query",
"name": "format",
"required": false
@@ -1985,7 +1985,7 @@
"required": false
},
{
"schema": { "type": "string", "enum": ["origin", "avif"] },
"schema": { "type": "string", "enum": ["origin", "avif", "webp"] },
"in": "query",
"name": "format",
"required": false
@@ -2055,7 +2055,7 @@
"required": false
},
{
"schema": { "type": "string", "enum": ["origin", "avif"] },
"schema": { "type": "string", "enum": ["origin", "avif", "webp"] },
"in": "query",
"name": "format",
"required": false
@@ -2116,7 +2116,7 @@
"required": false
},
{
"schema": { "type": "string", "enum": ["origin", "avif"] },
"schema": { "type": "string", "enum": ["origin", "avif", "webp"] },
"in": "query",
"name": "format",
"required": false
@@ -2332,7 +2332,7 @@
"required": false
},
{
"schema": { "type": "string", "enum": ["origin", "avif"] },
"schema": { "type": "string", "enum": ["origin", "avif", "webp"] },
"in": "query",
"name": "format",
"required": false
@@ -2395,7 +2395,7 @@
"required": false
},
{
"schema": { "type": "string", "enum": ["origin", "avif"] },
"schema": { "type": "string", "enum": ["origin", "avif", "webp"] },
"in": "query",
"name": "format",
"required": false
@@ -2457,7 +2457,7 @@
"required": false
},
{
"schema": { "type": "string", "enum": ["origin", "avif"] },
"schema": { "type": "string", "enum": ["origin", "avif", "webp"] },
"in": "query",
"name": "format",
"required": false
@@ -2524,7 +2524,7 @@
"required": false
},
{
"schema": { "type": "string", "enum": ["origin", "avif"] },
"schema": { "type": "string", "enum": ["origin", "avif", "webp"] },
"in": "query",
"name": "format",
"required": false
@@ -2679,7 +2679,7 @@
"required": false
},
{
"schema": { "type": "string", "enum": ["origin", "avif"] },
"schema": { "type": "string", "enum": ["origin", "avif", "webp"] },
"in": "query",
"name": "format",
"required": false
@@ -2746,7 +2746,7 @@
"required": false
},
{
"schema": { "type": "string", "enum": ["origin", "avif"] },
"schema": { "type": "string", "enum": ["origin", "avif", "webp"] },
"in": "query",
"name": "format",
"required": false
+5 -5
View File
@@ -667,17 +667,17 @@ functions:
```
- id: rpc
title: 'Stored Procedures: Rpc()'
title: 'Database Functions: Rpc()'
description: |
You can call stored procedures as a "Remote Procedure Call".
You can call 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.
examples:
- id: call-a-stored-procedure
name: Call a stored procedure
- id: call-a-database-function
name: Call a database function
isSpotlight: true
description: This is an example invoking a stored procedure.
description: This is an example invoking a database function.
code: |
```c#
await supabase.Rpc("hello_world", null);
+5 -5
View File
@@ -667,17 +667,17 @@ functions:
```
- id: rpc
title: 'Stored Procedures: Rpc()'
title: 'Database Functions: Rpc()'
description: |
You can call stored procedures as a "Remote Procedure Call".
You can call 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.
examples:
- id: call-a-stored-procedure
name: Call a stored procedure
- id: call-a-database-function
name: Call a database function
isSpotlight: true
description: This is an example invoking a stored procedure.
description: This is an example invoking a database function.
code: |
```c#
await supabase.Rpc("hello_world", null);
+27 -27
View File
@@ -1049,17 +1049,17 @@ functions:
```
- id: rpc
title: 'Stored Procedures: rpc()'
title: 'Database Functions: rpc()'
description: |
You can call stored procedures as a "Remote Procedure Call".
You can call 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.
examples:
- id: call-a-stored-procedure
name: Call a stored procedure
- id: call-a-database-function
name: Call a database function
isSpotlight: true
description: This is an example invoking a stored procedure.
description: This is an example invoking a database function.
code: |
```dart
final data = await supabase
@@ -1994,9 +1994,9 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_instruments)
.rpc('echo_all_instruments')
.not('name', 'eq', 'violin');
```
@@ -2037,7 +2037,7 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_instruments')
.match({'name': 'violin', 'country_id': 3});
@@ -2080,7 +2080,7 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_instruments')
.eq('name', 'guqin');
@@ -2123,7 +2123,7 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_instruments')
.neq('name', 'violin');
@@ -2166,7 +2166,7 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_cities')
.gt('country_id', 250);
@@ -2209,7 +2209,7 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_cities')
.gte('country_id', 250);
@@ -2252,7 +2252,7 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_cities')
.lt('country_id', 250);
@@ -2296,7 +2296,7 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_cities')
.lte('country_id', 250);
@@ -2340,7 +2340,7 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_cities')
.like('name', '%la%');
@@ -2383,7 +2383,7 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_cities')
.ilike('name', '%la%');
@@ -2428,7 +2428,7 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_cities')
.is_('name', null);
@@ -2473,7 +2473,7 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_cities')
.in_('name', ['Minas Tirith', 'Minas Morgul']);
@@ -2514,7 +2514,7 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_countries')
.contains('main_exports', ['oil']);
@@ -2555,7 +2555,7 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_countries')
.containedBy('main_exports', ['cars', 'food', 'machine']);
@@ -2596,7 +2596,7 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_countries')
.rangeLt('population_range_millions', '[150, 250]');
@@ -2637,7 +2637,7 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_countries')
.rangeGt('population_range_millions', '[150, 250]');
@@ -2678,7 +2678,7 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_countries')
.rangeGte('population_range_millions', '[150, 250]');
@@ -2720,7 +2720,7 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_countries')
.rangeLte('population_range_millions', [150, 250]);
@@ -2761,7 +2761,7 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_countries')
.rangeAdjacent('population_range_millions', '[70, 185]');
@@ -2802,7 +2802,7 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_countries')
.overlaps('main_exports', ['computers', 'minerals']);
@@ -2918,7 +2918,7 @@ functions:
name: With `rpc()`
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_cities')
.filter('name', 'in', '("Minas Tirith","Minas Morgul")');
+31 -36
View File
@@ -1506,55 +1506,50 @@ functions:
description: |
Receive a notification every time an auth event happens.
notes: |
- Types of auth events: `AuthChangeEvent.passwordRecovery`, `AuthChangeEvent.signedIn`, `AuthChangeEvent.signedOut`, `AuthChangeEvent.tokenRefreshed`, `AuthChangeEvent.userUpdated`and `AuthChangeEvent.userDeleted`
- **You must provide an `onError` handler.** Network errors (e.g. an offline token refresh) are emitted as stream errors. If no `onError` is provided, Dart rethrows them as unhandled zone exceptions, crashing the app.
- Auth event types: `initialSession`, `signedIn`, `signedOut`, `passwordRecovery`, `tokenRefreshed`, `userUpdated`, `userDeleted`, `mfaChallengeVerified`
examples:
- id: listen-to-auth-changes
name: Listen to auth changes
isSpotlight: true
code: |
```dart
final authSubscription = supabase.auth.onAuthStateChange.listen((data) {
final AuthChangeEvent event = data.event;
final Session? session = data.session;
print('event: $event, session: $session');
switch (event) {
case AuthChangeEvent.initialSession:
// handle initial session
case AuthChangeEvent.signedIn:
// handle signed in
case AuthChangeEvent.signedOut:
// handle signed out
case AuthChangeEvent.passwordRecovery:
// handle password recovery
case AuthChangeEvent.tokenRefreshed:
// handle token refreshed
case AuthChangeEvent.userUpdated:
// handle user updated
case AuthChangeEvent.userDeleted:
// handle user deleted
case AuthChangeEvent.mfaChallengeVerified:
// handle mfa challenge verified
}
});
final authSubscription = supabase.auth.onAuthStateChange.listen(
(data) {
final AuthChangeEvent event = data.event;
final Session? session = data.session;
// handle event
},
onError: (error, stackTrace) {
// Network errors (e.g. offline) are emitted here.
// Handle or log them to avoid an unhandled exception crash.
},
);
```
- id: listen-to-a-specific-event
name: Listen to a specific event
code: |
```dart
final authSubscription = supabase.auth.onAuthStateChange.listen((data) {
final AuthChangeEvent event = data.event;
if (event == AuthChangeEvent.signedIn) {
// handle signIn
}
});
final authSubscription = supabase.auth.onAuthStateChange.listen(
(data) {
final AuthChangeEvent event = data.event;
if (event == AuthChangeEvent.signedIn) {
// handle signIn
}
},
onError: (error, stackTrace) {
// Handle or log network / auth errors here.
},
);
```
- id: unsubscribe-from-auth-subscription
name: Unsubscribe from auth subscription
code: |
```dart
final authSubscription = supabase.auth.onAuthStateChange.listen((data) {});
final authSubscription = supabase.auth.onAuthStateChange.listen(
(data) {},
onError: (error, stackTrace) {},
);
authSubscription.cancel();
```
@@ -3537,7 +3532,7 @@ functions:
```
- id: rpc
title: 'Stored Procedures: rpc()'
title: 'Database Functions: rpc()'
description: |
Perform a function call.
@@ -5685,7 +5680,7 @@ functions:
name: With rpc()
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_cities')
.not('name', 'eq', 'Mordor');
@@ -7052,7 +7047,7 @@ functions:
name: With rpc()
code: |
```dart
// Only valid if the Stored Procedure returns a table type.
// Only valid if the database function returns a table type.
final data = await supabase
.rpc('echo_all_countries')
.filter('name', 'in', '("Rohan","Mordor")');
+2
View File
@@ -452,6 +452,8 @@ functions:
$ref: '@supabase/postgrest-js.PostgrestTransformBuilder.maybeSingle'
- id: csv
$ref: '@supabase/postgrest-js.PostgrestTransformBuilder.csv'
- id: strip-nulls
$ref: '@supabase/postgrest-js.PostgrestTransformBuilder.stripNulls'
- id: returns
$ref: '@supabase/postgrest-js.PostgrestTransformBuilder.returns'
- id: overrideTypes
+5 -5
View File
@@ -553,19 +553,19 @@ functions:
}.decodeSingle<City>()
```
- id: rpc
title: 'Stored Procedures: rpc()'
title: 'Database Functions: rpc()'
description: |
You can call stored procedures as a "Remote Procedure Call".
You can call 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.
- When calling `rpc` with parameters, you have to provide a [serializable value](/docs/reference/kotlin/installing#serialization) in the function parameter.
examples:
- id: call-a-stored-procedure
name: Call a stored procedure
- id: call-a-database-function
name: Call a database function
isSpotlight: true
description: This is an example invoking a stored procedure.
description: This is an example invoking a database function.
code: |
```kotlin
supabase.postgrest.rpc("hello_world")
+5 -5
View File
@@ -684,9 +684,9 @@ functions:
}.decodeSingle<City>()
```
- id: rpc
title: 'Stored Procedures: rpc()'
title: 'Database Functions: rpc()'
description: |
You can call stored procedures as a "Remote Procedure Call".
You can call 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.
@@ -710,10 +710,10 @@ functions:
type: PostgrestRequestBuilder.() -> Unit
description: Additional configuration & filtering for the request.
examples:
- id: call-a-stored-procedure
name: Call a stored procedure
- id: call-a-database-function
name: Call a database function
isSpotlight: true
description: This is an example invoking a stored procedure.
description: This is an example invoking a database function.
code: |
```kotlin
supabase.postgrest.rpc("hello_world")
+121 -8
View File
@@ -697,9 +697,9 @@ functions:
}.decodeSingle<City>()
```
- id: rpc
title: 'Stored Procedures: rpc()'
title: 'Database Functions: rpc()'
description: |
You can call stored procedures as a "Remote Procedure Call".
You can call 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.
@@ -728,10 +728,10 @@ functions:
type: String
description: The schema to use for the function. Defaults to `public`
examples:
- id: call-a-stored-procedure
name: Call a stored procedure
- id: call-a-database-function
name: Call a database function
isSpotlight: true
description: This is an example invoking a stored procedure.
description: This is an example invoking a database function.
code: |
```kotlin
supabase.postgrest.rpc("hello_world")
@@ -3116,6 +3116,10 @@ functions:
isOptional: true
type: String?
description: The captcha token when having captcha enabled.
- name: data
isOptional: true
type: JsonObject?
description: '**Deprecated** — use `extraData` or user metadata on the sign-up flow instead. Will be removed in a future release.'
examples:
- id: sign-in-with-id-token
@@ -3127,9 +3131,6 @@ functions:
provider = Google //Also supported: Apple, Azure and Facebook
//optional:
nonce = "nonce"
data = buildJsonObject {
//...
}
}
```
- id: sign-in-with-otp
@@ -4576,6 +4577,118 @@ functions:
```kotlin
supabase.auth.admin.deleteFactor(uid = "id", factorId = "factor_id")
```
- id: oauth-admin-api
title: OAuth Admin API
notes: |
The OAuth Admin API allows you to manage OAuth clients programmatically.
Only relevant when the OAuth 2.1 server is enabled in Supabase Auth.
These functions should only be called on a server. Never expose your `secret key` in the browser.
- id: admin-oauth-list-clients
title: 'admin.oauth.listClients()'
notes: |
Lists all OAuth 2.1 clients. Requires a `secret key`.
params:
- name: page
isOptional: true
type: Int?
description: The page number for pagination.
- name: perPage
isOptional: true
type: Int?
description: The number of results per page.
examples:
- id: list-oauth-clients
name: List all OAuth clients
isSpotlight: true
code: |
```kotlin
val clients = supabase.auth.admin.oauth.listClients()
```
- id: admin-oauth-create-client
title: 'admin.oauth.createClient()'
notes: |
Creates a new OAuth 2.1 client. Requires a `secret key`.
examples:
- id: create-oauth-client
name: Create an OAuth client
isSpotlight: true
code: |
```kotlin
val client = supabase.auth.admin.oauth.createClient {
name = "My App"
redirectUris = listOf("https://example.com/callback")
}
```
- id: admin-oauth-get-client
title: 'admin.oauth.getClient()'
notes: |
Retrieves an OAuth 2.1 client by ID. Requires a `secret key`.
params:
- name: clientId
isOptional: false
type: String
description: The ID of the OAuth client to retrieve.
examples:
- id: get-oauth-client
name: Get an OAuth client
isSpotlight: true
code: |
```kotlin
val client = supabase.auth.admin.oauth.getClient(clientId = "client_id")
```
- id: admin-oauth-update-client
title: 'admin.oauth.updateClient()'
notes: |
Updates an existing OAuth 2.1 client. Requires a `secret key`.
params:
- name: clientId
isOptional: false
type: String
description: The ID of the OAuth client to update.
examples:
- id: update-oauth-client
name: Update an OAuth client
isSpotlight: true
code: |
```kotlin
val client = supabase.auth.admin.oauth.updateClient(clientId = "client_id") {
name = "Updated App Name"
}
```
- id: admin-oauth-delete-client
title: 'admin.oauth.deleteClient()'
notes: |
Deletes an OAuth 2.1 client. Requires a `secret key`.
params:
- name: clientId
isOptional: false
type: String
description: The ID of the OAuth client to delete.
examples:
- id: delete-oauth-client
name: Delete an OAuth client
isSpotlight: true
code: |
```kotlin
supabase.auth.admin.oauth.deleteClient(clientId = "client_id")
```
- id: admin-oauth-regenerate-client-secret
title: 'admin.oauth.regenerateClientSecret()'
notes: |
Regenerates the client secret for an OAuth 2.1 client. Requires a `secret key`.
params:
- name: clientId
isOptional: false
type: String
description: The ID of the OAuth client whose secret should be regenerated.
examples:
- id: regenerate-client-secret
name: Regenerate client secret
isSpotlight: true
code: |
```kotlin
val client = supabase.auth.admin.oauth.regenerateClientSecret(clientId = "client_id")
```
- id: invoke
title: 'invoke()'
description: |
+2 -2
View File
@@ -4154,11 +4154,11 @@ functions:
- name: fn
isOptional: false
type: callable
description: The stored procedure call to be executed.
description: The database function call to be executed.
- name: params
isOptional: true
type: dict of any
description: Parameters passed into the stored procedure call.
description: Parameters passed into the database function call.
- name: get
isOptional: true
type: dict of any
+1 -1
View File
@@ -4052,7 +4052,7 @@ functions:
.execute()
```
description: |
Ensure that the RPC call affects at most 10 rows. Useful for limiting the impact of stored procedures.
Ensure that the RPC call affects at most 10 rows. Useful for limiting the impact of functions.
- id: single
title: single()
@@ -5411,7 +5411,7 @@
"description": "Rate limit exceeded"
},
"500": {
"description": "Failed to retrieve project's JIT access config"
"description": "Failed to retrieve project's temporary access configuration."
}
},
"security": [
@@ -5422,7 +5422,7 @@
"fga_permissions": ["project_admin_read"]
}
],
"summary": "[Beta] Get project's just-in-time access configuration.",
"summary": "[Beta] Get project's temporary access configuration.",
"tags": ["Database"],
"x-badges": [
{
@@ -5459,7 +5459,7 @@
"properties": {
"state": {
"type": "string",
"enum": ["enabled", "disabled", "unavailable"]
"enum": ["enabled", "disabled"]
}
},
"required": ["state"],
@@ -5543,7 +5543,7 @@
"description": "Rate limit exceeded"
},
"500": {
"description": "Failed to update project's just-in-time access configuration."
"description": "Failed to update project's temporary access configuration."
}
},
"security": [
@@ -5554,7 +5554,7 @@
"fga_permissions": ["project_admin_write"]
}
],
"summary": "[Beta] Update project's just-in-time access configuration.",
"summary": "[Beta] Update project's temporary access configuration.",
"tags": ["Database"],
"x-badges": [
{
@@ -21593,6 +21593,7 @@
"security.audit_logs_days",
"security.questionnaire",
"security.soc2_report",
"security.iso27001_certificate",
"security.private_link",
"security.enforce_mfa",
"log.retention_days",
@@ -24144,7 +24145,7 @@
"properties": {
"state": {
"type": "string",
"enum": ["enabled", "disabled", "unavailable"]
"enum": ["enabled", "disabled"]
}
},
"required": ["state"],
@@ -30845,6 +30846,7 @@
"security.audit_logs_days",
"security.questionnaire",
"security.soc2_report",
"security.iso27001_certificate",
"security.private_link",
"security.enforce_mfa",
"log.retention_days",
@@ -1620,7 +1620,7 @@
{
"schema": {
"type": "string",
"enum": ["origin", "avif"]
"enum": ["origin", "avif", "webp"]
},
"in": "query",
"name": "format",
@@ -2103,7 +2103,7 @@
{
"schema": {
"type": "string",
"enum": ["origin", "avif"]
"enum": ["origin", "avif", "webp"]
},
"in": "query",
"name": "format",
@@ -2366,7 +2366,7 @@
},
"format": {
"type": "string",
"enum": ["origin", "avif"]
"enum": ["origin", "avif", "webp"]
},
"quality": {
"type": "integer",
@@ -3149,7 +3149,7 @@
{
"schema": {
"type": "string",
"enum": ["origin", "avif"]
"enum": ["origin", "avif", "webp"]
},
"in": "query",
"name": "format",
@@ -3255,7 +3255,7 @@
{
"schema": {
"type": "string",
"enum": ["origin", "avif"]
"enum": ["origin", "avif", "webp"]
},
"in": "query",
"name": "format",
@@ -3364,7 +3364,7 @@
{
"schema": {
"type": "string",
"enum": ["origin", "avif"]
"enum": ["origin", "avif", "webp"]
},
"in": "query",
"name": "format",
@@ -3462,7 +3462,7 @@
{
"schema": {
"type": "string",
"enum": ["origin", "avif"]
"enum": ["origin", "avif", "webp"]
},
"in": "query",
"name": "format",
@@ -3862,7 +3862,7 @@
{
"schema": {
"type": "string",
"enum": ["origin", "avif"]
"enum": ["origin", "avif", "webp"]
},
"in": "query",
"name": "format",
@@ -3962,7 +3962,7 @@
{
"schema": {
"type": "string",
"enum": ["origin", "avif"]
"enum": ["origin", "avif", "webp"]
},
"in": "query",
"name": "format",
@@ -4061,7 +4061,7 @@
{
"schema": {
"type": "string",
"enum": ["origin", "avif"]
"enum": ["origin", "avif", "webp"]
},
"in": "query",
"name": "format",
@@ -4167,7 +4167,7 @@
{
"schema": {
"type": "string",
"enum": ["origin", "avif"]
"enum": ["origin", "avif", "webp"]
},
"in": "query",
"name": "format",
@@ -4411,7 +4411,7 @@
{
"schema": {
"type": "string",
"enum": ["origin", "avif"]
"enum": ["origin", "avif", "webp"]
},
"in": "query",
"name": "format",
@@ -4517,7 +4517,7 @@
{
"schema": {
"type": "string",
"enum": ["origin", "avif"]
"enum": ["origin", "avif", "webp"]
},
"in": "query",
"name": "format",
@@ -43,14 +43,14 @@ body {
color: #333 !important;
}
// a {
// text-decoration: none !important;
// }
/* a { */
/* text-decoration: none !important; */
/* } */
article h1 {
// margin-bottom: 2rem !important;
// font-size: 3rem !important;
// font-weight: 400 !important;
/* margin-bottom: 2rem !important; */
/* font-size: 3rem !important; */
/* font-weight: 400 !important; */
}
.thin-scrollbar {
@@ -91,8 +91,8 @@ pre[class*='language-'] {
text-shadow: none !important;
}
// Spec doc specifics ported from docusaurus
// @TODO these should be converted to Tailwind classes
/* Spec doc specifics ported from docusaurus */
/* @TODO these should be converted to Tailwind classes */
.method-list-item {
@apply border-t border-gray-400;
@@ -157,18 +157,18 @@ pre[class*='language-'] {
margin-bottom: 4px;
}
// These should move to their own components
// wasn't able to get an import path working
/* These should move to their own components */
/* wasn't able to get an import path working */
.parent-menu-toggle.active {
svg {
transform: rotate(90deg);
}
}
// ToC styles
// .toc__menu-item--active {
// color: hsl(var(--brand-default)) !important;
// }
/* ToC styles */
/* .toc__menu-item--active { */
/* color: hsl(var(--brand-default)) !important; */
/* } */
.video-container {
position: relative;
@@ -189,7 +189,7 @@ pre[class*='language-'] {
@apply m-0;
}
// format <code> inside <p>
/* format <code> inside <p> */
h2 code,
h3 code,
h4 code {
@@ -205,7 +205,7 @@ h4 code {
}
}
// code inside admonitions
/* code inside admonitions */
.admonition-content p code {
@apply bg-control;
word-break: keep-all !important;
@@ -216,13 +216,13 @@ article p strong {
color: inherit !important;
}
// fix box shadow when <code> is inside <a>
/* fix box shadow when <code> is inside <a> */
a:has(code) {
box-shadow: none !important;
}
// fix code line wrapping
// need to set this to happen from medium onwards, otherwise the would cause horizontal scroll
/* fix code line wrapping */
/* need to set this to happen from medium onwards, otherwise the would cause horizontal scroll */
article p code {
&::before,
&::after {
@@ -237,12 +237,12 @@ article p code {
}
}
// fix firefox issue with li wrapping
/* fix firefox issue with li wrapping */
.doc-content-container ul li div.relative {
display: inline-block;
}
// fix ToC links when they have <code> inside
/* fix ToC links when they have <code> inside */
.toc-menu li a code {
background: none;
border: none;
@@ -317,12 +317,12 @@ th code {
@apply not-sr-only;
}
// Code blocks need margin applied when in content container
/* Code blocks need margin applied when in content container */
.prose :where(.shiki:not(.shiki-wrapper *), .shiki-wrapper) {
margin-block: 2rem;
}
// Code block theme colors for use with Supabase Theme
/* Code block theme colors for use with Supabase Theme */
[data-theme='dark'],
[data-theme='deep-dark'],
.dark,
+22
View File
@@ -0,0 +1,22 @@
/* overwrite for typography */
/* .prose ul { */
/* li { */
/* position: relative; */
/* } */
/* li::before { */
/* position: absolute; */
/* top: 0.75rem; */
/* left: -1rem; */
/* height: 0.125rem; */
/* width: 0.5rem; */
/* border-radius: 0.25rem; */
/* background-color: var(--colors-scale9); */
/* opacity: 0.6; */
/* content: ''; */
/* } */
/* } */
/* article { */
/* background: yellow !important; */
/* } */
-22
View File
@@ -1,22 +0,0 @@
// overwrite for typography
// .prose ul {
// li {
// position: relative;
// }
// li::before {
// position: absolute;
// top: 0.75rem;
// left: -1rem;
// height: 0.125rem;
// width: 0.5rem;
// border-radius: 0.25rem;
// background-color: var(--colors-scale9);
// opacity: 0.6;
// content: '';
// }
// }
// article {
// background: yellow !important;
// }
File renamed without changes.
-4
View File
@@ -1,4 +0,0 @@
declare module '*.scss' {
export const styles: Record<string, string>
export default styles
}
+1 -5
View File
@@ -1,5 +1 @@
module.exports = {
plugins: {
tailwindcss: {},
},
}
module.exports = require('config/postcss.config')
+8 -14
View File
@@ -1,12 +1,12 @@
{
"rules": {
"react-hooks/exhaustive-deps": 189,
"react-hooks/exhaustive-deps": 183,
"import/no-anonymous-default-export": 57,
"@tanstack/query/exhaustive-deps": 12,
"@typescript-eslint/no-explicit-any": 1070,
"@typescript-eslint/no-explicit-any": 1066,
"no-restricted-imports": 0,
"no-restricted-exports": 269,
"react/no-unstable-nested-components": 62,
"react/no-unstable-nested-components": 59,
"studio/require-safe-sql-fragment": 158
},
"ruleFiles": {
@@ -37,7 +37,7 @@
"components/interfaces/Auth/ThirdPartyAuthForm/CreateWorkOSDialog.tsx": 1,
"components/interfaces/Billing/Payment/AddNewPaymentMethodModal.tsx": 1,
"components/interfaces/Billing/Payment/PaymentConfirmation.tsx": 1,
"components/interfaces/Billing/Payment/PaymentMethods/NewPaymentMethodElement.tsx": 2,
"components/interfaces/Billing/Payment/PaymentMethods/NewPaymentMethodElement.tsx": 1,
"components/interfaces/Connect/DatabaseConnectionString.tsx": 2,
"components/interfaces/ConnectSheet/content/steps/mcp/cursor/content.tsx": 1,
"components/interfaces/Database/Backups/PITR/TimeInput.tsx": 4,
@@ -90,7 +90,6 @@
"components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/index.tsx": 2,
"components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.tsx": 1,
"components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/TextEditor.tsx": 2,
"components/interfaces/TableGridEditor/TableDefinition.tsx": 1,
"components/interfaces/TableGridEditor/TableGridEditor.tsx": 2,
"components/interfaces/UnifiedLogs/ServiceFlow/components/ServiceFlowHeader.tsx": 2,
"components/layouts/EdgeFunctionsLayout/EdgeFunctionDetailsLayout.tsx": 1,
@@ -135,7 +134,6 @@
"pages/integrations/vercel/[slug]/deploy-button/new-project.tsx": 1,
"pages/integrations/vercel/install.tsx": 1,
"pages/logout.tsx": 1,
"pages/new/[slug].tsx": 4,
"pages/new/index.tsx": 1,
"pages/organizations.tsx": 1,
"pages/project/[ref]/auth/policies.tsx": 2,
@@ -263,7 +261,7 @@
"components/interfaces/Auth/RedirectUrls/RedirectUrlList.tsx": 1,
"components/interfaces/Auth/SessionsAuthSettingsForm/SessionsAuthSettingsForm.tsx": 2,
"components/interfaces/Auth/SiteUrl/SiteUrl.tsx": 1,
"components/interfaces/Auth/SmtpForm/SmtpForm.tsx": 4,
"components/interfaces/Auth/SmtpForm/SmtpForm.tsx": 3,
"components/interfaces/Auth/Users/UserLogs.tsx": 1,
"components/interfaces/Auth/Users/UserPanel.tsx": 1,
"components/interfaces/Auth/Users/Users.utils.tsx": 5,
@@ -274,12 +272,10 @@
"components/interfaces/Billing/Payment/PaymentMethods/PaymentMethods.tsx": 3,
"components/interfaces/BranchManagement/Branch.Commands.tsx": 1,
"components/interfaces/BranchManagement/DatabaseDiffPanel.tsx": 1,
"components/interfaces/BranchManagement/EmptyStates.tsx": 1,
"components/interfaces/BranchManagement/ReviewWithAI.tsx": 1,
"components/interfaces/Connect/ConnectTabs.tsx": 1,
"components/interfaces/Database/Backups/PITR/PITR.utils.ts": 1,
"components/interfaces/Database/Backups/RestoreToNewProject/BackupsList.tsx": 1,
"components/interfaces/Database/EnumeratedTypes/EnumeratedTypeValueRow.tsx": 1,
"components/interfaces/Database/Functions/CreateFunction/FunctionEditor.tsx": 1,
"components/interfaces/Database/Functions/FunctionsList/FunctionList.tsx": 3,
"components/interfaces/Database/Indexes/Indexes.tsx": 1,
@@ -292,7 +288,6 @@
"components/interfaces/Database/Replication/RowMenu.tsx": 2,
"components/interfaces/Database/Replication/UpdateVersionModal.tsx": 2,
"components/interfaces/Database/RestoreToNewProject/RestoreToNewProject.tsx": 1,
"components/interfaces/Database/Schemas/SchemaGraph.tsx": 1,
"components/interfaces/Docs/Description.tsx": 2,
"components/interfaces/Docs/GeneratingTypes.tsx": 1,
"components/interfaces/Docs/Param.tsx": 1,
@@ -312,6 +307,7 @@
"components/interfaces/Integrations/CronJobs/CronJobTableCell.tsx": 2,
"components/interfaces/Integrations/CronJobs/PreviousRunsTab.tsx": 2,
"components/interfaces/Integrations/GraphQL/GraphiQLTab.tsx": 1,
"components/interfaces/Integrations/Integration/IntegrationOverviewTabV2/InstallIntegrationSheet/InstallationSettings.tsx": 1,
"components/interfaces/Integrations/Queues/QueuesSettings.tsx": 1,
"components/interfaces/Integrations/Queues/SingleQueue/MessageDetailsPanel.tsx": 1,
"components/interfaces/Integrations/Queues/SingleQueue/QueueFilters.tsx": 1,
@@ -457,7 +453,7 @@
"components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.utils.ts": 9,
"components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/TextEditor.tsx": 2,
"components/interfaces/TableGridEditor/SidePanelEditor/SchemaEditor.tsx": 2,
"components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx": 12,
"components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx": 13,
"components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.types.ts": 1,
"components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.utils.tsx": 2,
"components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadSheetTextInput.tsx": 1,
@@ -602,7 +598,7 @@
"data/projects/project-create-mutation.ts": 1,
"data/projects/project-detail-query.ts": 2,
"data/replication/restart-pipeline-helper.ts": 2,
"data/replication/rollback-tables-mutation.ts": 2,
"data/replication/rollback-tables-mutation.ts": 1,
"data/reports/database-charts.ts": 4,
"data/reports/v2/auth.config.ts": 16,
"data/reports/v2/edge-functions.config.ts": 9,
@@ -667,7 +663,6 @@
"pages/integrations/vercel/[slug]/deploy-button/new-project.tsx": 1,
"pages/integrations/vercel/[slug]/marketplace/choose-project.tsx": 1,
"pages/new/index.tsx": 1,
"pages/project/[ref]/auth/templates/[templateId].tsx": 1,
"pages/project/[ref]/functions/[functionSlug]/index.tsx": 3,
"pages/project/[ref]/settings/log-drains.tsx": 1,
"state/ai-assistant-state.tsx": 4,
@@ -968,7 +963,6 @@
"components/interfaces/Integrations/VercelGithub/ProjectLinker.tsx": 1,
"components/interfaces/Linter/LintPageTabs.tsx": 1,
"components/interfaces/Linter/LinterDataGrid.tsx": 3,
"components/interfaces/Markdown.tsx": 3,
"components/interfaces/Organization/BillingSettings/Subscription/PaymentMethodSelection.tsx": 1,
"components/interfaces/Organization/IntegrationSettings/IntegrationSettings.tsx": 1,
"components/interfaces/Organization/Usage/UsageBarChart.tsx": 1,
@@ -7,6 +7,10 @@ function includes(array: string[], element: string) {
/**
* Hook for listening on key events.
*
* @deprecated Use `useShortcut` from `state/shortcuts/useShortcut` instead.
* The new hook reads from a central registry, respects user preferences, and
* can surface shortcuts in the Cmd+P command menu.
*
* @param {Object|Map} keyMap Key names mapped to event handlers. If a key name exists, its
* default behavior will be suppressed.
* @param {Array} whitelistNodes If target element is in the whitelist nodes array, will not
Loaded 100 of 301 files, more files were not shown because too many files have changed in this diff. Show more