Merge branch 'master' into docs/move-self-hosting

This commit is contained in:
Jonathan Summers-Muir committed 2022-12-20 11:09:32 +08:00
commit 42dfc32d49
52 files changed
+701 -1314

No files matched your search

+1 -1
View File
@@ -142,7 +142,7 @@ Our approach for client libraries is modular. Each sub-library is a standalone i
<td>-</td>
<td><a href="https://github.com/supabase-community/gotrue-java" target="_blank" rel="noopener noreferrer">gotrue-java</a></td>
<td>-</td>
<td>-</td>
<td><a href="https://github.com/supabase-community/storage-java" target="_blanke" rel="noopener noreferrer">storage-java</a></td>
<td>-</td>
</tr>
<tr>
@@ -1,45 +0,0 @@
import { useTheme } from 'common/Providers'
import { IconSun, IconMoon } from '@supabase/ui'
function DarkModeToggle() {
const { isDarkMode, toggleTheme } = useTheme()
const toggleDarkMode = () => {
localStorage.setItem('supabaseDarkMode', (!isDarkMode).toString())
toggleTheme()
const key = localStorage.getItem('supabaseDarkMode')
document.documentElement.className = key === 'true' ? 'dark' : ''
}
return (
<div className="flex items-center">
<IconSun className="text-scale-900" strokeWidth={2} />
<button
type="button"
aria-pressed="false"
className={`
relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent
transition-colors duration-200 ease-in-out focus:outline-none ${
isDarkMode ? 'bg-scale-500' : 'bg-scale-900'
} mx-5
`}
onClick={() => toggleDarkMode()}
>
<span className="sr-only">Toggle Themes</span>
<span
aria-hidden="true"
className={`
${
isDarkMode ? 'translate-x-5' : 'translate-x-0'
} dark:bg-scale-300 inline-block h-5 w-5
transform rounded-full bg-white shadow-lg ring-0 transition duration-200 ease-in-out
`}
/>
</button>
<IconMoon className="text-scale-900" strokeWidth={2} />
</div>
)
}
export default DarkModeToggle
-133
View File
@@ -1,133 +0,0 @@
import { Badge } from 'ui'
import Link from 'next/link'
import Image from 'next/image'
import FooterLinks from 'data/footer.json'
import DarkModeToggle from './DarkModeToggle'
import { useTheme } from 'common/Providers'
import * as supabaseLogoWordmarkDark from 'common/assets/images/supabase-logo-wordmark--dark.png'
import * as supabaseLogoWordmarkLight from 'common/assets/images/supabase-logo-wordmark--light.png'
const Footer = () => {
const { isDarkMode } = useTheme()
return (
<footer
className="border-scale-500 dark:border-scale-600 border-t"
aria-labelledby="footerHeading"
>
<h2 id="footerHeading" className="sr-only">
Footer
</h2>
<div className="sm:py-18 container relative mx-auto px-6 py-16 md:py-24 lg:px-16 lg:py-24 xl:px-20">
<div className="xl:grid xl:grid-cols-3 xl:gap-8">
<div className="space-y-8 xl:col-span-1">
<Link href="#" as="/">
<a className="w-40">
<Image
src={isDarkMode ? supabaseLogoWordmarkDark : supabaseLogoWordmarkLight}
width={160}
height={30}
alt="Supabase"
/>
</a>
</Link>
<div className="flex space-x-5">
<a
href="https://twitter.com/supabase"
className="text-scale-900 hover:text-scale-1200 transition"
>
<span className="sr-only">Twitter</span>
<svg className="h-6 w-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path d="M8.29 20.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0022 5.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-6.993 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.072 4.072 0 012.8 9.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 012 18.407a11.616 11.616 0 006.29 1.84" />
</svg>
</a>
<a
href="https://github.com/supabase"
className="text-scale-900 hover:text-scale-1200 transition"
>
<span className="sr-only">GitHub</span>
<svg className="h-6 w-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path
fillRule="evenodd"
d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"
clipRule="evenodd"
/>
</svg>
</a>
<a
href="https://discord.supabase.com/"
className="text-scale-900 hover:text-scale-1200 transition"
>
<span className="sr-only">Discord</span>
<svg className="h-6 w-6" fill="currentColor" viewBox="0 0 71 55" aria-hidden="true">
<path
fillRule="evenodd"
d="M60.1045 4.8978C55.5792 2.8214 50.7265 1.2916 45.6527 0.41542C45.5603 0.39851 45.468 0.440769 45.4204 0.525289C44.7963 1.6353 44.105 3.0834 43.6209 4.2216C38.1637 3.4046 32.7345 3.4046 27.3892 4.2216C26.905 3.0581 26.1886 1.6353 25.5617 0.525289C25.5141 0.443589 25.4218 0.40133 25.3294 0.41542C20.2584 1.2888 15.4057 2.8186 10.8776 4.8978C10.8384 4.9147 10.8048 4.9429 10.7825 4.9795C1.57795 18.7309 -0.943561 32.1443 0.293408 45.3914C0.299005 45.4562 0.335386 45.5182 0.385761 45.5576C6.45866 50.0174 12.3413 52.7249 18.1147 54.5195C18.2071 54.5477 18.305 54.5139 18.3638 54.4378C19.7295 52.5728 20.9469 50.6063 21.9907 48.5383C22.0523 48.4172 21.9935 48.2735 21.8676 48.2256C19.9366 47.4931 18.0979 46.6 16.3292 45.5858C16.1893 45.5041 16.1781 45.304 16.3068 45.2082C16.679 44.9293 17.0513 44.6391 17.4067 44.3461C17.471 44.2926 17.5606 44.2813 17.6362 44.3151C29.2558 49.6202 41.8354 49.6202 53.3179 44.3151C53.3935 44.2785 53.4831 44.2898 53.5502 44.3433C53.9057 44.6363 54.2779 44.9293 54.6529 45.2082C54.7816 45.304 54.7732 45.5041 54.6333 45.5858C52.8646 46.6197 51.0259 47.4931 49.0921 48.2228C48.9662 48.2707 48.9102 48.4172 48.9718 48.5383C50.038 50.6034 51.2554 52.5699 52.5959 54.435C52.6519 54.5139 52.7526 54.5477 52.845 54.5195C58.6464 52.7249 64.529 50.0174 70.6019 45.5576C70.6551 45.5182 70.6887 45.459 70.6943 45.3942C72.1747 30.0791 68.2147 16.7757 60.1968 4.9823C60.1772 4.9429 60.1437 4.9147 60.1045 4.8978ZM23.7259 37.3253C20.2276 37.3253 17.3451 34.1136 17.3451 30.1693C17.3451 26.225 20.1717 23.0133 23.7259 23.0133C27.308 23.0133 30.1626 26.2532 30.1066 30.1693C30.1066 34.1136 27.28 37.3253 23.7259 37.3253ZM47.3178 37.3253C43.8196 37.3253 40.9371 34.1136 40.9371 30.1693C40.9371 26.225 43.7636 23.0133 47.3178 23.0133C50.9 23.0133 53.7545 26.2532 53.6986 30.1693C53.6986 34.1136 50.9 37.3253 47.3178 37.3253Z"
clipRule="evenodd"
/>
</svg>
</a>
<a
href="https://youtube.com/c/supabase"
className="text-scale-900 hover:text-scale-1200 transition"
>
<span className="sr-only">Youtube</span>
<svg
className="h-6 w-6"
fill="currentColor"
viewBox="0 0 576 512"
aria-hidden="true"
>
<path d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z" />
</svg>
</a>
</div>
</div>
<div className="mt-12 grid grid-cols-1 gap-8 xl:col-span-2 xl:mt-0">
<div className="grid grid-cols-2 gap-8 md:grid-cols-4">
{FooterLinks.map((segment: any) => {
return (
<div key={`footer_${segment.title}`}>
<h6 className="text-scale-1200 overwrite text-base">{segment.title}</h6>
<ul className="mt-4 space-y-2">
{segment.links.map((link: any, idx: number) => (
<li key={`${segment.title}_link_${idx}`}>
<a
href={link.url}
className={`text-sm transition-colors ${
link.url
? 'text-scale-1100 hover:text-scale-1200 '
: 'text-scale-900 hover:text-scale-900'
} `}
>
{link.text}
{!link.url && (
<div className="ml-2 inline text-xs xl:ml-0 xl:block 2xl:ml-2 2xl:inline">
<Badge color="scale" size="small">
Coming soon
</Badge>
</div>
)}
</a>
</li>
))}
</ul>
</div>
)
})}
</div>
</div>
</div>
<div className="border-scale-500 dark:border-scale-600 mt-32 flex justify-between border-t pt-8">
<small className="small">&copy; Supabase Inc</small>
<DarkModeToggle />
</div>
</div>
</footer>
)
}
export default Footer
+8 -6
View File
@@ -1,11 +1,13 @@
const FooterHelpCallout = () => {
return (
<div className="min-w-full px-8 py-6 prose bg-scale-300 dark:bg-whiteA-200 rounded">
<h5 className="text-sm m-0 text-scale-1100">Need some help?</h5>
<p className="m-0 text-sm text-scale-900">
Not to worry, our specialist engineers are here to help. Submit a support ticket through the{' '}
<a href="https://app.supabase.com/support/new">Dashboard</a>.
</p>
<div className="mt-32">
<div className="min-w-full px-8 py-6 prose bg-scale-300 dark:bg-whiteA-200 rounded">
<h5 className="text-sm m-0 text-scale-1100">Need some help?</h5>
<p className="m-0 text-sm text-scale-900">
Not to worry, our specialist engineers are here to help. Submit a support ticket through
the <a href="https://app.supabase.com/support/new">Dashboard</a>.
</p>
</div>
</div>
)
}
@@ -0,0 +1,56 @@
import Image from 'next/image'
import Link from 'next/link'
import { Button, IconGitHub, IconTwitter } from '~/../../packages/ui'
import footerData from '~/data/footer.json'
import { useTheme } from 'common/Providers'
const Footer = () => {
const { isDarkMode } = useTheme()
return (
<div>
<hr className="border-scale-400 mt-8"></hr>
<div className="flex gap-4 items-center mt-6 justify-between">
<div className="flex flex-col lg:flex-row gap-3 ">
<span className="text-xs text-scale-900">Supabase 2022</span>
<span className="text-xs text-scale-900">—</span>
{footerData.map((item) => (
<Link href={item.url}>
<a className="text-xs text-scale-800 hover:underline">{item.title}</a>
</Link>
))}
</div>
<div className="flex items-center gap-2">
<Button
type="text"
as="a"
// @ts-ignore
href="https://twitter.com/supabase"
target="_blank"
rel="noreferrer noopener"
>
<IconTwitter size={16} />
</Button>
<Button
type="text"
as="a"
// @ts-ignore
href="https://discord.supabase.com/"
target="_blank"
rel="noreferrer noopener"
>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="16">
<path
fill="none"
fill-rule="nonzero"
stroke={`${isDarkMode ? '#fff' : '#333'}`}
d="M16.238 2.16a14.628 14.628 0 0 0-3.664-1.159.055.055 0 0 0-.059.028c-.158.288-.333.662-.456.957a13.432 13.432 0 0 0-4.115 0 9.76 9.76 0 0 0-.464-.957.057.057 0 0 0-.058-.028 14.587 14.587 0 0 0-3.664 1.16.053.053 0 0 0-.024.02C1.4 5.74.76 9.21 1.074 12.637c.002.017.011.033.024.043a14.813 14.813 0 0 0 4.494 2.318.058.058 0 0 0 .064-.02c.346-.483.654-.992.92-1.527a.059.059 0 0 0-.032-.08c-.49-.19-.956-.421-1.404-.684a.06.06 0 0 1-.006-.097c.094-.072.189-.148.279-.223a.055.055 0 0 1 .058-.008c2.946 1.372 6.135 1.372 9.046 0a.055.055 0 0 1 .06.007 7.2 7.2 0 0 0 .279.224.06.06 0 0 1-.005.097 9.143 9.143 0 0 1-1.405.683.06.06 0 0 0-.03.081c.27.534.578 1.043.918 1.526.014.02.04.029.063.021A14.763 14.763 0 0 0 18.9 12.68a.06.06 0 0 0 .023-.042c.376-3.962-.628-7.404-2.66-10.455a.046.046 0 0 0-.024-.021Zm-9.223 8.39c-.887 0-1.618-.831-1.618-1.852 0-1.02.717-1.851 1.618-1.851.908 0 1.632.838 1.618 1.851 0 1.02-.717 1.851-1.618 1.851Zm5.981 0c-.887 0-1.618-.831-1.618-1.852 0-1.02.717-1.851 1.618-1.851.908 0 1.632.838 1.618 1.851 0 1.02-.71 1.851-1.618 1.851Z"
/>
</svg>
</Button>
</div>
</div>
</div>
)
}
export default Footer
@@ -2,19 +2,7 @@ import Image from 'next/image'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { FC, useEffect, useState } from 'react'
import {
Badge,
Button,
Dropdown,
IconCommand,
IconMenu,
IconMessageSquare,
IconMoon,
IconSearch,
IconSun,
Input,
Listbox,
} from 'ui'
import { Button, IconCommand, IconGitHub, IconMoon, IconSearch, IconSun } from 'ui'
import { SearchButton } from '~/components/DocSearch'
import { REFERENCES } from '~/components/Navigation/Navigation.constants'
import { useTheme } from 'common/Providers'
@@ -134,7 +122,7 @@ const TopNavBarRef: FC = () => {
target="_blank"
rel="noreferrer noopener"
>
Main site
Supabase.com
</Button>
<Button
type="text"
@@ -146,6 +134,18 @@ const TopNavBarRef: FC = () => {
>
Dashboard
</Button>
<ul className="flex items-center">
<Button
type="text"
as="a"
// @ts-ignore
href="https://github.com/supabase/supabase"
target="_blank"
rel="noreferrer noopener"
>
<IconGitHub size={16} />
</Button>
</ul>
<ul className="flex items-center">
<li className="px-4">
<div className="cursor-pointer" onClick={toggleDarkMode}>
+5
View File
@@ -27,6 +27,9 @@ import RefHeaderSection from './reference/RefHeaderSection'
// Ref version specific
import CliGlobalFlagsHandler from '~/components/reference/enrichments/cli/CliGlobalFlagsHandler'
import Options from '~/components/Options'
import Param from '~/components/Params'
const components = {
Admonition,
Button,
@@ -68,6 +71,8 @@ const components = {
code: (props: any) => <CodeBlock {...props} />,
RefHeaderSection: (props: any) => <RefHeaderSection {...props} />,
CliGlobalFlagsHandler: () => <CliGlobalFlagsHandler />,
Options,
Param,
}
export default components
+25
View File
@@ -0,0 +1,25 @@
import { NextSeo } from 'next-seo'
import { useRouter } from 'next/router'
function RefSEO({ title }) {
const router = useRouter()
const path = router.asPath.replace('crawlers/', '')
return (
<NextSeo
title={title}
openGraph={{
title,
url: `https://supabase.com/docs${path}`,
images: [
{
url: `https://supabase.com/docs/img/supabase-og-image.png`,
},
],
}}
/>
)
}
export default RefSEO
@@ -5,7 +5,7 @@ import { useEffect } from 'react'
import components from '~/components'
import RefEducationSection from '~/components/reference/RefEducationSection'
import RefFunctionSection from '~/components/reference/RefFunctionSection'
import OldLayout from '~/layouts/Default'
import RefSubLayout from '~/layouts/ref/RefSubLayout'
import ApiOperationSection from './ApiOperationSection'
import CliCommandSection from './CLICommandSection'
@@ -34,18 +34,6 @@ const RefSectionHandler = (props) => {
}
})
/*
* handle old ref pages
*/
if (!isNewDocs) {
return (
// @ts-ignore
<OldLayout meta={props.pageProps.meta} toc={props.pageProps.toc}>
<MDXRemote {...props.pageProps.content} components={components} />
</OldLayout>
)
}
return (
<RefSubLayout>
{props.sections.map((x) => {
+6 -146
View File
@@ -1,150 +1,10 @@
[
{ "title": "Contributing", "url": "/handbook/contributing" },
{ "title": "Changelog", "url": "https://supabase.com/changelog" },
{
"title": "Product",
"links": [
{
"text": "Database",
"url": "/database"
},
{
"text": "Auth",
"url": "/auth"
},
{
"text": "Functions",
"url": "/edge-functions"
},
{
"text": "Realtime",
"url": "/realtime"
},
{
"text": "Storage",
"url": "/storage"
},
{
"text": "Pricing",
"url": "/pricing"
},
{
"text": "Beta",
"url": "/beta"
}
]
"title": "Author Styleguide",
"url": "https://github.com/supabase/supabase/blob/master/DEVELOPERS.md"
},
{
"title": "Resources",
"links": [
{
"text": "Support",
"url": "/support"
},
{
"text": "System Status",
"url": "https://status.supabase.com/"
},
{
"text": "Integrations",
"url": "/partners/integrations"
},
{
"text": "Experts",
"url": "/partners/experts"
},
{
"text": "Brand Assets / Logos",
"url": "/brand-assets"
},
{
"text": "DPA",
"url": "/legal/dpa"
},
{
"text": "SOC2",
"url": "/legal/soc2"
}
]
},
{
"title": "Developers",
"links": [
{
"text": "Documentation",
"url": "/docs"
},
{
"text": "API Reference",
"url": "/docs/reference"
},
{
"text": "Changelog",
"url": "/changelog"
},
{
"text": "Contributing",
"url": "/docs/handbook/contributing"
},
{
"text": "Open Source",
"url": "/docs/oss"
},
{
"text": "SupaSquad",
"url": "/supasquad"
},
{
"text": "DevTo",
"url": "https://dev.to/supabase"
},
{
"text": "RSS",
"url": "/rss.xml"
}
]
},
{
"title": "Company",
"links": [
{
"text": "Blog",
"url": "/blog"
},
{
"text": "Careers",
"url": "https://about.supabase.com/careers"
},
{
"text": "Company",
"url": "/company"
},
{
"text": "Terms of Service",
"url": "/docs/company/terms"
},
{
"text": "Privacy Policy",
"url": "/docs/company/privacy"
},
{
"text": "Acceptable Use Policy",
"url": "/docs/company/aup"
},
{
"text": "Service Level Agreement",
"url": "/docs/company/sla"
},
{
"text": "Humans.txt",
"url": "/humans.txt"
},
{
"text": "Lawyers.txt",
"url": "/lawyers.txt"
},
{
"text": "Security.txt",
"url": "/.well-known/security.txt"
}
]
}
{ "title": "Open Source", "url": "https://supabase.com/docs/oss" },
{ "title": "SupaSquad", "url": "https://supabase.com/supasquad" }
]
-94
View File
@@ -1,94 +0,0 @@
import { useEffect, FC } from 'react'
import { NextSeo } from 'next-seo'
import NavBar from '../components/Navigation/NavBar'
import SideBar from '../components/Navigation/SideBar'
import Footer from '../components/Footer'
import TableOfContents from '~/components/TableOfContents'
import { menuItems } from '~/components/Navigation/Navigation.constants'
import { useRouter } from 'next/router'
import { getPageType } from '~/lib/helpers'
interface Props {
meta: { title: string; description?: string; hide_table_of_contents?: boolean }
children: any
toc?: any
menuItems?: any
currentPage?: string
}
const Layout: FC<Props> = ({ meta, children, toc }) => {
const { asPath } = useRouter()
useEffect(() => {
const key = localStorage.getItem('supabaseDarkMode')
if (!key) {
// Default to dark mode if no preference config
document.documentElement.className = 'dark'
} else {
document.documentElement.className = key === 'true' ? 'dark' : ''
}
}, [])
const hasTableOfContents =
toc !== undefined && toc.json.filter((item) => item.lvl !== 1 && item.lvl <= 3).length > 0
const pageType = getPageType(asPath)
console.log('Default, pageType', pageType)
return (
<>
<NextSeo
title={`${meta?.title} | Supabase`}
description={meta?.description ? meta?.description : meta?.title}
openGraph={{
title: meta?.title,
description: meta?.description,
url: `https://supabase.com/docs/${asPath}`,
images: [
{
url: `https://supabase.com/docs/img/supabase-og-image.png`,
},
],
}}
/>
<main>
<NavBar />
<div className="flex w-full flex-row">
<SideBar menuItems={menuItems[pageType]} />
<div className="main-content-pane docs-width grid md:grid-cols-12 gap-4 justify-between p-4 pb-8 w-full">
<div
className={`${
meta?.hide_table_of_contents || !hasTableOfContents
? 'col-span-12 xl:col-start-2 xl:col-span-10 2xl:col-start-3 2xl:col-span-8'
: 'col-span-12 lg:col-span-9'
} py-2 lg:py-4 px-2 lg:px-8 mx-auto`}
>
<article
className={`${
meta?.hide_table_of_contents || !hasTableOfContents ? 'xl:min-w-[880px]' : ''
} doc-content-container prose dark:prose-dark dark:bg-scale-200 width-full mt-8 2xl:max-w-[880px]`}
>
{children}
</article>
</div>
{hasTableOfContents && !meta?.hide_table_of_contents && (
<div
className={[
'border-scale-400 dark:bg-scale-200 table-of-contents-height border-l',
'thin-scrollbar overflow-y-auto sticky hidden xl:block md:col-span-3 px-2',
].join(' ')}
>
<TableOfContents toc={toc} />
</div>
)}
</div>
</div>
<Footer />
</main>
</>
)
}
export default Layout
+5 -27
View File
@@ -9,8 +9,9 @@ import FooterHelpCallout from '~/components/FooterHelpCallout'
import { menuState, useMenuLevelId, useMenuMobileOpen } from '~/hooks/useMenuState'
import { useEffect } from 'react'
import Footer from '~/components/Navigation/Footer'
const SiteRefLayout = ({ children }) => {
const SiteLayout = ({ children }) => {
const { isDarkMode } = useTheme()
useEffect(() => {
@@ -274,31 +275,8 @@ const SiteRefLayout = ({ children }) => {
</div>
<div className="grow px-5 max-w-7xl mx-auto py-16">
{children}
<div className="mt-32">
<FooterHelpCallout />
</div>
<hr className="border-scale-400 mt-8"></hr>
<div className="flex flex-col lg:flex-row gap-3 mt-6">
<span className="text-xs text-scale-900">Supabase 2022</span>
<span className="text-xs text-scale-900">—</span>
<Link href="/handbook/contributing">
<a className="text-xs text-scale-800 hover:underline">Contributing</a>
</Link>
<Link href="https://supabase.com/changelog">
<a className="text-xs text-scale-800 hover:underline">Changelog</a>
</Link>
<Link href="https://github.com/supabase/supabase/blob/master/DEVELOPERS.md">
<a className="text-xs text-scale-800 hover:underline">Author Styleguide</a>
</Link>
<Link href="https://supabase.com/docs/oss">
<a className="text-xs text-scale-800 hover:underline">Open Source</a>
</Link>
<Link href="https://supabase.com/supasquad">
<a className="text-xs text-scale-800 hover:underline">SupaSquad</a>
</Link>
</div>
<FooterHelpCallout />
<Footer />
</div>
<div
@@ -321,4 +299,4 @@ const SiteRefLayout = ({ children }) => {
)
}
export default SiteRefLayout
export default SiteLayout
-321
View File
@@ -1,321 +0,0 @@
import { useTheme } from 'common/Providers'
import Image from 'next/image'
import Link from 'next/link'
import { useRouter } from 'next/router'
import NavigationMenu from '~/components/Navigation/NavigationMenu/NavigationMenu'
import TopNavBarRef from '~/components/Navigation/NavigationMenu/TopNavBarRef'
import FooterHelpCallout from '~/components/FooterHelpCallout'
import { menuState } from '~/hooks/useMenuState'
import { useEffect } from 'react'
const SiteRefLayout = ({ children }) => {
const { isDarkMode } = useTheme()
useEffect(() => {
const key = localStorage.getItem('supabaseDarkMode')
if (!key) {
// Default to dark mode if no preference config
document.documentElement.className = 'dark'
} else {
document.documentElement.className = key === 'true' ? 'dark' : ''
}
}, [])
const menuLevel = 'home'
// useMenuLevelId()
const mobileMenuOpen = false
const levelsData = {
home: {
icon: '/docs/img/icons/menu/home',
name: 'Home',
},
gettingstarted: {
icon: '/docs/img/icons/menu/getting-started',
name: 'Getting Started',
},
database: {
icon: '/docs/img/icons/menu/database',
name: 'Database',
},
auth: {
icon: '/docs/img/icons/menu/auth',
name: 'Auth',
},
functions: {
icon: '/docs/img/icons/menu/functions',
name: 'Functions',
},
realtime: {
icon: '/docs/img/icons/menu/realtime',
name: 'Realtime',
},
storage: {
icon: '/docs/img/icons/menu/storage',
name: 'Storage',
},
platform: {
icon: '/docs/img/icons/menu/platform',
name: 'Platform',
},
resources: {
icon: '/docs/img/icons/menu/resources',
name: 'Resources',
},
integrations: {
icon: '/docs/img/icons/menu/integrations',
name: 'Integrations',
},
reference_javascript_v1: {
icon: '/docs/img/icons/menu/reference-javascript',
name: 'Javascript Reference v1.0',
},
reference_javascript_v2: {
icon: '/docs/img/icons/menu/reference-javascript',
name: 'Javascript Reference v2.0',
},
reference_dart_v0: {
icon: '/docs/img/icons/menu/reference-dart',
name: 'Dart Reference v0.0',
},
reference_dart_v1: {
icon: '/docs/img/icons/menu/reference-dart',
name: 'Dart Reference v0.0',
},
reference_cli: {
icon: '/docs/img/icons/menu/reference-cli',
name: 'CLI Reference',
},
reference_api: {
icon: '/docs/img/icons/menu/reference-api',
name: 'Management API Reference',
},
reference_self_hosting_auth: {
icon: '/docs/img/icons/menu/reference-auth',
name: 'Auth Server Reference',
},
reference_self_hosting_storage: {
icon: '/docs/img/icons/menu/reference-storage',
name: 'Storage Server Reference',
},
reference_self_hosting_realtime: {
icon: '/docs/img/icons/menu/reference-realtime',
name: 'Realtime Server Reference',
},
}
return (
<main>
{/* <img
src={`${router.basePath}/img/gradient-bg.png`}
className="absolute left-0 w-[520px] top-0 -z-1 pointer-events-none"
/> */}
<div className="flex flex-row h-screen">
<div
className={[
'hidden', // experiment hidden
'transition-all',
'top-0',
'relative',
'h-screen w-[420px]',
'z-10',
'lg:flex flex-col ml-0',
].join(' ')}
>
<div
className={[
'top-0',
'relative',
'w-auto',
'z-10',
'border-r overflow-auto h-screen',
'backdrop-blur backdrop-filter bg-white-1200 dark:bg-blackA-300',
'flex flex-col',
].join(' ')}
>
<div className="top-0 sticky z-10">
<div>
<div>
<div
className={[
'hidden md:flex md:height-auto',
'pt-8 bg-scale-200 flex-col gap-8',
].join(' ')}
>
<Link href="/">
<a className="px-10 flex items-center gap-2">
<Image
className="cursor-pointer"
src={isDarkMode ? '/docs/supabase-dark.svg' : '/docs/supabase-light.svg'}
width={96}
height={24}
alt="Supabase Logo"
/>
<span className="font-mono text-sm font-medium text-brand-900">DOCS</span>
</a>
</Link>
{/* {router.asPath.includes('/reference/') && <RefSwitcher />} */}
</div>
<div className="h-4 bg-scale-200 w-full"></div>
<div className="bg-gradient-to-b from-scale-200 to-transparent h-4 w-full"></div>
</div>
</div>
</div>
<div className={['pb-10 px-5 md:px-10 md:flex'].join(' ')}>
<NavigationMenu />
</div>
</div>
</div>
<div
// #docs-content-container is used by layout to scroll to top
id="docs-content-container"
className={[
'w-full h-screen transition-all ease-out',
mobileMenuOpen ? 'overflow-hidden' : 'overflow-auto',
].join(' ')}
>
<div className="flex flex-col relative">
{/* <NavigationMenu /> */}
<div className={['lg:sticky top-0 z-10 overflow-hidden'].join(' ')}>
<TopNavBarRef />
</div>
<div
className={[
'sticky transition-all top-0',
'z-10',
'backdrop-blur backdrop-filter bg-white-1200 dark:bg-blackA-300',
].join(' ')}
>
<div className={['lg:hidden', 'px-5 ', 'border-b z-10'].join(' ')}>
<div
className={[
'transition-all ease-out z-10',
'top-0',
mobileMenuOpen && 'absolute',
'flex items-center h-[40px]',
mobileMenuOpen ? 'gap-0' : 'gap-3',
].join(' ')}
>
<button
className={['mr-2', mobileMenuOpen && 'mt-0.5'].join(' ')}
onClick={() => menuState.setMenuMobileOpen(!mobileMenuOpen)}
>
<div
className={[
'space-y-1 group cursor-pointer relative',
mobileMenuOpen ? 'w-4 h-4' : 'w-4 h-[8px]',
].join(' ')}
>
<span
className={[
'transition-all ease-out block w-4 h-px bg-scale-900 group-hover:bg-scale-1200',
!mobileMenuOpen ? 'w-4' : 'absolute rotate-45 top-[6px]',
].join(' ')}
></span>
<span
className={[
'transition-all ease-out block h-px bg-scale-900 group-hover:bg-scale-1200',
!mobileMenuOpen
? 'w-3 group-hover:w-4'
: 'absolute w-4 -rotate-45 top-[2px]',
].join(' ')}
></span>
</div>
</button>
<div className={[].join(' ')}>
<img
src={
menuLevel
? levelsData[menuLevel].icon + '.svg'
: levelsData['home'].icon + '.svg'
}
className={[
'transition-all duration-200',
mobileMenuOpen ? 'invisible w-0 h-0' : 'w-4 h-4',
].join(' ')}
/>
</div>
<span
className={[
'transition-all duration-200',
'text-scale-1200',
mobileMenuOpen ? 'text-xs' : 'text-sm',
].join(' ')}
>
{mobileMenuOpen
? 'Close'
: menuLevel
? levelsData[menuLevel].name
: levelsData['home'].name}
</span>
</div>
<div
className={[
'transition-all ease-out duration-200',
'absolute left-0 right-0 h-screen',
'px-5 pl-5 py-16',
'top-[0px]',
'bg-scale-200',
mobileMenuOpen
? 'overflow-y-auto opacity-100 left-[0px] visible'
: 'left-[-40px] h-0 opacity-0 invisible',
].join(' ')}
>
<NavigationMenu />
</div>
</div>
</div>
<div className="grow px-5 max-w-7xl mx-auto py-16">
{children}
<div className="mt-32">
<FooterHelpCallout />
</div>
<hr className="border-scale-400 mt-8"></hr>
<div className="flex flex-col lg:flex-row gap-3 mt-6">
<span className="text-xs text-scale-900">Supabase 2022</span>
<span className="text-xs text-scale-900">—</span>
<Link href="/handbook/contributing">
<a className="text-xs text-scale-800 hover:underline">Contributing</a>
</Link>
<Link href="https://supabase.com/changelog">
<a className="text-xs text-scale-800 hover:underline">Changelog</a>
</Link>
<Link href="https://github.com/supabase/supabase/blob/master/DEVELOPERS.md">
<a className="text-xs text-scale-800 hover:underline">Author Styleguide</a>
</Link>
<Link href="https://supabase.com/docs/oss">
<a className="text-xs text-scale-800 hover:underline">Open Source</a>
</Link>
<Link href="https://supabase.com/supasquad">
<a className="text-xs text-scale-800 hover:underline">SupaSquad</a>
</Link>
</div>
</div>
<div
className={[
// 'top-0 left-0',
'hidden', // experiment hidden
'h-full',
'left-0',
'right-0',
'z-10',
'backdrop-blur-sm backdrop-filter bg-white-1200 dark:bg-blackA-600',
mobileMenuOpen ? 'absolute MOBILE-MENU-OPEN' : 'hidden h-0 MOBILE-MENU-CLOSED',
].join(' ')}
onClick={() => menuState.setMenuMobileOpen(!mobileMenuOpen)}
></div>
</div>
</div>
</div>
</main>
)
}
export default SiteRefLayout
+1 -1
View File
@@ -76,7 +76,7 @@ const Layout: FC<Props> = (props) => {
}}
/>
<div className={['grid grid-cols-12 relative'].join(' ')}>
<div className={['grid grid-cols-12 relative gap-4'].join(' ')}>
<div
className={[
'relative',
+23 -13
View File
@@ -4,6 +4,7 @@ import { highlightSelectedNavItem } from '~/components/CustomHTMLElements/Custom
import { useRouter } from 'next/router'
import { useNavigationMenuContext } from '~/components/Navigation/NavigationMenu/NavigationMenu.Context'
import { menuState } from '~/hooks/useMenuState'
import Image from 'next/image'
interface ISectionContainer {
id: string
@@ -77,8 +78,13 @@ const Section: FC<ISectionContainer> = (props) => {
const StickyHeader: FC<StickyHeader> = ({ icon, ...props }) => {
const router = useRouter()
const { setActiveRefItem } = useNavigationMenuContext()
// we're serving search bots a different file (/crawlers/[...slug])
// and need to modify content to suit that
const isCrawlerPage = router.route.includes('/crawlers/[...slug]')
const { ref } = useInView({
threshold: 1,
rootMargin: '30% 0% -35% 0px',
@@ -99,21 +105,25 @@ const StickyHeader: FC<StickyHeader> = ({ icon, ...props }) => {
<div className={['flex items-center gap-3 not-prose', icon && 'mb-8'].join(' ')}>
{icon && (
<div className="w-8 h-8 bg-brand-500 rounded flex items-center justify-center">
<img className="w-6 h-6" src={`${icon}.svg`} />
<Image width={16} height={16} alt={icon} src={`${icon}.svg`} />
</div>
)}
<h2
ref={ref}
id={props.slug}
data-ref-id={props.id}
className={[
'text-2xl font-medium text-scale-1200 scroll-mt-24',
!icon && 'mb-8',
props.monoFont && 'font-mono',
].join(' ')}
>
{props.title && <span className="max-w-xl">{props.title}</span>}
</h2>
{isCrawlerPage ? (
<h1>{props.title}</h1>
) : (
<h2
ref={ref}
id={props.slug}
data-ref-id={props.id}
className={[
'text-2xl font-medium text-scale-1200 scroll-mt-24',
!icon && 'mb-8',
props.monoFont && 'font-mono',
].join(' ')}
>
{props.title && <span className="max-w-xl">{props.title}</span>}
</h2>
)}
</div>
)
}
@@ -2,7 +2,6 @@ import { MDXProvider } from '@mdx-js/react'
import Head from 'next/head'
import { FC, useEffect, useState } from 'react'
import components from '~/components'
import Footer from '~/components/Footer'
import SideBar from '~/components/Navigation/SideBar'
import TableOfContents from '~/components/TableOfContents'
+2
View File
@@ -60,6 +60,8 @@ function recurseThroughParams(paramDefinition: any) {
children = dereferenced.children
} else if (dereferenced.type?.declaration?.children) {
children = dereferenced.type.declaration.children
} else if (dereferenced.type?.type === 'query') {
// skip: ignore types created from `typeof` for now, like `type Fetch = typeof fetch`
} else if (dereferenced.type?.type === 'union') {
// skip: we don't want to show unions as nested parameters
} else if (Object.keys(dereferenced).length === 0) {
-74
View File
@@ -1,74 +0,0 @@
import toc from 'markdown-toc'
import { MDXRemote } from 'next-mdx-remote'
import { serialize } from 'next-mdx-remote/serialize'
import components from '../components/index'
import NewLayout from '~/layouts/DefaultGuideLayout'
import Layout from '~/layouts/Default'
import { getAllDocs, getDocsBySlug } from '../lib/docs'
interface Meta {
id: string
title: string
sidebar_label: string
hide_table_of_contents: boolean
}
interface Props {
meta: Meta
content: any
toc: any
}
const isNewDocs = process.env.NEXT_PUBLIC_NEW_DOCS === 'true'
export default function Doc({ meta, content, toc }: Props) {
return (
// @ts-ignore
<>
{Object.entries(meta).length > 0 || !isNewDocs ? (
<Layout meta={meta} toc={toc}>
<MDXRemote {...content} components={components} />
</Layout>
) : (
<NewLayout meta={meta} toc={toc}>
<MDXRemote {...content} components={components} />
</NewLayout>
)}
</>
)
}
export async function getStaticProps({ params }: { params: { slug: string[] } }) {
let slug
if (params.slug.length > 1) {
slug = `docs/${params.slug.join('/')}`
} else {
slug = `docs/${params.slug[0]}`
}
let doc = getDocsBySlug(slug)
const content = await serialize(doc.content || '')
return {
props: {
...doc,
content,
toc: toc(doc.content, { maxdepth: 1, firsth1: false }),
},
}
}
export function getStaticPaths() {
let docs = getAllDocs()
return {
paths: docs.map(() => {
return {
params: {
slug: docs.map((d) => d.slug),
},
}
}),
fallback: 'blocking',
}
}
@@ -95,7 +95,7 @@ Create a new file at `/utils/supabase-browser.ts` and populate with the followin
```ts
import { createBrowserSupabaseClient } from '@supabase/auth-helpers-nextjs'
import { Database } from '../db_types'
import { Database } from '../lib/database.types'
export default createBrowserSupabaseClient<Database>()
```
@@ -109,7 +109,7 @@ Create a new file at `/utils/supabase-server.ts` and populate with the following
```ts title="/utils/supabase-server.ts"
import { headers, cookies } from 'next/headers'
import { createServerComponentSupabaseClient } from '@supabase/auth-helpers-nextjs'
import { Database } from '../db_types'
import { Database } from '../lib/database.types'
export default () =>
createServerComponentSupabaseClient<Database>({
@@ -139,6 +139,8 @@ Middleware runs before every route declared in the `matcher` array. Since we don
>
<TabPanel id="js" label="JavaScript">
Create a new file at `/pages/middleware.js` and populate with the following:
```jsx title="middleware.js"
import { createMiddlewareSupabaseClient } from '@supabase/auth-helpers-nextjs'
import { NextResponse } from 'next/server'
@@ -164,6 +166,8 @@ export const config = {
<TabPanel id="ts" label="TypeScript">
Create a new file at `/middleware.ts` (a sibling of /pages) and populate with the following:
```tsx title="middleware.ts"
import { createMiddlewareSupabaseClient } from '@supabase/auth-helpers-nextjs'
import { NextResponse } from 'next/server'
@@ -254,7 +258,7 @@ export default async function RootLayout({ children }) {
}
```
We don't want Next.js to cache this `session` value, so we need to export a `revalidate` value of `0`.
We don't want Next.js to cache this `session` value, so we need to export a `revalidate` value of `0` in the layout file.
```jsx
export const revalidate = 0
@@ -641,7 +645,7 @@ Create a new file at `/app/realtime/posts.tsx` and populate with the following:
'use client'
import { useEffect, useState } from 'react'
import { Database } from '../../db_types'
import { Database } from '../lib/database.types'
import supabase from '../../utils/supabase-browser'
type Post = Database['public']['Tables']['posts']['Row']
+1 -1
View File
@@ -38,7 +38,7 @@ export const meta = {
### Tutorials
<div className="grid grid-cols-12 gap-6 not-prose">
<div className="grid lg:grid-cols-12 gap-6 not-prose">
{webapps.map((item) => {
return (
<Link href={`/${item.href}`} key={item.title} passHref>
@@ -205,7 +205,7 @@ export class AuthComponent implements OnInit {
</div>
</form>
</div>
</div
</div>
```
### Account page
@@ -50,7 +50,9 @@ Add `io.supabase.flutterquickstart://login-callback/` as a new [redirect URL](ht
That is it on Supabase's end and the rest are platform specific settings:
For Android, add an intent-filter to enable deep linking:
For Android, edit the `android/app/src/main/AndroidManifest.xml` file.
Add an intent-filter to enable deep linking:
```xml title=android/app/src/main/AndroidManifest.xml
<manifest ...>
@@ -75,7 +77,9 @@ For Android, add an intent-filter to enable deep linking:
</manifest>
```
For iOS add CFBundleURLTypes to enable deep linking:
For iOS, edit the ios/Runner/Info.plist file.
Add CFBundleURLTypes to enable deep linking:
```xml title=ios/Runner/Info.plist"
<!-- ... other tags -->
@@ -37,7 +37,7 @@ Then let's install the only additional dependency: [supabase-js](https://github.
npm install @supabase/supabase-js
```
And finally we want to save the environment variables in a `.env`.
And finally we want to save the environment variables in a `.env.local` file.
All we need are the API URL and the `anon` key that you copied [earlier](#get-the-api-keys).
```bash title=.env
@@ -48,6 +48,8 @@ REACT_APP_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY
Now that we have the API credentials in place, let's create a helper file to initialize the Supabase client. These variables will be exposed
on the browser, and that's completely fine since we have [Row Level Security](/docs/guides/auth#row-level-security) enabled on our Database.
Create and edit `src/supabaseClient.js`:
```js title=src/supabaseClient.js
import { createClient } from '@supabase/supabase-js'
@@ -64,6 +66,8 @@ You can find the full contents of this file [here](https://raw.githubusercontent
Let's set up a React component to manage logins and sign ups. We'll use Magic Links, so users can sign in with their email without using passwords.
Create and edit `src/Auth.js`:
```jsx title=src/Auth.js
import { useState } from 'react'
import { supabase } from './supabaseClient'
@@ -120,7 +124,7 @@ export default function Auth() {
After a user is signed in we can allow them to edit their profile details and manage their account.
Let's create a new component for that called `Account.js`.
Let's create a new component for that called `src/Account.js`.
```jsx title=src/Account.js
import { useState, useEffect } from 'react'
@@ -234,7 +238,7 @@ export default Account
### Launch!
Now that we have all the components in place, let's update `App.js`:
Now that we have all the components in place, let's update `src/App.js`:
```jsx title=src/App.js
import './index.css'
@@ -282,6 +286,8 @@ Every Supabase project is configured with [Storage](/docs/guides/storage) for ma
Let's create an avatar for the user so that they can upload a profile photo. We can start by creating a new component:
Create and edit `src/Avatar.js`:
```jsx title=src/Avatar.js
import { useEffect, useState } from 'react'
import { supabase } from './supabaseClient'
@@ -367,7 +373,7 @@ export default function Avatar({ url, size, onUpload }) {
### Add the new widget
And then we can add the widget to the Account page:
And then we can add the widget to the Account page at `src/Account.js`:
```jsx title=src/Account.js
// Import the new component
@@ -376,7 +382,7 @@ import Avatar from './Avatar'
// ...
return (
<div className="form-widget">
<form onSubmit={updateProfile} className="form-widget">
{/* Add to the body */}
<Avatar
url={avatar_url}
@@ -1,84 +1,81 @@
import Layout from '~/layouts/DefaultGuideLayout'
import { IconCheck } from 'ui'
export const meta = {
title: 'Access Control',
description: 'Roles and permissions at the organization level',
}
Supabase provides granular access control features that let you manage permissions across your organizations.
Within a Supabase organization, a member can have one of the following roles:
Supabase provides granular access controls to manage permissions across your organizations.
For each organization, a member can have one of the following roles:
- Owner
- Administrator
- Developer
A default organization is created for a user when they first sign-in and
assigned the **Owner** role. If the user wants to invite others
to collaborate within the organization, they can visit the organization team
settings (`https://app.supabase.com/org/<org-slug>/settings#team`) to send an
invite link to another user's email. The invite expires after 24 hours.
Invites sent from a SSO account can only be accepted by another SSO account
coming from the same identity provider. This is a security measure that
prevents accidental invites to accounts not managed by your company's
enterprise systems.
Project level invites are not available at this time. A member of the
organization will be able to access all projects under the organization. If you
wish to restrict access to certain projects, please create another organization
to manage this.
A default organization is created when you first sign in and
you'll be assigned the **Owner** role.
Each member can access all projects under the organization.
Project level invites are not available at this time.
Create a separate organization if you need to restrict access to certain projects.
## Manage team members
You can invite your team members into your organizations to collaborate on projects.
To invite others to collaborate, visit your organization's team settings in the
[Dashboard](https://app.supabase.com/projects) to send an invite link to
another user's email. The invite expires after 24 hours.
<video width="99%" muted playsInline controls="true">
<source src="/docs/videos/invite-team.mp4" type="video/mp4" muted playsInline />
</video>
### Transferring ownership of an organization
Each Supabase organization can have one or more owners. If you no longer want be an owner of an organization, click **Leave team** in the members view (`https://app.supabase.com/org/<org-slug>/settings#team`) of your organization.
However, you can only leave an organization when there is _at least one other owner_.
If you are transferring ownership of your organization to someone else, you will need to invite the new member with the **Owner** role. You can leave the organization after they've accepted the invitation.
### Permissions across roles [#permission-across-roles]
The table below shows the corresponding permissions for each available role you can assign a team member in the Dashboard.
| Permissions | Owner | Administrator | Developer |
| ------------------------ | ----- | ------------- | --------- |
| Permissions | Owner | Administrator | Developer |
| ------------------------ | ----------------------- | ----------------------- | ----------------------- |
| **Organization** |
| Change organization name | ✅ | | |
| Delete organization | ✅ | | |
| Change organization name | <IconCheck size={14} /> | | |
| Delete organization | <IconCheck size={14} /> | | |
| **Members** |
| Add an Owner | ✅ | | |
| Remove an Owner | ✅ | | |
| Add an Administrator | ✅ | ✅ | |
| Remove an Administrator | ✅ | ✅ | |
| Add a Developer | ✅ | ✅ | |
| Remove a Developer | ✅ | ✅ | |
| Revoke an invite | ✅ | ✅ | |
| Resend an invite | ✅ | ✅ | |
| Accept an invite[^1] | ✅ | ✅ | ✅ |
| Add an Owner | <IconCheck size={14} /> | | |
| Remove an Owner | <IconCheck size={14} /> | | |
| Add an Administrator | <IconCheck size={14} /> | <IconCheck size={14} /> | |
| Remove an Administrator | <IconCheck size={14} /> | <IconCheck size={14} /> | |
| Add a Developer | <IconCheck size={14} /> | <IconCheck size={14} /> | |
| Remove a Developer | <IconCheck size={14} /> | <IconCheck size={14} /> | |
| Revoke an invite | <IconCheck size={14} /> | <IconCheck size={14} /> | |
| Resend an invite | <IconCheck size={14} /> | <IconCheck size={14} /> | |
| Accept an invite[^1] | <IconCheck size={14} /> | <IconCheck size={14} /> | <IconCheck size={14} /> |
| **Billing** |
| Read invoices | ✅ | ✅ | ✅ |
| Read billing email | ✅ | ✅ | ✅ |
| Change billing email | ✅ | | |
| View subscription | ✅ | ✅ | ✅ |
| Update subscription | ✅ | ✅ | |
| Read billing address | ✅ | ✅ | ✅ |
| Update billing address | ✅ | ✅ | |
| Read tax codes | ✅ | ✅ | ✅ |
| Update tax codes | ✅ | ✅ | |
| Read payment methods | ✅ | ✅ | ✅ |
| Update payment methods | ✅ | ✅ | |
| Read invoices | <IconCheck size={14} /> | <IconCheck size={14} /> | <IconCheck size={14} /> |
| Read billing email | <IconCheck size={14} /> | <IconCheck size={14} /> | <IconCheck size={14} /> |
| Change billing email | <IconCheck size={14} /> | | |
| View subscription | <IconCheck size={14} /> | <IconCheck size={14} /> | <IconCheck size={14} /> |
| Update subscription | <IconCheck size={14} /> | <IconCheck size={14} /> | |
| Read billing address | <IconCheck size={14} /> | <IconCheck size={14} /> | <IconCheck size={14} /> |
| Update billing address | <IconCheck size={14} /> | <IconCheck size={14} /> | |
| Read tax codes | <IconCheck size={14} /> | <IconCheck size={14} /> | <IconCheck size={14} /> |
| Update tax codes | <IconCheck size={14} /> | <IconCheck size={14} /> | |
| Read payment methods | <IconCheck size={14} /> | <IconCheck size={14} /> | <IconCheck size={14} /> |
| Update payment methods | <IconCheck size={14} /> | <IconCheck size={14} /> | |
| **Projects** |
| Create a project | ✅ | ✅ | |
| Delete a project | ✅ | ✅ | |
| Update a project | ✅ | ✅ | |
| Pause a project | ✅ | ✅ | |
| Resume a project | ✅ | ✅ | |
| Restart a project | ✅ | ✅ | ✅ |
| Create a project | <IconCheck size={14} /> | <IconCheck size={14} /> | |
| Delete a project | <IconCheck size={14} /> | <IconCheck size={14} /> | |
| Update a project | <IconCheck size={14} /> | <IconCheck size={14} /> | |
| Pause a project | <IconCheck size={14} /> | <IconCheck size={14} /> | |
| Resume a project | <IconCheck size={14} /> | <IconCheck size={14} /> | |
| Restart a project | <IconCheck size={14} /> | <IconCheck size={14} /> | <IconCheck size={14} /> |
[^1]:
If the invite was sent from a SSO account, it can only be accepted from
a user signed in via the same identity provider.
Invites sent from a SSO account can only be accepted by another SSO account
coming from the same identity provider. This is a security measure that
prevents accidental invites to accounts not managed by your company's
enterprise systems.
export const Page = ({ children }) => <Layout meta={meta} children={children} />
@@ -143,7 +143,8 @@ As with the final activation stage of the process for setting up a vanity subdom
## Limitations
Edge functions do not honor the custom domain or the vanity subdomain setting and they still have to be invoked via the `foobarbaz.supabase.co` domain.
- Edge functions do not honor the custom domain or the vanity subdomain setting and they still have to be invoked via the `foobarbaz.supabase.co` domain.
- A Supabase project can—at this time—use either a Custom Domain or a Vanity Subdomain, but not both.
export const Page = ({ children }) => <Layout meta={meta} children={children} />
@@ -20,7 +20,7 @@ To get started:
1. [Install](/docs/guides/cli) the Supabase CLI 1.22.0+.
1. [Log in](/docs/guides/cli/local-development#log-in-to-the-supabase-cli) to your Supabase account using the CLI.
1. Ensure that you have [Owner or Admin permissions](/docs/guides/hosting/platform#manage-team-members) for the project that you are enabling network restrictions.
1. Ensure that you have [Owner or Admin permissions](/docs/guides/hosting/platform/access-control#manage-team-members) for the project that you are enabling network restrictions.
## Check restrictions
@@ -173,7 +173,7 @@ Use the seed script in `supabase/seed.sql` (created with [`supabase init`](/docs
-- in supabase/seed.sql
insert into public.employees (name)
values
('Erlich Backman'),
('Erlich Bachman'),
('Richard Hendricks'),
('Monica Hall');
```
@@ -40,11 +40,11 @@ Now visit [http://localhost:3000](http://localhost:3000) to start using Supabase
While we provided you with some example secrets for getting started, you should NEVER deploy your Supabase setup using the defaults we have provided.
Please follow these steps to secure your Docker setup. We [strongly recommend](../../guides/hosting/overview#managing-your-secrets) using a secrets manager when deploying to production.
Follow these steps to secure your Docker setup. We strongly recommend using a [secrets manager](../self-hosting#managing-your-secrets) when deploying to production.
### Generate API Keys
Use your `JWT_SECRET` to generate a `anon` and `service` API keys using the [JWT generator](../../guides/hosting/overview#api-keys).
Use your `JWT_SECRET` to generate a `anon` and `service` API keys using the [JWT generator](../self-hosting#api-keys).
Replace the values in these files:
@@ -70,7 +70,7 @@ The Docker setup doesn't include a management database for managing users and lo
## Configuration
Each system can be [configured](../../guides/hosting/overview#configuration) to suit your particular use-case.
Each system can be [configured](../self-hosting#configuration) to suit your particular use-case.
To keep the setup simple, we made some choices that may not be optimal for production:
@@ -80,7 +80,7 @@ To keep the setup simple, we made some choices that may not be optimal for produ
### Using an external database
We strongly [recommend](../../guides/hosting/overview#managing-your-database) that you decouple your database from `docker-compose` before deploying.
We strongly recommend [decoupling your database](../self-hosting#managing-your-database) from `docker-compose` before deploying.
The middleware will run with any PostgreSQL database that has logical replication enabled. The following environment variables should be updated
in the `.env` file to point to your external database:
@@ -7,6 +7,7 @@ import { flattenSections } from '~/lib/helpers'
import handleRefGetStaticPaths from '~/lib/mdx/handleRefStaticPaths'
import handleRefStaticProps from '~/lib/mdx/handleRefStaticProps'
import { useRouter } from 'next/router'
import RefSEO from '~/components/reference/RefSEO'
const sections = flattenSections(clientLibsCommonSections)
@@ -15,13 +16,21 @@ export default function JSReference(props) {
const slug = router.query.slug[0]
const filteredSection = sections.filter((section) => section.id === slug)
const pageTitle = filteredSection[0]?.title
? `${filteredSection[0]?.title} | Supabase`
: 'Supabase'
return (
<RefSectionHandler
sections={filteredSection}
spec={spec}
typeSpec={typeSpec}
pageProps={props}
/>
<>
<RefSEO title={pageTitle} />
<RefSectionHandler
sections={filteredSection}
spec={spec}
typeSpec={typeSpec}
pageProps={props}
/>
</>
)
}
@@ -7,6 +7,7 @@ import { flattenSections } from '~/lib/helpers'
import handleRefGetStaticPaths from '~/lib/mdx/handleRefStaticPaths'
import handleRefStaticProps from '~/lib/mdx/handleRefStaticProps'
import { useRouter } from 'next/router'
import RefSEO from '~/components/reference/RefSEO'
const sections = flattenSections(clientLibsCommonSections)
@@ -15,13 +16,20 @@ export default function JSReference(props) {
const slug = router.query.slug[0]
const filteredSection = sections.filter((section) => section.id === slug)
const pageTitle = filteredSection[0]?.title
? `${filteredSection[0]?.title} | Supabase`
: 'Supabase'
return (
<RefSectionHandler
sections={filteredSection}
spec={spec}
typeSpec={typeSpec}
pageProps={props}
/>
<>
<RefSEO title={pageTitle} />
<RefSectionHandler
sections={filteredSection}
spec={spec}
typeSpec={typeSpec}
pageProps={props}
/>
</>
)
}
@@ -7,6 +7,7 @@ import { flattenSections } from '~/lib/helpers'
import handleRefGetStaticPaths from '~/lib/mdx/handleRefStaticPaths'
import handleRefStaticProps from '~/lib/mdx/handleRefStaticProps'
import { useRouter } from 'next/router'
import RefSEO from '~/components/reference/RefSEO'
const sections = flattenSections(clientLibsCommonSections)
@@ -15,13 +16,21 @@ export default function JSReference(props) {
const slug = router.query.slug[0]
const filteredSection = sections.filter((section) => section.id === slug)
const pageTitle = filteredSection[0]?.title
? `${filteredSection[0]?.title} | Supabase`
: 'Supabase'
return (
<RefSectionHandler
sections={filteredSection}
spec={spec}
typeSpec={typeSpec}
pageProps={props}
/>
<>
<RefSEO title={pageTitle} />
<RefSectionHandler
sections={filteredSection}
spec={spec}
typeSpec={typeSpec}
pageProps={props}
/>
</>
)
}
@@ -7,7 +7,7 @@ import { flattenSections } from '~/lib/helpers'
import handleRefGetStaticPaths from '~/lib/mdx/handleRefStaticPaths'
import handleRefStaticProps from '~/lib/mdx/handleRefStaticProps'
import { useRouter } from 'next/router'
import RefSEO from '~/components/reference/RefSEO'
const sections = flattenSections(clientLibsCommonSections)
export default function JSReference(props) {
@@ -15,13 +15,21 @@ export default function JSReference(props) {
const slug = router.query.slug[0]
const filteredSection = sections.filter((section) => section.id === slug)
const pageTitle = filteredSection[0]?.title
? `${filteredSection[0]?.title} | Supabase`
: 'Supabase'
return (
<RefSectionHandler
sections={filteredSection}
spec={spec}
typeSpec={typeSpec}
pageProps={props}
/>
<>
<RefSEO title={pageTitle} />
<RefSectionHandler
sections={filteredSection}
spec={spec}
typeSpec={typeSpec}
pageProps={props}
/>
</>
)
}
+9 -10
View File
@@ -1,10 +1,9 @@
<svg width="71" height="55" viewBox="0 0 71 55" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path d="M60.1045 4.8978C55.5792 2.8214 50.7265 1.2916 45.6527 0.41542C45.5603 0.39851 45.468 0.440769 45.4204 0.525289C44.7963 1.6353 44.105 3.0834 43.6209 4.2216C38.1637 3.4046 32.7345 3.4046 27.3892 4.2216C26.905 3.0581 26.1886 1.6353 25.5617 0.525289C25.5141 0.443589 25.4218 0.40133 25.3294 0.41542C20.2584 1.2888 15.4057 2.8186 10.8776 4.8978C10.8384 4.9147 10.8048 4.9429 10.7825 4.9795C1.57795 18.7309 -0.943561 32.1443 0.293408 45.3914C0.299005 45.4562 0.335386 45.5182 0.385761 45.5576C6.45866 50.0174 12.3413 52.7249 18.1147 54.5195C18.2071 54.5477 18.305 54.5139 18.3638 54.4378C19.7295 52.5728 20.9469 50.6063 21.9907 48.5383C22.0523 48.4172 21.9935 48.2735 21.8676 48.2256C19.9366 47.4931 18.0979 46.6 16.3292 45.5858C16.1893 45.5041 16.1781 45.304 16.3068 45.2082C16.679 44.9293 17.0513 44.6391 17.4067 44.3461C17.471 44.2926 17.5606 44.2813 17.6362 44.3151C29.2558 49.6202 41.8354 49.6202 53.3179 44.3151C53.3935 44.2785 53.4831 44.2898 53.5502 44.3433C53.9057 44.6363 54.2779 44.9293 54.6529 45.2082C54.7816 45.304 54.7732 45.5041 54.6333 45.5858C52.8646 46.6197 51.0259 47.4931 49.0921 48.2228C48.9662 48.2707 48.9102 48.4172 48.9718 48.5383C50.038 50.6034 51.2554 52.5699 52.5959 54.435C52.6519 54.5139 52.7526 54.5477 52.845 54.5195C58.6464 52.7249 64.529 50.0174 70.6019 45.5576C70.6551 45.5182 70.6887 45.459 70.6943 45.3942C72.1747 30.0791 68.2147 16.7757 60.1968 4.9823C60.1772 4.9429 60.1437 4.9147 60.1045 4.8978ZM23.7259 37.3253C20.2276 37.3253 17.3451 34.1136 17.3451 30.1693C17.3451 26.225 20.1717 23.0133 23.7259 23.0133C27.308 23.0133 30.1626 26.2532 30.1066 30.1693C30.1066 34.1136 27.28 37.3253 23.7259 37.3253ZM47.3178 37.3253C43.8196 37.3253 40.9371 34.1136 40.9371 30.1693C40.9371 26.225 43.7636 23.0133 47.3178 23.0133C50.9 23.0133 53.7545 26.2532 53.6986 30.1693C53.6986 34.1136 50.9 37.3253 47.3178 37.3253Z" fill="#5865F2"/>
</g>
<defs>
<clipPath id="clip0">
<rect width="71" height="55" fill="white"/>
</clipPath>
</defs>
</svg>
<?xml version="1.0" encoding="UTF-8"?>
<svg width="75px" height="59px" viewBox="0 0 75 59" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>discord-icon</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="discord-icon" transform="translate(2.000000, 2.411745)" fill-rule="nonzero" stroke="#636262" stroke-width="3">
<path d="M60.1044999,4.48605546 C55.5791999,2.40965546 50.7264999,0.879855461 45.6526999,0.00367546142 C45.5602999,-0.0132345386 45.4679999,0.0290244614 45.4203999,0.113544461 C44.7962999,1.22355546 44.1049999,2.67165546 43.6208999,3.80985546 C38.1636999,2.99285546 32.7344999,2.99285546 27.3891999,3.80985546 C26.9049999,2.64635546 26.1885999,1.22355546 25.5616999,0.113544461 C25.5140999,0.0318444614 25.4217999,-0.0104145386 25.3293999,0.00367546142 C20.2583999,0.877055461 15.4056999,2.40685546 10.8775999,4.48605546 C10.8383999,4.50295546 10.8047999,4.53115546 10.7824999,4.56775546 C1.57794989,18.3191555 -0.94356111,31.7325555 0.29340789,44.9796555 C0.29900489,45.0444555 0.33538589,45.1064555 0.38576089,45.1458555 C6.45865989,49.6056555 12.3412999,52.3131555 18.1146999,54.1077555 C18.2070999,54.1359555 18.3049999,54.1021555 18.3637999,54.0260555 C19.7294999,52.1610555 20.9468999,50.1945555 21.9906999,48.1265555 C22.0522999,48.0054555 21.9934999,47.8617555 21.8675999,47.8138555 C19.9365999,47.0813555 18.0978999,46.1882555 16.3291999,45.1740555 C16.1892999,45.0923555 16.1780999,44.8922555 16.3067999,44.7964555 C16.6789999,44.5175555 17.0512999,44.2273555 17.4066999,43.9343555 C17.4709999,43.8808555 17.5605999,43.8695555 17.6361999,43.9033555 C29.2557999,49.2084555 41.8353999,49.2084555 53.3178999,43.9033555 C53.3934999,43.8667555 53.4830999,43.8780555 53.5501999,43.9315555 C53.9056999,44.2245555 54.2778999,44.5175555 54.6528999,44.7964555 C54.7815999,44.8922555 54.7731999,45.0923555 54.6332999,45.1740555 C52.8645999,46.2079555 51.0258999,47.0813555 49.0920999,47.8110555 C48.9661999,47.8589555 48.9101999,48.0054555 48.9717999,48.1265555 C50.0379999,50.1916555 51.2553999,52.1581555 52.5958999,54.0232555 C52.6518999,54.1021555 52.7525999,54.1359555 52.8449999,54.1077555 C58.6463999,52.3131555 64.5289999,49.6056555 70.6018999,45.1458555 C70.6550999,45.1064555 70.6886999,45.0472555 70.6942999,44.9824555 C72.1746999,29.6673555 68.2146999,16.3639555 60.1967999,4.57055546 C60.1771999,4.53115546 60.1436999,4.50295546 60.1044999,4.48605546 Z M23.7258999,36.9135555 C20.2275999,36.9135555 17.3450999,33.7018555 17.3450999,29.7575555 C17.3450999,25.8132555 20.1716999,22.6015555 23.7258999,22.6015555 C27.3079999,22.6015555 30.1625999,25.8414555 30.1065999,29.7575555 C30.1065999,33.7018555 27.2799999,36.9135555 23.7258999,36.9135555 Z M47.3177999,36.9135555 C43.8195999,36.9135555 40.9370999,33.7018555 40.9370999,29.7575555 C40.9370999,25.8132555 43.7635999,22.6015555 47.3177999,22.6015555 C50.8999999,22.6015555 53.7544999,25.8414555 53.6985999,29.7575555 C53.6985999,33.7018555 50.8999999,36.9135555 47.3177999,36.9135555 Z" id="Shape"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

+83 -77
View File
@@ -24,30 +24,6 @@
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/handbook/contributing</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/handbook/introduction</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/reference/index</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/tutorials/nextjs</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/guides/api</loc>
<changefreq>weekly</changefreq>
@@ -114,6 +90,18 @@
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/handbook/contributing</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/handbook/introduction</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/new/auth</loc>
<changefreq>weekly</changefreq>
@@ -121,31 +109,13 @@
</url>
<url>
<loc>https://supabase.com/docs/learn/auth-deep-dive/auth-deep-dive-jwts</loc>
<loc>https://supabase.com/docs/reference/index</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/learn/auth-deep-dive/auth-google-oauth</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/learn/auth-deep-dive/auth-gotrue</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/learn/auth-deep-dive/auth-policies</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/learn/auth-deep-dive/auth-row-level-security</loc>
<loc>https://supabase.com/docs/tutorials/nextjs</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
@@ -594,6 +564,24 @@
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/guides/resources/glossary</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/guides/resources/self-hosting</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/guides/resources/supabase-cli</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/guides/storage/access-control</loc>
<changefreq>weekly</changefreq>
@@ -625,19 +613,31 @@
</url>
<url>
<loc>https://supabase.com/docs/guides/resources/glossary</loc>
<loc>https://supabase.com/docs/learn/auth-deep-dive/auth-deep-dive-jwts</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/guides/resources/self-hosting</loc>
<loc>https://supabase.com/docs/learn/auth-deep-dive/auth-google-oauth</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/guides/resources/supabase-cli</loc>
<loc>https://supabase.com/docs/learn/auth-deep-dive/auth-gotrue</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/learn/auth-deep-dive/auth-policies</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/learn/auth-deep-dive/auth-row-level-security</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
@@ -726,30 +726,6 @@
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/guides/getting-started/quickstarts/nextjs</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/guides/getting-started/quickstarts/nuxtjs</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/guides/getting-started/quickstarts/reactjs</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/guides/functions/examples/og-image</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/guides/auth/social-login/auth-apple</loc>
<changefreq>weekly</changefreq>
@@ -852,6 +828,30 @@
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/guides/functions/examples/og-image</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/guides/getting-started/quickstarts/nextjs</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/guides/getting-started/quickstarts/nuxtjs</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/guides/getting-started/quickstarts/reactjs</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/guides/getting-started/tutorials/with-angular</loc>
<changefreq>weekly</changefreq>
@@ -978,6 +978,12 @@
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/guides/resources/self-hosting/docker</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/guides/resources/supabase-cli/local-development</loc>
<changefreq>weekly</changefreq>
@@ -990,12 +996,6 @@
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/guides/resources/self-hosting/docker</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/reference/javascript/initializing</loc>
<changefreq>weekly</changefreq>
@@ -1544,6 +1544,12 @@
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/reference/javascript/v1/initializing</loc>
<changefreq>weekly</changefreq>
<changefreq>0.5</changefreq>
</url>
<url>
<loc>https://supabase.com/docs/reference/javascript/v1/auth-signup</loc>
<changefreq>weekly</changefreq>
@@ -70,7 +70,7 @@ We've released granular permissions for the Supabase Dashboard. Dashboard permis
We're starting with 3 roles—Owner, Administrator, and Developer—which you can edit in the Org settings of the Dashboard.
There's a tooltip in the header of the members table, which elaborates on the individual permissions available for each role.
[Read more](/docs/guides/platform#manage-team-members).
[Read more](/docs/guides/platform/access-control#manage-team-members).
---
@@ -46,7 +46,7 @@ Plus, we published three new functions examples: [Generate OG Images](https://gi
- Conda support (`conda install -c conda-forge supabase` and everything else in py)
## Content storm ⛈
## Content storm
![The Supabase Content Storm](/images/blog/2022-12-07-november-beta-update/content-storm.jpg)
@@ -41,7 +41,7 @@ In the event that the user faces difficulties entering a QR code the user can al
An MFA flow can be broken into two key steps: Enrollment and Verification. During the *Enrollment* process Supabase Auth exchanges a randomly generated secret with the user’s authenticator application. During the *Verification* process, the device makes use of the timestamp together with the secret to produce a six digit code that the server can verify.
![Flowchart of an MFA flow](/images/blog/lw6-auth/mfa-flow.png)
**Enrollment**
*Enrollment*
To generate a QR code, call the `/enroll` endpoint which returns an SVG encoded QR and the secret. Thereafter, create a challenge by calling the `/challenge` endpoint. Once the user has entered the six digit TOTP code generated by their authenticator app, call the`/verify` endpoint with the corresponding factor and challenge details.
@@ -36,7 +36,7 @@ An integration between FlutterFlow and Supabase has been long awaited by the com
This is just the beginning of our integration with FlutterFlow. We're working closely with the FlutterFlow team to deliver more features!
Watch John from the FlutterFlow team demonstrate how you can [get started with FlutterFlow and Supabase](https://youtu.be/TmViZsWEBY0).
Watch John from the FlutterFlow team demonstrate how you can [get started with FlutterFlow and Supabase](https://youtu.be/hw9Q-NjASbU).
### OneSignal
@@ -17,7 +17,7 @@ The PostgreSQL community [released](https://www.postgresql.org/docs/current/rele
`CREATE` permission is revoked from all users except the database owner. It makes permission assigning more tunable ([details](https://www.postgresql.org/docs/15/ddl-schemas.html#DDL-SCHEMAS-PATTERNS)). And for the migrated database don't forget to revoke `CREATE` permission on the public schema manually to fit the new policy.
There is a useful option `CREATE VIEW .. WITH security_invoker=on` to create a view that uses permissions of a view caller rather than a view creator to access underlying tables. With this, you should not worry that a user that doesn't have access to a table could see its data through a view.
There is a useful option `CREATE VIEW .. WITH (security_invoker=on)` to create a view that uses permissions of a view caller rather than a view creator to access underlying tables. With this, you should not worry that a user that doesn't have access to a table could see its data through a view.
## **Performance speed-up**
@@ -223,20 +223,17 @@ import { Customer } from 'types'
serve(async (req) => {
try {
// create a supabase client
// create a supabase client with Auth context of the user that called the function
const supabaseClient = createClient(
Deno.env.get('SUPABASE_URL') ?? '',
Deno.env.get('SUPABASE_ANON_KEY') ?? ''
Deno.env.get('SUPABASE_ANON_KEY') ?? '',
{ global: { headers: { Authorization: req.headers.get('Authorization')! } } }
)
// create a stripe client
const stripe = Stripe(Deno.env.get('STRIPE_SECRET_KEY'))
// Get the authorization header from the request.
const authHeader = req.headers.get('Authorization').replace("Bearer ","")
// Client now respects auth policies for this user
supabaseClient.auth.setAuth(authHeader)
// set the user profile
const user = supabase.auth.user()
// get the current logged in user
const {data: { user },} = supabase.auth.getUser()
// Retrieve user metadata that only the user is allowed to select
const { data, error } = await supabaseClient
+140 -140
View File
File diff suppressed because it is too large. Load diff
+33 -33
View File
@@ -11,7 +11,7 @@
- [x] হোস্ট করা পোস্টগ্রেস ডাটাবেস. [ডক্স](https://supabase.com/docs/guides/database)
- [x] অথেনটিকেশন এবং অথরাইজড . [ডক্স](https://supabase.com/docs/guides/auth)
- [x] স্বয়ংক্রিয়ভাবে তৈরি APIs.
- [x] স্বয়ংক্রিয়ভাবে তৈরি এপিআই.
- [x] রেস্ট. [ডক্স](https://supabase.com/docs/guides/api#rest-api)
- [x] রিয়েলটাইম সাবস্ক্রিপশন. [ডক্স](https://supabase.com/docs/guides/api#realtime-api)
- [x] গ্রাফকিউএল (বেটা). [ডক্স](https://supabase.com/docs/guides/api#graphql-api)
@@ -31,10 +31,10 @@
## কমিউনিটি ও সাপোর্ট
- [কমিউনিটি ফোরাম](https://github.com/supabase/supabase/discussions). এর জন্য সর্বোত্তম: তৈরিতে সহায়তা, ডাটাবেস সেরা অনুশীলন সম্পর্কে আলোচনা।
- [গিঠাব ইস্যু](https://github.com/supabase/supabase/issues). এর জন্য সেরা: সুপাবেস ব্যবহার করে আপনি যে বাগ এবং ত্রুটির সম্মুখীন হন।
- [ইমেইল সাপোর্ট](https://supabase.com/docs/support#business-support). এর জন্য সেরা: আপনার ডাটাবেস বা অবকাঠামো নিয়ে সমস্যা।
- [ডিসকোর্ড](https://discord.supabase.com). এর জন্য সর্বোত্তম: আপনার অ্যাপ্লিকেশনগুলি ভাগ করা এবং সম্প্রদায়ের সাথে হ্যাঙ্গআউট করা৷
- [কমিউনিটি ফোরাম](https://github.com/supabase/supabase/discussions)। সর্বোত্তম: তৈরি করতে সহায়তা, ডাটাবেস সেরা অনুশীলন সম্পর্কে আলোচনা।
- [গিটহাব ইস্যু](https://github.com/supabase/supabase/issues)। সর্বোত্তম: সুপাবেস ব্যবহার করতে আপনি যে বাগ এবং ত্রুটির সম্মুখীন হন।
- [ইমেইল সাপোর্ট](https://supabase.com/docs/support#business-support)। সর্বোত্তম: আপনার ডাটাবেস বা অবকাঠামো নিয়ে সমস্যা।
- [ডিসকোর্ড](https://discord.supabase.com)। সর্বোত্তম: আপনার অ্যাপ্লিকেশনগুলি শেয়ার করা এবং কমিউনিটির সাথে দেখা সাক্ষাৎ করা৷
## স্ট্যাটাস
@@ -43,30 +43,30 @@
- [x] পাবলিক বেটা: বেশিরভাগ নন-এন্টারপ্রাইজ ব্যবহারের ক্ষেত্রে যথেষ্ট স্থিতিশীল
- [ ] পাবলিক: প্রোডাকশন রেডি
আমরা বর্তমানে পাবলিক বেটাতে আছি। বড় আপডেটের বিজ্ঞপ্তি পেতে এই রেপোর "রিলিজ" দেখুন।
আমরা বর্তমানে পাবলিক বেটাতে আছি। বড় আপডেটের বিজ্ঞপ্তি পেতে এই রিপুর "রিলিজ" দেখুন।
<kbd><img src="https://raw.githubusercontent.com/supabase/supabase/d5f7f413ab356dc1a92075cb3cee4e40a957d5b1/web/static/watch-repo.gif" alt="এই রেপো দেখুন"/></kbd>
<kbd><img src="https://raw.githubusercontent.com/supabase/supabase/d5f7f413ab356dc1a92075cb3cee4e40a957d5b1/web/static/watch-repo.gif" alt="এই রিপু দেখুন"/></kbd>
---
## কিভাবে এটা কাজ করে
Supabase হল ওপেন সোর্স টুলের সংমিশ্রণ। আমরা এন্টারপ্রাইজ-গ্রেড, ওপেন সোর্স পণ্য ব্যবহার করে Firebase-এর বৈশিষ্ট্য তৈরি করছি। যদি MIT, Apache 2, বা সমতুল্য ওপেন লাইসেন্স সহ টুল এবং সম্প্রদায়গুলি বিদ্যমান থাকে, আমরা সেই টুলটি ব্যবহার করব এবং সমর্থন করব। যদি টুলটি বিদ্যমান না থাকে, তাহলে আমরা নিজেরাই এটি তৈরি এবং ওপেন সোর্স করি। Supabase Firebase-এর 1-থেকে-1 ম্যাপিং নয়। ওপেন সোর্স টুল ব্যবহার করে ডেভেলপারদের ফায়ারবেসের মতো ডেভেলপার অভিজ্ঞতা দেওয়াই আমাদের লক্ষ্য।
Supabase হল ওপেন সোর্স টুলের সংমিশ্রণ। আমরা এন্টারপ্রাইজ-গ্রেড, ওপেন সোর্স পণ্য ব্যবহার করে Firebase-এর ফিচারসমুহ তৈরি করছি। যদি MIT, Apache 2, বা সমতুল্য ওপেন লাইসেন্স সহ টুল এবং সম্প্রদায়গুলি বিদ্যমান থাকে, আমরা সেই টুলটি ব্যবহার করব এবং সমর্থন করব। যদি টুলটি বিদ্যমান না থাকে, তাহলে আমরা নিজেরাই এটি তৈরি এবং ওপেন সোর্স করি। Supabase Firebase-এর 1-থেকে-1 ম্যাপিং নয়। ওপেন সোর্স টুল ব্যবহার করে ডেভেলপারদের ফায়ারবেসের মতো ডেভেলপার অভিজ্ঞতা দেওয়াই আমাদের লক্ষ্য।
**স্থাপত্য**
সুপাবেস হল একটি [হোস্ট করা প্ল্যাটফর্ম](https://app.supabase.com)। আপনি সাইন আপ করতে পারেন এবং কিছু ইনস্টল না করে সুপাবেস ব্যবহার শুরু করতে পারেন।
সুপাবেস হল একটি [হোস্ট করা প্ল্যাটফর্ম](https://app.supabase.com)। আপনি সাইন আপ করে এবং কিছু ইনস্টল না করে সুপাবেস ব্যবহার শুরু করতে পারেন।
এছাড়াও আপনি [স্ব-হোস্ট](https://supabase.com/docs/guides/hosting/overview) এবং [ডেভেলপ লোকালি](https://supabase.com/docs/guides/local-development) করতে পারেন।
![আর্কিটেকচার](https://user-images.githubusercontent.com/70828596/187547862-ffa9d058-0c3a-4851-a3e7-92ccfca4b596.png)
- [PostgreSQL](https://www.postgresql.org/) হল একটি অবজেক্ট-রিলেশনাল ডাটাবেস সিস্টেম যার 30 বছরের বেশি সক্রিয় বিকাশ রয়েছে যা এটিকে নির্ভরযোগ্যতা, বৈশিষ্ট্যের দৃঢ়তা এবং কর্মক্ষমতার জন্য একটি শক্তিশালী খ্যাতি অর্জন করেছে।
- [রিয়েলটাইম](https://github.com/supabase/realtime) হল একটি Elixir সার্ভার যা আপনাকে ওয়েবসকেট ব্যবহার করে PostgreSQL সন্নিবেশ, আপডেট এবং মুছে ফেলা শুনতে দেয়। ডাটাবেস পরিবর্তনের জন্য রিয়েলটাইম পোল পোস্টগ্রেসের অন্তর্নির্মিত প্রতিলিপি কার্যকারিতা, পরিবর্তনগুলিকে JSON-এ রূপান্তরিত করে, তারপর অনুমোদিত ক্লায়েন্টদের কাছে ওয়েবসকেটের মাধ্যমে JSON সম্প্রচার করে।
- [PostgREST](http://postgrest.org/) একটি ওয়েব সার্ভার যা আপনার PostgreSQL ডাটাবেসকে সরাসরি একটি RESTful API-তে পরিণত করে
- [স্টোরেজ](https://github.com/supabase/storage-api) অনুমতিগুলি পরিচালনা করতে Postgres ব্যবহার করে S3-এ সঞ্চিত ফাইলগুলি পরিচালনা করার জন্য একটি RESTful ইন্টারফেস প্রদান করে।
- [postgres-meta](https://github.com/supabase/postgres-meta) হল আপনার পোস্টগ্রেস পরিচালনা করার জন্য একটি RESTful API, যা আপনাকে টেবিল আনতে, ভূমিকা যোগ করতে এবং কোয়েরি চালানোর অনুমতি দেয়।
- [GoTrue](https://github.com/netlify/gotrue) ব্যবহারকারীদের পরিচালনা এবং SWT টোকেন ইস্যু করার জন্য একটি SWT ভিত্তিক API।
- [কং](https://github.com/Kong/kong) হল একটি ক্লাউড-নেটিভ API গেটওয়ে।
- [PostgREST](http://postgrest.org/) একটি ওয়েব সার্ভার যা আপনার PostgreSQL ডাটাবেসকে সরাসরি একটি রেস্টফুল এপিআইতে পরিণত করে।
- [স্টোরেজ](https://github.com/supabase/storage-api) অনুমতিগুলি পরিচালনা করতে পোস্টগ্রেস ব্যবহার করে S3-এ সঞ্চিত ফাইলগুলি পরিচালনা করার জন্য একটি রেস্টফুল ইন্টারফেস প্রদান করে।
- [পোস্টগ্রেস-মেটা](https://github.com/supabase/postgres-meta) হল আপনার পোস্টগ্রেস পরিচালনা করার জন্য একটি রেস্টফুল এপিআই, যা আপনাকে টেবিল আনতে, ভূমিকা যোগ করতে এবং কোয়েরি চালানোর অনুমতি দেয়।
- [গোট্রু](https://github.com/netlify/gotrue) ব্যবহারকারীদের পরিচালনা এবং SWT টোকেন ইস্যু করার জন্য একটি SWT ভিত্তিক এপিআই
- [কং](https://github.com/Kong/kong) হল একটি ক্লাউড-নেটিভ এপিআই গেটওয়ে।
#### ক্লায়েন্ট লাইব্রেরি
@@ -82,7 +82,7 @@ Supabase হল ওপেন সোর্স টুলের সংমিশ্
<th></th>
<th>Supabase</th>
<th><a href="https://github.com/postgrest/postgrest" target="_blank" rel="noopener noreferrer">PostgREST</a></th>
<th><a href="https://github.com/supabase/gotrue" target="_blank" rel="noopener noreferrer">GoTrue</a></th>
<th><a href="https://github.com/supabase/gotrue" target="_blank" rel="noopener noreferrer">গোট্রু</a></th>
<th><a href="https://github.com/supabase/realtime" target="_blank" rel="noopener noreferrer">রিয়েলটাইম</a></th>
<th><a href="https://github.com/supabase/storage-api" target="_blank" rel="noopener noreferrer">স্টোরেজ</a></th>
</tr>
@@ -100,28 +100,28 @@ Supabase হল ওপেন সোর্স টুলের সংমিশ্
<th colspan="6">⚡️ অফিসিয়াল ⚡️</th>
<tr>
<td>জাভাস্ক্রিপ্ট (টাইপস্ক্রিপ্ট)</td>
<td><a href="https://github.com/supabase/supabase-js" target="_blank" rel="noopener noreferrer">supabase-js</a></td>
<td><a href="https://github.com/supabase/supabase-js" target="_blank" rel="noopener noreferrer">সুপাবেস-জেএস</a></td>
<td><a href="https://github.com/supabase/postgrest-js" target="_blank" rel="noopener noreferrer">postgrest-js</a></td>
<td><a href="https://github.com/supabase/gotrue-js" target="_blank" rel="noopener noreferrer">gotrue-js</a></td>
<td><a href="https://github.com/supabase/gotrue-js" target="_blank" rel="noopener noreferrer">গোট্রু-জেএস</a></td>
<td><a href="https://github.com/supabase/realtime-js" target="_blank" rel="noopener noreferrer">রিয়েলটাইম-জেএস</a></td>
<td><a href="https://github.com/supabase/storage-js" target="_blank" rel="noopener noreferrer">storage-js</a></td>
<td><a href="https://github.com/supabase/storage-js" target="_blank" rel="noopener noreferrer">স্টোরেজ-জেএস</a></td>
</tr>
<th colspan="6">💚 সম্প্রদায় 💚</th>
<tr>
<td>C#</td>
<td><a href="https://github.com/supabase-community/supabase-csharp" target="_blank" rel="noopener noreferrer">supabase-csharp</a></td>
<td><a href="https://github.com/supabase-community/postgrest-csharp" target="_blank" rel="noopener noreferrer">postgrest-csharp</a></td>
<td><a href="https://github.com/supabase-community/gotrue-csharp" target="_blank" rel="noopener noreferrer">gotrue-csharp</a></td>
<td><a href="https://github.com/supabase-community/gotrue-csharp" target="_blank" rel="noopener noreferrer">গোট্রু-csharp</a></td>
<td><a href="https://github.com/supabase-community/realtime-csharp" target="_blank" rel="noopener noreferrer">রিয়েলটাইম-csharp</a></td>
<td>-</td>
</tr>
<tr>
<td>ডার্ট (ফ্লাটার)</td>
<td><a href="https://github.com/supabase/supabase-Flutter" target="_blank" rel="noopener noreferrer">supabase-dart</a></td>
<td><a href="https://github.com/supabase/postgrest-dart" target="_blank" rel="noopener noreferrer">postgrest-dart</a></td>
<td><a href="https://github.com/supabase/gotrue-dart" target="_blank" rel="noopener noreferrer">gotrue-dart</a></td>
<td><a href="https://github.com/supabase/supabase-Flutter" target="_blank" rel="noopener noreferrer">সুপাবেস-ডার্ট</a></td>
<td><a href="https://github.com/supabase/postgrest-dart" target="_blank" rel="noopener noreferrer">postgrest-ডার্ট</a></td>
<td><a href="https://github.com/supabase/gotrue-dart" target="_blank" rel="noopener noreferrer">গোট্রু-ডার্ট</a></td>
<td><a href="https://github.com/supabase/realtime-dart" target="_blank" rel="noopener noreferrer">রিয়েলটাইম-ডার্ট</a></td>
<td><a href="https://github.com/supabase/storage-dart" target="_blank" rel="noopener noreferrer">storage-dart</a></td>
<td><a href="https://github.com/supabase/storage-dart" target="_blank" rel="noopener noreferrer">স্টোরেজ-ডার্ট</a></td>
</tr>
<tr>
<td>গো</td>
@@ -135,7 +135,7 @@ Supabase হল ওপেন সোর্স টুলের সংমিশ্
<td>জাভা</td>
<td>-</td>
<td>-</td>
<td><a href="https://github.com/supabase-community/gotrue-java" target="_blank" rel="noopener noreferrer">gotrue-java</a></td>
<td><a href="https://github.com/supabase-community/gotrue-java" target="_blank" rel="noopener noreferrer">গোট্রু-জাভা</a></td>
<td>-</td>
<td>-</td>
</tr>
@@ -143,7 +143,7 @@ Supabase হল ওপেন সোর্স টুলের সংমিশ্
<td>কোটলিন</td>
<td>-</td>
<td><a href="https://github.com/supabase-community/postgrest-kt" target="_blank" rel="noopener noreferrer">postgrest-kt</a></td>
<td><a href="https://github.com/supabase-community/gotrue-kt" target="_blank" rel="noopener noreferrer">gotrue-kt</a></td>
<td><a href="https://github.com/supabase-community/gotrue-kt" target="_blank" rel="noopener noreferrer">গোট্রু-kt</a></td>
<td>-</td>
<td>-</td>
</tr>
@@ -151,13 +151,13 @@ Supabase হল ওপেন সোর্স টুলের সংমিশ্
<td>পাইথন</td>
<td><a href="https://github.com/supabase-community/supabase-py" target="_blank" rel="noopener noreferrer">supabase-py</a></td>
<td><a href="https://github.com/supabase-community/postgrest-py" target="_blank" rel="noopener noreferrer">postgrest-py</a></td>
<td><a href="https://github.com/supabase-community/gotrue-py" target="_blank" rel="noopener noreferrer">gotrue-py</a></td>
<td><a href="https://github.com/supabase-community/realtime-py" target="_blank" rel="noopener noreferrer">realtime-py</a></td>
<td><a href="https://github.com/supabase-community/gotrue-py" target="_blank" rel="noopener noreferrer">গোট্রু-py</a></td>
<td><a href="https://github.com/supabase-community/realtime-py" target="_blank" rel="noopener noreferrer">রিয়েলটাইম-py</a></td>
<td>-</td>
</tr>
<tr>
<td>রুবি</td>
<td><a href="https://github.com/supabase-community/supabase-rb" target="_blank" rel="noopener noreferrer">supabase-rb</a></td>
<td><a href="https://github.com/supabase-community/supabase-rb" target="_blank" rel="noopener noreferrer">সুপাবেস-rb</a></td>
<td><a href="https://github.com/supabase-community/postgrest-rb" target="_blank" rel="noopener noreferrer">postgrest-rb</a></td>
<td>-</td>
<td>-</td>
@@ -173,9 +173,9 @@ Supabase হল ওপেন সোর্স টুলের সংমিশ্
</tr>
<tr>
<td>সুইফট</td>
<td><a href="https://github.com/supabase-community/supabase-swift" target="_blank" rel="noopener noreferrer">supabase-swift</a></td>
<td><a href="https://github.com/supabase-community/postgrest-swift" target="_blank" rel="noopener noreferrer">postgrest-swift</a></td>
<td><a href="https://github.com/supabase-community/gotrue-swift" target="_blank" rel="noopener noreferrer">gotrue-swift</a></td>
<td><a href="https://github.com/supabase-community/supabase-swift" target="_blank" rel="noopener noreferrer">সুপাবেস-সুইফট</a></td>
<td><a href="https://github.com/supabase-community/postgrest-swift" target="_blank" rel="noopener noreferrer">postgrest-সুইফট</a></td>
<td><a href="https://github.com/supabase-community/gotrue-swift" target="_blank" rel="noopener noreferrer">গোট্রু-সুইফট</a></td>
<td><a href="https://github.com/supabase-community/realtime-swift" target="_blank" rel="noopener noreferrer">রিয়েলটাইম-সুইফট</a></td>
<td><a href="https://github.com/supabase-community/storage-swift" target="_blank" rel="noopener noreferrer">স্টোরেজ-সুইফট</a></td>
</tr>
@@ -185,6 +185,6 @@ Supabase হল ওপেন সোর্স টুলের সংমিশ্
- [অনুবাদের তালিকা](/i18n/languages.md) <!--- Keep only this -->
## স্পনসর
## পৃষ্ঠপোষক
[![নতুন স্পনসর](https://user-images.githubusercontent.com/10214025/90518111-e74bbb00-e198-11ea-8f88-c9e3c1aa4b5b.png)](https://github.com/sponsors/supabase)
[![নতুন পৃষ্ঠপোষক](https://user-images.githubusercontent.com/10214025/90518111-e74bbb00-e198-11ea-8f88-c9e3c1aa4b5b.png)](https://github.com/sponsors/supabase)
+1 -2
View File
@@ -17,8 +17,7 @@
"title": "Initializing",
"id": "initializing",
"slug": "initializing",
"type": "markdown",
"libs": ["dart", "dart_v0"]
"type": "function"
},
{
"title": "Typescript Support",
+62
View File
@@ -16,6 +16,68 @@ info:
version: '0.0.1'
functions:
- id: initializing
title: 'Initializing'
$ref: '@supabase/supabase-js.index.SupabaseClient.constructor'
examples:
- id: create-client
name: Create Client
code: |
```js
import { createClient } from '@supabase/supabase-js'
// Create a single supabase client for interacting with your database
const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key')
```
- id: with-additional-parameters
name: With Additional Parameters
code: |
```js
import { createClient } from '@supabase/supabase-js'
const options = {
schema: 'public',
headers: { 'x-my-custom-header': 'my-app-name' },
autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: true,
}
const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key', options)
```
- id: api-schemas
name: API schemas
code: |
```js
import { createClient } from '@supabase/supabase-js'
const options = {
schema: 'public',
headers: { 'x-my-custom-header': 'my-app-name' },
autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: true,
}
const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key', options)
```
description: |
By default the API server points to the `public` schema. You can enable other database schemas within the Dashboard.
Go to `Settings > API > Schema` and add the schema which you want to expose to the API. You also need to grant `USAGE` on your new schema with the grants you desire, such as `SELECT, INSERT, UPDATE, DELETE`.
Note: each client connection can only access a single schema, so the code above can access the `other_schema` schema but cannot access the `public` schema.
- id: custom-fetch-implementation
name: Custom Fetch Implementation
code: |
```js
import { createClient } from '@supabase/supabase-js'
const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key', {
fetch: fetch.bind(globalThis),
})
```
description: |
`supabase-js` uses the [`cross-fetch`](https://www.npmjs.com/package/cross-fetch) library to make HTTP requests,
but an alternative `fetch` implementation can be provided as an option.
This is most useful in environments where `cross-fetch` is not compatible (for instance Cloudflare Workers).
- id: sign-up
title: 'signUp()'
$ref: '@supabase/gotrue-js.GoTrueClient.signUp'
@@ -1,18 +1,17 @@
import { FC, useState, useContext } from 'react'
import { observer } from 'mobx-react-lite'
import * as Tooltip from '@radix-ui/react-tooltip'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { Button, Dropdown, IconTrash, IconMoreHorizontal } from 'ui'
import { observer } from 'mobx-react-lite'
import { FC, useContext, useState } from 'react'
import { Button, Dropdown, IconMoreHorizontal, IconTrash } from 'ui'
import { Member, Role } from 'types'
import { useStore, useOrganizationDetail, checkPermissions } from 'hooks'
import { confirmAlert } from 'components/to-be-cleaned/ModalsDeprecated/ConfirmModal'
import { checkPermissions, useOrganizationDetail, useStore } from 'hooks'
import { delete_, post } from 'lib/common/fetch'
import { API_URL } from 'lib/constants'
import TextConfirmModal from 'components/ui/Modals/TextConfirmModal'
import { confirmAlert } from 'components/to-be-cleaned/ModalsDeprecated/ConfirmModal'
import { Member, Role } from 'types'
import { PageContext } from 'pages/org/[slug]/settings'
import { getUserDisplayName, isInviteExpired } from '../Organization.utils'
import { isInviteExpired } from '../Organization.utils'
import { getRolesManagementPermissions } from './TeamSettings.utils'
interface Props {
@@ -30,7 +29,6 @@ const MemberActions: FC<Props> = ({ members, member, roles }) => {
const { mutateOrgMembers } = useOrganizationDetail(ui.selectedOrganization?.slug || '')
const [loading, setLoading] = useState(false)
const [ownerTransferIsVisible, setOwnerTransferIsVisible] = useState(false)
const isExpired = isInviteExpired(member?.invited_at ?? '')
const isPendingInviteAcceptance = member.invited_id
@@ -96,7 +94,7 @@ const MemberActions: FC<Props> = ({ members, member, roles }) => {
})
mutateOrgMembers(updatedMembers)
setOwnerTransferIsVisible(false)
ui.setNotification({ category: 'success', message: 'Successfully transferred organization' })
}
@@ -180,19 +178,9 @@ const MemberActions: FC<Props> = ({ members, member, roles }) => {
<Dropdown
side="bottom"
align="end"
size="small"
overlay={
<>
{!isPendingInviteAcceptance && (
<>
<Dropdown.Item onClick={() => setOwnerTransferIsVisible(!ownerTransferIsVisible)}>
<div className="flex flex-col">
<p>Make owner</p>
<p className="block opacity-50">Transfer ownership of "{orgName}"</p>
</div>
</Dropdown.Item>
<Dropdown.Separator />
</>
)}
{isPendingInviteAcceptance ? (
<>
{canRevokeInvite && (
@@ -231,25 +219,6 @@ const MemberActions: FC<Props> = ({ members, member, roles }) => {
icon={<IconMoreHorizontal />}
/>
</Dropdown>
<TextConfirmModal
title="Transfer organization"
visible={ownerTransferIsVisible}
confirmString={slug}
loading={loading}
confirmLabel="I understand, transfer ownership"
confirmPlaceholder="Type in name of orgnization"
onCancel={() => setOwnerTransferIsVisible(!ownerTransferIsVisible)}
onConfirm={handleTransferOwnership}
alert="Payment methods such as credit cards will also be transferred. You may want to delete credit card information first before transferring."
text={
<span>
By transferring this organization, it will be solely owned by{' '}
<span className="font-medium dark:text-white">{getUserDisplayName(member)}</span>, they
will also be able to remove you from the organization as a member
</span>
}
/>
</div>
)
}
@@ -95,6 +95,7 @@ const MembersView = () => {
const memberIsPendingInvite = !!x.invited_id
const canRemoveRole = rolesRemovable.includes(memberRoleId)
const disableRoleEdit = !canRemoveRole || memberIsUser || memberIsPendingInvite
const isEmailUser = x.username === x.primary_email
const validateSelectedRoleToChange = (roleId: any) => {
if (!role || role.id === roleId) return
@@ -126,6 +127,10 @@ const MembersView = () => {
<span className="flex rounded-full border-2 border-border-secondary-light p-2 dark:border-border-secondary-dark">
<IconUser size={20} strokeWidth={2} />
</span>
) : isEmailUser ? (
<div className="w-[40px] h-[40px] bg-scale-300 border border-scale-400 rounded-full text-scale-900 flex items-center justify-center">
<IconUser strokeWidth={1.5} />
</div>
) : (
<Image
src={`https://github.com/${x.username}.png?size=80`}
@@ -1,13 +1,14 @@
import { useState, useContext } from 'react'
import { observer } from 'mobx-react-lite'
import { Button, Input, IconSearch } from 'ui'
import * as Tooltip from '@radix-ui/react-tooltip'
import { useStore } from 'hooks'
import { post } from 'lib/common/fetch'
import { API_URL } from 'lib/constants'
import InviteMemberButton from './InviteMemberButton'
import MembersView from './MembersView'
import { getRolesManagementPermissions } from './TeamSettings.utils'
import { getRolesManagementPermissions, hasMultipleOwners } from './TeamSettings.utils'
import { confirmAlert } from 'components/to-be-cleaned/ModalsDeprecated/ConfirmModal'
import { PageContext } from 'pages/org/[slug]/settings'
@@ -24,6 +25,8 @@ const TeamSettings = observer(() => {
const [isLeaving, setIsLeaving] = useState(false)
const canAddMembers = rolesAddable.length > 0
const canLeave = !isOwner || (isOwner && hasMultipleOwners(members, roles))
function onFilterMemberChange(e: any) {
PageState.membersFilterString = e.target.value
}
@@ -77,13 +80,35 @@ const TeamSettings = observer(() => {
/>
</div>
)}
{!isOwner && (
<div>
<Button type="default" onClick={() => leaveTeam()} loading={isLeaving}>
Leave team
</Button>
</div>
)}
<div>
<Tooltip.Root delayDuration={0}>
<Tooltip.Trigger>
<Button
type="default"
disabled={!canLeave}
onClick={() => leaveTeam()}
loading={isLeaving}
>
Leave team
</Button>
</Tooltip.Trigger>
{!canLeave && (
<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">
An organization requires at least 1 owner
</span>
</div>
</Tooltip.Content>
)}
</Tooltip.Root>
</div>
</div>
</div>
</div>
@@ -1,4 +1,4 @@
import { Role } from 'types'
import { Member, Role } from 'types'
import { checkPermissions } from 'hooks'
import { PermissionAction } from '@supabase/shared-types/out/constants'
@@ -23,3 +23,12 @@ export const getRolesManagementPermissions = (
return { rolesAddable, rolesRemovable }
}
export const hasMultipleOwners = (members: Member[] = [], roles: Role[] = []) => {
const membersWhoAreOwners = members.filter((member) => {
const [memberRoleId] = member.role_ids ?? []
const role = roles.find((role: Role) => role.id === memberRoleId)
return role?.name === 'Owner' && !member.invited_at
})
return membersWhoAreOwners.length > 1
}
@@ -307,6 +307,10 @@ const FileExplorerRow = ({
className={`flex items-center justify-end ${
view === STORAGE_VIEWS.LIST ? 'flex-grow' : 'w-[10%]'
}`}
onClick={(event) =>
// Stops click event from this div, to resolve an issue with menu item's click event triggering unexpected row select
event.stopPropagation()
}
>
{item.status === STORAGE_ROW_STATUS.LOADING ? (
<IconLoader
@@ -1183,7 +1183,7 @@ class StorageExplorerStore {
const files = await this.getAllItemsAlongFolder(folder)
await this.deleteFiles(files, isDeleteFolder)
const isFolderOpen = this.openedFolders[this.openedFolders.length - 1].name === folder.name
const isFolderOpen = this.openedFolders[this.openedFolders.length - 1]?.name === folder.name
if (isFolderOpen) {
this.popColumnAtIndex(folder.columnIndex)
this.popOpenedFoldersAtIndex(folder.columnIndex - 1)
+6
View File
@@ -216,6 +216,12 @@ div.fixed.inset-0 {
}
}
@media (prefers-color-scheme: dark) {
html {
color-scheme: dark;
}
}
.text-area-resize-none {
textarea {
@apply resize-none;
+3 -1
View File
@@ -40,7 +40,9 @@
// scroll-behavior: smooth;
// }
.storage-row:hover {
.storage-row:hover,
button[aria-haspopup='menu'][data-state='open'],
button[aria-haspopup='menu']:focus-visible {
.storage-row-menu {
@apply opacity-100;
}