diff --git a/apps/docs/components/index.tsx b/apps/docs/components/index.tsx index 524a64f2399..4351050cbf0 100644 --- a/apps/docs/components/index.tsx +++ b/apps/docs/components/index.tsx @@ -24,6 +24,9 @@ import RefSubLayout from '~/layouts/ref/RefSubLayout' // import { CH } from '@code-hike/mdx/components' import RefHeaderSection from './reference/RefHeaderSection' +// Ref version specific +import CliGlobalFlagsHandler from '~/components/reference/enrichments/cli/CliGlobalFlagsHandler' + const components = { Admonition, Button, @@ -64,6 +67,7 @@ const components = { // CH, code: (props: any) => , RefHeaderSection: (props: any) => , + CliGlobalFlagsHandler: () => , } export default components diff --git a/apps/docs/components/reference/CLICommandSection.tsx b/apps/docs/components/reference/CLICommandSection.tsx index 473ad848907..89cae3bfb24 100644 --- a/apps/docs/components/reference/CLICommandSection.tsx +++ b/apps/docs/components/reference/CLICommandSection.tsx @@ -1,3 +1,4 @@ +import { IconChevronRight } from '~/../../packages/ui' // @ts-expect-error import spec from '~/../../spec/cli_v1_commands.yaml' assert { type: 'yml' } import CodeBlock from '~/components/CodeBlock/CodeBlock' @@ -80,13 +81,19 @@ const CliCommandSection = (props) => { )} */} {command.subcommands.length > 0 && ( -
-

Available Commands

+
+

