Merge pull request #10957 from supabase/master

This commit is contained in:
Inian authored and GitHub committed 2022-12-14 18:31:12 +08:00
commit 4eecc99176
27 files changed
+796 -533

No files matched your search

+4
View File
@@ -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) => <CodeBlock {...props} />,
RefHeaderSection: (props: any) => <RefHeaderSection {...props} />,
CliGlobalFlagsHandler: () => <CliGlobalFlagsHandler />,
}
export default components
@@ -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 && (
<div className="">
<h3 className="text-sm text-scale-1200 mb-3">Available Commands</h3>
<div className="mb-3">
<h3 className="text-lg text-scale-1200 mb-3">Available Commands</h3>
<ul>
{command.subcommands.map((subcommand) => (
<li key={subcommand}>
<a href={`#${subcommand}`} className="text-scale-1200">
<CodeBlock language="bash">{subcommand}</CodeBlock>
<li key={subcommand} className="flex items-center gap-3">
<div className="text-scale-900">
<IconChevronRight size={14} strokeWidth={2} />
</div>
<a
href={`#${subcommand}`}
className="transition text-scale-1100 hover:text-brand-900"
>
$ {subcommand.replace(/-/g, ' ')}
</a>
</li>
))}
@@ -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 (
<RefSubLayout.EducationRow className="not-prose">
<RefSubLayout.Details>
<h3 className="text-lg text-scale-1200 mb-3">Flags</h3>
<ul className="">
{spec.flags.map((flag) => {
return (
<Param
{...flag}
isOptional={flag.required === undefined ? true : !flag.required}
></Param>
)
})}
</ul>
</RefSubLayout.Details>
<RefSubLayout.Examples></RefSubLayout.Examples>
</RefSubLayout.EducationRow>
)
}
export default CliGlobalFlagsHandler
+8
View File
@@ -0,0 +1,8 @@
---
title: Global Flags
description: 'Supabase CLI supports global flags for every command.'
---
Supabase CLI supports global flags for every command.
<CliGlobalFlagsHandler />
+16
View File
@@ -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> = (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) => {
)}
<div className="max-w-xs w-32 h-[1px] bg-gradient-to-r from-brand-800 to-brand-900 my-8"></div>
<MDXProvider components={components}>{props.children}</MDXProvider>
<div className="mt-16 not-prose">
<div>
<Link
href={`https://github.com/supabase/supabase/edit/master/apps/docs/pages${router.asPath}.mdx`}
passHref
>
<a className="text-sm transition flex items-center gap-1 text-scale-1000 hover:text-scale-1200">
Edit this page on GitHub <IconExternalLink size={14} strokeWidth={1.5} />
</a>
</Link>
</div>
</div>
</article>
</div>
{!props.hideToc && hasTableOfContents && !props.meta?.hide_table_of_contents && (
+8 -2
View File
@@ -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<ISectionExamples> = (props) => {
}
const EducationRow: FC<IEducationRow> = (props) => {
return <div className="grid lg:grid-cols-2 gap-8 lg:gap-16">{props.children}</div>
return (
<div className={['grid lg:grid-cols-2 gap-8 lg:gap-16', props.className].join(' ')}>
{props.children}
</div>
)
}
const EducationSection: FC<IEducationSection> = ({ icon, hideTitle = false, ...props }) => {
@@ -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('<INSERT PROJECT URL>', '<INSERT PROJECT ANON API KEY>')
const supabase = createClient(
'<INSERT PROJECT URL>',
'<INSERT PROJECT ANON API KEY>'
)
const App = () => <Auth supabaseClient={supabase} />
```
@@ -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(
'<INSERT PROJECT URL>',
'<INSERT PROJECT ANON API KEY>'
)
const App = () => (
<Auth
supabaseClient={supabase}
@@ -59,6 +67,28 @@ 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(
'<INSERT PROJECT URL>',
'<INSERT PROJECT ANON API KEY>'
)
const App = () => (
<Auth
supabaseClient={supabase}
appearance={{ theme: ThemeSupa }}
providers={['google', 'facebook', 'twitter']}
/>
)
```
## 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('<INSERT PROJECT URL>', '<INSERT PROJECT ANON API KEY>')
const supabase = createClient(
'<INSERT PROJECT URL>',
'<INSERT PROJECT ANON API KEY>'
)
const App = () => (
<Auth
@@ -99,11 +132,14 @@ Currently there is only one predefined theme available, but we plan to add more.
Auth UI comes with two theme variations: `default` and `dark`. You can switch between these themes with the `theme` prop.
```js lines=11 title=/src/index.js
```js lines=14 title=/src/index.js
import { createClient } from '@supabase/supabase-js'
import { Auth, ThemeSupa } from '@supabase/auth-ui-react'
const supabase = createClient('<INSERT PROJECT URL>', '<INSERT PROJECT ANON API KEY>')
const supabase = createClient(
'<INSERT PROJECT URL>',
'<INSERT PROJECT ANON API KEY>'
)
const App = () => (
<Auth
@@ -121,11 +157,14 @@ If you don't pass a value to `theme` it uses the `"default"` theme. You can pass
Auth UI themes can be overridden using variable tokens. See the [list of variable tokens](https://github.com/supabase-community/auth-ui/blob/main/packages/react/common/theming/Themes.tsx).
```js lines=11-18 title=/src/index.js
```js lines=14-21 title=/src/index.js
import { createClient } from '@supabase/supabase-js'
import { Auth, ThemeSupa } from '@supabase/auth-ui-react'
const supabase = createClient('<INSERT PROJECT URL>', '<INSERT PROJECT ANON API KEY>')
const supabase = createClient(
'<INSERT PROJECT URL>',
'<INSERT PROJECT ANON API KEY>'
)
const App = () => (
<Auth
@@ -208,7 +247,10 @@ You can use custom CSS classes for the following elements:
import { createClient } from '@supabase/supabase-js'
import { Auth } from '@supabase/auth-ui-react'
const supabase = createClient('<INSERT PROJECT URL>', '<INSERT PROJECT ANON API KEY>')
const supabase = createClient(
'<INSERT PROJECT URL>',
'<INSERT PROJECT ANON API KEY>'
)
const App = () => (
<Auth
@@ -233,7 +275,10 @@ You can use custom CSS inline styles for the following elements:
import { createClient } from '@supabase/supabase-js'
import { Auth } from '@supabase/auth-ui-react'
const supabase = createClient('<INSERT PROJECT URL>', '<INSERT PROJECT ANON API KEY>')
const supabase = createClient(
'<INSERT PROJECT URL>',
'<INSERT PROJECT ANON API KEY>'
)
const App = () => (
<Auth
@@ -257,7 +302,10 @@ You can use custom labels with `localization.variables`. See the [list of labels
import { createClient } from '@supabase/supabase-js'
import { Auth } from '@supabase/auth-ui-react'
const supabase = createClient('<INSERT PROJECT URL>', '<INSERT PROJECT ANON API KEY>')
const supabase = createClient(
'<INSERT PROJECT URL>',
'<INSERT PROJECT ANON API KEY>'
)
const App = () => (
<Auth
+303 -82
View File
@@ -1,101 +1,322 @@
import Layout from '~/layouts/DefaultGuideLayout'
import NewContent from '~/pages/new/index.mdx'
import Layout from '~/layouts/DefaultLayout'
import Link from 'next/link'
import { GlassPanel, IconPanel, Button, IconChevronRight } from 'ui'
export const meta = {
id: 'introduction',
title: 'Introduction',
description: 'Introduction to Supabase',
hide_table_of_contents: false,
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',
}
export function CheckDoc() {
if (process.env.NEXT_PUBLIC_NEW_DOCS === 'true') return NewContent
}
<h2 className="text-base max-w-xl m-0">
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.
</h2>
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.
<div className="flex flex-col gap-12 my-12">
## Learn about features
<div className="space-y-8 hidden">
<div className="
border border-scale-400
relative overflow-hidden
grid grid-cols-12
rounded-lg
px-8 md:px-12 py-5 md:py-12
">
<div className="col-span-12 lg:col-span-7 flex flex-col gap-6">
<img className="hidden lg:visible absolute right-0 top-0 w-[500px]" src="/docs/img/cards/dark.png" />
<div classNam="">
<h3 className="text-2xl m-0 mb-3">Getting Started</h3>
Discover how to set up a database to an app making queries in just a few minutes.
<div className="font-mono uppercase text-xs mb-2">What you will learn</div>
<div className="flex flex-col">
<div className="flex flex-row items-center gap-3">
<div className="text-brand-900">
<IconChevronRight size={14} strokeWidth={1.5} />
</div>
<span className="text-scale-1200">Setting up a Supabase project and app</span>
</div>
<div className="flex flex-row items-center gap-3">
<div className="text-brand-900">
<IconChevronRight size={14} strokeWidth={1.5} />
</div>
<span className="text-scale-1200">Adding some sample data to your project</span>
</div>
<div className="flex flex-row items-center gap-3">
<div className="text-brand-900">
<IconChevronRight size={14} strokeWidth={1.5} />
</div>
<span className="text-scale-1200">Select() from your new database table</span>
</div>
</div>
<div className="mt-6">
<div className="hidden">
<Button size="small">Get started</Button>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-3 md:gap-6">
<Link href={`/getting-started/quickstarts/reactjs`} passHref>
<a className="no-underline">
<IconPanel title="ReactJS" icon="/docs/img/icons/react-icon" />
</a>
</Link>
<Link href={`/getting-started/quickstarts/nextjs`} passHref>
<a className="no-underline">
<IconPanel title="NextJS" icon="/docs/img/icons/nextjs-icon" />
</a>
</Link>
</div>
</div>
</div>
</div>
<div className="grid md:grid-cols-12 gap-4 not-prose">
<div className="col-span-4">
<ButtonCard
className="card"
to={'/guides/auth'}
title={'Auth'}
description={'User management with Row Level Security.'}
style={{ height: '100%' }}
/>
</div>
<div className="col-span-4">
<ButtonCard
className="card"
to={'/guides/api'}
title={'Auto-generated APIs'}
description={'Instantly generate APIs for your database.'}
style={{ height: '100%' }}
<div
className="
border
relative
px-8 md:px-12 h-20
border-scale-400
overflow-hidden
min-w-full
rounded-lg
flex flex-row gap-6 items-center
"
>
<img
className="w-[48px] lg:w-[64px]"
src="/docs/img/cards/tutorials-small.svg"
/>
</div>
<div className="col-span-4">
<ButtonCard
className="card"
to={'/guides/database'}
title={'Database'}
description={'A dedicated, scalable Postgres database.'}
style={{ height: '100%' }}
/>
</div>
<div className="col-span-4">
<ButtonCard
className="card"
to={'/guides/functions'}
title={'Edge Functions'}
description={'Server-side functions, distributed globally.'}
style={{ height: '100%' }}
/>
</div>
<div className="col-span-4">
<ButtonCard
className="card"
to={'/guides/realtime'}
title={'Realtime'}
description={'Build with Broadcast, Presence, and Postgres Changes.'}
style={{ height: '100%' }}
/>
</div>
<div className="col-span-4">
<ButtonCard
className="card"
to={'/guides/storage'}
title={'File Storage'}
description={'Store, organize, and serve large files.'}
style={{ height: '100%' }}
/>
</div>
<div className="col-span-4">
<ButtonCard
className="card"
to={'/guides/platform/logs'}
title={'Observability'}
description={'Monitor and debug your infrastucture.'}
style={{ height: '100%' }}
<img
className="z-0 absolute -left-32 -bottom-48 w-[320px]"
src="/docs/img/purple-glow-dark.png"
/>
<div className="
flex flex-col md:flex-row not-prose
h-full justify-center
md:items-center md:gap-3
">
<h2 className="text-sm lg:text-base text-scale-1200 m-0">Ready to make a fully working app?</h2>
<p className="text-sm lg:text-base text-scale-1100 m-0">Follow the step-by-step <Link href="/guides/tutorials"><a className="m-0 text-scale-1200 underline">tutorials</a></Link>.</p>
</div>
</div>
</div>
## Start with a framework
<div>
<div className="max-w-xl">
Supabase is just Postgres, which makes it compatible with a large number of tools and frameworks.
### Product Documentation
<Frameworks />
</div>
export const Page = ({ children }) => {
if (process.env.NEXT_PUBLIC_NEW_DOCS === 'true') {
return NewContent()
}
return <Layout meta={meta} children={children} />
}
<div className="grid grid-cols-12 gap-6 not-prose">
{products.map((product) => {
return (
<Link
href={`${product.href}`}
key={product.title}
passHref
>
<a className={product.span ?? 'col-span-12 md:col-span-4'}>
<GlassPanel {...product} background={true} showIconBg={true} showLink={true}>
{product.description}
</GlassPanel>
</a>
</Link>
)
})}
{platform.map((product) => {
return (
<Link
href={`/${product.href}`}
key={product.title}
passHref
>
<a className={'col-span-12 md:col-span-4'}>
<GlassPanel {...product} background={false} showIconBg={true}>
{product.description}
</GlassPanel>
</a>
</Link>
)
})}
</div>
</div>
<div>
<div className="max-w-xl">
### Reference Documentation
</div>
<div className="grid grid-cols-12 gap-6 not-prose">
{apis.map((product) => {
return (
<Link
href={`/${product.href}`}
key={product.title}
passHref
>
<a className={product.span ?? 'col-span-12 lg:col-span-4'}>
<GlassPanel {...product} background={false}>
{product.description}
</GlassPanel>
</a>
</Link>
)
})}
</div>
</div>
{/* end of container */}
</div>
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 }) => <Layout meta={meta} children={children} />
export default Page
-323
View File
@@ -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',
}
<h2 className="text-base max-w-xl m-0">
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.
</h2>
{/* start container */}
<div className="flex flex-col gap-12 my-12">
<div className="space-y-8 hidden">
<div className="
border border-scale-400
relative overflow-hidden
grid grid-cols-12
rounded-lg
px-8 md:px-12 py-5 md:py-12
">
<div className="col-span-12 lg:col-span-7 flex flex-col gap-6">
<img className="hidden lg:visible absolute right-0 top-0 w-[500px]" src="/docs/img/cards/dark.png" />
<div classNam="">
<h3 className="text-2xl m-0 mb-3">Getting Started</h3>
Discover how to set up a database to an app making queries in just a few minutes.
<div className="font-mono uppercase text-xs mb-2">What you will learn</div>
<div className="flex flex-col">
<div className="flex flex-row items-center gap-3">
<div className="text-brand-900">
<IconChevronRight size={14} strokeWidth={1.5} />
</div>
<span className="text-scale-1200">Setting up a Supabase project and app</span>
</div>
<div className="flex flex-row items-center gap-3">
<div className="text-brand-900">
<IconChevronRight size={14} strokeWidth={1.5} />
</div>
<span className="text-scale-1200">Adding some sample data to your project</span>
</div>
<div className="flex flex-row items-center gap-3">
<div className="text-brand-900">
<IconChevronRight size={14} strokeWidth={1.5} />
</div>
<span className="text-scale-1200">Select() from your new database table</span>
</div>
</div>
<div className="mt-6">
<div className="hidden">
<Button size="small">Get started</Button>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-3 md:gap-6">
<Link href={`/getting-started/quickstarts/reactjs`} passHref>
<a className="no-underline">
<IconPanel title="ReactJS" icon="/docs/img/icons/react-icon" />
</a>
</Link>
<Link href={`/getting-started/quickstarts/nextjs`} passHref>
<a className="no-underline">
<IconPanel title="NextJS" icon="/docs/img/icons/nextjs-icon" />
</a>
</Link>
</div>
</div>
</div>
</div>
</div>
<div
className="
border
relative
px-8 md:px-12 h-20
border-scale-400
overflow-hidden
min-w-full
rounded-lg
flex flex-row gap-6 items-center
"
>
<img
className="w-[48px] lg:w-[64px]"
src="/docs/img/cards/tutorials-small.svg"
/>
<img
className="z-0 absolute -left-32 -bottom-48 w-[320px]"
src="/docs/img/purple-glow-dark.png"
/>
<div className="
flex flex-col md:flex-row not-prose
h-full justify-center
md:items-center md:gap-3
">
<h2 className="text-sm lg:text-base text-scale-1200 m-0">Ready to make a fully working app?</h2>
<p className="text-sm lg:text-base text-scale-1100 m-0">Follow the step-by-step <Link href="/guides/tutorials"><a className="m-0 text-scale-1200 underline">tutorials</a></Link>.</p>
</div>
</div>
</div>
<div>
<div className="max-w-xl">
### Product Documentation
</div>
<div className="grid grid-cols-12 gap-6 not-prose">
{products.map((product) => {
return (
<Link
href={`${product.href}`}
key={product.title}
passHref
>
<a className={product.span ?? 'col-span-12 md:col-span-4'}>
<GlassPanel {...product} background={true} showIconBg={true} showLink={true}>
{product.description}
</GlassPanel>
</a>
</Link>
)
})}
{platform.map((product) => {
return (
<Link
href={`/${product.href}`}
key={product.title}
passHref
>
<a className={'col-span-12 md:col-span-4'}>
<GlassPanel {...product} background={false} showIconBg={true}>
{product.description}
</GlassPanel>
</a>
</Link>
)
})}
</div>
</div>
<div>
<div className="max-w-xl">
### Reference Documentation
</div>
<div className="grid grid-cols-12 gap-6 not-prose">
{apis.map((product) => {
return (
<Link
href={`/${product.href}`}
key={product.title}
passHref
>
<a className={product.span ?? 'col-span-12 lg:col-span-4'}>
<GlassPanel {...product} background={false}>
{product.description}
</GlassPanel>
</a>
</Link>
)
})}
</div>
</div>
{/* end of container */}
</div>
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 }) => <Layout meta={meta} children={children} />
export default Page
+7
View File
@@ -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"
}
]
+87 -31
View File
@@ -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 <string>
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 <string>
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 <string>
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 <string>
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 <string>
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 <string>
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 <strings>
description: CIDR to allow DB connections from.
default_value: '[]'
- id: project-ref
name: --project-ref <string>
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 <string>
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 <string>
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 <Function name> [flags]
subcommands: []
flags:
- id: import-map
name: --import-map <string>
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 <string>
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 <string>
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 <string>
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 <string>
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 <string>
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 <string>
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 <string>
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 <string>
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
+115 -44
View File
@@ -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"
}
]
+1 -1
View File
@@ -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
@@ -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<Props> = ({ user, canRemoveUser }) => {
const UserDropdown: FC<Props> = ({ user, canRemoveUser, canRemoveMFAFactors }) => {
const showDeleteFactorsDropdown = useFlag('mfaSso')
const PageState: any = useContext(PageContext)
const { ui } = useStore()
const [loading, setLoading] = useState<boolean>(false)
@@ -120,6 +122,33 @@ const UserDropdown: FC<Props> = ({ 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 (
<Dropdown
size="medium"
@@ -141,6 +170,38 @@ const UserDropdown: FC<Props> = ({ user, canRemoveUser }) => {
</Dropdown.Item>
) : null}
<Dropdown.Separator />
{showDeleteFactorsDropdown && (
<Tooltip.Root delayDuration={0}>
<Tooltip.Trigger className="w-full">
<Dropdown.Item
onClick={handleDeleteFactors}
icon={<IconShieldOff size="tiny" />}
disabled={!canRemoveMFAFactors}
>
Remove MFA factors
</Dropdown.Item>
</Tooltip.Trigger>
{/*
[Joshen] Deleting MFA factors should be different ABAC perms i think
need to double check with KM / anyone familiar with ABAC
*/}
{!canRemoveMFAFactors && (
<Tooltip.Content side="bottom">
<Tooltip.Arrow className="radix-tooltip-arrow" />
<div
className={[
'rounded bg-scale-100 py-1 px-2 leading-none shadow',
'border border-scale-200',
].join(' ')}
>
<span className="text-xs text-scale-1200">
You need additional permissions to remove a user's authentication factors.
</span>
</div>
</Tooltip.Content>
)}
</Tooltip.Root>
)}
<Tooltip.Root delayDuration={0}>
<Tooltip.Trigger className="w-full">
<Dropdown.Item
@@ -11,7 +11,13 @@ import { PermissionAction } from '@supabase/shared-types/out/constants'
const UsersList = ({}) => {
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 (
<Loading active={PageState.usersLoading}>
@@ -49,7 +55,12 @@ const UsersList = ({}) => {
)}
{PageState.users.length > 0 &&
PageState.users.map((x: any) => (
<UserListItem key={x.id} user={x} canRemoveUser={canRemoveUser} />
<UserListItem
key={x.id}
user={x}
canRemoveUser={canRemoveUser}
canRemoveMFAFactors={canRemoveMFAFactors}
/>
))}
<Table.tr>
<Table.td colSpan={7}>
@@ -11,9 +11,10 @@ import { User } from './Users.types'
interface Props {
user: User
canRemoveUser: boolean
canRemoveMFAFactors: boolean
}
const UserListItem: FC<Props> = ({ user, canRemoveUser }) => {
const UserListItem: FC<Props> = ({ 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<Props> = ({ user, canRemoveUser }) => {
</div>
</Table.td>
<Table.td className="text-right">
<UserDropdown user={user} canRemoveUser={canRemoveUser} />
<UserDropdown
user={user}
canRemoveUser={canRemoveUser}
canRemoveMFAFactors={canRemoveMFAFactors}
/>
</Table.td>
</Table.tr>
)
@@ -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 = () => {
</div> */}
</div>
{isWrappersEnabled ? (
{isLoadingExtensions ? (
<div className="border rounded border-scale-500 p-12 space-y-2">
<ShimmeringLoader />
<ShimmeringLoader className="w-3/4" />
<ShimmeringLoader className="w-1/2" />
</div>
) : isWrappersEnabled ? (
<div>
{WRAPPERS.map((wrapper, i) => {
return (
@@ -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)
@@ -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<Props> = ({ 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 (
<>
@@ -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<Props> = ({ 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"
/>
@@ -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"
/>
+2 -2
View File
@@ -1,5 +1,5 @@
const ShimmeringLoader = () => {
return <div className="shimmering-loader rounded py-3 mx-1" />
const ShimmeringLoader = ({ className = '' }) => {
return <div className={`shimmering-loader rounded py-3 mx-1 ${className}`} />
}
export default ShimmeringLoader
@@ -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) => {
+2 -1
View File
@@ -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(':', '')
+2 -1
View File
@@ -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<any> = observer(({}) => {
...data.autoApiService,
endpoint: IS_PLATFORM
? `https://${data?.autoApiService?.endpoint}`
: data.autoApiService.endpoint,
: `${PROJECT_ENDPOINT_PROTOCOL}://${data.autoApiService.endpoint}`,
}
const { query } = router
@@ -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 (
<div className="1xl:px-28 mx-auto flex flex-col px-5 py-6 lg:px-16 xl:px-24 2xl:px-32 ">
<FormHeader title="Vault" description="Application level encryption for your project" />
{!isEnabled ? (
{isLoading ? (
<div className="border rounded border-scale-500 p-12 space-y-2">
<ShimmeringLoader />
<ShimmeringLoader className="w-3/4" />
<ShimmeringLoader className="w-1/2" />
</div>
) : !isEnabled ? (
<VaultToggle />
) : (
<Tabs
+6 -3
View File
@@ -10,7 +10,8 @@ import Divider from 'components/ui/Divider'
import { Dictionary } from 'components/grid'
import { useStore, withAuth } from 'hooks'
import { API_URL } from 'lib/constants'
import { API_URL, IS_PLATFORM } from 'lib/constants'
import { PROJECT_ENDPOINT_PROTOCOL } from 'pages/api/constants'
import { get } from 'lib/common/fetch'
import {
VERCEL_INTEGRATION_CONFIGS,
@@ -280,7 +281,7 @@ const IntegrationProject: FC = observer(() => {
</Select>
</div>
<div
className="w-full rounded-sm border border-border-secondary-light
className="w-full rounded-sm border border-border-secondary-light
bg-panel-header-light dark:border-border-secondary-dark dark:bg-panel-header-dark"
>
<div className="flex items-center justify-between p-6">
@@ -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,
})