diff --git a/apps/docs/components/Navigation/Navigation.constants.ts b/apps/docs/components/Navigation/Navigation.constants.ts index 96799eb177d..5a89f426a91 100644 --- a/apps/docs/components/Navigation/Navigation.constants.ts +++ b/apps/docs/components/Navigation/Navigation.constants.ts @@ -80,6 +80,7 @@ export const menuItems: NavMenu = { label: 'Auth', items: [ { name: 'Overview', url: '/guides/auth', items: [] }, + { name: 'Quickstarts', url: '/guides/auth/quickstarts/react', items: [] }, { name: 'Authentication', url: undefined, @@ -174,14 +175,6 @@ export const menuItems: NavMenu = { { name: 'Database Webhooks', url: '/guides/database/webhooks', items: [] }, { name: 'Full Text Search', url: '/guides/database/full-text-search', items: [] }, { name: 'Database Testing', url: '/guides/database/testing', items: [] }, - { - name: 'Serverless APIs', - url: undefined, - items: [ - { name: 'Overview', url: '/guides/database/api', items: [] }, - { name: 'Generating Types', url: '/guides/database/api/generating-types', items: [] }, - ], - }, { name: 'Extensions', url: undefined, @@ -228,6 +221,13 @@ export const menuItems: NavMenu = { }, ], }, + { + label: 'Serverless APIs', + items: [ + { name: 'Overview', url: '/guides/api', items: [] }, + { name: 'Generating Types', url: '/guides/api/generating-types', items: [] }, + ], + }, { label: 'Edge Functions', items: [ @@ -388,7 +388,6 @@ export const menuItems: NavMenu = { url: undefined, items: [ { name: 'Appsmith', url: '/guides/integrations/appsmith', items: [] }, - { name: 'Dashibase', url: '/guides/integrations/dashibase', items: [] }, { name: 'DhiWise', url: '/guides/integrations/dhiwise', items: [] }, { name: 'Directus', url: '/guides/integrations/directus', items: [] }, { name: 'Draftbit', url: '/guides/integrations/draftbit', items: [] }, diff --git a/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx b/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx index a202f5d5548..1798c82798d 100644 --- a/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx @@ -27,6 +27,12 @@ const home = [ href: '/guides/database', level: 'database', }, + { + label: 'Serverless APIs', + icon: '/img/icons/menu/reference', + href: '/guides/api', + level: 'api', + }, { label: 'Auth', icon: '/img/icons/menu/auth', diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index 14f72d845cc..8b88fe60fa9 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -131,7 +131,7 @@ export const gettingstarted = { } export const cli = { - label: 'CLI', + title: 'CLI', items: [ { name: 'Overview', url: '/guides/cli' }, { name: 'Local Development', url: '/guides/cli/local-development' }, @@ -253,12 +253,16 @@ export const PhoneLoginsItems = [ export const auth = { icon: 'auth', - label: 'Auth', + title: 'Auth', items: [ { name: 'Overview', url: '/guides/auth', }, + { + name: 'Quickstarts', + items: [{ name: 'Auth with React', url: '/guides/auth/quickstarts/react', items: [] }], + }, { name: 'Authentication', url: undefined, @@ -339,7 +343,7 @@ export const auth = { export const database = { icon: 'database', - label: 'Database', + title: 'Database', url: '/guides/database', items: [ { name: 'Database Connections', url: '/guides/database/connecting-to-postgres' }, @@ -348,14 +352,6 @@ export const database = { { name: 'Database Webhooks', url: '/guides/database/webhooks' }, { name: 'Full Text Search', url: '/guides/database/full-text-search' }, { name: 'Database Testing', url: '/guides/database/testing' }, - { - name: 'Serverless APIs', - url: undefined, - items: [ - { name: 'Overview', url: '/guides/database/api' }, - { name: 'Generating Types', url: '/guides/database/api/generating-types' }, - ], - }, { name: 'Extensions', url: undefined, @@ -496,9 +492,47 @@ export const database = { ], } +export const api = { + icon: 'reference', + title: 'Serverless APIs', + url: '/guides/api', + items: [ + { name: 'Overview', url: '/guides/api', items: [] }, + { name: 'Quickstart', url: '/guides/api/quickstart', items: [] }, + { + name: 'Guides', + url: '/guides/api', + items: [ + { name: 'Creating API routes', url: '/guides/api/creating-routes', items: [] }, + { name: 'How API Keys work', url: '/guides/api/api-keys', items: [] }, + { name: 'Securing your API', url: '/guides/api/securing-your-api', items: [] }, + { + name: 'Querying joins and nested tables', + url: '/guides/api/joins-and-nesting', + items: [], + }, + ], + }, + { + name: 'REST & REALTIME', + url: undefined, + items: [ + { name: 'Auto-generated Docs', url: '/guides/api/rest/auto-generated-docs', items: [] }, + { name: 'Client Libraries', url: '/guides/api/rest/client-libs', items: [] }, + { name: 'Generating Types', url: '/guides/api/rest/generating-types', items: [] }, + ], + }, + { + name: 'GRAPHQL', + url: undefined, + items: [{ name: 'GraphiQL Documentation', url: '/guides/api/graphql/graphiql', items: [] }], + }, + ], +} + export const functions = { icon: 'functions', - label: 'Edge Functions', + title: 'Edge Functions', url: '/guides/functions', items: [ { @@ -565,7 +599,7 @@ export const functions = { export const realtime = { icon: 'realtime', - label: 'Realtime', + title: 'Realtime', url: '/guides/realtime', items: [ { @@ -628,7 +662,7 @@ export const realtime = { export const storage = { icon: 'storage', - label: 'Storage', + title: 'Storage', url: '/guides/storage', items: [ { name: 'Overview', url: '/guides/storage' }, @@ -660,7 +694,7 @@ export const supabase_cli = { export const platform = { icon: 'platform', - label: 'Platform', + title: 'Platform', url: '/guides/platform', items: [ { @@ -732,7 +766,7 @@ export const platform = { export const resources = { icon: 'resources', - label: 'Resources', + title: 'Resources', url: '/guides/resources', items: [ { name: 'Examples', url: '/guides/resources/examples' }, @@ -798,7 +832,7 @@ export const self_hosting = { } export const migrate = { - label: 'Migrate to Supabase', + title: 'Migrate to Supabase', url: '/guides/migrate', items: [ { name: 'Firebase Auth', url: '/guides/migrations/firebase-auth' }, @@ -811,7 +845,7 @@ export const migrate = { export const integrations = { icon: 'integrations', - label: 'Integrations', + title: 'Integrations', url: '/guides/integrations', items: [ { name: 'Overview', url: '/guides/integrations/integrations' }, @@ -856,7 +890,6 @@ export const integrations = { url: undefined, items: [ { name: 'Appsmith', url: '/guides/integrations/appsmith' }, - { name: 'Dashibase', url: '/guides/integrations/dashibase' }, { name: 'DhiWise', url: '/guides/integrations/dhiwise' }, { name: 'Directus', url: '/guides/integrations/directus' }, { name: 'Draftbit', url: '/guides/integrations/draftbit' }, diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx index e585077975f..0b481973cb8 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx @@ -85,6 +85,9 @@ const NavigationMenu = () => { case url.includes(`/docs/guides/database`) && url: menuState.setMenuLevelId('database') break + case url.includes(`/docs/guides/api`) && url: + menuState.setMenuLevelId('api') + break case url.includes(`/docs/guides/auth`) && url: menuState.setMenuLevelId('auth') break @@ -174,6 +177,7 @@ const NavigationMenu = () => { const isHomeActive = 'home' === level const isGettingStartedActive = 'gettingstarted' === level const isDatabaseActive = 'database' === level + const isApiActive = 'api' === level const isAuthActive = 'auth' === level const isFunctionsActive = 'functions' === level const isRealtimeActive = 'realtime' === level @@ -203,6 +207,7 @@ const NavigationMenu = () => { + As you update your database the changes are immediately accessible through your API. +- **Self documenting.**
Supabase generates documentation in the Dashboard which updates as you make database changes. +- **Secure.**
The API is configured to work with PostgreSQL's Row Level Security, provisioned behind an API gateway with key-auth enabled. +- **Fast.**
Our benchmarks for basic reads are more than 300% faster than Firebase. The API is a very thin layer on top of Postgres, which does most of the heavy lifting. +- **Scalable.**
The API can serve thousands of simultaneous requests, and works well for Serverless workloads. + +## REST API [#rest-api-overview] + +Supabase provides a RESTful API using [PostgREST](https://postgrest.org/). This is a very thin API layer on top of Postgres. +It provides everything you need from a CRUD API: + +- Basic CRUD operations +- Deeply nested joins, allowing you to fetch data from multiple tables in a single fetch +- Works with Postgres Views +- Works with Postgres Functions +- Works with the Postgres security model - including Row Level Security, Roles, and Grants. + +## GraphQL API [#graphql-api-overview] + +GraphQL in Supabase works through [pg_graphql](https://supabase.com/blog/pg-graphql), an open source PostgreSQL extension for GraphQL. + +## Realtime API [#realtime-api-overview] + +Supabase provides a Realtime API using [Realtime](https://github.com/supabase/realtime). You can use this to listen to database changes over websockets. +Realtime leverages PostgreSQL's built-in logical replication. You can manage your Realtime API simply by managing Postgres publications. +Go to your project's [Replication section](https://app.supabase.com/project/_/database/replication) to get started. + +export const Page = ({ children }) => + +export default Page diff --git a/apps/docs/pages/guides/api/api-keys.mdx b/apps/docs/pages/guides/api/api-keys.mdx new file mode 100644 index 00000000000..3f9869586f5 --- /dev/null +++ b/apps/docs/pages/guides/api/api-keys.mdx @@ -0,0 +1,70 @@ +import Layout from '~/layouts/DefaultGuideLayout' + +export const meta = { + id: 'api-keys', + title: 'Understanding API Keys', + description: 'Securing your Serverless API with Postgres Row Level Security.', +} + +Supabase provides two default keys when you create a project: an `anon` key, and a `service_role` key. You can find both keys in the [API Settings](https://app.supabase.com/project/_/settings/api). + +The Serverless APIs are designed to work with Postgres Row Level Security (RLS). These keys both map to Postgres roles. You can find an `anon` user and a `service_role` user in the [Roles](http://app.supabase.com/project/_/database/roles) section of the dashboard. + +The keys are both long-lived JWTs. If you decode these keys, you will see that they contain the "role", an "issued date", and an "expiry date" ~10 years in the future. + +```json +{ + "role": "anon", + "iat": 1625137684, + "exp": 1940713684 +} +``` + +## The `anon` key + +The `anon` key has very few privileges. You can use it in your [RLS policies](/docs/guides/auth/row-level-security) for "anonymous" access. For example, this policy will allow access to the `profiles` table: + +```sql +create policy "Allow anonymous access" on profiles to anon for +select + using (true); +``` + +And similarity for disallowing access: + +```sql +create policy "Disallow anonymous access" on profiles to anon for +select + using (false); +``` + +If you are using [Supabase Auth](/docs/guides/auth/overview), then the `anon` role will automatically update to `authenticated` once a user is logged in: + +```sql +create policy "Allow access to authenticated users" on profiles to authenticated for +select + using (true); +``` + +## The `service_role` key + +The "service_role" is a predefined Postgres role with elevated privileges, designed to perform various administrative and service-related tasks. It can bypass Row Level Security, so it should only be used on a private server. + + + Never expose the `service_role` key in a browser or anywhere where a user can see it. + + +A common use case for the `service_role` key is running data analytics jobs on the backend. To support joins on user id, it is often useful to grant the service role read access to `auth.users` table. + +```sql +grant +select + on table auth.users to service_role; +``` + +We have [partnered with GitHub](https://github.blog/changelog/2022-03-28-supabase-is-now-a-github-secret-scanning-partner/) to scan for Supabase `service_role` keys pushed to public repositories. +If they detect any keys with service_role privileges being pushed to GitHub, they will forward the API key to us, so that we can automatically revoke the detected secrets and notify you, protecting your data against malicious actors. + +export const Page = ({ children }) => + +export default Page diff --git a/apps/docs/pages/guides/api/creating-routes.mdx b/apps/docs/pages/guides/api/creating-routes.mdx new file mode 100644 index 00000000000..c48442f12d1 --- /dev/null +++ b/apps/docs/pages/guides/api/creating-routes.mdx @@ -0,0 +1,252 @@ +import Layout from '~/layouts/DefaultGuideLayout' + +export const meta = { + id: 'creating-routes', + title: 'Creating API Routes', + description: + 'API routes are automatically created when you create Postgres Tables, Views, or Functions.', +} + +API routes are automatically created when you create Postgres Tables, Views, or Functions. + +## Create a table + +Let's create our first API route by creating a table called `todos` to store tasks. +This creates a corresponding route `todos` which can accept `GET`, `POST`, `PATCH`, & `DELETE` requests. + + + + +1. Go to the [Table editor](https://app.supabase.com/project/_/editor) page in the Dashboard. +1. Click **New Table** and create a table with the name `todos`. +1. Click **Save**. +1. Click **New Column** and create a column with the name `task` and type `text`. +1. Click **Save**. + + + + + + +```sql + -- 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) + ); +``` + + + + +## 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. + +1. Go to the [Settings](https://app.supabase.com/project/_/settings/general) page in the Dashboard. +2. Click **API** in the sidebar. +3. Find your API `URL`, `anon`, and `service_role` keys on this page. + + + +The REST API and the GraphQL API are both accessible through this URL: + +- REST: `https://.supabase.co/rest/v1` +- GraphQL: `https://.supabase.co/graphql/v1` + +Both of these routes require the `anon` key to be passed through an `apikey` header. + +## Using the API + +### REST API + +You can interact with your API directly via HTTP requests, or you can use the client libraries which we provide. + +Let's see how to make a request to the `todos` table which we created in the first step, +using the API URL (`SUPABASE_URL`) and Key (`SUPABASE_ANON_KEY`) we provided: + + + + +```javascript +// Initialize the JS client +import { createClient } from '@supabase/supabase-js' +const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY) + +// Make a request +const { data: todos, error } = await supabase.from('todos').select('*') +``` + + + + +```bash +# Append /rest/v1/ to your URL, and then use the table name as the route +curl '/rest/v1/todos' \ +-H "apikey: " \ +-H "Authorization: Bearer " +``` + + + + +JS Reference: [select()](/docs/reference/javascript/select), +[insert()](/docs/reference/javascript/insert), +[update()](/docs/reference/javascript/update), +[upsert()](/docs/reference/javascript/upsert), +[delete()](/docs/reference/javascript/delete), +[rpc()](/docs/reference/javascript/rpc) (call Postgres functions). + +### GraphQL API + +You can use any GraphQL client with the Supabase GraphQL API. For our GraphQL example we will use [urql](https://formidable.com/open-source/urql/docs/). + + + + +```javascript +import { createClient, useQuery } from 'urql' + +// Prepare API key and Authorization header +const headers = { + apikey: , + authorization: `Bearer ${}`, +} + +// Create GraphQL client +// See: https://formidable.com/open-source/urql/docs/basics/react-preact/#setting-up-the-client +const client = createClient({ + url: '/graphql/v1', + fetchOptions: function createFetchOptions() { + return { headers } + }, +}) + +// Prepare our GraphQL query +const TodosQuery = ` + query { + todosCollection { + edges { + node { + id + title + } + } + } + } +` + +// Query for the data (React) +const [result, reexecuteQuery] = useQuery({ + query: TodosQuery, +}) + +// Read the result +const { data, fetching, error } = result +``` + + + + +```bash +# Append /graphql/v1/ to your URL, and then use the table name as the route +curl --request POST '/graphql/v1' \ +-H 'apikey: ' \ +-H 'Authorization: Bearer ' \ +-H 'Content-Type: application/json' \ +-d '{ "query":"{ todos(first: 3) { edges { node { id } } } }" }' +``` + + + + +### Realtime API + +By default Realtime is disabled on your database. Let's turn on Realtime for the `todos` table. + + + + +1. Go to the [Database](https://app.supabase.com/project/_/database/tables) page in the Dashboard. +2. Click on **Replication** in the sidebar. +3. Control which database events are sent by toggling **Insert**, **Update**, and **Delete**. +4. Control which tables broadcast changes by selecting **Source** and toggling each table. + + + + + + +```sql +alter + publication supabase_realtime add table todos; +``` + + + + +From the client, we can listen to any new data that is inserted into the `todos` table: + +```javascript +// Initialize the JS client +import { createClient } from '@supabase/supabase-js' +const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY) + +// Create a function to handle inserts +const handleInserts = (payload) => { + console.log('Change received!', payload) +} + +// Listen to inserts +const { data: todos, error } = await supabase.from('todos').on('INSERT', handleInserts).subscribe() +``` + +Use [subscribe()](/docs/reference/javascript/subscribe) to listen to database changes. +The Realtime API works through PostgreSQL's replication functionality. Postgres sends database changes to a [publication](/docs/guides/database/replication#publications) +called `supabase_realtime`, and by managing this publication you can control which data is broadcast. + +export const Page = ({ children }) => + +export default Page diff --git a/apps/docs/pages/guides/api/graphql/graphiql.mdx b/apps/docs/pages/guides/api/graphql/graphiql.mdx new file mode 100644 index 00000000000..a3ce41073fd --- /dev/null +++ b/apps/docs/pages/guides/api/graphql/graphiql.mdx @@ -0,0 +1,22 @@ +import Layout from '~/layouts/DefaultGuideLayout' + +export const meta = { + id: 'graphiql', + title: 'GraphiQL documentation', + description: 'Some docs on graphiql.', + video: 'https://www.youtube.com/v/7CqlTU9aOR4', +} + +Every Supabase project has a GraphQL Endpoint: `https://.supabase.co/graphql/v1`. + +This endpoint is compatible with any GraphiQL implementation that can pass an `apikey` header. +Some suggested applications: + +- [paw.cloud](https://paw.cloud) +- [insomnia.rest](https://insomnia.rest) +- [postman.com/graphql](https://www.postman.com/graphql/) +- Self-hosted GraphiQL: GraphiQL can be served through a simple HTML file. See [this discussion](https://github.com/supabase/supabase/discussions/6144) for more details. + +export const Page = ({ children }) => + +export default Page diff --git a/apps/docs/pages/guides/api/joins-and-nesting.mdx b/apps/docs/pages/guides/api/joins-and-nesting.mdx new file mode 100644 index 00000000000..470eba7a5aa --- /dev/null +++ b/apps/docs/pages/guides/api/joins-and-nesting.mdx @@ -0,0 +1,206 @@ +import Layout from '~/layouts/DefaultGuideLayout' + +export const meta = { + id: 'joins-and-nested-tables', + title: 'Querying Joins and Nested tables', + description: 'The Serverless APIs automatically detect relationships between Postgres tables.', +} + +The Serverless APIs automatically detect relationships between Postgres tables. Since Postgres is a relational database, this is a very common scenario. + +## One-to-many joins + +Let's use an example database that stores `countries` and `cities`: + + + + +**Countries** + +| `id` | `name` | +| ---- | -------------- | +| 1 | United Kingdom | +| 2 | United States | + +**Cities** + +| `id` | `name` | `country_id` | +| ---- | ----------- | ------------ | +| 1 | London | 1 | +| 2 | Manchester | 1 | +| 3 | Los Angeles | 2 | +| 4 | New York | 2 | + + + + +```sql +create table + countries ("id" serial primary key, "name" text); + +insert into + countries (id, name) +values + (1, 'United Kingdom'), + (2, 'United States'); + +create table + cities ( + "id" serial primary key, + "name" text, + "country_id" int references "countries" + ); + +insert into + cities (name, country_id) +values + ('London', 1), + ('Manchester', 1), + ('Los Angeles', 2), + ('New York', 2); +``` + + + + +The APIs will automatically detect relationships based on the foreign keys: + + + + +```js +const { data, error } = await supabase.from('countries').select(` + id, + name, + cities ( id, name ) +`) +``` + + + + +```dart +final data = await supabase.from('todos').select('id, name, cities(id, name)'); +``` + + + + +```javascript +const Query = ` + query { + countriesCollection { + edges { + node { + id + name + cities { + id, + name + } + } + } + } + } +` +``` + + + + +```bash +GET https://[REF].supabase.co/rest/v1/countries?select=id,name,cities(id,name) +``` + + + + +## Many-to-many joins + +The Serverless APIs will detect many-to-many joins. For example, if you have a database which stored teams of users (where each user could below to many teams): + +```sql +create table + users ("id" serial primary key, "name" text); + +create table + teams ("id" serial primary key, "team_name" text); + +create table + members ( + "id" serial primary key, + "user_id" int references users, + "team_id" int references teams + ); +``` + +In these cases you don't need to explicitly define the joining table (members). If we wanted to fetch all the teams and the members in each team: + + + + +```js +const { data, error } = await supabase.from('teams').select(` + id, + team_name, + users ( id, name ) +`) +``` + + + + +```dart +final data = await supabase.from('teams').select('id, team_name, users(id, name)'); +``` + + + + +```javascript +const Query = ` + query { + teamsCollection { + edges { + node { + id + team_name + users { + id, + name + } + } + } + } + } +` +``` + + + + +```bash +GET https://[REF].supabase.co/rest/v1/teams?select=id,team_name,users(id,name) +``` + + + + +export const Page = ({ children }) => + +export default Page diff --git a/apps/docs/pages/guides/api/quickstart.mdx b/apps/docs/pages/guides/api/quickstart.mdx new file mode 100644 index 00000000000..7d645a8b5f7 --- /dev/null +++ b/apps/docs/pages/guides/api/quickstart.mdx @@ -0,0 +1,236 @@ +import Layout from '~/layouts/DefaultGuideLayout' +import StepHikeCompact from '~/components/StepHikeCompact' + +export const meta = { + title: 'Build an API route in less than 2 minutes.', + subtitle: 'Create your first API route by creating a table called `todos` to store tasks.', + breadcrumb: 'API Quickstart', +} + +Let's create our first REST route which we can query using `cURL` or the browser. + +We'll create a database table called `todos` for storing tasks. This creates a corresponding API route `/rest/v1/todos` which can accept `GET`, `POST`, `PATCH`, & `DELETE` requests. + + + + + + + [Create a new project](https://app.supabase.com) in the Supabase Dashboard. + + After your project is ready, create a table in your Supabase database. You can do this with either the Table interface or the [SQL Editor](https://app.supabase.com/project/_/sql). + + + + + + + + + ```sql + -- Create a table called "todos" + -- with a column to store tasks. + create table todos ( + id serial primary key, + task text + ); + ``` + + + + + + + + + + + + + + + + + + Let's turn on Row Level Security for this table and allow anonymous access. + + + + + + ```sql + -- Turn on security + alter table "todos" + enable row level security; + + -- Allow anonymous access + create policy "Allow anonymous access" + on todos + to anon + for select + using (true); + ``` + + + + + + + + + Now we can add some data to our table which we can access through our API. + + + + + + ```sql + insert into todos (task) + values + ('Create tables'), + ('Enable security'), + ('Add data'), + ('Fetch data from the API'); + ``` + + + + + + + + + Find your API URL and Keys in your Dashboard [API Settings](https://app.supabase.com/project/_/settings/api). You can now query your "todos" table by appending `/rest/v1/todos` to the API URL. + + Copy this block of code, substitute `` and ``, then run it from a terminal. + + + + + ```bash Terminal + curl 'https://.supabase.co/rest/v1/todos' \ + -H "apikey: " \ + -H "Authorization: Bearer " + ``` + + + + + + + +## Bonus + +There are several options for accessing your data: + +### Browser + +You can query the route in your browser, by appending the `anon` key as a query parameter: + +`https://.supabase.co/rest/v1/users?apikey=` + +### Client libraries + +We provide a numerous [Client Libraries](https://github.com/supabase/supabase#client-libraries). + + + + +```js +const { data, error } = await supabase.from('todos').select() +``` + + + + +```dart +final data = await supabase.from('todos').select('*'); +``` + + + + +```python +response = supabase.table('todos').select("*").execute() +``` + + + + +### GraphQL + +Every table can be accessed through the GraphQL API by switching `/rest/v1` with `/graphql/v1`. + + + + +```javascript +import { createClient, useQuery } from 'urql' + +const URL = '/graphql/v1' +const ANON_KEY = '' + +// Prepare API key and Authorization header +const headers = { + apikey: `${ANON_KEY}`, + authorization: `Bearer ${ANON_KEY}`, +} + +const client = createClient({ + url: URL, + fetchOptions: function createFetchOptions() { + return { headers } + }, +}) + +// Prepare our GraphQL query +const TodosQuery = ` + query { + todosCollection { + edges { + node { + id + task + } + } + } + } +` + +// Query for the data (React) +const [result, reexecuteQuery] = useQuery({ + query: TodosQuery, +}) + +// Read the result +const { data, fetching, error } = result +``` + + + + +export const Page = ({ children }) => + +export default Page diff --git a/apps/docs/pages/guides/api/rest/auto-generated-docs.mdx b/apps/docs/pages/guides/api/rest/auto-generated-docs.mdx new file mode 100644 index 00000000000..82709aa7a1a --- /dev/null +++ b/apps/docs/pages/guides/api/rest/auto-generated-docs.mdx @@ -0,0 +1,26 @@ +import Layout from '~/layouts/DefaultGuideLayout' + +export const meta = { + id: 'auto-docs', + title: 'Auto-generated documentation', + description: 'Supabase provides documentation that updates automatically.', +} + +Supabase generates documentation in the [Dashboard](https://app.supabase.com) which updates as you make database changes. + +1. Go to the [API](https://app.supabase.com/project/_/api) page in the Dashboard. +2. Select any table under **Tables and Views** in the sidebar. +3. Switch between the JavaScript and the cURL docs using the tabs. + + + +export const Page = ({ children }) => + +export default Page diff --git a/apps/docs/pages/guides/api/rest/client-libs.mdx b/apps/docs/pages/guides/api/rest/client-libs.mdx new file mode 100644 index 00000000000..4b6272e1f6d --- /dev/null +++ b/apps/docs/pages/guides/api/rest/client-libs.mdx @@ -0,0 +1,33 @@ +import Layout from '~/layouts/DefaultGuideLayout' + +export const meta = { + id: 'client-libs', + title: 'Client Libraries', + description: 'Supabase provides several client libraries for the REST and Realtime APIs.', + video: 'https://www.youtube.com/v/7CqlTU9aOR4', +} + +Supabase provides client libraries for the REST and Realtime APIs. Some libraries are officially supported, and some are contributed by the community. + +## Official Libraries + +| `Language` | `Source Code` | `Documentation` | +| --------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------- | +| Javascript/Typescript | [supabase-js](https://github.com/supabase/supabase-js) | [Docs](https://supabase.com/docs/reference/javascript/introduction) | +| Dart/Flutter | [supabase-dart](https://github.com/supabase/supabase-dart) | [Docs](https://supabase.com/docs/reference/dart/introduction) | + +## Community Libraries + +| `Language` | `Source Code` | `Documentation` | +| ----------------------- | -------------------------------------------------------------------------------- | --------------------------------------------------------------- | +| C# | [supabase-js](https://github.com/supabase-community/supabase-csharp) | [Docs](https://supabase.com/docs/reference/csharp/introduction) | +| Go | [supabase-go](https://github.com/supabase-community/supabase-go) | | +| Kotlin | [supabase-kt](https://github.com/supabase-community/supabase-kt) | | +| Python | [supabase-py](https://github.com/supabase-community/supabase-py) | [Docs](https://supabase.com/docs/reference/python/initializing) | +| Ruby | [supabase-rb](https://github.com/supabase-community/supabase-rb) | | +| Swift | [supabase-swift](https://github.com/supabase-community/supabase-swift) | | +| Godot Engine (GDScript) | [supabase-gdscript](https://github.com/supabase-community/godot-engine.supabase) | | + +export const Page = ({ children }) => + +export default Page diff --git a/apps/docs/pages/guides/database/api/generating-types.mdx b/apps/docs/pages/guides/api/rest/generating-types.mdx similarity index 100% rename from apps/docs/pages/guides/database/api/generating-types.mdx rename to apps/docs/pages/guides/api/rest/generating-types.mdx diff --git a/apps/docs/pages/guides/api/securing-your-api.mdx b/apps/docs/pages/guides/api/securing-your-api.mdx new file mode 100644 index 00000000000..70fa2ef38ae --- /dev/null +++ b/apps/docs/pages/guides/api/securing-your-api.mdx @@ -0,0 +1,66 @@ +import Layout from '~/layouts/DefaultGuideLayout' + +export const meta = { + id: 'securing-your-api', + title: 'Securing your API', + description: 'Securing your Serverless API with Postgres Row Level Security.', +} + +The Serverless APIs are designed to work with Postgres Row Level Security (RLS). If you use [Supabase Auth](/docs/guides/auth), you can restrict data based on the logged-in user. +To control access to your data, you can use [Policies](/docs/guides/auth#policies). + +## Enabling Row Level Security + +If you create a table through the Dashboard, RLS will be enabled by default. This is not the case, however, if you create a table or view using SQL. +To enable RLS on any table: + + + + +1. Go to the [Authentication](https://app.supabase.com/project/_/auth/users) page in the Dashboard. +2. Click on **Policies** in the sidebar. +3. Select **Enable RLS** to enable Row Level Security. + + + + +```sql +alter table + todos enable row level security; +``` + + + + +With RLS enabled, you can create Policies that allow or disallow users to access and update data. We provide a detailed guide for creating Row Level Security Policies in our [Authorization documentation](/docs/guides/auth/row-level-security). + +## Safeguards towards accidental deletes and updates + +By default, all projects have the [safeupdate](https://github.com/eradman/pg-safeupdate) Postgres extension enabled for API queries. +This ensures that `delete()` and `update()` requests will fail if there are no filters provided. +To confirm that safeupdate is enabled for API queries, run the following query: + +```sql +select + usename, + useconfig +from + pg_shadow +where + usename = 'authenticator'; +``` + +The expected value for `useconfig` should be: + +```sql +['session_preload_libraries=supautils, safeupdate'] +``` + +export const Page = ({ children }) => + +export default Page diff --git a/apps/docs/pages/guides/auth/auth-helpers/nextjs-server-components.mdx b/apps/docs/pages/guides/auth/auth-helpers/nextjs-server-components.mdx index 21ec7369f1f..c819a3f745f 100644 --- a/apps/docs/pages/guides/auth/auth-helpers/nextjs-server-components.mdx +++ b/apps/docs/pages/guides/auth/auth-helpers/nextjs-server-components.mdx @@ -255,7 +255,9 @@ export default function SupabaseProvider({ children }) { const [supabase] = useState(() => createClient()) useEffect(() => { - const { data: { subscription } } = supabase.auth.onAuthStateChange((event, session) => { + const { + data: { subscription }, + } = supabase.auth.onAuthStateChange((event, session) => { if (session?.access_token !== accessToken) { router.refresh() } @@ -306,11 +308,11 @@ export default function SupabaseProvider({ children }: { children: React.ReactNo } export const useSupabase = () => { - let context = useContext(Context); + let context = useContext(Context) if (context === undefined) { - throw new Error("useSupabase must be used inside SupabaseProvider"); + throw new Error('useSupabase must be used inside SupabaseProvider') } else { - return context; + return context } } ``` @@ -515,7 +517,7 @@ import { useSupabase } from './supabase-provider' // Supabase auth needs to be triggered client-side export default function Login() { - const { supabase, session } = useSupabase() + const { supabase } = useSupabase() const handleEmailLogin = async () => { await supabase.auth.signInWithPassword({ @@ -555,7 +557,7 @@ import { useSupabase } from './supabase-provider' // Supabase auth needs to be triggered client-side export default function Login() { - const { supabase, session } = useSupabase() + const { supabase } = useSupabase() const handleEmailLogin = async () => { await supabase.auth.signInWithPassword({ diff --git a/apps/docs/pages/guides/auth/auth-helpers/sveltekit.mdx b/apps/docs/pages/guides/auth/auth-helpers/sveltekit.mdx index f4d71380697..99449d191e0 100644 --- a/apps/docs/pages/guides/auth/auth-helpers/sveltekit.mdx +++ b/apps/docs/pages/guides/auth/auth-helpers/sveltekit.mdx @@ -86,7 +86,7 @@ import type { LayoutServerLoad } from './$types'; export const load: LayoutServerLoad = async ({ locals: { getSession } }) => { return { - session: getSession() + session: await getSession() }; }; ``` diff --git a/apps/docs/pages/guides/auth/quickstarts/react.mdx b/apps/docs/pages/guides/auth/quickstarts/react.mdx new file mode 100644 index 00000000000..c2ae0efb7fb --- /dev/null +++ b/apps/docs/pages/guides/auth/quickstarts/react.mdx @@ -0,0 +1,137 @@ +import Layout from '~/layouts/DefaultGuideLayout' +import StepHikeCompact from '~/components/StepHikeCompact' + +export const meta = { + title: 'Use Supabase Auth with React', + subtitle: 'Learn how to Supabase Auth with React.js.', + breadcrumb: 'Auth Quickstarts', +} + + + + + + + [Launch a new project](https://app.supabase.com) in the Supabase Dashboard. + + Your new database has a table for storing your users. You can see that this table is currently empty by running some SQL in the [SQL Editor](https://app.supabase.com/project/_/sql). + + + + + + ```sql SQL_EDITOR + select * from auth.users; + ```` + + + + + + + + + + Create a React app using the `create-react-app` command. + + + + + + ```bash Terminal + npx create-react-app my-app + ``` + + + + + + + + + The fastest way to get started is to use Supabase's `auth-ui-react` library which provides a convenient interface for working with Supabase Auth from a React app. + + Navigate to the React app and install the Supabase libraries. + + + + + + ```bash Terminal + cd my-app && npm install @supabase/supabase-js @supabase/auth-ui-react + ``` + + + + + + + + + In `index.js`, create a Supabase client using your [Project URL and public API (anon) key](https://app.supabase.com/project/_/settings/api). + + You can configure the Auth component to display whenever there is no session inside `supabase.auth.getSession()` + + + + + + ```js src/index.js + import './index.css' + import { useState, useEffect } from 'react' + import { createClient } from '@supabase/supabase-js' + import { Auth, ThemeSupa } from '@supabase/auth-ui-react' + + const supabase = createClient('https://.supabase.co', '') + + export default function App() { + const [session, setSession] = useState(null) + + useEffect(() => { + supabase.auth.getSession().then(({ data: { session } }) => { + setSession(session) + }) + + const { + data: { subscription }, + } = supabase.auth.onAuthStateChange((_event, session) => { + setSession(session) + }) + + return () => subscription.unsubscribe() + }, []) + + if (!session) { + return () + } + else { + return (
Logged in!
) + } + } + ``` + +
+ +
+ + + + + Start the app, go to http://localhost:3000 in a browser, and open the browser console and you should be able to log in. + + + + + + ```bash Terminal + npm start + ``` + + + + +
+ +export const Page = ({ children }) => + +export default Page diff --git a/apps/docs/pages/guides/auth/server-side-rendering.mdx b/apps/docs/pages/guides/auth/server-side-rendering.mdx index 346984a63fb..87235781711 100644 --- a/apps/docs/pages/guides/auth/server-side-rendering.mdx +++ b/apps/docs/pages/guides/auth/server-side-rendering.mdx @@ -130,6 +130,9 @@ if (refreshToken && accessToken) { await supabase.auth.setSession({ refresh_token: refreshToken, access_token: accessToken, + { + auth: { persistSession: false }, + } }) } else { // make sure you handle this case! diff --git a/apps/docs/pages/guides/database/api.mdx b/apps/docs/pages/guides/database/api.mdx deleted file mode 100644 index 04e5ecb97db..00000000000 --- a/apps/docs/pages/guides/database/api.mdx +++ /dev/null @@ -1,404 +0,0 @@ -import Layout from '~/layouts/DefaultGuideLayout' - -export const meta = { - id: 'api', - title: 'Serverless APIs', - description: 'Auto-generating and Realtime APIs.', - sidebar_label: 'Overview', - video: 'https://www.youtube.com/v/rPAJJFdtPw0', -} - -Supabase auto-generates three types of API directly from your database schema. - -- REST - interact with your database through a restful interface. -- Realtime - listen to database changes. -- GraphQL - [in beta](https://supabase.com/blog/pg-graphql). - -The APIs are: - -- **Instant and auto-generated.**
As you update your database the changes are immediately accessible through your API. -- **Self documenting.**
Supabase generates documentation in the Dashboard which updates as you make database changes. -- **Secure.**
The API is configured to work with PostgreSQL's Row Level Security, provisioned behind an API gateway with key-auth enabled. -- **Fast.**
Our benchmarks for basic reads are more than 300% faster than Firebase. The API is a very thin layer on top of Postgres, which does most of the heavy lifting. -- **Scalable.**
The API can serve thousands of simultaneous requests, and works well for Serverless workloads. - -## REST API [#rest-api-overview] - -Supabase provides a RESTful API using [PostgREST](https://postgrest.org/). This is a very thin API layer on top of Postgres. -It provides everything you need from a CRUD API: - -- Basic CRUD operations -- Deeply nested joins, allowing you to fetch data from multiple tables in a single fetch -- Works with Postgres Views -- Works with Postgres Functions -- Works with the Postgres security model - including Row Level Security, Roles, and Grants. - -
- -
- -## GraphQL API [#graphql-api-overview] - - - -GraphQL is in Beta, and may have breaking changes. It is only available on self-hosted setups and Supabase projects created after 28th March 2022. - - - -GraphQL in Supabase works through [pg_graphql](https://supabase.com/blog/pg-graphql), an open source PostgreSQL extension for GraphQL. - -## Realtime API [#realtime-api-overview] - -Supabase provides a Realtime API using [Realtime](https://github.com/supabase/realtime). You can use this to listen to database changes over websockets. -Realtime leverages PostgreSQL's built-in logical replication. You can manage your Realtime API simply by managing Postgres publications. -Go to your project's [Replication section](https://app.supabase.com/project/_/database/replication) to get started. - -## Getting started - -All APIs are auto-created from Database tables. After you have added tables or functions to your database, you can use the APIs provided. - -### Creating API Routes - -API routes are automatically created when you create Postgres Tables, Views, or Functions. - -Let's create our first -API route by creating a table called `todos` to store tasks. -This creates a corresponding route `todos` which can accept `GET`, `POST`, `PATCH`, & `DELETE` requests. - - - - -1. Go to the [Table editor](https://app.supabase.com/project/_/editor) page in the Dashboard. -1. Click **New Table** and create a table with the name `todos`. -1. Click **Save**. -1. Click **New Column** and create a column with the name `task` and type `text`. -1. Click **Save**. - - - - - - -```sql --- 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) -); - -``` - - - - -### 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. - -1. Go to the [Settings](https://app.supabase.com/project/_/settings/general) page in the Dashboard. -2. Click **API** in the sidebar. -3. Find your API `URL`, `anon`, and `service_role` keys on this page. - - - -The REST API and the GraphQL API are both accessible through this URL: - -- REST: `https://.supabase.co/rest/v1` -- GraphQL: `https://.supabase.co/graphql/v1` - -Both of these routes require the `anon` key to be passed through an `apikey` header. - -#### API Keys - -You are provided with two keys: - -- an `anon` key, which is safe to be used in a browser context. -- a `service_role` key, which should only be used on a server. This key can bypass Row Level Security. NEVER use this key in a browser. - -### Accessing the docs in the Dashboard - -#### REST API [#rest-api-dashboard-docs] - -Supabase generates documentation in the [Dashboard](https://app.supabase.com) which updates as you make database changes. -Let's view the documentation for a `countries` table which we created in our database. - -1. Go to the [API](https://app.supabase.com/project/_/api) page in the Dashboard. -2. Find the `countries` table under **Tables and Views** in the sidebar. -3. Switch between the JavaScript and the cURL docs using the tabs. - - - -#### GraphQL - -The GraphQL Endpoint that we provide (`https://.supabase.co/graphql/v1`) is compatible with any GraphiQL implementation that can pass an `apikey` header. -Some suggested applications: - -- [paw.cloud](https://paw.cloud) -- [insomnia.rest](https://insomnia.rest) -- [postman.com/graphql](https://www.postman.com/graphql/) -- Self-hosted GraphiQL: GraphiQL can be served through a simple HTML file. See [this discussion](https://github.com/supabase/supabase/discussions/6144) for more details. - -## Using the API - -### REST API - -You can interact with your API directly via HTTP requests, or you can use the client libraries which we provide. - -Let's see how to make a request to the `todos` table which we created in the first step, -using the API URL (`SUPABASE_URL`) and Key (`SUPABASE_ANON_KEY`) we provided: - - - - -```javascript -// Initialize the JS client -import { createClient } from '@supabase/supabase-js' -const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY) - -// Make a request -const { data: todos, error } = await supabase.from('todos').select('*') -``` - - - - -```bash -# Append /rest/v1/ to your URL, and then use the table name as the route -curl '/rest/v1/todos' \ --H "apikey: " \ --H "Authorization: Bearer " -``` - - - - -JS Reference: [select()](/docs/reference/javascript/select), -[insert()](/docs/reference/javascript/insert), -[update()](/docs/reference/javascript/update), -[upsert()](/docs/reference/javascript/upsert), -[delete()](/docs/reference/javascript/delete), -[rpc()](/docs/reference/javascript/rpc) (call Postgres functions). - -### GraphQL API - -You can use any GraphQL client with the Supabase GraphQL API. For our GraphQL example we will use [urql](https://formidable.com/open-source/urql/docs/). - - - - -```javascript -import { createClient, useQuery } from 'urql' - -// Prepare API key and Authorization header -const headers = { - apikey: , - authorization: `Bearer ${}`, -} - -// Create GraphQL client -// See: https://formidable.com/open-source/urql/docs/basics/react-preact/#setting-up-the-client -const client = createClient({ - url: '/graphql/v1', - fetchOptions: function createFetchOptions() { - return { headers } - }, -}) - -// Prepare our GraphQL query -const TodosQuery = ` - query { - todosCollection { - edges { - node { - id - title - } - } - } - } -` - -// Query for the data (React) -const [result, reexecuteQuery] = useQuery({ - query: TodosQuery, -}) - -// Read the result -const { data, fetching, error } = result -``` - - - - -```bash -# Append /graphql/v1/ to your URL, and then use the table name as the route -curl --request POST '/graphql/v1' \ --H 'apikey: ' \ --H 'Authorization: Bearer ' \ --H 'Content-Type: application/json' \ --d '{ "query":"{ todos(first: 3) { edges { node { id } } } }" }' -``` - - - - -### Realtime API - -By default Realtime is disabled on your database. Let's turn on Realtime for the `todos` table. - - - - -1. Go to the [Database](https://app.supabase.com/project/_/database/tables) page in the Dashboard. -2. Click on **Replication** in the sidebar. -3. Control which database events are sent by toggling **Insert**, **Update**, and **Delete**. -4. Control which tables broadcast changes by selecting **Source** and toggling each table. - - - - - - -```sql -alter publication supabase_realtime add table todos; -``` - - - - -From the client, we can listen to any new data that is inserted into the `todos` table: - -```javascript -// Initialize the JS client -import { createClient } from '@supabase/supabase-js' -const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY) - -// Create a function to handle inserts -const handleInserts = (payload) => { - console.log('Change received!', payload) -} - -// Listen to inserts -const { data: todos, error } = await supabase.from('todos').on('INSERT', handleInserts).subscribe() -``` - -Use [subscribe()](/docs/reference/javascript/subscribe) to listen to database changes. -The Realtime API works through PostgreSQL's replication functionality. Postgres sends database changes to a [publication](/docs/guides/database/replication#publications) -called `supabase_realtime`, and by managing this publication you can control which data is broadcast. - -## API Security - -### Securing your Routes - -Your API is designed to work with Postgres Row Level Security (RLS). If you use Supabase [Auth](/docs/guides/auth), you can restrict data based on the logged-in user. -To control access to your data, you can use [Policies](/docs/guides/auth#policies). -When you create a table in Postgres, Row Level Security is disabled by default. To enable RLS: - - - - -1. Go to the [Authentication](https://app.supabase.com/project/_/auth/users) page in the Dashboard. -2. Click on **Policies** in the sidebar. -3. Select **Enable RLS** to enable Row Level Security. - - - - -```sql -alter table todos enable row level security; -``` - - - - -### The `service_role` key - -Never expose the `service_role` key in a browser or anywhere where a user can see it. This Key is designed to bypass Row Level Security - so it should only be used on a private server. - -A common use case for the `service_role` key is to run data analytics jobs on the backend. To support joins on user id, it is often useful to grant the service role read access to `auth.users` table. - -```sql -grant select on table auth.users to service_role; -``` - -We have [partnered with GitHub](https://github.blog/changelog/2022-03-28-supabase-is-now-a-github-secret-scanning-partner/) to scan for Supabase `service_role` keys pushed to public repositories. -If they detect any keys with service_role privileges being pushed to GitHub, they will forward the API key to us, so that we can automatically revoke the detected secrets and notify you, protecting your data against malicious actors. - -### Safeguards towards accidental deletes and updates - -For all projects, by default, the Postgres extension [safeupdate](https://github.com/eradman/pg-safeupdate) is enabled for all queries coming from the API. -This ensures that any `delete()` or `update()` would fail if there are no accompanying filters provided. -To confirm that safeupdate is enabled for queries going through the API of your project, the following query could be run: - -```sql -select usename, useconfig from pg_shadow where usename = 'authenticator'; -``` - -The expected value for `useconfig` should be: - -```sql -['session_preload_libraries=supautils, safeupdate'] -``` - -export const Page = ({ children }) => - -export default Page diff --git a/apps/docs/pages/guides/getting-started/features.mdx b/apps/docs/pages/guides/getting-started/features.mdx index 4cf63f342c0..f69a2f41901 100755 --- a/apps/docs/pages/guides/getting-started/features.mdx +++ b/apps/docs/pages/guides/getting-started/features.mdx @@ -149,35 +149,38 @@ Manage your projects programmatically. [Docs](/docs/reference/api). Both Postgres and the Supabase Platform are production-ready. Some tools we offer on top of Postgres are still under development. -| Product | Feature | Stage | -| -------------------------- | ---------------------- | ------- | -| Database | Postgres | `GA` | -| Database | Triggers | `GA` | -| Database | Functions | `GA` | -| Database | Extensions | `GA` | -| Database | Full Text Search | `GA` | -| Database | Webhooks | `alpha` | -| Database | Point-in-Time Recovery | `alpha` | -| Database | Vault | `alpha` | -| Studio | | `GA` | -| Realtime | Postgres Changes | `GA` | -| Realtime | Broadcast | `beta` | -| Realtime | Presence | `beta` | -| Storage | | `GA` | -| Storage | S3 Backend | `GA` | -| Storage | CDN | `GA` | -| Storage | Smart CDN | `beta` | -| Storage | Image Transformations | `beta` | -| Edge Functions | | `beta` | -| Auth | OAuth Providers | `beta` | -| Auth | Passwordless | `beta` | -| Auth | Next.js Auth Helpers | `alpha` | -| Auth | SvelteKit Auth Helpers | `alpha` | -| Auth | Remix Auth Helpers | `alpha` | -| Management API | | `beta` | -| CLI | | `beta` | -| Client Library: JavaScript | | `GA` | -| Client Library: Dart | | `beta` | +| Product | Feature | Stage | Available on self-hosted | +| -------------------------- | ---------------------- | ------- | ------------------------------------------- | +| Database | Postgres | `GA` | ✅ | +| Database | Triggers | `GA` | ✅ | +| Database | Functions | `GA` | ✅ | +| Database | Extensions | `GA` | ✅ | +| Database | Full Text Search | `GA` | ✅ | +| Database | Webhooks | `GA` | ✅ | +| Database | Point-in-Time Recovery | `alpha` | 🚧 [wal-g](https://github.com/wal-g/wal-g) | +| Database | Vault | `alpha` | ✅ | +| Studio | | `GA` | ✅ | +| Realtime | Postgres Changes | `GA` | ✅ | +| Realtime | Broadcast | `beta` | ✅ | +| Realtime | Presence | `beta` | ✅ | +| Storage | | `GA` | ✅ | +| Storage | S3 Backend | `GA` | ✅ | +| Storage | CDN | `GA` | 🚧 [Cloudflare](https://www.cloudflare.com) | +| Storage | Smart CDN | `beta` | 🚧 [Cloudflare](https://www.cloudflare.com) | +| Storage | Image Transformations | `beta` | ✅ | +| Edge Functions | | `beta` | 🚧 [Deno Deploy](https://deno.com/deploy) | +| Auth | OAuth Providers | `beta` | ✅ | +| Auth | Passwordless | `beta` | ✅ | +| Auth | Next.js Auth Helpers | `alpha` | ✅ | +| Auth | SvelteKit Auth Helpers | `alpha` | ✅ | +| Auth | Remix Auth Helpers | `alpha` | ✅ | +| Management API | | `beta` | N/A | +| CLI | | `beta` | N/A | +| Client Library: JavaScript | | `GA` | N/A | +| Client Library: Dart | | `beta` | N/A | + +- ✅ = Fully Available +- 🚧 = Available, but requires external tools or configuration export const Page = ({ children }) => diff --git a/apps/docs/pages/guides/getting-started/tutorials/with-expo.mdx b/apps/docs/pages/guides/getting-started/tutorials/with-expo.mdx index 2ad275085aa..aa420134d55 100644 --- a/apps/docs/pages/guides/getting-started/tutorials/with-expo.mdx +++ b/apps/docs/pages/guides/getting-started/tutorials/with-expo.mdx @@ -36,6 +36,7 @@ Then let's install the additional dependencies: [supabase-js](https://github.com ```bash npm install @supabase/supabase-js npm install react-native-elements @react-native-async-storage/async-storage react-native-url-polyfill +npx expo install expo-secure-store ``` Now let's create a helper file to initialize the Supabase client. @@ -44,15 +45,28 @@ These variables will be exposed on the browser, and that's completely fine since [Row Level Security](/docs/guides/auth#row-level-security) enabled on our Database. ```ts title=lib/supabase.ts -import AsyncStorage from '@react-native-async-storage/async-storage' +import * as SecureStore from "expo-secure-store"; import { createClient } from '@supabase/supabase-js' + +const ExpoSecureStoreAdapter = { + getItem: (key: string) => { + return SecureStore.getItemAsync(key); + }, + setItem: (key: string, value: string) => { + SecureStore.setItemAsync(key, value); + }, + removeItem: (key: string) => { + SecureStore.deleteItemAsync(key); + }, +}; + const supabaseUrl = YOUR_REACT_NATIVE_SUPABASE_URL const supabaseAnonKey = YOUR_REACT_NATIVE_SUPABASE_ANON_KEY export const supabase = createClient(supabaseUrl, supabaseAnonKey, { auth: { - storage: AsyncStorage as any, + storage: ExpoSecureStoreAdapter as any, autoRefreshToken: true, persistSession: true, detectSessionInUrl: false, diff --git a/apps/docs/pages/guides/integrations/dashibase.mdx b/apps/docs/pages/guides/integrations/dashibase.mdx deleted file mode 100644 index 962f1397b29..00000000000 --- a/apps/docs/pages/guides/integrations/dashibase.mdx +++ /dev/null @@ -1,105 +0,0 @@ -import Layout from '~/layouts/DefaultGuideLayout' - -export const meta = { - id: 'dashibase', - title: 'Dashibase', - description: 'Create an internal CRUD dashboard with Supabase and Dashibase in 15 mins.', -} - -Are you tired of building admin panels? [Dashibase](https://dashibase.com/) is a super fast way to build internal CRUD dashboards with a Notion-like UI. - -This guide walks you through how to build a customer admin panel using Supabase on the backend and Dashibase on the front so that you and your team can easily find and update customer information. - -## Quick explanation - -Just so we are on the same page, here are some of the terms we use: - -- **Data source:** This is the data that powers your dashboard (i.e. your Supabase database). -- **Dashboard:** This is the friendly interface that you build on top of your Supabase database using Dashibase. -- **Page:** Each dashboard can have multiple pages. Each page can have multiple blocks of text or tables. - -Now that is out of the way, let's build our customer admin panel. - -(Start your stopwatch!) - -## Step 1. Connect Supabase to Dashibase - -First, in Dashibase, go to “Data Sources” via the left sidebar and click on “Connect data source” in the upper-right corner. - -Note: We do not download or store any of your database data. - -![Connect Supabase to Dashibase](/docs/img/guides/integrations/dashibase/connect-database.png) - -Enter your database credentials, which you can find in Supabase under Settings > Database > Connection info. For additional security, you can also download your SSL certificate and upload it to Dashibase. - -![Supabase credentials](/docs/img/guides/integrations/dashibase/supabase-credentials.png) - -## Step 2. Set up your data access policy - -Once you have connected your database, you can also control what your team can see and edit in your database via Dashibase. There are usually certain data that you don’t want others to edit or even see (e.g. address, email, identification number). - -Note: If you prefer to restrict access to your database _before_ you connect to Dashibase for security reasons, you can [create a restricted user](https://aws.amazon.com/blogs/database/managing-postgresql-users-and-roles/) via [Supabase's SQL Editor](/docs/guides/database#the-sql-editor). The slight advantage of doing this in Dashibase is that there is a GUI, which makes it easier to set up the access control (but we understand some developers might find it more secure to restrict the access themselves). - -![Set data access in Dashibase](/docs/img/guides/integrations/dashibase/set-data-access.png) - -You can even control which columns within a table that others can see and edit. In the example below, for the `tags` table, the `name` column can be read and updated, the `created_at` column can be read, and the `id` column cannot even be read. - -![Set column-level access in Dashibase](/docs/img/guides/integrations/dashibase/set-column-access.png) - -Once you are happy with the data access control, you can decide who in your organization can edit this data source (usually other developers) or use this data source to create dashboards. - -![Set user access to data source in Dashibase](/docs/img/guides/integrations/dashibase/data-source-user-access.png) - -## Step 3. Build your dashboard - -To create a dashboard, go to “Dashboards” via the left sidebar in Dashibase and click on “Create dashboard” in the upper-right corner. - -Here’s where the fun begins. There are many ways to build your dashboards in Dashibase using features such as markdown formatting and slash command. - -You will see some automatically-generated content in your dashboard so that you can set up your dashboard more quickly. For this example, let's clear them out and start from scratch. - -![Automatically-generated content for your dashboard](/docs/img/guides/integrations/dashibase/initial-dashboard-content.png) - -Using our Notion-like UI, you can quickly build out your dashboard through typing. For example, you can type '/table' to add a table from your database to your dashboard. No more dragging components across your screen and dropping them on a blank canvas repeatedly. - -![Automatically-generated content for your dashboard](/docs/img/guides/integrations/dashibase/slash-command.gif) - -If you have set up [foreign keys in your Supabase database](/docs/guides/database/tables#joining-tables-with-foreign-keys), you can easily show data from multiple tables on the table in your Dashibase dashboard. Simply click on the "Columns" button beside the "Filter" button and select the columns you want to show or hide. For this example, we want to show the customers' country and plan price, which are in separate `countries` and `plans` tables. - -![Setting up the Customers table](/docs/img/guides/integrations/dashibase/customers-table.png) - -For all the tables in your dashboard, you can rename the column headers, add filter and sort, adjust the column width, and more. - -You can also add text to provide context or instructions for the rest of your team as they are using your dashboard. This saves you the trouble of having your dashboard and documentation in separate places. - -![Customers table with instructions](/docs/img/guides/integrations/dashibase/customers-table-with-text.png) - -Most importantly, we automatically generate a single-item view for each of the items on your table so that you do not have to manually create it yourself. You can easily edit or rearrange the blocks just like in Notion. - -![Automatically generated single-item view](/docs/img/guides/integrations/dashibase/single-item-view.png) - -## Step 4. Share your dashboard with your team - -Finally, save and share the dashboard with your team. There are two levels of access: - -- Edit dashboard: Edit the text blocks, edit the tables, etc. -- Use dashboard: View and update the data via the dashboard - -Click on the “Share” button in the upper-right corner of your dashboard to share access: - -![Share dashboard access](/docs/img/guides/integrations/dashibase/share-dashboard.png) - -Now your team can use this customer admin panel to find and update customer information easily! - -P.S. How long did we take? :) - -## Resources - -- [Dashibase website](https://dashibase.com/) -- [Dashibase open-source repo](https://github.com/dashibase) -- [Dashibase Twitter](https://twitter.com/dashibase) -- [Dashibase Discord](https://discord.gg/crhDFYvbbq) - -export const Page = ({ children }) => - -export default Page diff --git a/apps/docs/public/sitemap.xml b/apps/docs/public/sitemap.xml index c8b69531b42..5af30326761 100644 --- a/apps/docs/public/sitemap.xml +++ b/apps/docs/public/sitemap.xml @@ -426,12 +426,6 @@ 0.5 - - https://supabase.com/docs/guides/integrations/dashibase - weekly - 0.5 - - https://supabase.com/docs/guides/integrations/dhiwise weekly diff --git a/apps/www/lib/redirects.js b/apps/www/lib/redirects.js index 84d361dd379..d0dc70bb328 100644 --- a/apps/www/lib/redirects.js +++ b/apps/www/lib/redirects.js @@ -1892,4 +1892,20 @@ module.exports = [ source: '/docs/guides/realtime/postgres-changes', destination: '/docs/guides/realtime/extensions/postgres-changes', }, + // Serverless APIs + { + permanent: true, + source: '/docs/guides/database/api', + destination: '/docs/guides/api', + }, + { + permanent: true, + source: '/docs/guides/database/api/generating-types', + destination: '/docs/guides/api/rest/generating-types', + }, + { + permanent: true, + source: '/docs/guides/integrations/dashibase', + destination: '/docs', + }, ] diff --git a/apps/www/package.json b/apps/www/package.json index 97701e883d8..e34b14c8ab1 100644 --- a/apps/www/package.json +++ b/apps/www/package.json @@ -31,7 +31,7 @@ "gray-matter": "^4.0.2", "markdown-toc": "^1.2.0", "marked": "^4.0.12", - "next": "12.1.0", + "next": "12.3.2", "next-compose-plugins": "^2.2.1", "next-mdx-remote": "^4.1.0", "next-seo": "^4.20.0", diff --git a/package-lock.json b/package-lock.json index 0e726b52315..36fb6bd2e93 100644 --- a/package-lock.json +++ b/package-lock.json @@ -225,24 +225,6 @@ "react": "^16.13.1 || ^17.0.0" } }, - "apps/docs/node_modules/@next/env": { - "version": "12.3.2", - "license": "MIT" - }, - "apps/docs/node_modules/@next/swc-darwin-arm64": { - "version": "12.3.2", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, "apps/docs/node_modules/ajv": { "version": "6.12.6", "dev": true, @@ -413,97 +395,6 @@ "unist-util-visit": "^4.1.0" } }, - "apps/docs/node_modules/next": { - "version": "12.3.2", - "license": "MIT", - "dependencies": { - "@next/env": "12.3.2", - "@swc/helpers": "0.4.11", - "caniuse-lite": "^1.0.30001406", - "postcss": "8.4.14", - "styled-jsx": "5.0.7", - "use-sync-external-store": "1.2.0" - }, - "bin": { - "next": "dist/bin/next" - }, - "engines": { - "node": ">=12.22.0" - }, - "optionalDependencies": { - "@next/swc-android-arm-eabi": "12.3.2", - "@next/swc-android-arm64": "12.3.2", - "@next/swc-darwin-arm64": "12.3.2", - "@next/swc-darwin-x64": "12.3.2", - "@next/swc-freebsd-x64": "12.3.2", - "@next/swc-linux-arm-gnueabihf": "12.3.2", - "@next/swc-linux-arm64-gnu": "12.3.2", - "@next/swc-linux-arm64-musl": "12.3.2", - "@next/swc-linux-x64-gnu": "12.3.2", - "@next/swc-linux-x64-musl": "12.3.2", - "@next/swc-win32-arm64-msvc": "12.3.2", - "@next/swc-win32-ia32-msvc": "12.3.2", - "@next/swc-win32-x64-msvc": "12.3.2" - }, - "peerDependencies": { - "fibers": ">= 3.1.0", - "node-sass": "^6.0.0 || ^7.0.0", - "react": "^17.0.2 || ^18.0.0-0", - "react-dom": "^17.0.2 || ^18.0.0-0", - "sass": "^1.3.0" - }, - "peerDependenciesMeta": { - "fibers": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - } - } - }, - "apps/docs/node_modules/next/node_modules/styled-jsx": { - "version": "5.0.7", - "license": "MIT", - "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "babel-plugin-macros": { - "optional": true - } - } - }, - "apps/docs/node_modules/postcss": { - "version": "8.4.14", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, "apps/docs/node_modules/proxy-compare": { "version": "2.3.0", "license": "MIT" @@ -720,7 +611,7 @@ "gray-matter": "^4.0.2", "markdown-toc": "^1.2.0", "marked": "^4.0.12", - "next": "12.1.0", + "next": "12.3.2", "next-compose-plugins": "^2.2.1", "next-mdx-remote": "^4.1.0", "next-seo": "^4.20.0", @@ -4563,8 +4454,9 @@ } }, "node_modules/@next/env": { - "version": "12.1.0", - "license": "MIT" + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/env/-/env-12.3.2.tgz", + "integrity": "sha512-upwtMaHxlv/udAWGq0kE+rg8huwmcxQPsKZFhS1R5iVO323mvxEBe1YrSXe1awLbg9sTIuEHbgxjLLt7JbeuAQ==" }, "node_modules/@next/eslint-plugin-next": { "version": "12.3.4", @@ -4599,6 +4491,201 @@ "@mdx-js/react": "*" } }, + "node_modules/@next/swc-android-arm-eabi": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.2.tgz", + "integrity": "sha512-r2rrz+DZ8YYGqzVrbRrpP6GKzwozpOrnFbErc4k36vUTSFMag9yQahZfaBe06JYdqu/e5yhm/saIDEaSVPRP4g==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-android-arm64": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.3.2.tgz", + "integrity": "sha512-B+TINJhCf+CrY1+b3/JWQlkecv53rAGa/gA7gi5B1cnBa/2Uvoe+Ue0JeCefTjfiyl1ScsyNx+NcESY8Ye2Ngg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.2.tgz", + "integrity": "sha512-PTUfe1ZrwjsiuTmr3bOM9lsoy5DCmfYsLOUF9ZVhtbi5MNJVmUTy4VZ06GfrvnCO5hGCr48z3vpFE9QZ0qLcPw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.2.tgz", + "integrity": "sha512-1HkjmS9awwlaeEY8Y01nRSNkSv3y+qnC/mjMPe/W66hEh3QKa/LQHqHeS7NOdEs19B2mhZ7w+EgMRXdLQ0Su8w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-freebsd-x64": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.2.tgz", + "integrity": "sha512-h5Mx0BKDCJ5Vu/U8e07esF6PjPv1EJgmRbYWTUZMAflu13MQpCJkKEJir7+BeRfTXRfgFf+llc7uocrpd7mcrg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm-gnueabihf": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.2.tgz", + "integrity": "sha512-EuRZAamoxfe/WoWRaC0zsCAoE4gs/mEhilcloNM4J5Mnb3PLY8PZV394W7t5tjBjItMCF7l2Ebwjwtm46tq2RA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.2.tgz", + "integrity": "sha512-T9GCFyOIb4S3acA9LqflUYD+QZ94iZketHCqKdoO0Nx0OCHIgGJV5rotDe8TDXwh/goYpIfyHU4j1qqw4w4VnA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.2.tgz", + "integrity": "sha512-hxNVZS6L3c2z3l9EH2GP0MGQ9exu6O8cohYNZyqC9WUl6C03sEn8xzDH1y+NgD3fVurvYkGU5F0PDddJJLfDIw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.2.tgz", + "integrity": "sha512-fCPkLuwDwY8/QeXxciJJjDHG09liZym/Bhb4A+RLFQ877wUkwFsNWDUTSdUx0YXlYK/1gf67BKauqKkOKp6CYw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.2.tgz", + "integrity": "sha512-o+GifBIQ2K+/MEFxHsxUZoU3bsuVFLXZYWd3idimFHiVdDCVYiKsY6mYMmKDlucX+9xRyOCkKL9Tjf+3tuXJpw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.2.tgz", + "integrity": "sha512-crii66irzGGMSUR0L8r9+A06eTv7FTXqw4rgzJ33M79EwQJOdpY7RVKXLQMurUhniEeQEEOfamiEdPIi/qxisw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.2.tgz", + "integrity": "sha512-5hRUSvn3MdQ4nVRu1rmKxq5YJzpTtZfaC/NyGw6wa4NSF1noUn/pdQGUr+I5Qz3CZkd1gZzzC0eaXQHlrk0E2g==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.2.tgz", + "integrity": "sha512-tpQJYUH+TzPMIsdVl9fH8uDg47iwiNjKY+8e9da3dXqlkztKzjSw0OwSADoqh3KrifplXeKSta+BBGLdBqg3sg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "license": "MIT", @@ -26036,14 +26123,16 @@ "dev": true }, "node_modules/next": { - "version": "12.1.0", - "license": "MIT", + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/next/-/next-12.3.2.tgz", + "integrity": "sha512-orzvvebCwOqaz1eA5ZA0R5dbKxqtJyw7yeig7kDspu6p8OrplfyelzpvMHcDTKscv/l0nn/0l0v3mSsE8w4k7A==", "dependencies": { - "@next/env": "12.1.0", - "caniuse-lite": "^1.0.30001283", - "postcss": "8.4.5", - "styled-jsx": "5.0.0", - "use-subscription": "1.5.1" + "@next/env": "12.3.2", + "@swc/helpers": "0.4.11", + "caniuse-lite": "^1.0.30001406", + "postcss": "8.4.14", + "styled-jsx": "5.0.7", + "use-sync-external-store": "1.2.0" }, "bin": { "next": "dist/bin/next" @@ -26052,17 +26141,19 @@ "node": ">=12.22.0" }, "optionalDependencies": { - "@next/swc-android-arm64": "12.1.0", - "@next/swc-darwin-arm64": "12.1.0", - "@next/swc-darwin-x64": "12.1.0", - "@next/swc-linux-arm-gnueabihf": "12.1.0", - "@next/swc-linux-arm64-gnu": "12.1.0", - "@next/swc-linux-arm64-musl": "12.1.0", - "@next/swc-linux-x64-gnu": "12.1.0", - "@next/swc-linux-x64-musl": "12.1.0", - "@next/swc-win32-arm64-msvc": "12.1.0", - "@next/swc-win32-ia32-msvc": "12.1.0", - "@next/swc-win32-x64-msvc": "12.1.0" + "@next/swc-android-arm-eabi": "12.3.2", + "@next/swc-android-arm64": "12.3.2", + "@next/swc-darwin-arm64": "12.3.2", + "@next/swc-darwin-x64": "12.3.2", + "@next/swc-freebsd-x64": "12.3.2", + "@next/swc-linux-arm-gnueabihf": "12.3.2", + "@next/swc-linux-arm64-gnu": "12.3.2", + "@next/swc-linux-arm64-musl": "12.3.2", + "@next/swc-linux-x64-gnu": "12.3.2", + "@next/swc-linux-x64-musl": "12.3.2", + "@next/swc-win32-arm64-msvc": "12.3.2", + "@next/swc-win32-ia32-msvc": "12.3.2", + "@next/swc-win32-x64-msvc": "12.3.2" }, "peerDependencies": { "fibers": ">= 3.1.0", @@ -26509,19 +26600,26 @@ } }, "node_modules/next/node_modules/postcss": { - "version": "8.4.5", - "license": "MIT", + "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], "dependencies": { - "nanoid": "^3.1.30", + "nanoid": "^3.3.4", "picocolors": "^1.0.0", - "source-map-js": "^1.0.1" + "source-map-js": "^1.0.2" }, "engines": { "node": "^10 || ^12 || >=14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" } }, "node_modules/nice-try": { @@ -33750,13 +33848,14 @@ } }, "node_modules/styled-jsx": { - "version": "5.0.0", - "license": "MIT", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz", + "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==", "engines": { "node": ">= 12.0.0" }, "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || 18.x.x" + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" }, "peerDependenciesMeta": { "@babel/core": { @@ -35540,16 +35639,6 @@ } } }, - "node_modules/use-subscription": { - "version": "1.5.1", - "license": "MIT", - "dependencies": { - "object-assign": "^4.1.1" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0" - } - }, "node_modules/use-sync-external-store": { "version": "1.2.0", "license": "MIT", @@ -37519,24 +37608,6 @@ "webpack-bundle-analyzer": "4.3.0" } }, - "studio/node_modules/@next/env": { - "version": "12.3.2", - "license": "MIT" - }, - "studio/node_modules/@next/swc-darwin-arm64": { - "version": "12.3.2", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, "studio/node_modules/@tailwindcss/typography": { "version": "0.5.8", "dev": true, @@ -37764,81 +37835,15 @@ "version": "1.0.1", "license": "ISC" }, - "studio/node_modules/next": { - "version": "12.3.2", - "license": "MIT", - "dependencies": { - "@next/env": "12.3.2", - "@swc/helpers": "0.4.11", - "caniuse-lite": "^1.0.30001406", - "postcss": "8.4.14", - "styled-jsx": "5.0.7", - "use-sync-external-store": "1.2.0" - }, - "bin": { - "next": "dist/bin/next" - }, - "engines": { - "node": ">=12.22.0" - }, - "optionalDependencies": { - "@next/swc-android-arm-eabi": "12.3.2", - "@next/swc-android-arm64": "12.3.2", - "@next/swc-darwin-arm64": "12.3.2", - "@next/swc-darwin-x64": "12.3.2", - "@next/swc-freebsd-x64": "12.3.2", - "@next/swc-linux-arm-gnueabihf": "12.3.2", - "@next/swc-linux-arm64-gnu": "12.3.2", - "@next/swc-linux-arm64-musl": "12.3.2", - "@next/swc-linux-x64-gnu": "12.3.2", - "@next/swc-linux-x64-musl": "12.3.2", - "@next/swc-win32-arm64-msvc": "12.3.2", - "@next/swc-win32-ia32-msvc": "12.3.2", - "@next/swc-win32-x64-msvc": "12.3.2" - }, - "peerDependencies": { - "fibers": ">= 3.1.0", - "node-sass": "^6.0.0 || ^7.0.0", - "react": "^17.0.2 || ^18.0.0-0", - "react-dom": "^17.0.2 || ^18.0.0-0", - "sass": "^1.3.0" - }, - "peerDependenciesMeta": { - "fibers": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - } - } - }, - "studio/node_modules/next/node_modules/styled-jsx": { - "version": "5.0.7", - "license": "MIT", - "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "babel-plugin-macros": { - "optional": true - } - } - }, "studio/node_modules/openapi-types": { "version": "9.3.1", "license": "MIT" }, "studio/node_modules/postcss": { "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "dev": true, "funding": [ { "type": "opencollective", @@ -40511,7 +40516,9 @@ } }, "@next/env": { - "version": "12.1.0" + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/env/-/env-12.3.2.tgz", + "integrity": "sha512-upwtMaHxlv/udAWGq0kE+rg8huwmcxQPsKZFhS1R5iVO323mvxEBe1YrSXe1awLbg9sTIuEHbgxjLLt7JbeuAQ==" }, "@next/eslint-plugin-next": { "version": "12.3.4", @@ -40536,6 +40543,84 @@ "version": "12.3.4", "requires": {} }, + "@next/swc-android-arm-eabi": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.2.tgz", + "integrity": "sha512-r2rrz+DZ8YYGqzVrbRrpP6GKzwozpOrnFbErc4k36vUTSFMag9yQahZfaBe06JYdqu/e5yhm/saIDEaSVPRP4g==", + "optional": true + }, + "@next/swc-android-arm64": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.3.2.tgz", + "integrity": "sha512-B+TINJhCf+CrY1+b3/JWQlkecv53rAGa/gA7gi5B1cnBa/2Uvoe+Ue0JeCefTjfiyl1ScsyNx+NcESY8Ye2Ngg==", + "optional": true + }, + "@next/swc-darwin-arm64": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.2.tgz", + "integrity": "sha512-PTUfe1ZrwjsiuTmr3bOM9lsoy5DCmfYsLOUF9ZVhtbi5MNJVmUTy4VZ06GfrvnCO5hGCr48z3vpFE9QZ0qLcPw==", + "optional": true + }, + "@next/swc-darwin-x64": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.2.tgz", + "integrity": "sha512-1HkjmS9awwlaeEY8Y01nRSNkSv3y+qnC/mjMPe/W66hEh3QKa/LQHqHeS7NOdEs19B2mhZ7w+EgMRXdLQ0Su8w==", + "optional": true + }, + "@next/swc-freebsd-x64": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.2.tgz", + "integrity": "sha512-h5Mx0BKDCJ5Vu/U8e07esF6PjPv1EJgmRbYWTUZMAflu13MQpCJkKEJir7+BeRfTXRfgFf+llc7uocrpd7mcrg==", + "optional": true + }, + "@next/swc-linux-arm-gnueabihf": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.2.tgz", + "integrity": "sha512-EuRZAamoxfe/WoWRaC0zsCAoE4gs/mEhilcloNM4J5Mnb3PLY8PZV394W7t5tjBjItMCF7l2Ebwjwtm46tq2RA==", + "optional": true + }, + "@next/swc-linux-arm64-gnu": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.2.tgz", + "integrity": "sha512-T9GCFyOIb4S3acA9LqflUYD+QZ94iZketHCqKdoO0Nx0OCHIgGJV5rotDe8TDXwh/goYpIfyHU4j1qqw4w4VnA==", + "optional": true + }, + "@next/swc-linux-arm64-musl": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.2.tgz", + "integrity": "sha512-hxNVZS6L3c2z3l9EH2GP0MGQ9exu6O8cohYNZyqC9WUl6C03sEn8xzDH1y+NgD3fVurvYkGU5F0PDddJJLfDIw==", + "optional": true + }, + "@next/swc-linux-x64-gnu": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.2.tgz", + "integrity": "sha512-fCPkLuwDwY8/QeXxciJJjDHG09liZym/Bhb4A+RLFQ877wUkwFsNWDUTSdUx0YXlYK/1gf67BKauqKkOKp6CYw==", + "optional": true + }, + "@next/swc-linux-x64-musl": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.2.tgz", + "integrity": "sha512-o+GifBIQ2K+/MEFxHsxUZoU3bsuVFLXZYWd3idimFHiVdDCVYiKsY6mYMmKDlucX+9xRyOCkKL9Tjf+3tuXJpw==", + "optional": true + }, + "@next/swc-win32-arm64-msvc": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.2.tgz", + "integrity": "sha512-crii66irzGGMSUR0L8r9+A06eTv7FTXqw4rgzJ33M79EwQJOdpY7RVKXLQMurUhniEeQEEOfamiEdPIi/qxisw==", + "optional": true + }, + "@next/swc-win32-ia32-msvc": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.2.tgz", + "integrity": "sha512-5hRUSvn3MdQ4nVRu1rmKxq5YJzpTtZfaC/NyGw6wa4NSF1noUn/pdQGUr+I5Qz3CZkd1gZzzC0eaXQHlrk0E2g==", + "optional": true + }, + "@next/swc-win32-x64-msvc": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.2.tgz", + "integrity": "sha512-tpQJYUH+TzPMIsdVl9fH8uDg47iwiNjKY+8e9da3dXqlkztKzjSw0OwSADoqh3KrifplXeKSta+BBGLdBqg3sg==", + "optional": true + }, "@nodelib/fs.scandir": { "version": "2.1.5", "requires": { @@ -49391,13 +49476,6 @@ "version": "1.6.22", "requires": {} }, - "@next/env": { - "version": "12.3.2" - }, - "@next/swc-darwin-arm64": { - "version": "12.3.2", - "optional": true - }, "ajv": { "version": "6.12.6", "dev": true, @@ -49497,44 +49575,6 @@ "version": "2.0.0-rc3", "requires": {} }, - "next": { - "version": "12.3.2", - "requires": { - "@next/env": "12.3.2", - "@next/swc-android-arm-eabi": "12.3.2", - "@next/swc-android-arm64": "12.3.2", - "@next/swc-darwin-arm64": "12.3.2", - "@next/swc-darwin-x64": "12.3.2", - "@next/swc-freebsd-x64": "12.3.2", - "@next/swc-linux-arm-gnueabihf": "12.3.2", - "@next/swc-linux-arm64-gnu": "12.3.2", - "@next/swc-linux-arm64-musl": "12.3.2", - "@next/swc-linux-x64-gnu": "12.3.2", - "@next/swc-linux-x64-musl": "12.3.2", - "@next/swc-win32-arm64-msvc": "12.3.2", - "@next/swc-win32-ia32-msvc": "12.3.2", - "@next/swc-win32-x64-msvc": "12.3.2", - "@swc/helpers": "0.4.11", - "caniuse-lite": "^1.0.30001406", - "postcss": "8.4.14", - "styled-jsx": "5.0.7", - "use-sync-external-store": "1.2.0" - }, - "dependencies": { - "styled-jsx": { - "version": "5.0.7", - "requires": {} - } - } - }, - "postcss": { - "version": "8.4.14", - "requires": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - }, "proxy-compare": { "version": "2.3.0" }, @@ -55594,32 +55634,39 @@ "dev": true }, "next": { - "version": "12.1.0", + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/next/-/next-12.3.2.tgz", + "integrity": "sha512-orzvvebCwOqaz1eA5ZA0R5dbKxqtJyw7yeig7kDspu6p8OrplfyelzpvMHcDTKscv/l0nn/0l0v3mSsE8w4k7A==", "requires": { - "@next/env": "12.1.0", - "@next/swc-android-arm64": "12.1.0", - "@next/swc-darwin-arm64": "12.1.0", - "@next/swc-darwin-x64": "12.1.0", - "@next/swc-linux-arm-gnueabihf": "12.1.0", - "@next/swc-linux-arm64-gnu": "12.1.0", - "@next/swc-linux-arm64-musl": "12.1.0", - "@next/swc-linux-x64-gnu": "12.1.0", - "@next/swc-linux-x64-musl": "12.1.0", - "@next/swc-win32-arm64-msvc": "12.1.0", - "@next/swc-win32-ia32-msvc": "12.1.0", - "@next/swc-win32-x64-msvc": "12.1.0", - "caniuse-lite": "^1.0.30001283", - "postcss": "8.4.5", - "styled-jsx": "5.0.0", - "use-subscription": "1.5.1" + "@next/env": "12.3.2", + "@next/swc-android-arm-eabi": "12.3.2", + "@next/swc-android-arm64": "12.3.2", + "@next/swc-darwin-arm64": "12.3.2", + "@next/swc-darwin-x64": "12.3.2", + "@next/swc-freebsd-x64": "12.3.2", + "@next/swc-linux-arm-gnueabihf": "12.3.2", + "@next/swc-linux-arm64-gnu": "12.3.2", + "@next/swc-linux-arm64-musl": "12.3.2", + "@next/swc-linux-x64-gnu": "12.3.2", + "@next/swc-linux-x64-musl": "12.3.2", + "@next/swc-win32-arm64-msvc": "12.3.2", + "@next/swc-win32-ia32-msvc": "12.3.2", + "@next/swc-win32-x64-msvc": "12.3.2", + "@swc/helpers": "0.4.11", + "caniuse-lite": "^1.0.30001406", + "postcss": "8.4.14", + "styled-jsx": "5.0.7", + "use-sync-external-store": "1.2.0" }, "dependencies": { "postcss": { - "version": "8.4.5", + "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", "requires": { - "nanoid": "^3.1.30", + "nanoid": "^3.3.4", "picocolors": "^1.0.0", - "source-map-js": "^1.0.1" + "source-map-js": "^1.0.2" } } } @@ -60581,13 +60628,6 @@ "webpack-bundle-analyzer": "4.3.0" } }, - "@next/env": { - "version": "12.3.2" - }, - "@next/swc-darwin-arm64": { - "version": "12.3.2", - "optional": true - }, "@tailwindcss/typography": { "version": "0.5.8", "dev": true, @@ -60726,41 +60766,14 @@ "internmap": { "version": "1.0.1" }, - "next": { - "version": "12.3.2", - "requires": { - "@next/env": "12.3.2", - "@next/swc-android-arm-eabi": "12.3.2", - "@next/swc-android-arm64": "12.3.2", - "@next/swc-darwin-arm64": "12.3.2", - "@next/swc-darwin-x64": "12.3.2", - "@next/swc-freebsd-x64": "12.3.2", - "@next/swc-linux-arm-gnueabihf": "12.3.2", - "@next/swc-linux-arm64-gnu": "12.3.2", - "@next/swc-linux-arm64-musl": "12.3.2", - "@next/swc-linux-x64-gnu": "12.3.2", - "@next/swc-linux-x64-musl": "12.3.2", - "@next/swc-win32-arm64-msvc": "12.3.2", - "@next/swc-win32-ia32-msvc": "12.3.2", - "@next/swc-win32-x64-msvc": "12.3.2", - "@swc/helpers": "0.4.11", - "caniuse-lite": "^1.0.30001406", - "postcss": "8.4.14", - "styled-jsx": "5.0.7", - "use-sync-external-store": "1.2.0" - }, - "dependencies": { - "styled-jsx": { - "version": "5.0.7", - "requires": {} - } - } - }, "openapi-types": { "version": "9.3.1" }, "postcss": { "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "dev": true, "requires": { "nanoid": "^3.3.4", "picocolors": "^1.0.0", @@ -60881,7 +60894,9 @@ } }, "styled-jsx": { - "version": "5.0.0", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz", + "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==", "requires": {} }, "stylis": { @@ -62249,12 +62264,6 @@ "tslib": "^2.0.0" } }, - "use-subscription": { - "version": "1.5.1", - "requires": { - "object-assign": "^4.1.1" - } - }, "use-sync-external-store": { "version": "1.2.0", "requires": {} @@ -63193,7 +63202,7 @@ "gray-matter": "^4.0.2", "markdown-toc": "^1.2.0", "marked": "^4.0.12", - "next": "12.1.0", + "next": "12.3.2", "next-compose-plugins": "^2.2.1", "next-mdx-remote": "^4.1.0", "next-seo": "^4.20.0", diff --git a/packages/common/hooks/index.ts b/packages/common/hooks/index.ts new file mode 100644 index 00000000000..6e0d89b50b7 --- /dev/null +++ b/packages/common/hooks/index.ts @@ -0,0 +1,3 @@ +import React from 'react' + +export * from './useParams' diff --git a/studio/hooks/misc/useParams.ts b/packages/common/hooks/useParams.ts similarity index 100% rename from studio/hooks/misc/useParams.ts rename to packages/common/hooks/useParams.ts diff --git a/packages/common/index.tsx b/packages/common/index.tsx index 20c30bb757c..a445ad407d6 100644 --- a/packages/common/index.tsx +++ b/packages/common/index.tsx @@ -2,6 +2,7 @@ import SidebarLayout from './layouts/SidebarLayout' export * from './Button' export * from './Providers' +export * from './hooks' export * from './gotrue' export * from './auth' diff --git a/spec/supabase_js_v2.yml b/spec/supabase_js_v2.yml index 09cbcec793e..3e63efe3756 100644 --- a/spec/supabase_js_v2.yml +++ b/spec/supabase_js_v2.yml @@ -177,7 +177,7 @@ functions: - id: sign-up-with-redirect name: Sign up with a redirect URL description: | - - See [redirect URLs and wildcards](/docs/guides/auth/overview#redirect-urls-and-wildcards) to add additional redirect URLs to your project. + - See [redirect URLs and wildcards](/docs/guides/auth#redirect-urls-and-wildcards) to add additional redirect URLs to your project. code: | ```js const { data, error } = await supabase.auth.signUp( @@ -232,7 +232,7 @@ functions: - If you're using an email, you can configure whether you want the user to receive a magiclink or a OTP. - If you're using phone, you can configure whether you want the user to receive a OTP. - The magic link's destination URL is determined by the [`SITE_URL`](/docs/reference/auth/config#site_url). - - See [redirect URLs and wildcards](/docs/guides/auth/overview#redirect-urls-and-wildcards) to add additional redirect URLs to your project. + - See [redirect URLs and wildcards](/docs/guides/auth#redirect-urls-and-wildcards) to add additional redirect URLs to your project. - Magic links and OTPs share the same implementation. To send users a one-time code instead of a magic link, [modify the magic link email template](https://app.supabase.com/project/_/auth/templates) to include `{{ .Token }}` instead of `{{ .ConfirmationURL }}`. examples: - id: sign-in-with-email @@ -263,7 +263,7 @@ functions: $ref: '@supabase/gotrue-js.GoTrueClient.signInWithOAuth' notes: | - This method is used for signing in using a third-party provider. - - Supabase supports many different [third-party providers](https://supabase.com/docs/guides/auth#providers). + - Supabase supports many different [third-party providers](https://supabase.com/docs/guides/auth#configure-third-party-providers). examples: - id: sign-in-using-a-third-party-provider name: Sign in using a third-party provider @@ -279,7 +279,7 @@ functions: isSpotlight: false description: | - When the third-party provider successfully authenticates the user, the provider redirects the user to the URL specified in the `redirectTo` parameter. This parameter defaults to the [`SITE_URL`](/docs/reference/auth/config#site_url). It does not redirect the user immediately after invoking this method. - - See [redirect URLs and wildcards](/docs/guides/auth/overview#redirect-urls-and-wildcards) to add additional redirect URLs to your project. + - See [redirect URLs and wildcards](/docs/guides/auth#redirect-urls-and-wildcards) to add additional redirect URLs to your project. code: | ```js const { data, error } = await supabase.auth.signInWithOAuth({ @@ -753,7 +753,7 @@ functions: You can use [`onAuthStateChange()`](/docs/reference/javascript/auth-onauthstatechange) to listen and invoke a callback function on these events. - When the user clicks the reset link in the email they are redirected back to your application. You can configure the URL that the user is redirected to with the `redirectTo` parameter. - See [redirect URLs and wildcards](/docs/guides/auth/overview#redirect-urls-and-wildcards) to add additional redirect URLs to your project. + See [redirect URLs and wildcards](/docs/guides/auth#redirect-urls-and-wildcards) to add additional redirect URLs to your project. - After the user has been redirected successfully, prompt them for a new password and call `updateUser()`: ```js const { data, error } = await supabase.auth.updateUser({ diff --git a/studio/components/grid/components/formatter/ForeignKeyFormatter.tsx b/studio/components/grid/components/formatter/ForeignKeyFormatter.tsx index df6b3e1d1da..cab2f3416a2 100644 --- a/studio/components/grid/components/formatter/ForeignKeyFormatter.tsx +++ b/studio/components/grid/components/formatter/ForeignKeyFormatter.tsx @@ -5,7 +5,8 @@ import { SupaRow } from '../../types' import { NullValue } from '../common' import * as Tooltip from '@radix-ui/react-tooltip' import { Button, IconArrowRight } from 'ui' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' export const ForeignKeyFormatter = (props: PropsWithChildren>) => { const { ref, id } = useParams() diff --git a/studio/components/grid/components/header/RLSBannerWarning.tsx b/studio/components/grid/components/header/RLSBannerWarning.tsx index 9d5e16f422f..e1fdeb35f48 100644 --- a/studio/components/grid/components/header/RLSBannerWarning.tsx +++ b/studio/components/grid/components/header/RLSBannerWarning.tsx @@ -1,7 +1,8 @@ import { useState } from 'react' import { Button, IconAlertCircle, IconExternalLink, Modal } from 'ui' import Link from 'next/link' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import ConfirmationModal from 'components/ui/ConfirmationModal' import type { PostgresTable } from '@supabase/postgres-meta' @@ -29,7 +30,7 @@ export default function RLSBannerWarning() { <> {!isAcknowledged && !rlsEnabled && isPublicTable ? (
-
+
Warning: This table is publicly readable and writable.{' '} @@ -41,7 +42,7 @@ export default function RLSBannerWarning() {
@@ -69,4 +69,4 @@ const DomainList: FC = ({ canUpdate, onSelectDomainToDelete }) => { ) } -export default observer(DomainList) +export default observer(RedirectUrlList) diff --git a/studio/components/interfaces/Auth/RedirectDomains/RedirectDomains.tsx b/studio/components/interfaces/Auth/RedirectUrls/RedirectUrls.tsx similarity index 68% rename from studio/components/interfaces/Auth/RedirectDomains/RedirectDomains.tsx rename to studio/components/interfaces/Auth/RedirectUrls/RedirectUrls.tsx index ea58410a4b8..8483d0df26d 100644 --- a/studio/components/interfaces/Auth/RedirectDomains/RedirectDomains.tsx +++ b/studio/components/interfaces/Auth/RedirectUrls/RedirectUrls.tsx @@ -7,10 +7,10 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { checkPermissions, useStore } from 'hooks' import { FormHeader } from 'components/ui/Forms' -import { domainRegex } from '../Auth.constants' -import DomainList from './DomainList' +import { urlRegex } from '../Auth.constants' +import RedirectUrlList from './RedirectUrlList' -const RedirectDomains = () => { +const RedirectUrls = () => { const { authConfig, ui } = useStore() const URI_ALLOW_LIST_ARRAY = authConfig.config.URI_ALLOW_LIST @@ -19,24 +19,24 @@ const RedirectDomains = () => { const [open, setOpen] = useState(false) const [isDeleting, setIsDeleting] = useState(false) - const [selectedDomainToDelete, setSelectedDomainToDelete] = useState() + const [selectedUrlToDelete, setSelectedUrlToDelete] = useState() const canUpdateConfig = checkPermissions(PermissionAction.UPDATE, 'custom_config_gotrue') - const newDomainSchema = object({ - domain: string().matches(domainRegex, 'URL is not valid').required(), + const newUrlSchema = object({ + url: string().matches(urlRegex, 'URL is not valid').required(), }) - const onAddNewDomain = async (values: any, { setSubmitting }: any) => { + const onAddNewUrl = async (values: any, { setSubmitting }: any) => { setSubmitting(true) const payload = URI_ALLOW_LIST_ARRAY - payload.push(values.domain) + payload.push(values.url) const payloadString = payload.toString() if (payloadString.length > 2 * 1024) { ui.setNotification({ - message: 'Too many redirect domains, please remove some or try to use wildcards', + message: 'Too many redirect URLs, please remove some or try to use wildcards', category: 'error', }) @@ -47,36 +47,36 @@ const RedirectDomains = () => { const { error } = await authConfig.update({ URI_ALLOW_LIST: payloadString }) if (!error) { setOpen(false) - ui.setNotification({ category: 'success', message: 'Successfully added domain' }) + ui.setNotification({ category: 'success', message: 'Successfully added URL' }) } else { ui.setNotification({ error, category: 'error', - message: `Failed to update domain: ${error?.message}`, + message: `Failed to update URL: ${error?.message}`, }) } setSubmitting(false) } - const onConfirmDeleteDomain = async (domain?: string) => { - if (!domain) return + const onConfirmDeleteUrl = async (url?: string) => { + if (!url) return setIsDeleting(true) - // Remove selectedDomain from array and update - const payload = URI_ALLOW_LIST_ARRAY.filter((e: string) => e !== domain) + // Remove selectedUrl from array and update + const payload = URI_ALLOW_LIST_ARRAY.filter((e: string) => e !== url) const { error } = await authConfig.update({ URI_ALLOW_LIST: payload.toString() }) if (!error) { - setSelectedDomainToDelete(undefined) - ui.setNotification({ category: 'success', message: 'Successfully removed domain' }) + setSelectedUrlToDelete(undefined) + ui.setNotification({ category: 'success', message: 'Successfully removed URL' }) } else { ui.setNotification({ error, category: 'error', - message: `Failed to remove domain: ${error?.message}`, + message: `Failed to remove URL: ${error?.message}`, }) } @@ -115,50 +115,45 @@ const RedirectDomains = () => { )}
- + setOpen(!open)} - header={

Add a new domain

} + header={

Add a new URL

} >
{({ isSubmitting }: { isSubmitting: boolean }) => { return (

- This will add a domain to a list of allowed domains that can interact with your + This will add a URL to a list of allowed URLs that can interact with your Authenticaton services for this project.

- +
@@ -169,18 +164,18 @@ const RedirectDomains = () => { Remove domain} - onCancel={() => setSelectedDomainToDelete(undefined)} + visible={selectedUrlToDelete !== undefined} + header={

Remove URL

} + onCancel={() => setSelectedUrlToDelete(undefined)} >

Are you sure you want to remove{' '} - {selectedDomainToDelete}? + {selectedUrlToDelete}?

-

- This domain will no longer work with your authentication configuration. +

+ This URL will no longer work with your authentication configuration.

@@ -189,7 +184,7 @@ const RedirectDomains = () => { block type="default" size="medium" - onClick={() => setSelectedDomainToDelete(undefined)} + onClick={() => setSelectedUrlToDelete(undefined)} > Cancel @@ -198,9 +193,9 @@ const RedirectDomains = () => { size="medium" type="warning" loading={isDeleting} - onClick={() => onConfirmDeleteDomain(selectedDomainToDelete)} + onClick={() => onConfirmDeleteUrl(selectedUrlToDelete)} > - {isDeleting ? 'Removing...' : 'Remove domain'} + {isDeleting ? 'Removing...' : 'Remove URL'}
@@ -209,4 +204,4 @@ const RedirectDomains = () => { ) } -export default observer(RedirectDomains) +export default observer(RedirectUrls) diff --git a/studio/components/interfaces/Auth/RedirectDomains/ValueContainer.tsx b/studio/components/interfaces/Auth/RedirectUrls/ValueContainer.tsx similarity index 100% rename from studio/components/interfaces/Auth/RedirectDomains/ValueContainer.tsx rename to studio/components/interfaces/Auth/RedirectUrls/ValueContainer.tsx diff --git a/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx b/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx index 18d7ec4d7b1..4014bc69c75 100644 --- a/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx +++ b/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx @@ -13,7 +13,7 @@ import { FormSectionLabel, } from 'components/ui/Forms' import { useStore, checkPermissions } from 'hooks' -import { domainRegex } from './../Auth.constants' +import { urlRegex } from './../Auth.constants' import { defaultDisabledSmtpFormValues } from './SmtpForm.constants' import { generateFormValues, isSmtpEnabled } from './SmtpForm.utils' @@ -55,7 +55,7 @@ const SmtpForm = () => { }, then: (schema) => schema - .matches(domainRegex, 'Must be a valid URL or IP address') + .matches(urlRegex, 'Must be a valid URL or IP address') .required('Host URL is required.'), otherwise: (schema) => schema, }), diff --git a/studio/components/interfaces/Billing/AddOns/ComputeSizeSelection.tsx b/studio/components/interfaces/Billing/AddOns/ComputeSizeSelection.tsx index 3354fc5be98..437e7d152c1 100644 --- a/studio/components/interfaces/Billing/AddOns/ComputeSizeSelection.tsx +++ b/studio/components/interfaces/Billing/AddOns/ComputeSizeSelection.tsx @@ -2,7 +2,8 @@ import { FC } from 'react' import Link from 'next/link' import { Badge, Button, IconExternalLink, Radio } from 'ui' -import { useFlag, useParams } from 'hooks' +import { useFlag } from 'hooks' +import { useParams } from 'common/hooks' import { getProductPrice } from '../Billing.utils' import DisabledWarningDueToIncident from 'components/ui/DisabledWarningDueToIncident' import { SubscriptionAddon } from './AddOns.types' diff --git a/studio/components/interfaces/Billing/AddOns/CustomDomainSelection.tsx b/studio/components/interfaces/Billing/AddOns/CustomDomainSelection.tsx index 8e5515013f9..022940f66cd 100644 --- a/studio/components/interfaces/Billing/AddOns/CustomDomainSelection.tsx +++ b/studio/components/interfaces/Billing/AddOns/CustomDomainSelection.tsx @@ -2,7 +2,8 @@ import Link from 'next/link' import { FC } from 'react' import { Badge, Button, Radio } from 'ui' -import { useFlag, useParams } from 'hooks' +import { useFlag } from 'hooks' +import { useParams } from 'common/hooks' import { getProductPrice } from '../Billing.utils' import DisabledWarningDueToIncident from 'components/ui/DisabledWarningDueToIncident' import { SubscriptionAddon } from './AddOns.types' diff --git a/studio/components/interfaces/Billing/AddOns/PITRDurationSelection.tsx b/studio/components/interfaces/Billing/AddOns/PITRDurationSelection.tsx index 88609d60601..52476a92bd4 100644 --- a/studio/components/interfaces/Billing/AddOns/PITRDurationSelection.tsx +++ b/studio/components/interfaces/Billing/AddOns/PITRDurationSelection.tsx @@ -2,7 +2,8 @@ import Link from 'next/link' import { FC } from 'react' import { Badge, IconAlertCircle, Radio, Button } from 'ui' -import { useFlag, useParams, useStore } from 'hooks' +import { useFlag, useStore } from 'hooks' +import { useParams } from 'common/hooks' import { SubscriptionAddon } from './AddOns.types' import { getProductPrice } from '../Billing.utils' import DisabledWarningDueToIncident from 'components/ui/DisabledWarningDueToIncident' diff --git a/studio/components/interfaces/Billing/AddOns/SupportPlan.tsx b/studio/components/interfaces/Billing/AddOns/SupportPlan.tsx index 56f22afce68..5fa2c3af196 100644 --- a/studio/components/interfaces/Billing/AddOns/SupportPlan.tsx +++ b/studio/components/interfaces/Billing/AddOns/SupportPlan.tsx @@ -1,7 +1,7 @@ import { FC } from 'react' import Link from 'next/link' import { Button } from 'ui' -import { useParams } from 'hooks' +import { useParams } from 'common/hooks' interface Props { currentOption?: any diff --git a/studio/components/interfaces/Billing/Subscription/Subscription.tsx b/studio/components/interfaces/Billing/Subscription/Subscription.tsx index 8dc90989675..2203e92885c 100644 --- a/studio/components/interfaces/Billing/Subscription/Subscription.tsx +++ b/studio/components/interfaces/Billing/Subscription/Subscription.tsx @@ -5,7 +5,8 @@ import { Button, Loading } from 'ui' import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useFlag, useParams } from 'hooks' +import { checkPermissions, useFlag } from 'hooks' +import { useParams } from 'common/hooks' import { STRIPE_PRODUCT_IDS } from 'lib/constants' import { formatBytes } from 'lib/helpers' diff --git a/studio/components/interfaces/Database/Backups/PITR/PITRNotice.tsx b/studio/components/interfaces/Database/Backups/PITR/PITRNotice.tsx index fecbf2eafd1..00bbace11c8 100644 --- a/studio/components/interfaces/Database/Backups/PITR/PITRNotice.tsx +++ b/studio/components/interfaces/Database/Backups/PITR/PITRNotice.tsx @@ -2,7 +2,8 @@ import Link from 'next/link' import { Button, IconCalendar } from 'ui' import { FormPanel } from 'components/ui/Forms' import * as Tooltip from '@radix-ui/react-tooltip' -import { checkPermissions, useParams } from 'hooks' +import { checkPermissions } from 'hooks' +import { useParams } from 'common/hooks' import { useProjectSubscriptionQuery } from 'data/subscriptions/project-subscription-query' import { getPITRRetentionDuration } from './PITR.utils' import { PermissionAction } from '@supabase/shared-types/out/constants' diff --git a/studio/components/interfaces/Database/Extensions/Extensions.tsx b/studio/components/interfaces/Database/Extensions/Extensions.tsx index d53fc0d3026..48164cf331f 100644 --- a/studio/components/interfaces/Database/Extensions/Extensions.tsx +++ b/studio/components/interfaces/Database/Extensions/Extensions.tsx @@ -4,7 +4,8 @@ import { partition, isNull } from 'lodash' import { Input, IconSearch, IconAlertCircle, Button, IconBookOpen } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useStore, checkPermissions, useParams } from 'hooks' +import { useStore, checkPermissions } from 'hooks' +import { useParams } from 'common/hooks' import ExtensionCard from './ExtensionCard' import { HIDDEN_EXTENSIONS } from './Extensions.constants' import NoSearchResults from 'components/ui/NoSearchResults' diff --git a/studio/components/interfaces/Database/Hooks/EditHookPanel.tsx b/studio/components/interfaces/Database/Hooks/EditHookPanel.tsx index bc77c37b07f..1af30acba47 100644 --- a/studio/components/interfaces/Database/Hooks/EditHookPanel.tsx +++ b/studio/components/interfaces/Database/Hooks/EditHookPanel.tsx @@ -3,7 +3,8 @@ import { useState, useRef, useEffect } from 'react' import { PostgresTrigger } from '@supabase/postgres-meta' import { Button, SidePanel, Form, Input, Listbox, Checkbox, Radio, Badge, Modal } from 'ui' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import { tryParseJson, uuidv4 } from 'lib/helpers' import HTTPRequestFields from './HTTPRequestFields' import { isValidHttpUrl } from './Hooks.utils' diff --git a/studio/components/interfaces/Database/Hooks/HTTPRequestFields.tsx b/studio/components/interfaces/Database/Hooks/HTTPRequestFields.tsx index 59834d2da24..c1a9ba41eac 100644 --- a/studio/components/interfaces/Database/Hooks/HTTPRequestFields.tsx +++ b/studio/components/interfaces/Database/Hooks/HTTPRequestFields.tsx @@ -11,7 +11,8 @@ import { } from 'ui' import { FormSection, FormSectionLabel, FormSectionContent } from 'components/ui/Forms' import { HTTPArgument } from './EditHookPanel' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import { useEdgeFunctionsQuery } from 'data/edge-functions/edge-functions-query' import clsx from 'clsx' import { uuidv4 } from 'lib/helpers' diff --git a/studio/components/interfaces/Database/Hooks/HooksList/HookList.tsx b/studio/components/interfaces/Database/Hooks/HooksList/HookList.tsx index afccb7f5b5e..7e434e4cef5 100644 --- a/studio/components/interfaces/Database/Hooks/HooksList/HookList.tsx +++ b/studio/components/interfaces/Database/Hooks/HooksList/HookList.tsx @@ -6,7 +6,8 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' import { Badge, Button, Dropdown, IconMoreVertical, IconTrash, IconEdit3 } from 'ui' -import { checkPermissions, useParams, useStore } from 'hooks' +import { checkPermissions, useStore } from 'hooks' +import { useParams } from 'common/hooks' import { BASE_PATH } from 'lib/constants' import Table from 'components/to-be-cleaned/Table' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' diff --git a/studio/components/interfaces/Database/Wrappers/CreateWrapper.tsx b/studio/components/interfaces/Database/Wrappers/CreateWrapper.tsx index 242345a01f7..558873bb1e3 100644 --- a/studio/components/interfaces/Database/Wrappers/CreateWrapper.tsx +++ b/studio/components/interfaces/Database/Wrappers/CreateWrapper.tsx @@ -6,7 +6,8 @@ import { observer } from 'mobx-react-lite' import { Button, Form, Input, IconArrowLeft, IconExternalLink, IconEdit, IconTrash } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useParams, useStore } from 'hooks' +import { checkPermissions, useStore } from 'hooks' +import { useParams } from 'common/hooks' import { FormPanel, FormActions, diff --git a/studio/components/interfaces/Database/Wrappers/EditWrapper.tsx b/studio/components/interfaces/Database/Wrappers/EditWrapper.tsx index fdcec1aa4b8..a8661b6f3bf 100644 --- a/studio/components/interfaces/Database/Wrappers/EditWrapper.tsx +++ b/studio/components/interfaces/Database/Wrappers/EditWrapper.tsx @@ -16,7 +16,8 @@ import { import { PermissionAction } from '@supabase/shared-types/out/constants' import { VaultSecret } from 'types' -import { checkPermissions, useImmutableValue, useParams, useStore } from 'hooks' +import { checkPermissions, useImmutableValue, useStore } from 'hooks' +import { useParams } from 'common/hooks' import { useFDWsQuery } from 'data/fdw/fdws-query' import { useFDWUpdateMutation } from 'data/fdw/fdw-update-mutation' diff --git a/studio/components/interfaces/Database/Wrappers/WrapperRow.tsx b/studio/components/interfaces/Database/Wrappers/WrapperRow.tsx index 9628bde820c..13798aa8747 100644 --- a/studio/components/interfaces/Database/Wrappers/WrapperRow.tsx +++ b/studio/components/interfaces/Database/Wrappers/WrapperRow.tsx @@ -6,7 +6,8 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' import { Collapsible, IconChevronUp, Button, IconExternalLink, IconTrash, IconEdit } from 'ui' -import { useParams, useStore, checkPermissions } from 'hooks' +import { useStore, checkPermissions } from 'hooks' +import { useParams } from 'common/hooks' import { WrapperMeta } from './Wrappers.types' import { FDW } from 'data/fdw/fdws-query' import { useFDWDeleteMutation } from 'data/fdw/fdw-delete-mutation' diff --git a/studio/components/interfaces/Database/Wrappers/WrappersDisabledState.tsx b/studio/components/interfaces/Database/Wrappers/WrappersDisabledState.tsx index 07ce73df7b4..014c060780f 100644 --- a/studio/components/interfaces/Database/Wrappers/WrappersDisabledState.tsx +++ b/studio/components/interfaces/Database/Wrappers/WrappersDisabledState.tsx @@ -5,7 +5,8 @@ import { observer } from 'mobx-react-lite' import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useParams, useStore } from 'hooks' +import { checkPermissions, useStore } from 'hooks' +import { useParams } from 'common/hooks' import { BASE_PATH } from 'lib/constants' const WrappersDisabledState = () => { diff --git a/studio/components/interfaces/Database/Wrappers/WrappersDropdown.tsx b/studio/components/interfaces/Database/Wrappers/WrappersDropdown.tsx index ba76b237de1..33b5cd693ed 100644 --- a/studio/components/interfaces/Database/Wrappers/WrappersDropdown.tsx +++ b/studio/components/interfaces/Database/Wrappers/WrappersDropdown.tsx @@ -6,7 +6,8 @@ import { Button, Dropdown, IconPlus } from 'ui' import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useParams, checkPermissions } from 'hooks' +import { checkPermissions } from 'hooks' +import { useParams } from 'common/hooks' import { WRAPPERS } from './Wrappers.constants' interface Props { diff --git a/studio/components/interfaces/Docs/GeneratingTypes.tsx b/studio/components/interfaces/Docs/GeneratingTypes.tsx index 9cdabfe4ecc..e44e997c541 100644 --- a/studio/components/interfaces/Docs/GeneratingTypes.tsx +++ b/studio/components/interfaces/Docs/GeneratingTypes.tsx @@ -4,7 +4,8 @@ import React from 'react' import { Button, IconDownload, IconExternalLink } from 'ui' import { API_ADMIN_URL } from 'lib/constants' import { get } from 'lib/common/fetch' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import CodeSnippet from 'components/to-be-cleaned/Docs/CodeSnippet' interface Props { diff --git a/studio/components/interfaces/Docs/ResourceContent.tsx b/studio/components/interfaces/Docs/ResourceContent.tsx index 21e6a3dc5fb..efe0fec31df 100644 --- a/studio/components/interfaces/Docs/ResourceContent.tsx +++ b/studio/components/interfaces/Docs/ResourceContent.tsx @@ -231,49 +231,51 @@ const ResourceContent = ({
)} - <> -

Subscribe to changes

-
-
-

- Supabase provides realtime functionality and broadcasts database changes to authorized - users depending on Row Level Security (RLS) policies. -

-

- - Learn more - -

-
-
- - - - - -
-
- + {(methods.includes('DELETE') || methods.includes('POST') || methods.includes('PATCH')) && ( + <> +

Subscribe to changes

+
+
+

+ Supabase provides realtime functionality and broadcasts database changes to + authorized users depending on Row Level Security (RLS) policies. +

+

+ + Learn more + +

+
+
+ + + + + +
+
+ + )} ) } diff --git a/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionDetails.tsx b/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionDetails.tsx index 1da604d200e..1095bf70ed0 100644 --- a/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionDetails.tsx +++ b/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionDetails.tsx @@ -17,7 +17,8 @@ import { IconExternalLink, } from 'ui' -import { useStore, useParams, checkPermissions } from 'hooks' +import { useStore, checkPermissions } from 'hooks' +import { useParams } from 'common/hooks' import Panel from 'components/ui/Panel' import CommandRender from '../CommandRender' import { generateCLICommands } from './EdgeFunctionDetails.utils' diff --git a/studio/components/interfaces/Functions/EdgeFunctionsListItem.tsx b/studio/components/interfaces/Functions/EdgeFunctionsListItem.tsx index 2c4c666e417..9b90a9c2539 100644 --- a/studio/components/interfaces/Functions/EdgeFunctionsListItem.tsx +++ b/studio/components/interfaces/Functions/EdgeFunctionsListItem.tsx @@ -5,7 +5,8 @@ import { observer } from 'mobx-react-lite' import { IconCheck, IconClipboard } from 'ui' import * as Tooltip from '@radix-ui/react-tooltip' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import Table from 'components/to-be-cleaned/Table' import { EdgeFunctionsResponse } from 'data/edge-functions/edge-functions-query' diff --git a/studio/components/interfaces/Functions/TerminalInstructions.tsx b/studio/components/interfaces/Functions/TerminalInstructions.tsx index 0a933c1d0b9..a4448748dbd 100644 --- a/studio/components/interfaces/Functions/TerminalInstructions.tsx +++ b/studio/components/interfaces/Functions/TerminalInstructions.tsx @@ -1,7 +1,7 @@ import CommandRender from 'components/interfaces/Functions/CommandRender' import { useAccessTokensQuery } from 'data/access-tokens/access-tokens-query' import { useProjectApiQuery } from 'data/config/project-api-query' -import { useParams } from 'hooks' +import { useParams } from 'common/hooks' import Link from 'next/link' import { useRouter } from 'next/router' import { FC, useState } from 'react' diff --git a/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx b/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx index a2fc1baf0dd..42b39dbac4b 100644 --- a/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx +++ b/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx @@ -6,7 +6,8 @@ import { IconAlertCircle, IconLoader, Input } from 'ui' import { useProjectApiQuery } from 'data/config/project-api-query' import { useJwtSecretUpdatingStatusQuery } from 'data/config/jwt-secret-updating-status-query' -import { checkPermissions, useParams } from 'hooks' +import { checkPermissions } from 'hooks' +import { useParams } from 'common/hooks' import Snippets from 'components/to-be-cleaned/Docs/Snippets' import Panel from 'components/ui/Panel' import SimpleCodeBlock from 'components/to-be-cleaned/SimpleCodeBlock' diff --git a/studio/components/interfaces/Home/ProjectUsage.tsx b/studio/components/interfaces/Home/ProjectUsage.tsx index d113c2bd5c9..ff7ffc79c9b 100644 --- a/studio/components/interfaces/Home/ProjectUsage.tsx +++ b/studio/components/interfaces/Home/ProjectUsage.tsx @@ -7,7 +7,7 @@ import ChartHandler from 'components/to-be-cleaned/Charts/ChartHandler' import Panel from 'components/ui/Panel' import { DATE_FORMAT, METRICS } from 'lib/constants' import { ChartIntervals } from 'types' -import { useParams } from 'hooks' +import { useParams } from 'common/hooks' import { useProjectLogStatsQuery } from 'data/logs/project-log-stats-query' const CHART_INTERVALS: ChartIntervals[] = [ diff --git a/studio/components/interfaces/Home/ProjectUsageSection.tsx b/studio/components/interfaces/Home/ProjectUsageSection.tsx index 9064717135c..df3811a5e14 100644 --- a/studio/components/interfaces/Home/ProjectUsageSection.tsx +++ b/studio/components/interfaces/Home/ProjectUsageSection.tsx @@ -2,7 +2,7 @@ import { FC } from 'react' import { observer } from 'mobx-react-lite' import { IconLoader, IconAlertCircle } from 'ui' -import { useParams } from 'hooks' +import { useParams } from 'common/hooks' import { ProjectUsage, NewProjectPanel } from 'components/interfaces/Home' import InformationBox from 'components/ui/InformationBox' import { ProjectUsageResponseUsageKeys, useProjectUsageQuery } from 'data/usage/project-usage-query' diff --git a/studio/components/interfaces/Organization/BillingSettings/BillingEmail.tsx b/studio/components/interfaces/Organization/BillingSettings/BillingEmail.tsx index b9b25b40ede..db8b8d7b2fa 100644 --- a/studio/components/interfaces/Organization/BillingSettings/BillingEmail.tsx +++ b/studio/components/interfaces/Organization/BillingSettings/BillingEmail.tsx @@ -1,7 +1,8 @@ import { useEffect } from 'react' import { Form, Input } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useStore, checkPermissions, useParams } from 'hooks' +import { useStore, checkPermissions } from 'hooks' +import { useParams } from 'common/hooks' import { API_URL } from 'lib/constants' import { patch } from 'lib/common/fetch' import { FormActions, FormPanel, FormSection, FormSectionContent } from 'components/ui/Forms' diff --git a/studio/components/interfaces/Organization/BillingSettings/BillingSettings.tsx b/studio/components/interfaces/Organization/BillingSettings/BillingSettings.tsx index cd7cfb91c0f..ba01a03ef37 100644 --- a/studio/components/interfaces/Organization/BillingSettings/BillingSettings.tsx +++ b/studio/components/interfaces/Organization/BillingSettings/BillingSettings.tsx @@ -2,7 +2,8 @@ import { useState, useEffect } from 'react' import { observer } from 'mobx-react-lite' import { Project } from 'types' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import { API_URL } from 'lib/constants' import { get } from 'lib/common/fetch' diff --git a/studio/components/interfaces/Organization/GeneralSettings/GeneralSettings.tsx b/studio/components/interfaces/Organization/GeneralSettings/GeneralSettings.tsx index 5910d5043d6..848b15c8227 100644 --- a/studio/components/interfaces/Organization/GeneralSettings/GeneralSettings.tsx +++ b/studio/components/interfaces/Organization/GeneralSettings/GeneralSettings.tsx @@ -3,7 +3,8 @@ import { observer } from 'mobx-react-lite' import { Form, Input } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useStore, checkPermissions, useParams } from 'hooks' +import { useStore, checkPermissions } from 'hooks' +import { useParams } from 'common/hooks' import { API_URL } from 'lib/constants' import { patch } from 'lib/common/fetch' diff --git a/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx b/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx index 1be69a28efd..23225e0ff3b 100644 --- a/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx +++ b/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx @@ -2,10 +2,11 @@ import { isNil } from 'lodash' import { useEffect, useState } from 'react' import { object, string } from 'yup' import * as Tooltip from '@radix-ui/react-tooltip' -import { Button, Form, IconMail, Input, Modal, Select } from 'ui' +import { Button, Form, IconMail, Input, Listbox, Modal } from 'ui' import { Member, Role } from 'types' -import { checkPermissions, useParams, useStore } from 'hooks' +import { checkPermissions, useStore } from 'hooks' +import { useParams } from 'common/hooks' import { PermissionAction } from '@supabase/shared-types/out/constants' import { useOrganizationMemberInviteCreateMutation } from 'data/organizations/organization-member-invite-create-mutation' @@ -155,7 +156,7 @@ const InviteMemberButton = ({
{roles && ( - + )}
diff --git a/studio/components/interfaces/Organization/TeamSettings/MemberActions.tsx b/studio/components/interfaces/Organization/TeamSettings/MemberActions.tsx index aacca36a58a..ba2a47bf189 100644 --- a/studio/components/interfaces/Organization/TeamSettings/MemberActions.tsx +++ b/studio/components/interfaces/Organization/TeamSettings/MemberActions.tsx @@ -5,7 +5,8 @@ import { FC } from 'react' import { Button, Dropdown, IconMoreHorizontal, IconTrash } from 'ui' import { confirmAlert } from 'components/to-be-cleaned/ModalsDeprecated/ConfirmModal' -import { checkPermissions, useParams, useStore } from 'hooks' +import { checkPermissions, useStore } from 'hooks' +import { useParams } from 'common/hooks' import { Member, Role } from 'types' import { useOrganizationMemberDeleteMutation } from 'data/organizations/organization-member-delete-mutation' diff --git a/studio/components/interfaces/Organization/TeamSettings/MembersView.tsx b/studio/components/interfaces/Organization/TeamSettings/MembersView.tsx index ffbb54d6f65..3dca2403e09 100644 --- a/studio/components/interfaces/Organization/TeamSettings/MembersView.tsx +++ b/studio/components/interfaces/Organization/TeamSettings/MembersView.tsx @@ -5,7 +5,8 @@ import { observer } from 'mobx-react-lite' import { Badge, Button, Loading, Listbox, IconUser, Modal, IconAlertCircle, IconLoader } from 'ui' import { Member } from 'types' -import { useStore, useParams } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import Table from 'components/to-be-cleaned/Table' diff --git a/studio/components/interfaces/Organization/TeamSettings/TeamSettings.tsx b/studio/components/interfaces/Organization/TeamSettings/TeamSettings.tsx index 42140783088..bb5f155102d 100644 --- a/studio/components/interfaces/Organization/TeamSettings/TeamSettings.tsx +++ b/studio/components/interfaces/Organization/TeamSettings/TeamSettings.tsx @@ -3,7 +3,8 @@ import { observer } from 'mobx-react-lite' import { Button, Input, IconSearch } from 'ui' import * as Tooltip from '@radix-ui/react-tooltip' -import { useStore, useParams } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import { post } from 'lib/common/fetch' import { API_URL } from 'lib/constants' import { useProfileQuery } from 'data/profile/profile-query' diff --git a/studio/components/interfaces/Reports/Reports.tsx b/studio/components/interfaces/Reports/Reports.tsx index ecf0223e60c..4b41c46826b 100644 --- a/studio/components/interfaces/Reports/Reports.tsx +++ b/studio/components/interfaces/Reports/Reports.tsx @@ -16,7 +16,8 @@ import { } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useParams } from 'hooks' +import { checkPermissions } from 'hooks' +import { useParams } from 'common/hooks' import { uuidv4 } from 'lib/helpers' import { METRIC_CATEGORIES, METRICS, TIME_PERIODS_REPORTS } from 'lib/constants' import { useProjectContentStore } from 'stores/projectContentStore' diff --git a/studio/components/interfaces/Settings/API/JWTSettings.tsx b/studio/components/interfaces/Settings/API/JWTSettings.tsx index 8a0c66ed22a..231c445e6b1 100644 --- a/studio/components/interfaces/Settings/API/JWTSettings.tsx +++ b/studio/components/interfaces/Settings/API/JWTSettings.tsx @@ -23,7 +23,8 @@ import { import { PermissionAction } from '@supabase/shared-types/out/constants' import { uuidv4 } from 'lib/helpers' -import { useStore, checkPermissions, useParams } from 'hooks' +import { useStore, checkPermissions } from 'hooks' +import { useParams } from 'common/hooks' import { useJwtSecretUpdatingStatusQuery } from 'data/config/jwt-secret-updating-status-query' import { useJwtSecretUpdateMutation } from 'data/config/jwt-secret-update-mutation' import { useProjectPostgrestConfigQuery } from 'data/config/project-postgrest-config-query' diff --git a/studio/components/interfaces/Settings/API/PostgrestConfig.tsx b/studio/components/interfaces/Settings/API/PostgrestConfig.tsx index 1d3f6d74d74..2ed7d977be9 100644 --- a/studio/components/interfaces/Settings/API/PostgrestConfig.tsx +++ b/studio/components/interfaces/Settings/API/PostgrestConfig.tsx @@ -4,7 +4,8 @@ import { observer } from 'mobx-react-lite' import { Input, Form, IconAlertCircle, InputNumber } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useStore, useParams } from 'hooks' +import { checkPermissions, useStore } from 'hooks' +import { useParams } from 'common/hooks' import { useProjectPostgrestConfigQuery } from 'data/config/project-postgrest-config-query' import { useProjectPostgrestConfigUpdateMutation } from 'data/config/project-postgrest-config-update-mutation' import MultiSelect from 'components/ui/MultiSelect' diff --git a/studio/components/interfaces/Settings/API/ServiceList.tsx b/studio/components/interfaces/Settings/API/ServiceList.tsx index 3209ae9ae15..f22b65c0215 100644 --- a/studio/components/interfaces/Settings/API/ServiceList.tsx +++ b/studio/components/interfaces/Settings/API/ServiceList.tsx @@ -3,7 +3,8 @@ import { JwtSecretUpdateError, JwtSecretUpdateStatus } from '@supabase/shared-ty import { useEffect, useRef } from 'react' import { IconAlertCircle, Input } from 'ui' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import { useJwtSecretUpdatingStatusQuery } from 'data/config/jwt-secret-updating-status-query' import { useProjectApiQuery } from 'data/config/project-api-query' diff --git a/studio/components/interfaces/Settings/Database/DatabaseSettings/ResetDbPassword.tsx b/studio/components/interfaces/Settings/Database/DatabaseSettings/ResetDbPassword.tsx index 40c076a6b10..c3d88b9915f 100644 --- a/studio/components/interfaces/Settings/Database/DatabaseSettings/ResetDbPassword.tsx +++ b/studio/components/interfaces/Settings/Database/DatabaseSettings/ResetDbPassword.tsx @@ -5,7 +5,8 @@ import generator from 'generate-password' import { Input, Button, Modal } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useParams, useStore } from 'hooks' +import { checkPermissions, useStore } from 'hooks' +import { useParams } from 'common/hooks' import { patch } from 'lib/common/fetch' import { passwordStrength } from 'lib/helpers' import { API_URL, DEFAULT_MINIMUM_PASSWORD_STRENGTH } from 'lib/constants' diff --git a/studio/components/interfaces/Settings/Database/NetworkRestrictions/AddRestrictionModal.tsx b/studio/components/interfaces/Settings/Database/NetworkRestrictions/AddRestrictionModal.tsx index b79d99fa3c6..44fcec66a5f 100644 --- a/studio/components/interfaces/Settings/Database/NetworkRestrictions/AddRestrictionModal.tsx +++ b/studio/components/interfaces/Settings/Database/NetworkRestrictions/AddRestrictionModal.tsx @@ -3,7 +3,8 @@ import { Address4 } from 'ip-address' import { Button, Form, IconHelpCircle, Input, Modal } from 'ui' import * as Tooltip from '@radix-ui/react-tooltip' -import { useStore, useParams } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import InformationBox from 'components/ui/InformationBox' import { checkIfPrivate, getAddressEndRange } from './NetworkRestrictions.utils' import { useNetworkRestrictionsApplyMutation } from 'data/network-restrictions/network-retrictions-apply-mutation' diff --git a/studio/components/interfaces/Settings/Database/NetworkRestrictions/AllowAllModal.tsx b/studio/components/interfaces/Settings/Database/NetworkRestrictions/AllowAllModal.tsx index 084d12c3d89..880c176f9bb 100644 --- a/studio/components/interfaces/Settings/Database/NetworkRestrictions/AllowAllModal.tsx +++ b/studio/components/interfaces/Settings/Database/NetworkRestrictions/AllowAllModal.tsx @@ -1,7 +1,8 @@ import { FC, useState } from 'react' import { Modal, Button } from 'ui' -import { useStore, useParams } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import { useNetworkRestrictionsApplyMutation } from 'data/network-restrictions/network-retrictions-apply-mutation' interface Props { diff --git a/studio/components/interfaces/Settings/Database/NetworkRestrictions/DisallowAllModal.tsx b/studio/components/interfaces/Settings/Database/NetworkRestrictions/DisallowAllModal.tsx index 537d509515e..c843de5dcbc 100644 --- a/studio/components/interfaces/Settings/Database/NetworkRestrictions/DisallowAllModal.tsx +++ b/studio/components/interfaces/Settings/Database/NetworkRestrictions/DisallowAllModal.tsx @@ -1,7 +1,8 @@ import { FC, useState } from 'react' import { Modal, Button } from 'ui' -import { useStore, useParams } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import { useNetworkRestrictionsApplyMutation } from 'data/network-restrictions/network-retrictions-apply-mutation' import InformationBox from 'components/ui/InformationBox' diff --git a/studio/components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.tsx b/studio/components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.tsx index 35242df3cb8..31e465530f8 100644 --- a/studio/components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.tsx +++ b/studio/components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.tsx @@ -4,7 +4,8 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { Button, IconAlertCircle, IconExternalLink, IconGlobe, IconLock } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useParams } from 'hooks' +import { checkPermissions } from 'hooks' +import { useParams } from 'common/hooks' import Panel from 'components/ui/Panel' import { FormPanel, FormHeader } from 'components/ui/Forms' import ShimmeringLoader from 'components/ui/ShimmeringLoader' diff --git a/studio/components/interfaces/Settings/Database/NetworkRestrictions/RemoveRestrictionModal.tsx b/studio/components/interfaces/Settings/Database/NetworkRestrictions/RemoveRestrictionModal.tsx index cd2a4f7f654..c0aa9253ea7 100644 --- a/studio/components/interfaces/Settings/Database/NetworkRestrictions/RemoveRestrictionModal.tsx +++ b/studio/components/interfaces/Settings/Database/NetworkRestrictions/RemoveRestrictionModal.tsx @@ -1,7 +1,8 @@ import { FC, useState } from 'react' import { Alert, Button, Form, Input, Modal } from 'ui' -import { useStore, useParams } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import { useNetworkRestrictionsApplyMutation } from 'data/network-restrictions/network-retrictions-apply-mutation' interface Props { diff --git a/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx b/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx index 92e146e911e..c764afb0a4a 100644 --- a/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx +++ b/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx @@ -4,7 +4,8 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { Button, IconDownload, Toggle, IconLoader, Alert } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useParams, useStore, useFlag } from 'hooks' +import { checkPermissions, useStore, useFlag } from 'hooks' +import { useParams } from 'common/hooks' import { FormHeader, FormPanel, diff --git a/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainConfig.tsx b/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainConfig.tsx index 6ce9eb610cb..9e6192fab4b 100644 --- a/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainConfig.tsx +++ b/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainConfig.tsx @@ -2,7 +2,8 @@ import Link from 'next/link' import { observer } from 'mobx-react-lite' import { IconAlertCircle } from 'ui' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import { useProjectApiQuery } from 'data/config/project-api-query' import { useCustomDomainsQuery } from 'data/custom-domains/custom-domains-query' import Panel from 'components/ui/Panel' diff --git a/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainsConfigureHostname.tsx b/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainsConfigureHostname.tsx index 398f62b9ec3..c41ae2dd05f 100644 --- a/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainsConfigureHostname.tsx +++ b/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainsConfigureHostname.tsx @@ -4,7 +4,8 @@ import { observer } from 'mobx-react-lite' import { Button, Form, IconExternalLink, Input } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useParams, useStore } from 'hooks' +import { checkPermissions, useStore } from 'hooks' +import { useParams } from 'common/hooks' import { FormActions, FormPanel, diff --git a/studio/components/interfaces/Settings/General/Infrastructure/Infrastructure.tsx b/studio/components/interfaces/Settings/General/Infrastructure/Infrastructure.tsx index c437f5fb6e0..52e13db0717 100644 --- a/studio/components/interfaces/Settings/General/Infrastructure/Infrastructure.tsx +++ b/studio/components/interfaces/Settings/General/Infrastructure/Infrastructure.tsx @@ -4,7 +4,8 @@ import { Alert, Badge, Button, IconPackage, Input } from 'ui' import { observer } from 'mobx-react-lite' import * as Tooltip from '@radix-ui/react-tooltip' -import { useFlag, useParams, useStore } from 'hooks' +import { useFlag, useStore } from 'hooks' +import { useParams } from 'common/hooks' import { PRICING_TIER_PRODUCT_IDS } from 'lib/constants' import { FormHeader, diff --git a/studio/components/interfaces/Settings/General/Infrastructure/ProjectUpgradeAlert/ProjectUpgradeAlert.tsx b/studio/components/interfaces/Settings/General/Infrastructure/ProjectUpgradeAlert/ProjectUpgradeAlert.tsx index 453770469a2..0af657cae0e 100644 --- a/studio/components/interfaces/Settings/General/Infrastructure/ProjectUpgradeAlert/ProjectUpgradeAlert.tsx +++ b/studio/components/interfaces/Settings/General/Infrastructure/ProjectUpgradeAlert/ProjectUpgradeAlert.tsx @@ -12,7 +12,8 @@ import { IconExternalLink, } from 'ui' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import { post } from 'lib/common/fetch' import { API_ADMIN_URL, PROJECT_STATUS } from 'lib/constants' import InformationBox from 'components/ui/InformationBox' diff --git a/studio/components/interfaces/Settings/Logs/LogsPreviewer.tsx b/studio/components/interfaces/Settings/Logs/LogsPreviewer.tsx index 543c32821d8..1d718bcfb33 100644 --- a/studio/components/interfaces/Settings/Logs/LogsPreviewer.tsx +++ b/studio/components/interfaces/Settings/Logs/LogsPreviewer.tsx @@ -22,7 +22,7 @@ import ShimmerLine from 'components/ui/ShimmerLine' import LoadingOpacity from 'components/ui/LoadingOpacity' import { useUpgradePrompt } from 'hooks/misc/useUpgradePrompt' import UpgradePrompt from './UpgradePrompt' -import { useParams } from 'hooks' +import { useParams } from 'common/hooks' import { useProjectSubscriptionQuery } from 'data/subscriptions/project-subscription-query' /** diff --git a/studio/components/interfaces/Settings/Vault/Keys/EncryptionKeysManagement.tsx b/studio/components/interfaces/Settings/Vault/Keys/EncryptionKeysManagement.tsx index 6010ec432ca..135381a6600 100644 --- a/studio/components/interfaces/Settings/Vault/Keys/EncryptionKeysManagement.tsx +++ b/studio/components/interfaces/Settings/Vault/Keys/EncryptionKeysManagement.tsx @@ -18,7 +18,8 @@ import { IconExternalLink, } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useParams, useStore, checkPermissions } from 'hooks' +import { useStore, checkPermissions } from 'hooks' +import { useParams } from 'common/hooks' import Divider from 'components/ui/Divider' const DEFAULT_KEY_NAME = 'No description provided' diff --git a/studio/components/interfaces/Settings/Vault/Secrets/SecretRow.tsx b/studio/components/interfaces/Settings/Vault/Secrets/SecretRow.tsx index 9ff849dd7ae..1b17adc55e7 100644 --- a/studio/components/interfaces/Settings/Vault/Secrets/SecretRow.tsx +++ b/studio/components/interfaces/Settings/Vault/Secrets/SecretRow.tsx @@ -16,7 +16,8 @@ import { import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' import { VaultSecret } from 'types' -import { useParams, useStore, checkPermissions } from 'hooks' +import { useStore, checkPermissions } from 'hooks' +import { useParams } from 'common/hooks' interface Props { secret: VaultSecret diff --git a/studio/components/interfaces/Settings/Vault/Secrets/SecretsManagement.tsx b/studio/components/interfaces/Settings/Vault/Secrets/SecretsManagement.tsx index b3adab646d4..614e6e09b19 100644 --- a/studio/components/interfaces/Settings/Vault/Secrets/SecretsManagement.tsx +++ b/studio/components/interfaces/Settings/Vault/Secrets/SecretsManagement.tsx @@ -5,7 +5,8 @@ import { FC, Fragment, useState, useEffect } from 'react' import { IconSearch, Input, Button, Listbox, IconLoader, IconExternalLink, IconX } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useStore, useParams, checkPermissions } from 'hooks' +import { useStore, checkPermissions } from 'hooks' +import { useParams } from 'common/hooks' import SecretRow from './SecretRow' import EditSecretModal from './EditSecretModal' import DeleteSecretModal from './DeleteSecretModal' diff --git a/studio/components/interfaces/Settings/Vault/VaultToggle.tsx b/studio/components/interfaces/Settings/Vault/VaultToggle.tsx index f03f88633c7..510e6d66e70 100644 --- a/studio/components/interfaces/Settings/Vault/VaultToggle.tsx +++ b/studio/components/interfaces/Settings/Vault/VaultToggle.tsx @@ -5,7 +5,8 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { Button, IconExternalLink } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useParams, useStore } from 'hooks' +import { checkPermissions, useStore } from 'hooks' +import { useParams } from 'common/hooks' import { BASE_PATH } from 'lib/constants' interface Props {} diff --git a/studio/components/interfaces/TableGridEditor/APIDocumentationPanel.tsx b/studio/components/interfaces/TableGridEditor/APIDocumentationPanel.tsx index 0557b5e4d02..4565ba6ee28 100644 --- a/studio/components/interfaces/TableGridEditor/APIDocumentationPanel.tsx +++ b/studio/components/interfaces/TableGridEditor/APIDocumentationPanel.tsx @@ -1,7 +1,8 @@ import { useState } from 'react' import { SidePanel, IconBookOpen } from 'ui' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import { GeneralContent, ResourceContent } from '../Docs' import LangSelector from '../Docs/LangSelector' import GeneratingTypes from '../Docs/GeneratingTypes' diff --git a/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.tsx b/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.tsx index c5097858d28..79d492764e6 100644 --- a/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.tsx +++ b/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.tsx @@ -10,7 +10,8 @@ import type { PostgresType, } from '@supabase/postgres-meta' -import { useFlag, useParams, useStore } from 'hooks' +import { useFlag, useStore } from 'hooks' +import { useParams } from 'common/hooks' import ActionBar from '../ActionBar' import HeaderTitle from './HeaderTitle' import ColumnType from './ColumnType' diff --git a/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx b/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx index 64b3bdf0b9f..4e324a587ed 100644 --- a/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx +++ b/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx @@ -5,7 +5,7 @@ import { Dictionary } from 'components/grid' import { Modal } from 'ui' import type { PostgresTable, PostgresColumn } from '@supabase/postgres-meta' -import { useStore } from 'hooks' +import { useStore, useUrlState } from 'hooks' import { entityTypeKeys } from 'data/entity-types/keys' import { useTableRowCreateMutation } from 'data/table-rows/table-row-create-mutation' import { useTableRowUpdateMutation } from 'data/table-rows/table-row-update-mutation' @@ -66,6 +66,7 @@ const SidePanelEditor = ({ onTableCreated = noop, onColumnSaved = noop, }: SidePanelEditorProps) => { + const [_, setParams] = useUrlState({ arrayKeys: ['filter', 'sort'] }) const { meta, ui } = useStore() const queryClient = useQueryClient() @@ -263,6 +264,14 @@ const SidePanelEditor = ({ if (response?.error) { ui.setNotification({ category: 'error', message: response.error.message }) } else { + if ( + !isNewRecord && + payload.name && + selectedColumnToEdit && + selectedColumnToEdit.name !== payload.name + ) { + reAddRenamedColumnSortAndFilter(selectedColumnToEdit.name, payload.name) + } queryClient.invalidateQueries(sqlKeys.query(project?.ref, ['foreign-key-constraints'])) await Promise.all([ meta.tables.loadById(selectedTable!.id), @@ -283,6 +292,28 @@ const SidePanelEditor = ({ resolve() } + /** + * Adds the renamed column's filter and/or sort rules. + */ + const reAddRenamedColumnSortAndFilter = (oldColumnName: string, newColumnName: string) => { + setParams((prevParams) => { + const existingFilters = (prevParams?.filter ?? []) as string[] + const existingSorts = (prevParams?.sort ?? []) as string[] + + return { + ...prevParams, + filter: existingFilters.map((filter: string) => { + const [column] = filter.split(':') + return column === oldColumnName ? filter.replace(column, newColumnName) : filter + }), + sort: existingSorts.map((sort: string) => { + const [column] = sort.split(':') + return column === oldColumnName ? sort.replace(column, newColumnName) : sort + }), + } + }) + } + const saveTable = async ( payload: any, columns: ColumnField[], diff --git a/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx b/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx index 7014e0fe8e4..10cf2915fdd 100644 --- a/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx +++ b/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx @@ -7,7 +7,8 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { QueryKey, useQueryClient } from '@tanstack/react-query' import { SchemaView } from 'types' -import { checkPermissions, useFlag, useStore, useParams } from 'hooks' +import { checkPermissions, useFlag, useStore } from 'hooks' +import { useParams } from 'common/hooks' import GridHeaderActions from './GridHeaderActions' import NotFoundState from './NotFoundState' import SidePanelEditor from './SidePanelEditor' diff --git a/studio/components/layouts/FunctionsLayout.tsx b/studio/components/layouts/FunctionsLayout.tsx index d7f4cc6a7de..c7271b1d877 100644 --- a/studio/components/layouts/FunctionsLayout.tsx +++ b/studio/components/layouts/FunctionsLayout.tsx @@ -3,7 +3,8 @@ import { FC, ReactNode, useState } from 'react' import { observer } from 'mobx-react-lite' import { Button, IconExternalLink, IconCode, Modal, IconTerminal } from 'ui' -import { checkPermissions, useParams, withAuth } from 'hooks' +import { checkPermissions, withAuth } from 'hooks' +import { useParams } from 'common/hooks' import FunctionsNav from '../interfaces/Functions/FunctionsNav' import BaseLayout from 'components/layouts' import NoPermission from 'components/ui/NoPermission' @@ -44,11 +45,11 @@ const FunctionsLayout: FC = ({ title, children }) => { <>
diff --git a/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx b/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx index c7c599a6073..3abe0aead41 100644 --- a/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx +++ b/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx @@ -2,7 +2,8 @@ import Link from 'next/link' import { observer } from 'mobx-react-lite' import { IS_PLATFORM, PRICING_TIER_PRODUCT_IDS } from 'lib/constants' -import { useFlag, useParams, useStore } from 'hooks' +import { useFlag, useStore } from 'hooks' +import { useParams } from 'common/hooks' import BreadcrumbsView from './BreadcrumbsView' import OrgDropdown from './OrgDropdown' import ProjectDropdown from './ProjectDropdown' diff --git a/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx b/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx index 599436d22ac..3d534b80502 100644 --- a/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx +++ b/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx @@ -13,7 +13,7 @@ import { generateToolRoutes, } from './NavigationBar.utils' import NavigationIconButton from './NavigationIconButton' -import { useParams } from 'hooks/misc/useParams' +import { useParams } from 'common/hooks' interface Props {} diff --git a/studio/components/layouts/ProjectLayout/ProjectContext.tsx b/studio/components/layouts/ProjectLayout/ProjectContext.tsx index 0c7b2144f31..aa78d0ac3ad 100644 --- a/studio/components/layouts/ProjectLayout/ProjectContext.tsx +++ b/studio/components/layouts/ProjectLayout/ProjectContext.tsx @@ -1,4 +1,5 @@ -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import { observer } from 'mobx-react-lite' import { createContext, PropsWithChildren, useContext, useMemo } from 'react' import { Project } from 'types' diff --git a/studio/components/layouts/ProjectLayout/ProjectLayout.tsx b/studio/components/layouts/ProjectLayout/ProjectLayout.tsx index 8169fd225be..71a37032b0f 100644 --- a/studio/components/layouts/ProjectLayout/ProjectLayout.tsx +++ b/studio/components/layouts/ProjectLayout/ProjectLayout.tsx @@ -2,7 +2,8 @@ import Head from 'next/head' import { FC, ReactNode, PropsWithChildren, Fragment } from 'react' import { observer } from 'mobx-react-lite' import { useRouter } from 'next/router' -import { useStore, withAuth, useFlag, useParams } from 'hooks' +import { useStore, withAuth, useFlag } from 'hooks' +import { useParams } from 'common/hooks' import { PROJECT_STATUS } from 'lib/constants' import Connecting from 'components/ui/Loading' diff --git a/studio/components/layouts/ProjectLayout/UpgradingState/UpgradingState.tsx b/studio/components/layouts/ProjectLayout/UpgradingState/UpgradingState.tsx index 561f596c4c0..fbfacac365a 100644 --- a/studio/components/layouts/ProjectLayout/UpgradingState/UpgradingState.tsx +++ b/studio/components/layouts/ProjectLayout/UpgradingState/UpgradingState.tsx @@ -15,7 +15,8 @@ import { } from 'ui' import { DatabaseUpgradeStatus } from '@supabase/shared-types/out/events' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import { IS_PLATFORM } from 'lib/constants' import { DATABASE_UPGRADE_MESSAGES } from './UpgradingState.constants' import { useProjectUpgradingStatusQuery } from 'data/config/project-upgrade-status-query' diff --git a/studio/components/layouts/StorageLayout/StorageLayout.tsx b/studio/components/layouts/StorageLayout/StorageLayout.tsx index cb46bbb60d2..45cc14d9aa1 100644 --- a/studio/components/layouts/StorageLayout/StorageLayout.tsx +++ b/studio/components/layouts/StorageLayout/StorageLayout.tsx @@ -3,7 +3,8 @@ import { useRouter } from 'next/router' import { find, filter, get as _get } from 'lodash' import { observer } from 'mobx-react-lite' -import { useParams, useStore, withAuth } from 'hooks' +import { useStore, withAuth } from 'hooks' +import { useParams } from 'common/hooks' import { AutoApiService, useProjectApiQuery } from 'data/config/project-api-query' import BaseLayout from 'components/layouts' import ProjectLayout from '../ProjectLayout/ProjectLayout' diff --git a/studio/components/layouts/StorageLayout/StorageMenu.tsx b/studio/components/layouts/StorageLayout/StorageMenu.tsx index be1575b9caa..ab998bb3a17 100644 --- a/studio/components/layouts/StorageLayout/StorageMenu.tsx +++ b/studio/components/layouts/StorageLayout/StorageMenu.tsx @@ -6,7 +6,8 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { Button, Menu, IconLoader, Alert, IconEdit } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useParams } from 'hooks' +import { checkPermissions } from 'hooks' +import { useParams } from 'common/hooks' import BucketRow from './BucketRow' import { useStorageStore } from 'localStores/storageExplorer/StorageExplorerStore' diff --git a/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx b/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx index bd25b07380e..09e50969b71 100644 --- a/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx +++ b/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx @@ -4,7 +4,8 @@ import { noop } from 'lodash' import { observer } from 'mobx-react-lite' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useParams, useStore } from 'hooks' +import { checkPermissions, useStore } from 'hooks' +import { useParams } from 'common/hooks' import { Entity } from 'data/entity-types/entity-type-query' import { ENTITY_TYPE } from 'data/entity-types/entity-type-constants' import ProjectLayout from '../ProjectLayout/ProjectLayout' diff --git a/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx b/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx index 2ad3668090f..f8e875ee90b 100644 --- a/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx +++ b/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx @@ -25,8 +25,9 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' import type { PostgresSchema } from '@supabase/postgres-meta' +import { useParams } from 'common/hooks' import { BASE_PATH } from 'lib/constants' -import { checkPermissions, useStore, useParams, useLocalStorage } from 'hooks' +import { checkPermissions, useStore, useLocalStorage } from 'hooks' import ProductMenuItem from 'components/ui/ProductMenu/ProductMenuItem' import { useEntityTypesQuery } from 'data/entity-types/entity-types-infinite-query' import { ENTITY_TYPE } from 'data/entity-types/entity-type-constants' diff --git a/studio/components/to-be-cleaned/Docs/Pages/Tables/Introduction.tsx b/studio/components/to-be-cleaned/Docs/Pages/Tables/Introduction.tsx index ba2441ad011..28723badb85 100644 --- a/studio/components/to-be-cleaned/Docs/Pages/Tables/Introduction.tsx +++ b/studio/components/to-be-cleaned/Docs/Pages/Tables/Introduction.tsx @@ -1,6 +1,6 @@ import { FC } from 'react' import Link from 'next/link' -import { useParams } from 'hooks' +import { useParams } from 'common/hooks' import CodeSnippet from '../../CodeSnippet' import GeneratingTypes from 'components/interfaces/Docs/GeneratingTypes' diff --git a/studio/components/ui/OveragesBanner/OveragesBanner.tsx b/studio/components/ui/OveragesBanner/OveragesBanner.tsx index 991c9a05b86..5b0d0b73edf 100644 --- a/studio/components/ui/OveragesBanner/OveragesBanner.tsx +++ b/studio/components/ui/OveragesBanner/OveragesBanner.tsx @@ -2,7 +2,7 @@ import Link from 'next/link' import { FC } from 'react' import { Alert, Button } from 'ui' -import { useParams } from 'hooks' +import { useParams } from 'common/hooks' import { PRICING_TIER_PRODUCT_IDS } from 'lib/constants' import { getResourcesApproachingLimits, getResourcesExceededLimits } from './OveragesBanner.utils' import { useProjectUsageQuery } from 'data/usage/project-usage-query' diff --git a/studio/components/ui/ProjectSettings/DisplayApiSettings.tsx b/studio/components/ui/ProjectSettings/DisplayApiSettings.tsx index 587e742a41a..e1bebe6e641 100644 --- a/studio/components/ui/ProjectSettings/DisplayApiSettings.tsx +++ b/studio/components/ui/ProjectSettings/DisplayApiSettings.tsx @@ -5,7 +5,8 @@ import { IconAlertCircle, IconLoader, Input } from 'ui' import Panel from 'components/ui/Panel' import { useProjectSettingsQuery } from 'data/config/project-settings-query' import { useJwtSecretUpdatingStatusQuery } from 'data/config/jwt-secret-updating-status-query' -import { checkPermissions, useParams } from 'hooks' +import { checkPermissions } from 'hooks' +import { useParams } from 'common/hooks' import { DEFAULT_PROJECT_API_SERVICE_ID } from 'lib/constants' const DisplayApiSettings = () => { diff --git a/studio/components/ui/ProjectSettings/DisplayConfigSettings.tsx b/studio/components/ui/ProjectSettings/DisplayConfigSettings.tsx index 70f1c5eba57..5c36f018f4f 100644 --- a/studio/components/ui/ProjectSettings/DisplayConfigSettings.tsx +++ b/studio/components/ui/ProjectSettings/DisplayConfigSettings.tsx @@ -2,7 +2,7 @@ import { JwtSecretUpdateStatus } from '@supabase/shared-types/out/events' import Panel from 'components/ui/Panel' import { useJwtSecretUpdatingStatusQuery } from 'data/config/jwt-secret-updating-status-query' import { useProjectSettingsQuery } from 'data/config/project-settings-query' -import { useParams } from 'hooks' +import { useParams } from 'common/hooks' import { DEFAULT_PROJECT_API_SERVICE_ID } from 'lib/constants' import { FC } from 'react' import { IconAlertCircle, IconLoader, Input } from 'ui' diff --git a/studio/components/ui/ProjectUpgradeFailedBanner.tsx b/studio/components/ui/ProjectUpgradeFailedBanner.tsx index 19bab87189a..807b17f7620 100644 --- a/studio/components/ui/ProjectUpgradeFailedBanner.tsx +++ b/studio/components/ui/ProjectUpgradeFailedBanner.tsx @@ -2,7 +2,7 @@ import dayjs from 'dayjs' import Link from 'next/link' import { useState } from 'react' import { Alert, Button, IconX } from 'ui' -import { useParams } from 'hooks' +import { useParams } from 'common/hooks' import { IS_PLATFORM } from 'lib/constants' import { useProjectUpgradingStatusQuery } from 'data/config/project-upgrade-status-query' import { DatabaseUpgradeStatus } from '@supabase/shared-types/out/events' diff --git a/studio/components/ui/UpgradeToPro.tsx b/studio/components/ui/UpgradeToPro.tsx index 81ba2eedb2d..47259e9f7b7 100644 --- a/studio/components/ui/UpgradeToPro.tsx +++ b/studio/components/ui/UpgradeToPro.tsx @@ -4,7 +4,8 @@ import Link from 'next/link' import { FC, ReactNode } from 'react' import * as Tooltip from '@radix-ui/react-tooltip' -import { checkPermissions, useStore, useFlag, useParams } from 'hooks' +import { checkPermissions, useStore, useFlag } from 'hooks' +import { useParams } from 'common/hooks' import { PRICING_TIER_PRODUCT_IDS } from 'lib/constants' import { PermissionAction } from '@supabase/shared-types/out/constants' diff --git a/studio/hooks/index.ts b/studio/hooks/index.ts index bcfb55c58e7..83e5a772641 100644 --- a/studio/hooks/index.ts +++ b/studio/hooks/index.ts @@ -2,7 +2,6 @@ export * from './misc/useStore' export * from './misc/withAuth' export * from './misc/useOptimisticSqlSnippetCreate' export * from './misc/useImmutableValue' -export * from './misc/useParams' export * from './misc/useCheckPermissions' export * from './misc/useLocalStorage' export * from './deprecated' diff --git a/studio/hooks/misc/useUpgradePrompt.tsx b/studio/hooks/misc/useUpgradePrompt.tsx index f19f090c302..f58aca0c45d 100644 --- a/studio/hooks/misc/useUpgradePrompt.tsx +++ b/studio/hooks/misc/useUpgradePrompt.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react' -import { useParams } from 'hooks' +import { useParams } from 'common/hooks' import { maybeShowUpgradePrompt } from 'components/interfaces/Settings/Logs' import { useProjectSubscriptionQuery } from 'data/subscriptions/project-subscription-query' diff --git a/studio/hooks/misc/withAuth.tsx b/studio/hooks/misc/withAuth.tsx index e2c0ddcc643..35c36197825 100644 --- a/studio/hooks/misc/withAuth.tsx +++ b/studio/hooks/misc/withAuth.tsx @@ -3,7 +3,8 @@ import { useRouter } from 'next/router' import { ComponentType, useEffect } from 'react' import { usePermissionsQuery } from 'data/permissions/permissions-query' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import { useAuth } from 'lib/auth' import { IS_PLATFORM } from 'lib/constants' import { getReturnToPath, STORAGE_KEY } from 'lib/gotrue' diff --git a/studio/pages/new/[slug].tsx b/studio/pages/new/[slug].tsx index 52b630ad0a2..67305391615 100644 --- a/studio/pages/new/[slug].tsx +++ b/studio/pages/new/[slug].tsx @@ -21,7 +21,8 @@ import { PRICING_TIER_FREE_KEY, PRICING_TIER_PRODUCT_IDS, } from 'lib/constants' -import { useStore, useFlag, withAuth, checkPermissions, useParams } from 'hooks' +import { useStore, useFlag, withAuth, checkPermissions } from 'hooks' +import { useParams } from 'common/hooks' import { useFreeProjectLimitCheckQuery } from 'data/organizations/free-project-limit-check-query' import { WizardLayoutWithoutAuth } from 'components/layouts' diff --git a/studio/pages/org/[slug]/billing.tsx b/studio/pages/org/[slug]/billing.tsx index b8510f913f3..83c44735b40 100644 --- a/studio/pages/org/[slug]/billing.tsx +++ b/studio/pages/org/[slug]/billing.tsx @@ -3,7 +3,8 @@ import { observer } from 'mobx-react-lite' import { Tabs } from 'ui' import { NextPageWithLayout } from 'types' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import Loading from 'components/ui/Loading' import { OrganizationLayout } from 'components/layouts' import { BillingSettings } from 'components/interfaces/Organization' diff --git a/studio/pages/org/[slug]/general.tsx b/studio/pages/org/[slug]/general.tsx index 43cd730e8a2..f07415ba47e 100644 --- a/studio/pages/org/[slug]/general.tsx +++ b/studio/pages/org/[slug]/general.tsx @@ -3,7 +3,8 @@ import { observer } from 'mobx-react-lite' import { Tabs } from 'ui' import { NextPageWithLayout } from 'types' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import Loading from 'components/ui/Loading' import { OrganizationLayout } from 'components/layouts' import { GeneralSettings } from 'components/interfaces/Organization' diff --git a/studio/pages/org/[slug]/invoices.tsx b/studio/pages/org/[slug]/invoices.tsx index f6ee9ee7eae..5ccf1ebc825 100644 --- a/studio/pages/org/[slug]/invoices.tsx +++ b/studio/pages/org/[slug]/invoices.tsx @@ -3,7 +3,8 @@ import { observer } from 'mobx-react-lite' import { Tabs } from 'ui' import { NextPageWithLayout } from 'types' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import Loading from 'components/ui/Loading' import { OrganizationLayout } from 'components/layouts' import { InvoicesSettings } from 'components/interfaces/Organization' diff --git a/studio/pages/org/[slug]/team.tsx b/studio/pages/org/[slug]/team.tsx index f90d16a6486..7f96623cd61 100644 --- a/studio/pages/org/[slug]/team.tsx +++ b/studio/pages/org/[slug]/team.tsx @@ -3,7 +3,8 @@ import { observer } from 'mobx-react-lite' import { Tabs } from 'ui' import { NextPageWithLayout } from 'types' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import Loading from 'components/ui/Loading' import { OrganizationLayout } from 'components/layouts' import { TeamSettings } from 'components/interfaces/Organization' diff --git a/studio/pages/project/[ref]/api/graphiql.tsx b/studio/pages/project/[ref]/api/graphiql.tsx index 5317b8e57eb..a719540f4c8 100644 --- a/studio/pages/project/[ref]/api/graphiql.tsx +++ b/studio/pages/project/[ref]/api/graphiql.tsx @@ -3,7 +3,8 @@ import { observer } from 'mobx-react-lite' import { createGraphiQLFetcher, Fetcher } from '@graphiql/toolkit' import { NextPageWithLayout } from 'types' -import { useParams, useStore } from 'hooks' +import { useParams } from 'common/hooks' +import { useStore } from 'hooks' import { API_URL, IS_PLATFORM } from 'lib/constants' import ExtensionCard from 'components/interfaces/Database/Extensions/ExtensionCard' import GraphiQL from 'components/interfaces/GraphQL/GraphiQL' diff --git a/studio/pages/project/[ref]/api/index.tsx b/studio/pages/project/[ref]/api/index.tsx index 3ceb55c3383..a890cfd8de3 100644 --- a/studio/pages/project/[ref]/api/index.tsx +++ b/studio/pages/project/[ref]/api/index.tsx @@ -3,7 +3,8 @@ import { FC, createContext, useContext, useEffect, useState } from 'react' import { observer, useLocalObservable } from 'mobx-react-lite' import { NextPageWithLayout } from 'types' -import { checkPermissions, useParams, useStore } from 'hooks' +import { checkPermissions, useStore } from 'hooks' +import { useParams } from 'common/hooks' import { snakeToCamel } from 'lib/helpers' import { useProjectApiQuery } from 'data/config/project-api-query' import { DocsLayout } from 'components/layouts' diff --git a/studio/pages/project/[ref]/auth/policies.tsx b/studio/pages/project/[ref]/auth/policies.tsx index 3d4b440d580..5fe4fc3171b 100644 --- a/studio/pages/project/[ref]/auth/policies.tsx +++ b/studio/pages/project/[ref]/auth/policies.tsx @@ -6,7 +6,8 @@ import { PostgresTable, PostgresPolicy } from '@supabase/postgres-meta' import { PermissionAction } from '@supabase/shared-types/out/constants' import { NextPageWithLayout } from 'types' -import { checkPermissions, useParams, useStore } from 'hooks' +import { checkPermissions, useStore } from 'hooks' +import { useParams } from 'common/hooks' import { AuthLayout } from 'components/layouts' import { Policies } from 'components/interfaces/Auth/Policies' import NoPermission from 'components/ui/NoPermission' diff --git a/studio/pages/project/[ref]/auth/url-configuration.tsx b/studio/pages/project/[ref]/auth/url-configuration.tsx index fd7ced97616..b0415afb0c9 100644 --- a/studio/pages/project/[ref]/auth/url-configuration.tsx +++ b/studio/pages/project/[ref]/auth/url-configuration.tsx @@ -7,7 +7,7 @@ import { useStore, checkPermissions } from 'hooks' import { AuthLayout } from 'components/layouts' import NoPermission from 'components/ui/NoPermission' -import RedirectDomains from 'components/interfaces/Auth/RedirectDomains/RedirectDomains' +import RedirectUrls from 'components/interfaces/Auth/RedirectUrls/RedirectUrls' import { FormsContainer } from 'components/ui/Forms' import SiteUrl from 'components/interfaces/Auth/SiteUrl/SiteUrl' @@ -26,7 +26,7 @@ const URLConfiguration: NextPageWithLayout = () => { return ( - + ) } else { diff --git a/studio/pages/project/[ref]/editor/[id].tsx b/studio/pages/project/[ref]/editor/[id].tsx index 9fd9ca0e2dc..f9c3996736a 100644 --- a/studio/pages/project/[ref]/editor/[id].tsx +++ b/studio/pages/project/[ref]/editor/[id].tsx @@ -7,7 +7,8 @@ import { isUndefined, isNaN } from 'lodash' import { Alert, Button, Checkbox, IconExternalLink, Modal } from 'ui' import type { PostgresTable, PostgresColumn } from '@supabase/postgres-meta' -import { useStore, withAuth, useUrlState, useParams } from 'hooks' +import { useStore, withAuth, useUrlState } from 'hooks' +import { useParams } from 'common/hooks' import { entityTypeKeys } from 'data/entity-types/keys' import { Entity } from 'data/entity-types/entity-type-query' import { Dictionary } from 'components/grid' diff --git a/studio/pages/project/[ref]/functions/[functionSlug]/index.tsx b/studio/pages/project/[ref]/functions/[functionSlug]/index.tsx index 156a1da2897..403f83ceec8 100644 --- a/studio/pages/project/[ref]/functions/[functionSlug]/index.tsx +++ b/studio/pages/project/[ref]/functions/[functionSlug]/index.tsx @@ -5,7 +5,8 @@ import { Button } from 'ui' import { observer } from 'mobx-react-lite' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useParams } from 'hooks' +import { checkPermissions } from 'hooks' +import { useParams } from 'common/hooks' import { ChartIntervals, NextPageWithLayout } from 'types' import { DATE_FORMAT } from 'lib/constants' import Panel from 'components/ui/Panel' diff --git a/studio/pages/project/[ref]/functions/[functionSlug]/invocations.tsx b/studio/pages/project/[ref]/functions/[functionSlug]/invocations.tsx index 3fc638aa7c2..16e179787e9 100644 --- a/studio/pages/project/[ref]/functions/[functionSlug]/invocations.tsx +++ b/studio/pages/project/[ref]/functions/[functionSlug]/invocations.tsx @@ -1,7 +1,7 @@ import { observer } from 'mobx-react-lite' import { NextPageWithLayout } from 'types' -import { useParams } from 'hooks' +import { useParams } from 'common/hooks' import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' import FunctionsLayout from 'components/layouts/FunctionsLayout' import { useEdgeFunctionQuery } from 'data/edge-functions/edge-function-query' diff --git a/studio/pages/project/[ref]/functions/[functionSlug]/logs.tsx b/studio/pages/project/[ref]/functions/[functionSlug]/logs.tsx index fd9510aee15..404985c654a 100644 --- a/studio/pages/project/[ref]/functions/[functionSlug]/logs.tsx +++ b/studio/pages/project/[ref]/functions/[functionSlug]/logs.tsx @@ -1,6 +1,6 @@ import { observer } from 'mobx-react-lite' import { NextPageWithLayout } from 'types' -import { useParams } from 'hooks' +import { useParams } from 'common/hooks' import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' import FunctionsLayout from 'components/layouts/FunctionsLayout' import { useEdgeFunctionQuery } from 'data/edge-functions/edge-function-query' diff --git a/studio/pages/project/[ref]/functions/index.tsx b/studio/pages/project/[ref]/functions/index.tsx index e78b41e0996..0673931084f 100644 --- a/studio/pages/project/[ref]/functions/index.tsx +++ b/studio/pages/project/[ref]/functions/index.tsx @@ -1,6 +1,6 @@ import { observer } from 'mobx-react-lite' -import { useParams } from 'hooks' +import { useParams } from 'common/hooks' import { NextPageWithLayout } from 'types' import Table from 'components/to-be-cleaned/Table' import FunctionsLayout from 'components/layouts/FunctionsLayout' diff --git a/studio/pages/project/[ref]/index.tsx b/studio/pages/project/[ref]/index.tsx index b6bd9ded124..44249b8cb22 100644 --- a/studio/pages/project/[ref]/index.tsx +++ b/studio/pages/project/[ref]/index.tsx @@ -1,6 +1,7 @@ import { observer } from 'mobx-react-lite' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import { NextPageWithLayout } from 'types' import { IS_PLATFORM, PROJECT_STATUS } from 'lib/constants' import { ProjectLayoutWithAuth } from 'components/layouts' diff --git a/studio/pages/project/[ref]/logs/explorer/index.tsx b/studio/pages/project/[ref]/logs/explorer/index.tsx index a781fb52c3b..a45ba94cdc3 100644 --- a/studio/pages/project/[ref]/logs/explorer/index.tsx +++ b/studio/pages/project/[ref]/logs/explorer/index.tsx @@ -4,7 +4,8 @@ import { useRouter } from 'next/router' import { observer } from 'mobx-react-lite' import { Input, Modal, Form, Button } from 'ui' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import useLogsQuery from 'hooks/analytics/useLogsQuery' import { useProjectSubscriptionQuery } from 'data/subscriptions/project-subscription-query' import { NextPageWithLayout, UserContent } from 'types' diff --git a/studio/pages/project/[ref]/reports/api-overview.tsx b/studio/pages/project/[ref]/reports/api-overview.tsx index 00c45d7888b..9a2a9f8a60c 100644 --- a/studio/pages/project/[ref]/reports/api-overview.tsx +++ b/studio/pages/project/[ref]/reports/api-overview.tsx @@ -18,10 +18,10 @@ import ReportHeader from 'components/interfaces/Reports/ReportHeader' import { DatePickerToFrom, LogsEndpointParams } from 'components/interfaces/Settings/Logs' import ReportFilterBar from 'components/interfaces/Reports/ReportFilterBar' import { useProjectSubscriptionQuery } from 'data/subscriptions/project-subscription-query' -import { useParams } from 'hooks' +import { useParams } from 'common/hooks' import { isEqual } from 'lodash' import ShimmerLine from 'components/ui/ShimmerLine' -import ReportPadding from "components/interfaces/Reports/ReportPadding" +import ReportPadding from 'components/interfaces/Reports/ReportPadding' export const ApiReport: NextPageWithLayout = () => { const { ref: projectRef } = useParams() diff --git a/studio/pages/project/[ref]/reports/database.tsx b/studio/pages/project/[ref]/reports/database.tsx index 51ff8dfb946..ae7c16394cb 100644 --- a/studio/pages/project/[ref]/reports/database.tsx +++ b/studio/pages/project/[ref]/reports/database.tsx @@ -3,7 +3,8 @@ import { observer } from 'mobx-react-lite' import { FC, useEffect, useState } from 'react' import { Badge, Button, IconArrowRight, IconExternalLink } from 'ui' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import { PRICING_TIER_PRODUCT_IDS, TIME_PERIODS_INFRA, diff --git a/studio/pages/project/[ref]/reports/index.tsx b/studio/pages/project/[ref]/reports/index.tsx index aece220eb06..dfda77f3db6 100644 --- a/studio/pages/project/[ref]/reports/index.tsx +++ b/studio/pages/project/[ref]/reports/index.tsx @@ -4,7 +4,8 @@ import { useRouter } from 'next/router' import { PermissionAction } from '@supabase/shared-types/out/constants' import { NextPageWithLayout } from 'types' -import { checkPermissions, useFlag, useParams, useStore } from 'hooks' +import { checkPermissions, useFlag, useStore } from 'hooks' +import { useParams } from 'common/hooks' import { post } from 'lib/common/fetch' import { API_URL, PROJECT_STATUS } from 'lib/constants' import { useProjectContentStore } from 'stores/projectContentStore' diff --git a/studio/pages/project/[ref]/settings/api.tsx b/studio/pages/project/[ref]/settings/api.tsx index 288127c97a6..0446e3d361a 100644 --- a/studio/pages/project/[ref]/settings/api.tsx +++ b/studio/pages/project/[ref]/settings/api.tsx @@ -2,7 +2,8 @@ import { createContext } from 'react' import { useRouter } from 'next/router' import { observer, useLocalObservable } from 'mobx-react-lite' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import { NextPageWithLayout } from 'types' import { SettingsLayout } from 'components/layouts' import ServiceList from 'components/interfaces/Settings/API/ServiceList' diff --git a/studio/pages/project/[ref]/settings/database.tsx b/studio/pages/project/[ref]/settings/database.tsx index 026f211e571..d9b90a1cecb 100644 --- a/studio/pages/project/[ref]/settings/database.tsx +++ b/studio/pages/project/[ref]/settings/database.tsx @@ -1,6 +1,7 @@ import { observer } from 'mobx-react-lite' import { NextPageWithLayout } from 'types' -import { useFlag, useParams } from 'hooks' +import { useFlag } from 'hooks' +import { useParams } from 'common/hooks' import { SettingsLayout } from 'components/layouts' import { ConnectionPooling, diff --git a/studio/pages/project/[ref]/settings/storage.tsx b/studio/pages/project/[ref]/settings/storage.tsx index 7f2f2c15180..0ac1df2ea45 100644 --- a/studio/pages/project/[ref]/settings/storage.tsx +++ b/studio/pages/project/[ref]/settings/storage.tsx @@ -2,7 +2,8 @@ import React, { useEffect } from 'react' import { observer } from 'mobx-react-lite' import { API_URL, PROJECT_STATUS } from 'lib/constants' -import { useFlag, useParams, useStore } from 'hooks' +import { useFlag, useStore } from 'hooks' +import { useParams } from 'common/hooks' import { post } from 'lib/common/fetch' import { SettingsLayout } from 'components/layouts' import { StorageSettings } from 'components/to-be-cleaned/Storage' diff --git a/studio/pages/project/[ref]/settings/vault/keys.tsx b/studio/pages/project/[ref]/settings/vault/keys.tsx index 530c5b2fb3d..1b14ead4e9a 100644 --- a/studio/pages/project/[ref]/settings/vault/keys.tsx +++ b/studio/pages/project/[ref]/settings/vault/keys.tsx @@ -3,7 +3,8 @@ import { useRouter } from 'next/router' import { observer } from 'mobx-react-lite' import { Tabs } from 'ui' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import { NextPageWithLayout } from 'types' import { SettingsLayout } from 'components/layouts' import { VaultToggle, EncryptionKeysManagement } from 'components/interfaces/Settings/Vault' diff --git a/studio/pages/project/[ref]/settings/vault/secrets.tsx b/studio/pages/project/[ref]/settings/vault/secrets.tsx index 4a7a92ebb33..8b50c447ac0 100644 --- a/studio/pages/project/[ref]/settings/vault/secrets.tsx +++ b/studio/pages/project/[ref]/settings/vault/secrets.tsx @@ -3,7 +3,8 @@ import { useRouter } from 'next/router' import { observer } from 'mobx-react-lite' import { Tabs } from 'ui' -import { useParams, useStore } from 'hooks' +import { useStore } from 'hooks' +import { useParams } from 'common/hooks' import { NextPageWithLayout } from 'types' import { SettingsLayout } from 'components/layouts' import { VaultToggle, SecretsManagement } from 'components/interfaces/Settings/Vault' diff --git a/studio/pages/project/[ref]/storage/buckets/index.tsx b/studio/pages/project/[ref]/storage/buckets/index.tsx index 396a914ba2a..8f4ad3bba21 100644 --- a/studio/pages/project/[ref]/storage/buckets/index.tsx +++ b/studio/pages/project/[ref]/storage/buckets/index.tsx @@ -3,7 +3,8 @@ import { useRouter } from 'next/router' import { observer } from 'mobx-react-lite' import { API_URL } from 'lib/constants' -import { useFlag, useParams, useStore } from 'hooks' +import { useFlag, useStore } from 'hooks' +import { useParams } from 'common/hooks' import { post } from 'lib/common/fetch' import { PROJECT_STATUS } from 'lib/constants' import { StorageLayout } from 'components/layouts' diff --git a/studio/stores/authConfig/schema/AuthProviders/AuthProvidersFormValidation.tsx b/studio/stores/authConfig/schema/AuthProviders/AuthProvidersFormValidation.tsx index 084c21c0fcf..d5b9ece9210 100644 --- a/studio/stores/authConfig/schema/AuthProviders/AuthProvidersFormValidation.tsx +++ b/studio/stores/authConfig/schema/AuthProviders/AuthProvidersFormValidation.tsx @@ -1,5 +1,5 @@ import { boolean, number, object, string } from 'yup' -import { domainRegex } from 'components/interfaces/Auth/Auth.constants' +import { urlRegex } from 'components/interfaces/Auth/Auth.constants' const JSON_SCHEMA_VERSION = 'http://json-schema.org/draft-07/schema#' @@ -385,7 +385,7 @@ const EXTERNAL_PROVIDER_AZURE = { then: (schema) => schema.required('Secret ID is required'), otherwise: (schema) => schema, }), - EXTERNAL_AZURE_URL: string().matches(domainRegex, 'Must be a valid URL').optional(), + EXTERNAL_AZURE_URL: string().matches(urlRegex, 'Must be a valid URL').optional(), }), misc: { iconKey: 'microsoft-icon', @@ -583,7 +583,7 @@ const EXTERNAL_PROVIDER_GITLAB = { then: (schema) => schema.required('Client Secret is required'), otherwise: (schema) => schema, }), - EXTERNAL_GITLAB_URL: string().matches(domainRegex, 'Must be a valid URL').optional(), + EXTERNAL_GITLAB_URL: string().matches(urlRegex, 'Must be a valid URL').optional(), }), misc: { iconKey: 'gitlab-icon', @@ -671,8 +671,8 @@ const EXTERNAL_PROVIDER_KEYCLOAK = { EXTERNAL_KEYCLOAK_URL: string().when('EXTERNAL_KEYCLOAK_ENABLED', { is: true, then: (schema) => - schema.matches(domainRegex, 'Must be a valid URL').required('Realm URL is required'), - otherwise: (schema) => schema.matches(domainRegex, 'Must be a valid URL'), + schema.matches(urlRegex, 'Must be a valid URL').required('Realm URL is required'), + otherwise: (schema) => schema.matches(urlRegex, 'Must be a valid URL'), }), }), misc: { @@ -937,7 +937,7 @@ const EXTERNAL_PROVIDER_WORKOS = { validationSchema: object().shape({ EXTERNAL_WORKOS_ENABLED: boolean().required(), EXTERNAL_WORKOS_URL: string() - .matches(domainRegex, 'Must be a valid URL') + .matches(urlRegex, 'Must be a valid URL') .when('EXTERNAL_WORKOS_ENABLED', { is: true, then: (schema) => schema.required('WorkOS URL is required'), diff --git a/studio/tests/components/Auth/Auth.constants.test.js b/studio/tests/components/Auth/Auth.constants.test.js index 4c8a3fe62f3..ab7504014dc 100644 --- a/studio/tests/components/Auth/Auth.constants.test.js +++ b/studio/tests/components/Auth/Auth.constants.test.js @@ -1,87 +1,87 @@ -import { domainRegex } from 'components/interfaces/Auth/Auth.constants' +import { urlRegex } from 'components/interfaces/Auth/Auth.constants' describe('Auth.constants: domainRegex', () => { test('should validate typical URLs', () => { const mockInput1 = 'http://domain.com' - const output1 = domainRegex.test(mockInput1) + const output1 = urlRegex.test(mockInput1) expect(output1).toBe(true) const mockInput2 = 'https://supabase.io' - const output2 = domainRegex.test(mockInput2) + const output2 = urlRegex.test(mockInput2) expect(output2).toBe(true) const mockInput3 = 'https://new-domain-vercel.com' - const output3 = domainRegex.test(mockInput3) + const output3 = urlRegex.test(mockInput3) expect(output3).toBe(true) const mockInput4 = 'www.test-domain.com' - const output4 = domainRegex.test(mockInput4) + const output4 = urlRegex.test(mockInput4) expect(output4).toBe(true) }) test('should validate app-based domains', () => { const mockInput1 = 'exp://exp.host/some-app' - const output1 = domainRegex.test(mockInput1) + const output1 = urlRegex.test(mockInput1) expect(output1).toBe(true) const mockInput2 = 'exp://exp.host/some-app?release-channel=default' - const output2 = domainRegex.test(mockInput2) + const output2 = urlRegex.test(mockInput2) expect(output2).toBe(true) }) test('should validate subdomains', () => { const mockInput1 = 'https://app.supabase.com' - const output1 = domainRegex.test(mockInput1) + const output1 = urlRegex.test(mockInput1) expect(output1).toBe(true) }) test('should validate localhost URLs', () => { const mockInput1 = 'http://localhost:3000' - const output1 = domainRegex.test(mockInput1) + const output1 = urlRegex.test(mockInput1) expect(output1).toBe(true) }) test('should validate URLs with query params', () => { const mockInput1 = 'https://supabase.com?name=test' - const output1 = domainRegex.test(mockInput1) + const output1 = urlRegex.test(mockInput1) expect(output1).toBe(true) const mockInput2 = 'https://supabase.com?name=test&description=hello&page=2' - const output2 = domainRegex.test(mockInput2) + const output2 = urlRegex.test(mockInput2) expect(output2).toBe(true) }) test('should validate URLs with wildcards', () => { const mockInput1 = 'https://supabase*.com' - const output1 = domainRegex.test(mockInput1) + const output1 = urlRegex.test(mockInput1) expect(output1).toBe(true) const mockInput2 = 'https://supabase.com/*' - const output2 = domainRegex.test(mockInput2) + const output2 = urlRegex.test(mockInput2) expect(output2).toBe(true) const mockInput3 = 'https://new-*-domain.com/*' - const output3 = domainRegex.test(mockInput3) + const output3 = urlRegex.test(mockInput3) expect(output3).toBe(true) const mockInput4 = 'https://new-*-domain.com/*/*/*' - const output4 = domainRegex.test(mockInput4) + const output4 = urlRegex.test(mockInput4) expect(output4).toBe(true) const mockInput5 = 'https://sub-*-domain.new-*-domain.com/*/*/*' - const output5 = domainRegex.test(mockInput5) + const output5 = urlRegex.test(mockInput5) expect(output5).toBe(true) }) test('should invalidate invalid URLs', () => { const mockInput1 = 'supabase' - const output1 = domainRegex.test(mockInput1) + const output1 = urlRegex.test(mockInput1) expect(output1).toBe(false) const mockInput2 = 'mailto:test@gmail.com' - const output2 = domainRegex.test(mockInput2) + const output2 = urlRegex.test(mockInput2) expect(output2).toBe(false) const mockInput4 = 'hello world.com' - const output4 = domainRegex.test(mockInput4) + const output4 = urlRegex.test(mockInput4) expect(output4).toBe(false) const mockInput5 = 'email@domain.com' - const output5 = domainRegex.test(mockInput5) + const output5 = urlRegex.test(mockInput5) expect(output5).toBe(false) }) }) diff --git a/studio/tests/pages/projects/LogsPreviewer.test.js b/studio/tests/pages/projects/LogsPreviewer.test.js index 15774d0b66c..780a82f9d4a 100644 --- a/studio/tests/pages/projects/LogsPreviewer.test.js +++ b/studio/tests/pages/projects/LogsPreviewer.test.js @@ -23,7 +23,8 @@ import userEvent from '@testing-library/user-event' import { wait } from '@testing-library/user-event/dist/utils' import { logDataFixture } from '../../fixtures' import { LogsTableName } from 'components/interfaces/Settings/Logs' -import { useParams } from 'hooks' +jest.mock('common/hooks') +import { useParams } from 'common/hooks' beforeEach(() => { // reset mocks between tests diff --git a/studio/tests/pages/projects/logs-query.test.js b/studio/tests/pages/projects/logs-query.test.js index 378b62c6f02..eb1ce4d5c50 100644 --- a/studio/tests/pages/projects/logs-query.test.js +++ b/studio/tests/pages/projects/logs-query.test.js @@ -8,7 +8,8 @@ import { logDataFixture } from '../../fixtures' import { clickDropdown } from 'tests/helpers' import dayjs from 'dayjs' import { useProjectSubscriptionQuery } from 'data/subscriptions/project-subscription-query' -import { useParams } from 'hooks' +jest.mock('common/hooks') +import { useParams } from 'common/hooks' const defaultRouterMock = () => { const router = jest.fn() diff --git a/turbo.json b/turbo.json index 176ef881d41..3ca755f081d 100644 --- a/turbo.json +++ b/turbo.json @@ -4,6 +4,43 @@ "dependsOn": ["^build"], "outputs": ["dist/**", ".next/**"] }, + "www#build": { + "dependsOn": ["^build"], + "env": [ + "SUPABASE_SERVICE_ROLE_SECRET", + "EMAIL_TO_ID_SECRET", + "SUPABASE_URL", + "GITHUB_OAUTH_CLIENT_SECRET" + ], + "outputs": [".next/**", "!.next/cache/**"] + }, + "docs#build": { + "dependsOn": ["^build"], + "env": ["SUPABASE_SERVICE_ROLE_KEY", "OPENAI_KEY", "ALGOLIA_SEARCH_ADMIN_KEY"], + "outputs": [".next/**", "!.next/cache/**"] + }, + "studio#build": { + "dependsOn": ["^build"], + "env": [ + "SITE_URL", + "AUTH0_AUDIENCE", + "AUTH0_CLIENT_ID", + "AUTH0_CLIENT_SECRET", + "AUTH0_DOMAIN", + "COOKIE_DOMAIN", + "INTERCOM_API_KEY", + "READ_ONLY_API_KEY", + "READ_ONLY_URL", + "SENTRY_AUTH_TOKEN", + "SENTRY_ORG", + "SENTRY_PROJECT", + "SENTRY_URL", + "SESSION_COOKIE_SECRET", + "SUPABASE_ENCRYPTION_KEY", + "PLATFORM_PG_META_URL" + ], + "outputs": [".next/**", "!.next/cache/**"] + }, "lint": { "outputs": [] },