Available Commands

    {command.subcommands.map((subcommand) => ( -
  • - - {subcommand} +
  • +
    + +
    +
    + $ {subcommand.replace(/-/g, ' ')}
  • ))} diff --git a/apps/docs/components/reference/enrichments/cli/CliGlobalFlagsHandler.tsx b/apps/docs/components/reference/enrichments/cli/CliGlobalFlagsHandler.tsx new file mode 100644 index 00000000000..778f518b173 --- /dev/null +++ b/apps/docs/components/reference/enrichments/cli/CliGlobalFlagsHandler.tsx @@ -0,0 +1,30 @@ +import RefSubLayout from '~/layouts/ref/RefSubLayout' + +// @ts-expect-error +import spec from '~/../../spec/cli_v1_commands.yaml' assert { type: 'yaml' } +import Param from '~/components/Params' +import Options from '~/components/Options' + +const CliGlobalFlagsHandler = () => { + return ( + + +

    Flags

    +
      + {spec.flags.map((flag) => { + return ( + + ) + })} +
    +
    + + +
    + ) +} + +export default CliGlobalFlagsHandler diff --git a/apps/docs/docs/ref/cli/global-flags.mdx b/apps/docs/docs/ref/cli/global-flags.mdx new file mode 100644 index 00000000000..39aaf77295b --- /dev/null +++ b/apps/docs/docs/ref/cli/global-flags.mdx @@ -0,0 +1,8 @@ +--- +title: Global Flags +description: 'Supabase CLI supports global flags for every command.' +--- + +Supabase CLI supports global flags for every command. + + diff --git a/apps/docs/layouts/guides/index.tsx b/apps/docs/layouts/guides/index.tsx index 365bcdce23c..10ccfed870d 100644 --- a/apps/docs/layouts/guides/index.tsx +++ b/apps/docs/layouts/guides/index.tsx @@ -1,7 +1,9 @@ import { MDXProvider } from '@mdx-js/react' import { NextSeo } from 'next-seo' +import Link from 'next/link' import { useRouter } from 'next/router' import { FC, useEffect, useRef, useState } from 'react' +import { IconExternalLink } from 'ui' import components from '~/components' import { highlightSelectedTocItem } from '~/components/CustomHTMLElements/CustomHTMLElements.utils' import GuidesTableOfContents from '~/components/GuidesTableOfContents' @@ -31,6 +33,8 @@ const Layout: FC = (props) => { const { asPath } = useRouter() const page = getPageType(asPath) + const router = useRouter() + useEffect(() => { if (hash && tocList.length > 0) { highlightSelectedTocItem(hash as string) @@ -96,6 +100,18 @@ const Layout: FC = (props) => { )}
    {props.children} +
{!props.hideToc && hasTableOfContents && !props.meta?.hide_table_of_contents && ( diff --git a/apps/docs/layouts/ref/RefSubLayout.tsx b/apps/docs/layouts/ref/RefSubLayout.tsx index 3aa2b0930f0..26e1c612515 100644 --- a/apps/docs/layouts/ref/RefSubLayout.tsx +++ b/apps/docs/layouts/ref/RefSubLayout.tsx @@ -34,7 +34,9 @@ type StickyHeader = { type RefSubLayoutType = {} -interface IEducationRow {} +interface IEducationRow { + className?: string +} interface IEducationSection { id: string title?: string @@ -129,7 +131,11 @@ const Examples: FC = (props) => { } const EducationRow: FC = (props) => { - return
{props.children}
+ return ( +
+ {props.children} +
+ ) } const EducationSection: FC = ({ icon, hideTitle = false, ...props }) => { diff --git a/apps/docs/pages/guides/auth/auth-helpers/auth-ui.mdx b/apps/docs/pages/guides/auth/auth-helpers/auth-ui.mdx index 2a7814999e3..1d07fb9db94 100644 --- a/apps/docs/pages/guides/auth/auth-helpers/auth-ui.mdx +++ b/apps/docs/pages/guides/auth/auth-helpers/auth-ui.mdx @@ -34,7 +34,10 @@ Pass `supabaseClient` from `@supabase/supabase-js` as a prop to the component. import { createClient } from '@supabase/supabase-js' import { Auth } from '@supabase/auth-ui-react' -const supabase = createClient('', '') +const supabase = createClient( + '', + '' +) const App = () => ``` @@ -43,13 +46,18 @@ This renders the Auth component without any styling. We recommend using one of the predefined themes to style the UI. Import the theme you want to use and pass it to the `appearence.theme` prop. -```js lines=4,11 title=/src/index.js +```js lines=4,16 title=/src/index.js import { Auth, // Import predefined theme ThemeSupa, } from '@supabase/auth-ui-react' +const supabase = createClient( + '', + '' +) + const App = () => ( ( ) ``` +### Social Providers + +The Auth component also supports login with [offical social providers](../../auth#providers). + +```js lines=13 title=/src/index.js +import { createClient } from '@supabase/supabase-js' +import { Auth, ThemeSupa } from '@supabase/auth-ui-react' + +const supabase = createClient( + '', + '' +) + +const App = () => ( + +) +``` + ## Customization There are several ways to customize Auth UI: @@ -74,11 +104,14 @@ There are several ways to customize Auth UI: Auth UI comes with several themes to customize the appearance. Each predefined theme comes with at least two variations, a `default` variation, and a `dark` variation. You can switch between these themes using the `theme` prop. Import the theme you want to use and pass it to the `appearence.theme` prop. -```js lines=2,10 title=/src/index.js +```js lines=2,13 title=/src/index.js import { createClient } from '@supabase/supabase-js' import { Auth, ThemeSupa } from '@supabase/auth-ui-react' -const supabase = createClient('', '') +const supabase = createClient( + '', + '' +) const App = () => ( ', '') +const supabase = createClient( + '', + '' +) const App = () => ( ', '') +const supabase = createClient( + '', + '' +) const App = () => ( ', '') +const supabase = createClient( + '', + '' +) const App = () => ( ', '') +const supabase = createClient( + '', + '' +) const App = () => ( ', '') +const supabase = createClient( + '', + '' +) const App = () => ( + Supabase is an open source Firebase alternative providing all the backend features you need to + build a product. [Learn more](/docs/architecture) about Supabase, start with the + [tutorials](/docs/guides/getting-started#tutorials), or dive straight into the different products + and APIs. + -Supabase is an open source Firebase alternative providing all the backend features you need to build a product. -You can use it completely, or just the features you need. +{/* start container */} -[Start a project](https://app.supabase.com) with the hosted platform or learn how to [host Supabase](/docs/guides/hosting/overview) yourself. +
-## Learn about features +
+
+
+ +
+

Getting Started

+ + Discover how to set up a database to an app making queries in just a few minutes. + +
What you will learn
+ +
+
+
+ +
+ Setting up a Supabase project and app +
+
+
+ +
+ Adding some sample data to your project +
+
+
+ +
+ Select() from your new database table +
+
+ +
+
+ +
+
+ + + + + + + + + + +
+
+
+
-
-
-
-
- + + -
-
- -
-
- -
-
- -
-
- -
-
- +
+

Ready to make a fully working app?

+

Follow the step-by-step tutorials.

+
+
-## Start with a framework +
+
-Supabase is just Postgres, which makes it compatible with a large number of tools and frameworks. + ### Product Documentation - +
-export const Page = ({ children }) => { - if (process.env.NEXT_PUBLIC_NEW_DOCS === 'true') { - return NewContent() - } - return -} +
+ {products.map((product) => { + return ( + + + + {product.description} + + + + ) + +})} + + {platform.map((product) => { + return ( + + + + {product.description} + + + + ) + +})} + +
+ +
+ +
+ +
+ + ### Reference Documentation + +
+ +
+ {apis.map((product) => { + return ( + + + + {product.description} + + + + ) + +})} + +
+
+ +{/* end of container */} + +
+ +export const products = [ + { + title: 'Database', + icon: '/docs/img/icons/menu/database', + hasLightIcon: true, + href: '/guides/database', + description: + 'Supabase provides a full Postgres database for every project with Realtime functionality, database backups, extensions, and more.', + span: 'col-span-12 md:col-span-6', + }, + { + title: 'Auth', + icon: '/docs/img/icons/menu/auth', + hasLightIcon: true, + href: '/guides/auth/overview', + description: + 'Add and manage email and password, passwordless, OAuth, and mobile logins to your project through a suite of identity providers and APIs.', + span: 'col-span-12 md:col-span-6', + }, + { + title: 'Storage', + icon: '/docs/img/icons/menu/storage', + hasLightIcon: true, + href: '/guides/storage', + description: + 'Store, organize, transform, and serve large files—fully integrated with your Postgres database with Row Level Security access policies.', + }, + { + title: 'Realtime', + icon: '/docs/img/icons/menu/realtime', + hasLightIcon: true, + href: '/guides/realtime', + description: + 'Listen to database changes, store and sync user states across clients, broadcast data to clients subscribed to a channel, and more.', + }, + { + title: 'Edge Functions', + icon: '/docs/img/icons/menu/functions', + hasLightIcon: true, + href: '/guides/functions', + description: + 'Globally distributed, server-side functions to execute your code closest to your users for the lowest latency.', + }, +] + +export const apis = [ + { + title: 'JavaScript Client Library', + icon: '/docs/img/icons/menu/reference-javascript', + hasLightIcon: true, + href: 'reference/javascript/introduction', + description: 'Official client libraries for JavaScript and TypeScript.', + }, + { + title: 'Flutter Client Library', + icon: '/docs/img/icons/menu/reference-dart', + hasLightIcon: true, + href: 'reference/dart/introduction', + description: 'Official client libraries for Flutter and Dart.', + }, + { + title: 'Management API', + icon: '/docs/img/icons/menu/reference-api', + hasLightIcon: true, + href: 'reference/api/introduction', + description: 'Manage your Supabase projects and organizations programmatically.', + }, + { + title: 'Supabase CLI', + icon: '/docs/img/icons/menu/reference-api', + hasLightIcon: true, + href: 'reference/cli/introduction', + description: + 'Use the CLI to develop your project locally, manage database migrations, and deploy to the Supabase Platform or self-host.', + }, + { + title: 'Self-Hosting Auth', + icon: '/docs/img/icons/menu/reference-auth', + hasLightIcon: true, + href: 'reference/self-hosting-auth/introduction', + description: 'Self-host your own Auth server.', + }, + { + title: 'Self-Hosting Storage', + icon: '/docs/img/icons/menu/reference-storage', + hasLightIcon: true, + href: 'reference/self-hosting-storage/introduction', + description: 'Self-host your own Storage server.', + }, + { + title: 'Self-Hosting Realtime', + icon: '/docs/img/icons/menu/reference-realtime', + hasLightIcon: true, + href: 'reference/self-hosting-realtime/introduction', + description: 'Self-host your own Realtime server.', + }, +] + +export const platform = [ + { + // header: '/docs/img/cards/sample-card-header-3.svg', + title: 'Platform Guides', + icon: '/docs/img/icons/menu/platform', + hasLightIcon: true, + href: 'guides/platform', + description: + 'Learn more about the tools and services powering the Supabase Platform, available add-ons, and how to customize the platform for your needs.', + }, + { + // header: '/docs/img/cards/sample-card-header-2.svg', + title: 'Resources', + icon: '/docs/img/icons/menu/resources', + hasLightIcon: true, + href: 'guides/resources', + description: 'View examples, curated content from the community, migration guides, and more.', + }, + { + // header: '/docs/img/cards/sample-card-header-2.svg', + title: 'Integrations', + icon: '/docs/img/icons/menu/integrations', + hasLightIcon: true, + href: 'guides/integrations', + description: 'Explore a variety of integrations from Supabase partners.', + }, +] + +export const Page = ({ children }) => export default Page diff --git a/apps/docs/pages/new/index.mdx b/apps/docs/pages/new/index.mdx deleted file mode 100644 index b9762af04b1..00000000000 --- a/apps/docs/pages/new/index.mdx +++ /dev/null @@ -1,323 +0,0 @@ -import Layout from '~/layouts/DefaultLayout' -import Link from 'next/link' -import { GlassPanel, IconPanel, Button, IconChevronRight } from 'ui' - -export const meta = { - title: 'Supabase Docs', - description: - 'Supabase is an open source Firebase alternative providing all the backend features you need to build a product.', - subtitle: 'Supabase Developer Documentation and API Reference', -} - -

- Supabase is an open source Firebase alternative providing all the backend features you need to - build a product. - - [Learn more](/docs/architecture) about Supabase, start with the - [tutorials](/docs/guides/getting-started#tutorials), or dive straight into the different products and APIs. -

- -{/* start container */} - -
- -
-
-
- -
-

Getting Started

- - Discover how to set up a database to an app making queries in just a few minutes. - -
What you will learn
- -
-
-
- -
- Setting up a Supabase project and app -
-
-
- -
- Adding some sample data to your project -
-
-
- -
- Select() from your new database table -
-
- -
-
- -
-
- - - - - - - - - - -
-
-
-
- -
-
- - - -
-

Ready to make a fully working app?

-

Follow the step-by-step tutorials.

-
- -
-
- -
-
- - ### Product Documentation - -
- -
- {products.map((product) => { - return ( - - - - {product.description} - - - - ) - -})} - - {platform.map((product) => { - return ( - - - - {product.description} - - - - ) - -})} - -
- -
- -
- -
- - ### Reference Documentation - -
- -
- {apis.map((product) => { - return ( - - - - {product.description} - - - - ) - -})} - -
-
- -{/* end of container */} - -
- -export const products = [ - { - title: 'Database', - icon: '/docs/img/icons/menu/database', - hasLightIcon: true, - href: '/guides/database', - description: - 'Supabase provides a full Postgres database for every project with Realtime functionality, database backups, extensions, and more.', - span: 'col-span-12 md:col-span-6', - }, - { - title: 'Auth', - icon: '/docs/img/icons/menu/auth', - hasLightIcon: true, - href: '/guides/auth', - description: - 'Add and manage email and password, passwordless, OAuth, and mobile logins to your project through a suite of identity providers and APIs.', - span: 'col-span-12 md:col-span-6', - }, - { - title: 'Storage', - icon: '/docs/img/icons/menu/storage', - hasLightIcon: true, - href: '/guides/storage', - description: - 'Store, organize, transform, and serve large files—fully integrated with your Postgres database with Row Level Security access policies.', - }, - { - title: 'Realtime', - icon: '/docs/img/icons/menu/realtime', - hasLightIcon: true, - href: '/guides/realtime', - description: - 'Listen to database changes, store and sync user states across clients, broadcast data to clients subscribed to a channel, and more.', - }, - { - title: 'Edge Functions', - icon: '/docs/img/icons/menu/functions', - hasLightIcon: true, - href: '/guides/functions', - description: - 'Globally distributed, server-side functions to execute your code closest to your users for the lowest latency.', - }, -] - -export const apis = [ - { - title: 'JavaScript Client Library', - icon: '/docs/img/icons/menu/reference-javascript', - hasLightIcon: true, - href: 'reference/javascript/introduction', - description: 'Official client libraries for JavaScript and TypeScript.', - }, - { - title: 'Flutter Client Library', - icon: '/docs/img/icons/menu/reference-dart', - hasLightIcon: true, - href: 'reference/dart/introduction', - description: 'Official client libraries for Flutter and Dart.', - }, - { - title: 'Management API', - icon: '/docs/img/icons/menu/reference-api', - hasLightIcon: true, - href: 'reference/api/introduction', - description: 'Manage your Supabase projects and organizations programmatically.', - }, - { - title: 'Supabase CLI', - icon: '/docs/img/icons/menu/reference-api', - hasLightIcon: true, - href: 'reference/cli/introduction', - description: - 'Use the CLI to develop your project locally, manage database migrations, and deploy to the Supabase Platform or self-host.', - }, - { - title: 'Self-Hosting Auth', - icon: '/docs/img/icons/menu/reference-auth', - hasLightIcon: true, - href: 'reference/self-hosting-auth/introduction', - description: 'Self-host your own Auth server.', - }, - { - title: 'Self-Hosting Storage', - icon: '/docs/img/icons/menu/reference-storage', - hasLightIcon: true, - href: 'reference/self-hosting-storage/introduction', - description: 'Self-host your own Storage server.', - }, - { - title: 'Self-Hosting Realtime', - icon: '/docs/img/icons/menu/reference-realtime', - hasLightIcon: true, - href: 'reference/self-hosting-realtime/introduction', - description: 'Self-host your own Realtime server.', - }, -] - -export const platform = [ - { - // header: '/docs/img/cards/sample-card-header-3.svg', - title: 'Platform Guides', - icon: '/docs/img/icons/menu/platform', - hasLightIcon: true, - href: 'guides/platform', - description: - 'Learn more about the tools and services powering the Supabase Platform, available add-ons, and how to customize the platform for your needs.', - }, - { - // header: '/docs/img/cards/sample-card-header-2.svg', - title: 'Resources', - icon: '/docs/img/icons/menu/resources', - hasLightIcon: true, - href: 'guides/resources', - description: 'View examples, curated content from the community, migration guides, and more.', - }, - { - // header: '/docs/img/cards/sample-card-header-2.svg', - title: 'Integrations', - icon: '/docs/img/icons/menu/integrations', - hasLightIcon: true, - href: 'guides/integrations', - description: 'Explore a variety of integrations from Supabase partners.', - }, -] - -export const Page = ({ children }) => - -export default Page diff --git a/apps/www/lib/authors.json b/apps/www/lib/authors.json index 1f2a6e5fead..499ab21a0c2 100644 --- a/apps/www/lib/authors.json +++ b/apps/www/lib/authors.json @@ -250,5 +250,12 @@ "position": "Engineering", "author_url": "https://github.com/fenos", "author_image_url": "https://github.com/fenos.png" + }, + { + "author_id": "stojan", + "author": "Stojan Dimitrovski", + "position": "Engineering", + "author_url": "https://github.com/hf", + "author_image_url": "https://github.com/hf.png" } ] diff --git a/spec/cli_v1_commands.yaml b/spec/cli_v1_commands.yaml index ca9116bdf17..e0799ffd7c0 100644 --- a/spec/cli_v1_commands.yaml +++ b/spec/cli_v1_commands.yaml @@ -1,7 +1,7 @@ clispec: '001' info: id: cli - version: 1.23.0 + version: 1.24.0 title: Supabase CLI language: sh source: https://github.com/supabase/cli @@ -49,11 +49,7 @@ commands: - supabase-vanity-subdomains-check-availability - supabase-vanity-subdomains-delete - supabase-vanity-subdomains-get - flags: - - id: project-ref - name: --project-ref - description: Project ref of the Supabase project. - default_value: '' + flags: [] - id: supabase-vanity-subdomains-get title: supabase vanity-subdomains get summary: Get the current vanity subdomain @@ -61,7 +57,11 @@ commands: links: [] usage: supabase vanity-subdomains get subcommands: [] - flags: [] + flags: + - id: project-ref + name: --project-ref + description: Project ref of the Supabase project. + default_value: '' - id: supabase-vanity-subdomains-delete title: supabase vanity-subdomains delete summary: Deletes a project's vanity subdomain @@ -71,7 +71,11 @@ commands: links: [] usage: supabase vanity-subdomains delete subcommands: [] - flags: [] + flags: + - id: project-ref + name: --project-ref + description: Project ref of the Supabase project. + default_value: '' - id: supabase-vanity-subdomains-check-availability title: supabase vanity-subdomains check-availability summary: Checks if a desired subdomain is available for use @@ -85,6 +89,10 @@ commands: description: | The desired vanity subdomain to use for your Supabase project. default_value: '' + - id: project-ref + name: --project-ref + description: Project ref of the Supabase project. + default_value: '' - id: supabase-vanity-subdomains-activate title: supabase vanity-subdomains activate summary: Activate a vanity subdomain @@ -103,6 +111,10 @@ commands: description: | The desired vanity subdomain to use for your Supabase project. default_value: '' + - id: project-ref + name: --project-ref + description: Project ref of the Supabase project. + default_value: '' - id: supabase-test title: supabase test summary: Run tests on local Supabase containers @@ -343,11 +355,7 @@ commands: subcommands: - supabase-network-restrictions-get - supabase-network-restrictions-update - flags: - - id: project-ref - name: --project-ref - description: Project ref of the Supabase project. - default_value: '' + flags: [] - id: supabase-network-restrictions-update title: supabase network-restrictions update summary: Update network restrictions @@ -364,6 +372,10 @@ commands: name: --db-allow-cidr description: CIDR to allow DB connections from. default_value: '[]' + - id: project-ref + name: --project-ref + description: Project ref of the Supabase project. + default_value: '' - id: supabase-network-restrictions-get title: supabase network-restrictions get summary: Get the current network restrictions @@ -371,7 +383,11 @@ commands: links: [] usage: supabase network-restrictions get subcommands: [] - flags: [] + flags: + - id: project-ref + name: --project-ref + description: Project ref of the Supabase project. + default_value: '' - id: supabase-migration title: supabase migration summary: Manage database migration scripts @@ -531,6 +547,10 @@ commands: description: | Path to an env file to be populated to the Function environment. default_value: '' + - id: import-map + name: --import-map + description: Path to import map file. + default_value: '' - id: no-verify-jwt name: --no-verify-jwt description: Disable JWT verification for the Function. @@ -552,6 +572,10 @@ commands: usage: supabase functions deploy [flags] subcommands: [] flags: + - id: import-map + name: --import-map + description: Path to import map file. + default_value: '' - id: legacy-bundle name: --legacy-bundle description: Use legacy bundling mechanism. @@ -594,6 +618,14 @@ commands: - supabase-domains-delete - supabase-domains-get - supabase-domains-reverify + flags: [] + - id: supabase-domains-reverify + title: supabase domains reverify + summary: Re-verify the custom hostname config for your project + tags: [] + links: [] + usage: supabase domains reverify + subcommands: [] flags: - id: include-raw-output name: --include-raw-output @@ -603,14 +635,6 @@ commands: name: --project-ref description: Project ref of the Supabase project. default_value: '' - - id: supabase-domains-reverify - title: supabase domains reverify - summary: Re-verify the custom hostname config for your project - tags: [] - links: [] - usage: supabase domains reverify - subcommands: [] - flags: [] - id: supabase-domains-get title: supabase domains get summary: Get the current custom hostname config @@ -620,7 +644,15 @@ commands: links: [] usage: supabase domains get subcommands: [] - flags: [] + flags: + - id: include-raw-output + name: --include-raw-output + description: Include raw output (useful for debugging). + default_value: 'false' + - id: project-ref + name: --project-ref + description: Project ref of the Supabase project. + default_value: '' - id: supabase-domains-delete title: supabase domains delete summary: Deletes the custom hostname config for your project @@ -628,7 +660,15 @@ commands: links: [] usage: supabase domains delete subcommands: [] - flags: [] + flags: + - id: include-raw-output + name: --include-raw-output + description: Include raw output (useful for debugging). + default_value: 'false' + - id: project-ref + name: --project-ref + description: Project ref of the Supabase project. + default_value: '' - id: supabase-domains-create title: supabase domains create summary: Create a custom hostname @@ -645,6 +685,14 @@ commands: name: --custom-hostname description: The custom hostname to use for your Supabase project. default_value: '' + - id: include-raw-output + name: --include-raw-output + description: Include raw output (useful for debugging). + default_value: 'false' + - id: project-ref + name: --project-ref + description: Project ref of the Supabase project. + default_value: '' - id: supabase-domains-activate title: supabase domains activate summary: Activate the custom hostname for a project @@ -657,7 +705,15 @@ commands: links: [] usage: supabase domains activate subcommands: [] - flags: [] + flags: + - id: include-raw-output + name: --include-raw-output + description: Include raw output (useful for debugging). + default_value: 'false' + - id: project-ref + name: --project-ref + description: Project ref of the Supabase project. + default_value: '' - id: supabase-db title: supabase db summary: Manage local Postgres databases @@ -695,11 +751,7 @@ commands: links: [] subcommands: - supabase-db-remote-commit - flags: - - id: password - name: -p, --password - description: Password to your remote Postgres database. - default_value: '' + flags: [] - id: supabase-db-remote-commit title: supabase db remote commit summary: Commit remote changes as a new migration @@ -707,7 +759,11 @@ commands: links: [] usage: supabase db remote commit subcommands: [] - flags: [] + flags: + - id: password + name: -p, --password + description: Password to your remote Postgres database. + default_value: '' - id: supabase-db-push title: supabase db push summary: Push new migrations to the remote database diff --git a/spec/common-cli-sections.json b/spec/common-cli-sections.json index 94570bfab9b..9ce2b34c7e0 100644 --- a/spec/common-cli-sections.json +++ b/spec/common-cli-sections.json @@ -6,6 +6,13 @@ "isFunc": false, "type": "markdown" }, + { + "title": "Global flags", + "id": "global-flags", + "slug": "global-flags", + "isFunc": false, + "type": "markdown" + }, { "title": "general", "items": [ @@ -77,6 +84,77 @@ } ] }, + { + "title": "Database", + "items": [ + { "id": "supabase-db", "title": "supabase db", "slug": "supabase-db", "type": "cli-command" }, + { + "id": "supabase-db-reset", + "title": "supabase db reset", + "slug": "supabase-db-reset", + "type": "cli-command" + }, + { + "id": "supabase-db-remote", + "title": "supabase db remote", + "slug": "supabase-db-remote", + "type": "cli-command" + }, + { + "id": "supabase-db-remote-commit", + "title": "supabase db remote commit", + "slug": "supabase-db-remote-commit", + "type": "cli-command" + }, + { + "id": "supabase-db-push", + "title": "supabase db push", + "slug": "supabase-db-push", + "type": "cli-command" + }, + { + "id": "supabase-db-lint", + "title": "supabase db lint", + "slug": "supabase-db-lint", + "type": "cli-command" + }, + { + "id": "supabase-db-diff", + "title": "supabase db diff", + "slug": "supabase-db-diff", + "type": "cli-command" + } + ] + }, + { + "title": "migrations", + "items": [ + { + "id": "supabase-migration", + "title": "supabase migration", + "slug": "supabase-migration", + "type": "cli-command" + }, + { + "id": "supabase-migration-new", + "title": "supabase migration new", + "slug": "supabase-migration-new", + "type": "cli-command" + }, + { + "id": "supabase-migration-list", + "title": "supabase migration list", + "slug": "supabase-migration-list", + "type": "cli-command" + }, + { + "id": "supabase-migration-repair", + "title": "supabase migration repair", + "slug": "supabase-migration-repair", + "type": "cli-command" + } + ] + }, { "title": "secrets", "items": [ @@ -146,29 +224,6 @@ } ] }, - { - "title": "migrations", - "items": [ - { - "id": "supabase-migration", - "title": "supabase migration", - "slug": "supabase-migration", - "type": "cli-command" - }, - { - "id": "supabase-migration-new", - "title": "supabase migration new", - "slug": "supabase-migration-new", - "type": "cli-command" - }, - { - "id": "supabase-migration-list", - "title": "supabase migration list", - "slug": "supabase-migration-list", - "type": "cli-command" - } - ] - }, { "title": "Edge Functions", "items": [ @@ -206,7 +261,7 @@ }, { "title": "Domains", - "Items": [ + "items": [ { "id": "supabase-domains", "title": "supabase domains", @@ -246,43 +301,59 @@ ] }, { - "title": "Database", + "title": "Vanity Subdomains", "items": [ - { "id": "supabase-db", "title": "supabase db", "slug": "supabase-db", "type": "cli-command" }, { - "id": "supabase-db-reset", - "title": "supabase db reset", - "slug": "supabase-db-reset", + "id": "supabase-vanity-subdomains", + "title": "supabase vanity-subdomains", + "slug": "supabase-vanity-subdomains", "type": "cli-command" }, { - "id": "supabase-db-remote", - "title": "supabase db remote", - "slug": "supabase-db-remote", + "id": "supabase-vanity-subdomains-check-availability", + "title": "supabase vanity-subdomains check-availability", + "slug": "supabase-vanity-subdomains-check-availability", "type": "cli-command" }, { - "id": "supabase-db-remote-commit", - "title": "supabase db remote commit", - "slug": "supabase-db-remote-commit", + "id": "supabase-vanity-subdomains-activate", + "title": "supabase vanity-subdomains activate", + "slug": "supabase-vanity-subdomains-activate", "type": "cli-command" }, { - "id": "supabase-db-push", - "title": "supabase db push", - "slug": "supabase-db-push", + "id": "supabase-vanity-subdomains-delete", + "title": "supabase vanity-subdomains delete", + "slug": "supabase-vanity-subdomains-delete", "type": "cli-command" }, { - "id": "supabase-db-lint", - "title": "supabase db lint", - "slug": "supabase-db-lint", + "id": "supabase-vanity-subdomains-get", + "title": "supabase vanity-subdomains get", + "slug": "supabase-vanity-subdomains-get", + "type": "cli-command" + } + ] + }, + { + "title": "Network Restrictions", + "items": [ + { + "id": "supabase-network-restrictions", + "title": "supabase network-restrictions", + "slug": "supabase-network-restrictions", "type": "cli-command" }, { - "id": "supabase-db-diff", - "title": "supabase db diff", - "slug": "supabase-db-diff", + "id": "supabase-network-restrictions-get", + "title": "supabase network-restrictions get", + "slug": "supabase-network-restrictions-get", + "type": "cli-command" + }, + { + "id": "supabase-network-restrictions-update", + "title": "supabase network-restrictions update", + "slug": "supabase-network-restrictions-update", "type": "cli-command" } ] diff --git a/studio/.env b/studio/.env index d872e21ab40..90e1f679821 100644 --- a/studio/.env +++ b/studio/.env @@ -5,7 +5,7 @@ DEFAULT_ORGANIZATION_NAME=Default Organization DEFAULT_PROJECT_NAME=Default Project SUPABASE_URL=http://localhost:8000 -SUPABASE_PUBLIC_URL=https://localhost:8443 +SUPABASE_PUBLIC_URL=http://localhost:8000 SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE SUPABASE_SERVICE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q diff --git a/studio/components/interfaces/Auth/Users/UserDropdown.tsx b/studio/components/interfaces/Auth/Users/UserDropdown.tsx index f5534393e65..42dd95b7444 100644 --- a/studio/components/interfaces/Auth/Users/UserDropdown.tsx +++ b/studio/components/interfaces/Auth/Users/UserDropdown.tsx @@ -1,9 +1,9 @@ import { FC, useContext, useState } from 'react' import { observer } from 'mobx-react-lite' import * as Tooltip from '@radix-ui/react-tooltip' -import { Button, Dropdown, Divider, IconTrash, IconMail, IconMoreHorizontal } from 'ui' +import { Button, Dropdown, IconTrash, IconMail, IconMoreHorizontal, IconShieldOff } from 'ui' -import { useStore } from 'hooks' +import { useFlag, useStore } from 'hooks' import { timeout } from 'lib/helpers' import { post, delete_ } from 'lib/common/fetch' import { API_URL } from 'lib/constants' @@ -14,9 +14,11 @@ import { User } from './Users.types' interface Props { user: User canRemoveUser: boolean + canRemoveMFAFactors: boolean } -const UserDropdown: FC = ({ user, canRemoveUser }) => { +const UserDropdown: FC = ({ user, canRemoveUser, canRemoveMFAFactors }) => { + const showDeleteFactorsDropdown = useFlag('mfaSso') const PageState: any = useContext(PageContext) const { ui } = useStore() const [loading, setLoading] = useState(false) @@ -120,6 +122,33 @@ const UserDropdown: FC = ({ user, canRemoveUser }) => { }) } + async function handleDeleteFactors() { + await timeout(200) + + confirmAlert({ + title: 'Confirm to delete', + message: `This is permanent! Are you sure you want to delete the user's MFA factors?`, + onAsyncConfirm: async () => { + setLoading(true) + const response = await delete_( + `${API_URL}/auth/${PageState.projectRef}/users/${user.id}/factors` + ) + if (response.error) { + ui.setNotification({ + category: 'error', + message: `Failed to delete factors: ${response.error.message}`, + }) + } else { + ui.setNotification({ + category: 'success', + message: "Successfully deleted the user's factors", + }) + } + setLoading(false) + }, + }) + } + return ( = ({ user, canRemoveUser }) => { ) : null} + {showDeleteFactorsDropdown && ( + + + } + disabled={!canRemoveMFAFactors} + > + Remove MFA factors + + + {/* + [Joshen] Deleting MFA factors should be different ABAC perms i think + need to double check with KM / anyone familiar with ABAC + */} + {!canRemoveMFAFactors && ( + + +
+ + You need additional permissions to remove a user's authentication factors. + +
+
+ )} +
+ )} { const PageState: any = useContext(PageContext) + + // Check once on the top level, rather than checking for every row const canRemoveUser = checkPermissions(PermissionAction.TENANT_SQL_DELETE, 'auth.users') + const canRemoveMFAFactors = checkPermissions( + PermissionAction.TENANT_SQL_DELETE, + 'auth.mfa_factors' + ) return ( @@ -49,7 +55,12 @@ const UsersList = ({}) => { )} {PageState.users.length > 0 && PageState.users.map((x: any) => ( - + ))} diff --git a/studio/components/interfaces/Auth/Users/UsersListItem.tsx b/studio/components/interfaces/Auth/Users/UsersListItem.tsx index 43a6ec57d89..7ae8c894989 100644 --- a/studio/components/interfaces/Auth/Users/UsersListItem.tsx +++ b/studio/components/interfaces/Auth/Users/UsersListItem.tsx @@ -11,9 +11,10 @@ import { User } from './Users.types' interface Props { user: User canRemoveUser: boolean + canRemoveMFAFactors: boolean } -const UserListItem: FC = ({ user, canRemoveUser }) => { +const UserListItem: FC = ({ user, canRemoveUser, canRemoveMFAFactors }) => { const isUserConfirmed = user.email_confirmed_at || user.phone_confirmed_at const createdAt = getDateFromIsoString(user.created_at) const lastSignedIn = getDateFromIsoString(user.last_sign_in_at) @@ -54,7 +55,11 @@ const UserListItem: FC = ({ user, canRemoveUser }) => {
- + ) diff --git a/studio/components/interfaces/Database/Wrappers/Wrappers.tsx b/studio/components/interfaces/Database/Wrappers/Wrappers.tsx index 50bd723a799..a826e4c6f37 100644 --- a/studio/components/interfaces/Database/Wrappers/Wrappers.tsx +++ b/studio/components/interfaces/Database/Wrappers/Wrappers.tsx @@ -9,6 +9,7 @@ import { checkPermissions, useParams, useStore } from 'hooks' import { useFDWsQuery } from 'data/fdw/fdws-query' import { WRAPPERS } from './Wrappers.constants' import WrapperRow from './WrapperRow' +import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' const Wrappers = () => { @@ -26,6 +27,7 @@ const Wrappers = () => { const wrappersExtension = meta.extensions.byId('wrappers') const vaultExtension = meta.extensions.byId('supabase_vault') + const isLoadingExtensions = meta.extensions.isLoading const isNotAvailable = wrappersExtension === undefined || vaultExtension === undefined const isWrappersEnabled = @@ -120,7 +122,13 @@ const Wrappers = () => {
*/}
- {isWrappersEnabled ? ( + {isLoadingExtensions ? ( +
+ + + +
+ ) : isWrappersEnabled ? (
{WRAPPERS.map((wrapper, i) => { return ( diff --git a/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx b/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx index a70a125cc0b..ac11e16bd6f 100644 --- a/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx +++ b/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx @@ -6,7 +6,8 @@ import { JwtSecretUpdateStatus } from '@supabase/shared-types/out/events' import { PermissionAction } from '@supabase/shared-types/out/constants' import { checkPermissions, useJwtSecretUpdateStatus, useProjectSettings } from 'hooks' -import { DEFAULT_PROJECT_API_SERVICE_ID } from 'lib/constants' +import { DEFAULT_PROJECT_API_SERVICE_ID, IS_PLATFORM } from 'lib/constants' +import { PROJECT_ENDPOINT_PROTOCOL } from 'pages/api/constants' import Snippets from 'components/to-be-cleaned/Docs/Snippets' import Panel from 'components/ui/Panel' import SimpleCodeBlock from 'components/to-be-cleaned/SimpleCodeBlock' @@ -45,7 +46,7 @@ const APIKeys = () => { const isNotUpdatingJwtSecret = jwtSecretUpdateStatus === undefined || jwtSecretUpdateStatus === JwtSecretUpdateStatus.Updated - const apiUrl = `https://${apiConfig.endpoint}` + const apiUrl = `${IS_PLATFORM ? 'https' : PROJECT_ENDPOINT_PROTOCOL}://${apiConfig.endpoint}` const anonKey = apiKeys.find((key: any) => key.tags === 'anon') const clientInitSnippet: any = Snippets.init(apiUrl) diff --git a/studio/components/interfaces/Home/ProjectList/ProjectList.tsx b/studio/components/interfaces/Home/ProjectList/ProjectList.tsx index 8f0d99c1947..32472e694b4 100644 --- a/studio/components/interfaces/Home/ProjectList/ProjectList.tsx +++ b/studio/components/interfaces/Home/ProjectList/ProjectList.tsx @@ -3,6 +3,7 @@ import { Button, IconPlus } from 'ui' import { useRouter } from 'next/router' import { observer } from 'mobx-react-lite' +import { IS_PLATFORM } from 'lib/constants' import { checkPermissions, useStore } from 'hooks' import { Organization, Project } from 'types' import { makeRandomString } from 'lib/helpers' @@ -20,7 +21,7 @@ const ProjectList: FC = ({ rewriteHref }) => { const { organizations, projects } = app const { isLoading: isLoadingProjects } = projects - const isLoadingPermissions = (ui?.permissions ?? []).length === 0 + const isLoadingPermissions = IS_PLATFORM ? (ui?.permissions ?? []).length === 0 : false return ( <> diff --git a/studio/components/interfaces/Settings/API/ServiceList.tsx b/studio/components/interfaces/Settings/API/ServiceList.tsx index aba88820aac..ce2097d0b03 100644 --- a/studio/components/interfaces/Settings/API/ServiceList.tsx +++ b/studio/components/interfaces/Settings/API/ServiceList.tsx @@ -14,6 +14,8 @@ import Panel from 'components/ui/Panel' import PostgrestConfig from './PostgrestConfig' import { DisplayApiSettings } from 'components/ui/ProjectSettings' import { JWT_SECRET_UPDATE_ERROR_MESSAGES } from './API.constants' +import { PROJECT_ENDPOINT_PROTOCOL } from 'pages/api/constants' +import { IS_PLATFORM } from 'lib/constants' import JWTSettings from './JWTSettings' interface Props { @@ -77,7 +79,9 @@ const ServiceList: FC = ({ projectRef }) => { readOnly disabled className="input-mono" - value={`https://${apiConfig?.endpoint ?? '-'}`} + value={`${IS_PLATFORM ? 'https' : PROJECT_ENDPOINT_PROTOCOL}://${ + apiConfig?.endpoint ?? '-' + }`} descriptionText="A RESTful endpoint for querying and managing your database." layout="horizontal" /> diff --git a/studio/components/ui/ProjectSettings/DisplayConfigSettings.tsx b/studio/components/ui/ProjectSettings/DisplayConfigSettings.tsx index d43f8a3d478..ea70fb700dd 100644 --- a/studio/components/ui/ProjectSettings/DisplayConfigSettings.tsx +++ b/studio/components/ui/ProjectSettings/DisplayConfigSettings.tsx @@ -3,7 +3,8 @@ import { useRouter } from 'next/router' import { Input, IconAlertCircle, IconLoader } from 'ui' import { JwtSecretUpdateStatus } from '@supabase/shared-types/out/events' import { useJwtSecretUpdateStatus, useProjectSettings } from 'hooks' -import { DEFAULT_PROJECT_API_SERVICE_ID } from 'lib/constants' +import { DEFAULT_PROJECT_API_SERVICE_ID, IS_PLATFORM } from 'lib/constants' +import { PROJECT_ENDPOINT_PROTOCOL } from 'pages/api/constants' import Panel from 'components/ui/Panel' const DisplayConfigSettings = () => { @@ -55,7 +56,7 @@ const DisplayConfigSettings = () => { copy disabled className="input-mono" - value={`https://${apiConfig.endpoint}`} + value={`${IS_PLATFORM ? 'https' : PROJECT_ENDPOINT_PROTOCOL}://${apiConfig.endpoint}`} descriptionText="A RESTful endpoint for querying and managing your database." layout="horizontal" /> diff --git a/studio/components/ui/ShimmeringLoader.tsx b/studio/components/ui/ShimmeringLoader.tsx index a02e89c022f..5a97e10827e 100644 --- a/studio/components/ui/ShimmeringLoader.tsx +++ b/studio/components/ui/ShimmeringLoader.tsx @@ -1,5 +1,5 @@ -const ShimmeringLoader = () => { - return
+const ShimmeringLoader = ({ className = '' }) => { + return
} export default ShimmeringLoader diff --git a/studio/localStores/storageExplorer/StorageExplorerStore.js b/studio/localStores/storageExplorer/StorageExplorerStore.js index f3bcfd79a4b..d553efa0f76 100644 --- a/studio/localStores/storageExplorer/StorageExplorerStore.js +++ b/studio/localStores/storageExplorer/StorageExplorerStore.js @@ -24,6 +24,8 @@ import { STORAGE_SORT_BY, } from 'components/to-be-cleaned/Storage/Storage.constants.ts' import { copyToClipboard } from 'lib/helpers' +import { IS_PLATFORM } from 'lib/constants' +import { PROJECT_ENDPOINT_PROTOCOL } from 'pages/api/constants' /** * This is a preferred method rather than React Context and useStorageExplorerStore(). @@ -112,21 +114,26 @@ class StorageExplorerStore { /* Methods which are commonly used + For better readability */ initializeSupabaseClient = (serviceKey, serviceEndpoint) => { - this.supabaseClient = createClient(`https://${serviceEndpoint}`, serviceKey, { - auth: { - persistSession: false, - autoRefreshToken: false, - multiTab: false, - detectSessionInUrl: false, - localStorage: { - getItem: (key) => { - return undefined + console.debug(serviceEndpoint) + this.supabaseClient = createClient( + `${IS_PLATFORM ? 'https' : PROJECT_ENDPOINT_PROTOCOL}://${serviceEndpoint}`, + serviceKey, + { + auth: { + persistSession: false, + autoRefreshToken: false, + multiTab: false, + detectSessionInUrl: false, + localStorage: { + getItem: (key) => { + return undefined + }, + setItem: (key, value) => {}, + removeItem: (key) => {}, }, - setItem: (key, value) => {}, - removeItem: (key) => {}, }, - }, - }) + } + ) } updateFileInPreviewCache = (fileCache) => { diff --git a/studio/pages/api/constants.ts b/studio/pages/api/constants.ts index 3531bad779e..ae150beae97 100644 --- a/studio/pages/api/constants.ts +++ b/studio/pages/api/constants.ts @@ -1,4 +1,5 @@ -const PUBLIC_URL = new URL(process.env.SUPABASE_PUBLIC_URL || 'https://localhost:8443') +const PUBLIC_URL = new URL(process.env.SUPABASE_PUBLIC_URL || 'http://localhost:8000') export const PROJECT_REST_URL = `${PUBLIC_URL.origin}/rest/v1/` export const PROJECT_ENDPOINT = PUBLIC_URL.host +export const PROJECT_ENDPOINT_PROTOCOL = PUBLIC_URL.protocol.replace(':', '') diff --git a/studio/pages/project/[ref]/api/index.tsx b/studio/pages/project/[ref]/api/index.tsx index 8b4cfaa92f4..482494908ff 100644 --- a/studio/pages/project/[ref]/api/index.tsx +++ b/studio/pages/project/[ref]/api/index.tsx @@ -6,6 +6,7 @@ import { observer, useLocalObservable } from 'mobx-react-lite' import { NextPageWithLayout } from 'types' import { API_URL, IS_PLATFORM } from 'lib/constants' +import { PROJECT_ENDPOINT_PROTOCOL } from 'pages/api/constants' import { checkPermissions, useStore } from 'hooks' import { get } from 'lib/common/fetch' import { snakeToCamel } from 'lib/helpers' @@ -118,7 +119,7 @@ const DocView: FC = observer(({}) => { ...data.autoApiService, endpoint: IS_PLATFORM ? `https://${data?.autoApiService?.endpoint}` - : data.autoApiService.endpoint, + : `${PROJECT_ENDPOINT_PROTOCOL}://${data.autoApiService.endpoint}`, } const { query } = router diff --git a/studio/pages/project/[ref]/settings/vault/secrets.tsx b/studio/pages/project/[ref]/settings/vault/secrets.tsx index c60a79a88df..7d56cfff275 100644 --- a/studio/pages/project/[ref]/settings/vault/secrets.tsx +++ b/studio/pages/project/[ref]/settings/vault/secrets.tsx @@ -8,6 +8,7 @@ import { NextPageWithLayout } from 'types' import { SettingsLayout } from 'components/layouts' import { VaultToggle, SecretsManagement } from 'components/interfaces/Settings/Vault' import { FormHeader } from 'components/ui/Forms' +import ShimmeringLoader from 'components/ui/ShimmeringLoader' const VaultSettingsSecrets: NextPageWithLayout = () => { const router = useRouter() @@ -15,6 +16,7 @@ const VaultSettingsSecrets: NextPageWithLayout = () => { const { ref } = useParams() const vaultExtension = meta.extensions.byId('supabase_vault') + const isLoading = meta.extensions.isLoading const isEnabled = vaultExtension !== undefined && vaultExtension?.installed_version !== null useEffect(() => { @@ -26,7 +28,13 @@ const VaultSettingsSecrets: NextPageWithLayout = () => { return (
- {!isEnabled ? ( + {isLoading ? ( +
+ + + +
+ ) : !isEnabled ? ( ) : ( {
@@ -369,7 +370,9 @@ const ProjectLinks: FC = observer(() => { // Then create env for vercel project with supabase project const vercelEnvs = prepareVercelEvns(defaultVercelEnvs, { - endpoint: `https://${projectDetails.autoApiService.endpoint}`, + endpoint: `${IS_PLATFORM ? 'https' : PROJECT_ENDPOINT_PROTOCOL}://${ + projectDetails.autoApiService.endpoint + }`, anon_key: projectDetails.autoApiService.defaultApiKey, service_key: projectDetails.autoApiService.serviceApiKey, })