mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
Merge branch 'master' into chore/docs-console-warnings
This commit is contained in:
commit
fffe405d17
47 files changed
+1468
-13336
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import { useState, useCallback, useRef, createContext, useContext, useEffect } from 'react'
|
||||
import { useState, useCallback, useRef, createContext, useContext, useEffect, memo } from 'react'
|
||||
import { createPortal } from 'react-dom'
|
||||
import Link from 'next/link'
|
||||
import Head from 'next/head'
|
||||
@@ -84,7 +84,7 @@ export function SearchProvider({ children }: any) {
|
||||
hitComponent={Hit}
|
||||
transformItems={(items) => {
|
||||
return items.map((item, index) => {
|
||||
console.log('item', item)
|
||||
// console.log('item', item)
|
||||
// We transform the absolute URL into a relative URL to
|
||||
// leverage Next's preloading.
|
||||
const a = document.createElement('a')
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { useTheme } from 'common/Providers'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useMenuLevelId } from '~/hooks/useMenuState'
|
||||
import { useTheme } from 'common/Providers'
|
||||
import { Fragment } from 'react'
|
||||
|
||||
const home = [
|
||||
@@ -113,8 +112,7 @@ const home = [
|
||||
],
|
||||
]
|
||||
|
||||
const NavigationMenuHome = () => {
|
||||
const level = useMenuLevelId()
|
||||
const NavigationMenuHome = ({ active }) => {
|
||||
const router = useRouter()
|
||||
const { isDarkMode } = useTheme()
|
||||
|
||||
@@ -122,9 +120,7 @@ const NavigationMenuHome = () => {
|
||||
<div
|
||||
className={[
|
||||
'transition-all duration-150 ease-out',
|
||||
level === 'home' || !level
|
||||
? 'opacity-100 ml-0 delay-150'
|
||||
: 'opacity-0 -ml-8 invisible absolute',
|
||||
active ? 'opacity-100 ml-0 delay-150' : 'opacity-0 -ml-8 invisible absolute',
|
||||
].join(' ')}
|
||||
>
|
||||
<ul className="relative w-full flex flex-col gap-4">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useRouter } from 'next/router'
|
||||
import { memo, useEffect } from 'react'
|
||||
import { menuState } from '~/hooks/useMenuState'
|
||||
import { menuState, useMenuLevelId } from '~/hooks/useMenuState'
|
||||
import NavigationMenuGuideList from './NavigationMenuGuideList'
|
||||
import NavigationMenuRefList from './NavigationMenuRefList'
|
||||
// @ts-expect-error
|
||||
@@ -22,7 +22,7 @@ import { flattenSections } from '~/lib/helpers'
|
||||
import NavigationMenuHome from './HomeMenu'
|
||||
|
||||
// Filter libCommonSections for just the relevant sections in the current library
|
||||
function generateAllowedClientLibKeys(sections, spec) {
|
||||
export function generateAllowedClientLibKeys(sections, spec) {
|
||||
// Filter parent sections first
|
||||
|
||||
const specIds = spec.functions.map((func) => {
|
||||
@@ -156,60 +156,91 @@ const NavigationMenu = ({ context }) => {
|
||||
}
|
||||
}, [router.events])
|
||||
|
||||
const level = useMenuLevelId()
|
||||
|
||||
const isHomeActive = 'home' === level
|
||||
const isGettingStartedActive = 'gettingstarted' === level
|
||||
const isDatabaseActive = 'database' === level
|
||||
const isAuthActive = 'auth' === level
|
||||
const isFunctionsActive = 'functions' === level
|
||||
const isRealtimeActive = 'realtime' === level
|
||||
const isStorageActive = 'storage' === level
|
||||
const isPlatformActive = 'platform' === level
|
||||
const isResourcesActive = 'resources' === level
|
||||
const isSelfHosting = 'self_hosting' === level
|
||||
const isIntegrationsActive = 'integrations' === level
|
||||
const isReferenceActive = 'reference' === level
|
||||
|
||||
const isReference_Javascript_V1 = 'reference_javascript_v1' === level
|
||||
const isReference_Javascript_V2 = 'reference_javascript_v2' === level
|
||||
const isReference_Dart_V0 = 'reference_dart_v0' === level
|
||||
const isReference_Dart_V1 = 'reference_dart_v1' === level
|
||||
const isReference_Cli = 'reference_cli' === level
|
||||
const isReference_Api = 'reference_api' === level
|
||||
const isReference_Self_Hosting_Auth = 'reference_self_hosting_auth' === level
|
||||
const isReference_Self_Hosting_Storage = 'reference_self_hosting_storage' === level
|
||||
const isReference_Self_Hosting_Realtime = 'reference_self_hosting_realtime' === level
|
||||
|
||||
return (
|
||||
<div className="flex relative">
|
||||
<div className={['flex relative', 'justify-center lg:justify-start'].join(' ')}>
|
||||
{/* // main menu */}
|
||||
<NavigationMenuHome />
|
||||
<NavigationMenuGuideList id={'gettingstarted'} context={context} />
|
||||
<NavigationMenuGuideList id={'database'} context={context} />
|
||||
<NavigationMenuGuideList id={'auth'} context={context} />
|
||||
<NavigationMenuGuideList id={'functions'} context={context} />
|
||||
<NavigationMenuGuideList id={'realtime'} context={context} />
|
||||
<NavigationMenuGuideList id={'storage'} context={context} />
|
||||
<NavigationMenuGuideList id={'platform'} context={context} />
|
||||
<NavigationMenuGuideList id={'resources'} context={context} />
|
||||
<NavigationMenuGuideList id={'integrations'} context={context} />
|
||||
<NavigationMenuGuideList id={'self_hosting'} context={context} />
|
||||
<NavigationMenuGuideList id={'reference'} context={context} />
|
||||
<NavigationMenuHome active={isHomeActive} />
|
||||
<NavigationMenuGuideList id={'gettingstarted'} active={isGettingStartedActive} />
|
||||
<NavigationMenuGuideList id={'database'} active={isDatabaseActive} />
|
||||
<NavigationMenuGuideList id={'auth'} active={isAuthActive} />
|
||||
<NavigationMenuGuideList id={'functions'} active={isFunctionsActive} />
|
||||
<NavigationMenuGuideList id={'realtime'} active={isRealtimeActive} />
|
||||
<NavigationMenuGuideList id={'storage'} active={isStorageActive} />
|
||||
<NavigationMenuGuideList id={'platform'} active={isPlatformActive} />
|
||||
<NavigationMenuGuideList id={'resources'} active={isResourcesActive} />
|
||||
<NavigationMenuGuideList id={'self_hosting'} active={isSelfHosting} />
|
||||
<NavigationMenuGuideList id={'integrations'} active={isIntegrationsActive} />
|
||||
<NavigationMenuGuideList id={'reference'} active={isReferenceActive} />
|
||||
{/* // Client Libs */}
|
||||
<NavigationMenuRefList
|
||||
key={'reference-js-menu-v1'}
|
||||
id={'reference_javascript_v1'}
|
||||
active={isReference_Javascript_V1}
|
||||
commonSections={libCommonSections}
|
||||
lib="javascript"
|
||||
allowedClientKeys={generateAllowedClientLibKeys(libCommonSections, spec_js_v1)}
|
||||
spec={spec_js_v1}
|
||||
/>
|
||||
<NavigationMenuRefList
|
||||
key={'reference-js-menu'}
|
||||
id={'reference_javascript_v2'}
|
||||
active={isReference_Javascript_V2}
|
||||
commonSections={libCommonSections}
|
||||
lib="javascript"
|
||||
allowedClientKeys={generateAllowedClientLibKeys(libCommonSections, spec_js_v2)}
|
||||
spec={spec_js_v2}
|
||||
/>
|
||||
<NavigationMenuRefList
|
||||
key={'reference-dart-menu'}
|
||||
id={'reference_dart_v0'}
|
||||
active={isReference_Dart_V0}
|
||||
commonSections={libCommonSections}
|
||||
lib="dart"
|
||||
allowedClientKeys={generateAllowedClientLibKeys(libCommonSections, spec_dart_v0)}
|
||||
spec={spec_dart_v0}
|
||||
/>
|
||||
<NavigationMenuRefList
|
||||
key={'reference-dart-menu-v1'}
|
||||
id={'reference_dart_v1'}
|
||||
active={isReference_Dart_V1}
|
||||
commonSections={libCommonSections}
|
||||
lib="dart"
|
||||
allowedClientKeys={generateAllowedClientLibKeys(libCommonSections, spec_dart_v1)}
|
||||
spec={spec_dart_v1}
|
||||
/>
|
||||
{/* // Tools */}
|
||||
<NavigationMenuRefList
|
||||
key={'reference-cli-menu'}
|
||||
id={'reference_cli'}
|
||||
active={isReference_Cli}
|
||||
commonSections={cliCommonSections}
|
||||
lib="cli"
|
||||
/>
|
||||
<NavigationMenuRefList
|
||||
key={'reference-api-menu'}
|
||||
id={'reference_api'}
|
||||
active={isReference_Api}
|
||||
commonSections={apiCommonSections}
|
||||
lib="api"
|
||||
/>
|
||||
@@ -217,18 +248,21 @@ const NavigationMenu = ({ context }) => {
|
||||
<NavigationMenuRefList
|
||||
key={'reference-self-hosting-auth-menu'}
|
||||
id={'reference_self_hosting_auth'}
|
||||
active={isReference_Self_Hosting_Auth}
|
||||
commonSections={authServerCommonSections}
|
||||
lib="self-hosting-auth"
|
||||
/>
|
||||
<NavigationMenuRefList
|
||||
key={'reference-self-hosting-storage-menu'}
|
||||
id={'reference_self_hosting_storage'}
|
||||
active={isReference_Self_Hosting_Storage}
|
||||
commonSections={storageServerCommonSections}
|
||||
lib="self-hosting-storage"
|
||||
/>
|
||||
<NavigationMenuRefList
|
||||
key={'reference-self-hosting-realtime-menu'}
|
||||
id={'reference_self_hosting_realtime'}
|
||||
active={isReference_Self_Hosting_Realtime}
|
||||
commonSections={realtimeServerCommonSections}
|
||||
lib="self-hosting-auth"
|
||||
/>
|
||||
|
||||
@@ -140,28 +140,6 @@ const NavigationMenuCliList = ({ currentLevel, setLevel, id }) => {
|
||||
|
||||
<Divider />
|
||||
</ul>
|
||||
{menu.extras && (
|
||||
<>
|
||||
<Divider />{' '}
|
||||
<span className="font-mono text-xs uppercase text-scale-1200 font-medium tracking-wider mb-2">
|
||||
Resources
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
{menu.extras?.map((x) => {
|
||||
return (
|
||||
<div key={x.name}>
|
||||
<li>
|
||||
<Link href={`${x.href}`} passHref>
|
||||
<a className="cursor-pointer transition text-scale-1100 text-sm hover:text-brand-900 flex gap-3 my-1">
|
||||
{x.icon && <img className="w-4" src={`${router.basePath}${x.icon}`} />}
|
||||
{x.name}
|
||||
</a>
|
||||
</Link>
|
||||
</li>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,244 +1,38 @@
|
||||
import * as Accordion from '@radix-ui/react-accordion'
|
||||
import { useTheme } from 'common/Providers'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import React, { Fragment } from 'react'
|
||||
import { IconChevronLeft } from '~/../../packages/ui'
|
||||
import { useMenuLevelId } from '~/hooks/useMenuState'
|
||||
import * as NavItems from './NavigationMenu.constants'
|
||||
import React from 'react'
|
||||
import NavigationMenuGuideListItems from './NavigationMenuGuideListItems'
|
||||
|
||||
interface Props {
|
||||
id: string
|
||||
setMenuLevelId?: any
|
||||
context: 'side' | 'mobile'
|
||||
active: boolean
|
||||
}
|
||||
const NavigationMenuGuideList: React.FC<Props> = ({ id, setMenuLevelId, context }) => {
|
||||
const NavigationMenuGuideList: React.FC<Props> = ({ id, active }) => {
|
||||
const router = useRouter()
|
||||
const { isDarkMode } = useTheme()
|
||||
|
||||
const menu = NavItems[id]
|
||||
|
||||
//console.log(id, 'url is:', menu.url)
|
||||
|
||||
// get url
|
||||
const url = router.asPath
|
||||
// remove the end of the url if a deep link
|
||||
const firstLevelRoute = url?.split('/')?.slice(0, 4)?.join('/')
|
||||
|
||||
const level = useMenuLevelId()
|
||||
|
||||
return (
|
||||
<Accordion.Root
|
||||
collapsible
|
||||
key={id + context}
|
||||
key={id}
|
||||
type="single"
|
||||
value={firstLevelRoute}
|
||||
className={[
|
||||
'transition-all ml-8 duration-150 ease-out',
|
||||
// enabled
|
||||
level === id && 'opacity-100 ml-0 delay-150',
|
||||
level === 'home' && 'ml-12',
|
||||
active && 'opacity-100 ml-0 delay-150',
|
||||
// level === 'home' && 'ml-12',
|
||||
|
||||
// disabled
|
||||
level !== 'home' && level !== id ? '-ml-8' : '',
|
||||
level !== id ? 'opacity-0 invisible absolute' : '',
|
||||
// level !== 'home' && level !== id ? '-ml-8' : '',
|
||||
!active ? 'opacity-0 invisible absolute' : '',
|
||||
].join(' ')}
|
||||
>
|
||||
<ul className={['relative w-full flex flex-col gap-0'].join(' ')}>
|
||||
<Link href={`${menu.parent ?? '/'}`} passHref>
|
||||
<a
|
||||
className={[
|
||||
'flex items-center gap-1 text-xs group mb-3',
|
||||
'text-base transition-all duration-200 text-brand-900 hover:text-brand-1200 hover:cursor-pointer ',
|
||||
].join(' ')}
|
||||
>
|
||||
<div className="relative w-2">
|
||||
<div className="transition-all ease-out ml-0 group-hover:-ml-1">
|
||||
<IconChevronLeft size={10} strokeWidth={3} />
|
||||
</div>
|
||||
</div>
|
||||
<span>Back to Home</span>
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
<Link href={menu.url ?? ''} passHref>
|
||||
<a>
|
||||
<div className="flex items-center gap-3 my-3">
|
||||
<Image
|
||||
alt={menu.icon}
|
||||
width={15}
|
||||
height={15}
|
||||
src={
|
||||
`${router.basePath}` +
|
||||
`/img/icons/menu/${menu.icon}${isDarkMode ? '' : '-light'}.svg`
|
||||
}
|
||||
/>
|
||||
<span
|
||||
className={[
|
||||
' ',
|
||||
!menu.title && 'capitalize',
|
||||
menu.url === router.pathname
|
||||
? 'text-brand-900'
|
||||
: 'hover:text-brand-900 text-scale-1200',
|
||||
].join(' ')}
|
||||
>
|
||||
{menu.title ?? level}
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
{menu.items.map((x, index) => {
|
||||
// console.log('1st type of link?', x.items && x.items.length > 0)
|
||||
// console.log()
|
||||
return (
|
||||
<div key={x.name + context}>
|
||||
{x.items && x.items.length > 0 ? (
|
||||
<div>
|
||||
{x.items.map((subItem, subItemIndex) => {
|
||||
// console.log('subitem', { subItem })
|
||||
// console.log('router', router)
|
||||
//console.log('subitem url', subItem.url)
|
||||
let subItemMenuOpen = false
|
||||
|
||||
if (router.asPath.includes(subItem.url)) {
|
||||
subItemMenuOpen = true
|
||||
}
|
||||
|
||||
const LinkContainer = (props) => {
|
||||
return (
|
||||
<Link href={props.url} passHref>
|
||||
<a className={props.className}>{props.children}</a>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment key={x.name + context + subItemIndex}>
|
||||
{subItemIndex === 0 && (
|
||||
<>
|
||||
<div className="h-px w-full bg-green-500 my-3"></div>
|
||||
<span className="font-mono text-xs uppercase text-scale-1200 font-medium tracking-wider">
|
||||
{x.name}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
<Accordion.Item key={subItem.label + context} value={subItem.url}>
|
||||
<li key={subItem.name + context}>
|
||||
<LinkContainer
|
||||
url={subItem.url}
|
||||
className={[
|
||||
'flex items-center gap-2',
|
||||
'cursor-pointer transition text-sm',
|
||||
subItem.url === router.pathname
|
||||
? 'text-brand-900'
|
||||
: 'hover:text-brand-900 text-scale-1000',
|
||||
].join(' ')}
|
||||
parent={subItem.parent}
|
||||
>
|
||||
{subItem.icon && (
|
||||
<Image
|
||||
alt={subItem.name + router.basePath}
|
||||
src={
|
||||
`${router.basePath}` +
|
||||
`${subItem.icon}${!isDarkMode ? '-light' : ''}.svg`
|
||||
}
|
||||
width={15}
|
||||
height={15}
|
||||
/>
|
||||
)}
|
||||
{subItem.name}
|
||||
</LinkContainer>
|
||||
</li>
|
||||
|
||||
{subItem.items && subItem.items.length > 0 && (
|
||||
<Accordion.Content className="transition data-open:animate-slide-down data-closed:animate-slide-up ml-2">
|
||||
{subItem.items.map((subSubItem, subSubItemIndex) => {
|
||||
return (
|
||||
<li key={subItem.name + context}>
|
||||
<Link href={`${subSubItem.url}`} passHref>
|
||||
<a
|
||||
className={[
|
||||
'cursor-pointer transition text-sm',
|
||||
subSubItem.url === router.pathname
|
||||
? 'text-brand-900'
|
||||
: 'hover:text-brand-900 text-scale-1000',
|
||||
].join(' ')}
|
||||
>
|
||||
{subSubItem.name}
|
||||
</a>
|
||||
</Link>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</Accordion.Content>
|
||||
)}
|
||||
</Accordion.Item>
|
||||
</Fragment>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
<Fragment key={x.url + context}>
|
||||
<li>
|
||||
<Link href={`${x.url}`} passHref>
|
||||
<a
|
||||
className={[
|
||||
'cursor-pointer transition text-sm',
|
||||
x.url === router.pathname
|
||||
? 'text-brand-900'
|
||||
: 'hover:text-brand-900 text-scale-1000',
|
||||
].join(' ')}
|
||||
>
|
||||
{x.icon && (
|
||||
<Image
|
||||
width={12}
|
||||
height={12}
|
||||
alt={x.icon}
|
||||
src={`${router.basePath}${x.icon}`}
|
||||
/>
|
||||
)}
|
||||
|
||||
{x.name}
|
||||
</a>
|
||||
</Link>
|
||||
</li>
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
{menu.extras && (
|
||||
<>
|
||||
<div className="h-px w-full bg-green-500 my-3"></div>
|
||||
<span className="font-mono text-xs uppercase text-scale-1200 font-medium tracking-wider mb-2">
|
||||
Resources
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
{menu.extras?.map((x) => {
|
||||
return (
|
||||
<div key={x.name + context}>
|
||||
<li>
|
||||
<Link href={`${x.href}`} passHref>
|
||||
<a className="cursor-pointer transition text-scale-1100 text-sm hover:text-brand-900 flex gap-3 my-1">
|
||||
{x.icon && (
|
||||
<Image
|
||||
width={15}
|
||||
height={15}
|
||||
alt={x.icon}
|
||||
src={`${router.basePath}${x.icon}`}
|
||||
/>
|
||||
)}
|
||||
{x.name}
|
||||
</a>
|
||||
</Link>
|
||||
</li>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
<NavigationMenuGuideListItems id={id} />
|
||||
</Accordion.Root>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
import { useTheme } from 'common/Providers'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import React from 'react'
|
||||
import { IconChevronLeft } from '~/../../packages/ui'
|
||||
import * as NavItems from './NavigationMenu.constants'
|
||||
import * as Accordion from '@radix-ui/react-accordion'
|
||||
|
||||
interface ImPureProps {
|
||||
// users: Array<User>
|
||||
}
|
||||
|
||||
const HeaderImage = React.memo(function HeaderImage(props: any) {
|
||||
const router = useRouter()
|
||||
const { isDarkMode } = useTheme()
|
||||
|
||||
return (
|
||||
<Image
|
||||
alt={props.icon}
|
||||
width={15}
|
||||
height={15}
|
||||
src={`${router.basePath}` + `/img/icons/menu/${props.icon}${isDarkMode ? '' : '-light'}.svg`}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
const HeaderLink = React.memo(function HeaderLink(props: any) {
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<span
|
||||
className={[
|
||||
' ',
|
||||
!props.title && 'capitalize',
|
||||
props.url === router.pathname ? 'text-brand-900' : 'hover:text-brand-900 text-scale-1200',
|
||||
].join(' ')}
|
||||
>
|
||||
{props.title ?? props.id}
|
||||
</span>
|
||||
)
|
||||
})
|
||||
|
||||
const ContentAccordionLink = React.memo(function ContentAccordionLink(props: any) {
|
||||
const router = useRouter()
|
||||
const { isDarkMode } = useTheme()
|
||||
|
||||
let subItemMenuOpen = false
|
||||
|
||||
if (router.asPath.includes(props.subItem.url)) {
|
||||
subItemMenuOpen = true
|
||||
}
|
||||
|
||||
const LinkContainer = (props) => {
|
||||
return (
|
||||
<Link href={props.url} passHref>
|
||||
<a className={props.className}>{props.children}</a>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{props.subItemIndex === 0 && (
|
||||
<>
|
||||
<div className="h-px w-full bg-green-500 my-3"></div>
|
||||
<span className="font-mono text-xs uppercase text-scale-1200 font-medium tracking-wider">
|
||||
{props.parent.name}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
<Accordion.Item key={props.subItem.label} value={props.subItem.url}>
|
||||
<li key={props.subItem.name}>
|
||||
<LinkContainer
|
||||
url={props.subItem.url}
|
||||
className={[
|
||||
'flex items-center gap-2',
|
||||
'cursor-pointer transition text-sm',
|
||||
props.subItem.url === router.pathname
|
||||
? 'text-brand-900'
|
||||
: 'hover:text-brand-900 text-scale-1000',
|
||||
].join(' ')}
|
||||
parent={props.subItem.parent}
|
||||
>
|
||||
{props.subItem.icon && (
|
||||
<Image
|
||||
alt={props.subItem.name + router.basePath}
|
||||
src={
|
||||
`${router.basePath}` + `${props.subItem.icon}${!isDarkMode ? '-light' : ''}.svg`
|
||||
}
|
||||
width={15}
|
||||
height={15}
|
||||
/>
|
||||
)}
|
||||
{props.subItem.name}
|
||||
</LinkContainer>
|
||||
</li>
|
||||
|
||||
{props.subItem.items && props.subItem.items.length > 0 && (
|
||||
<Accordion.Content className="transition data-open:animate-slide-down data-closed:animate-slide-up ml-2">
|
||||
{props.subItem.items.map((subSubItem) => {
|
||||
return (
|
||||
<li key={props.subItem.name}>
|
||||
<Link href={`${subSubItem.url}`} passHref>
|
||||
<a
|
||||
className={[
|
||||
'cursor-pointer transition text-sm',
|
||||
subSubItem.url === router.pathname
|
||||
? 'text-brand-900'
|
||||
: 'hover:text-brand-900 text-scale-1000',
|
||||
].join(' ')}
|
||||
>
|
||||
{subSubItem.name}
|
||||
</a>
|
||||
</Link>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</Accordion.Content>
|
||||
)}
|
||||
</Accordion.Item>
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
||||
const ContentLink = React.memo(function ContentLink(props: any) {
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<li>
|
||||
<Link href={`${props.url}`} passHref>
|
||||
<a
|
||||
className={[
|
||||
'cursor-pointer transition text-sm',
|
||||
props.url === router.pathname
|
||||
? 'text-brand-900'
|
||||
: 'hover:text-brand-900 text-scale-1000',
|
||||
].join(' ')}
|
||||
>
|
||||
{props.icon && <img className="w-3" src={`${router.basePath}${props.icon}`} />}
|
||||
{props.name}
|
||||
</a>
|
||||
</Link>
|
||||
</li>
|
||||
)
|
||||
})
|
||||
|
||||
const Content = (props) => {
|
||||
const { id } = props
|
||||
|
||||
const menu = NavItems[id]
|
||||
|
||||
return (
|
||||
<ul className={['relative w-full flex flex-col gap-0'].join(' ')}>
|
||||
<Link href={`${menu.parent ?? '/'}`} passHref>
|
||||
<a
|
||||
className={[
|
||||
'flex items-center gap-1 text-xs group mb-3',
|
||||
'text-base transition-all duration-200 text-brand-900 hover:text-brand-1200 hover:cursor-pointer ',
|
||||
].join(' ')}
|
||||
>
|
||||
<div className="relative w-2">
|
||||
<div className="transition-all ease-out ml-0 group-hover:-ml-1">
|
||||
<IconChevronLeft size={10} strokeWidth={3} />
|
||||
</div>
|
||||
</div>
|
||||
<span>Back to Home</span>
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
<Link href={menu.url ?? ''} passHref>
|
||||
<a>
|
||||
<div className="flex items-center gap-3 my-3">
|
||||
<HeaderImage icon={menu.icon} />
|
||||
<HeaderLink title={menu.title} url={menu.url} id={id} />
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
{menu.items.map((x, index) => {
|
||||
return (
|
||||
<div key={x.url}>
|
||||
{x.items && x.items.length > 0 ? (
|
||||
<div>
|
||||
{x.items.map((subItem, subItemIndex) => {
|
||||
return (
|
||||
<ContentAccordionLink
|
||||
subItem={subItem}
|
||||
subItemIndex={subItemIndex}
|
||||
parent={x}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
<ContentLink url={x.url} icon={x.icon} name={x.name} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(Content)
|
||||
@@ -1,76 +1,9 @@
|
||||
import * as Accordion from '@radix-ui/react-accordion'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { IconChevronLeft } from 'ui'
|
||||
import * as NavItems from './NavigationMenu.constants'
|
||||
// import apiCommonSections from '~/../../spec/common-client-libs-sections.json'
|
||||
|
||||
import { find } from 'lodash'
|
||||
import Image from 'next/image'
|
||||
import { useTheme } from 'common/Providers'
|
||||
|
||||
import RevVersionDropdown from '~/components/RefVersionDropdown'
|
||||
import { useMenuActiveRefId, useMenuLevelId } from '~/hooks/useMenuState'
|
||||
import { RefIdOptions, RefKeyOptions } from './NavigationMenu'
|
||||
import { isFuncNotInLibraryOrVersion } from './NavigationMenu.utils'
|
||||
import { Fragment } from 'react'
|
||||
import NavigationMenuRefListItems from './NavigationMenuRefListItems'
|
||||
|
||||
const FunctionLink = ({
|
||||
title,
|
||||
id,
|
||||
icon,
|
||||
library,
|
||||
slug,
|
||||
}: {
|
||||
title: string
|
||||
name?: string
|
||||
id: string
|
||||
icon?: string
|
||||
product?: string
|
||||
library: string
|
||||
slug: string
|
||||
}) => {
|
||||
const router = useRouter()
|
||||
const activeAccordianItem = useMenuActiveRefId()
|
||||
|
||||
// check if we're on a versioned page
|
||||
let version = ''
|
||||
if (router.asPath.includes('v1')) {
|
||||
version = 'v1'
|
||||
}
|
||||
|
||||
if (router.asPath.includes('v0')) {
|
||||
version = 'v0'
|
||||
}
|
||||
|
||||
const active = activeAccordianItem === id
|
||||
return (
|
||||
<li key={id} className="function-link-item">
|
||||
<Link href={`/reference/${library}/${version ? version + '/' : ''}${slug}`} passHref>
|
||||
<a
|
||||
className={[
|
||||
'cursor-pointer transition text-sm hover:text-brand-900 flex gap-3',
|
||||
active ? 'text-brand-900' : 'text-scale-1000',
|
||||
].join(' ')}
|
||||
>
|
||||
{icon && <Image width={16} height={16} alt={icon} src={`${router.basePath}${icon}`} />}
|
||||
{title}
|
||||
</a>
|
||||
</Link>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
const SideMenuTitle = ({ title }: { title: string }) => {
|
||||
return (
|
||||
<span className="font-mono text-xs uppercase text-scale-1200 font-medium tracking-wider mb-3">
|
||||
{title}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
const Divider = () => {
|
||||
return <div className="h-px w-full bg-blackA-300 dark:bg-whiteA-300 my-3"></div>
|
||||
}
|
||||
import React from 'react'
|
||||
|
||||
interface INavigationMenuRefList {
|
||||
id: RefIdOptions
|
||||
@@ -80,203 +13,34 @@ interface INavigationMenuRefList {
|
||||
// the keys of menu items that are allowed to be shown on the side menu
|
||||
// if undefined, we show all the menu items
|
||||
allowedClientKeys?: string[]
|
||||
active: boolean
|
||||
spec?: any
|
||||
}
|
||||
|
||||
const NavigationMenuRefList: React.FC<INavigationMenuRefList> = ({
|
||||
id,
|
||||
lib,
|
||||
commonSections,
|
||||
allowedClientKeys,
|
||||
|
||||
active,
|
||||
spec,
|
||||
}) => {
|
||||
const router = useRouter()
|
||||
const { isDarkMode } = useTheme()
|
||||
|
||||
let sections = commonSections
|
||||
|
||||
const allowedKeys = allowedClientKeys
|
||||
|
||||
if (!sections) console.error('no common sections imported')
|
||||
|
||||
const menu = NavItems[id]
|
||||
|
||||
const databaseFunctions = find(sections, { title: 'Database' })
|
||||
? find(sections, { title: 'Database' }).items
|
||||
: []
|
||||
|
||||
const authFunctions = find(sections, { title: 'Auth' })
|
||||
? find(sections, { title: 'Auth' }).items
|
||||
: []
|
||||
|
||||
const filterIds =
|
||||
databaseFunctions.length > 0
|
||||
? find(databaseFunctions, {
|
||||
id: 'using-filters',
|
||||
}) &&
|
||||
find(databaseFunctions, {
|
||||
id: 'using-filters',
|
||||
})
|
||||
.items.filter((x) => allowedKeys.includes(x.id))
|
||||
.map((x) => x.id)
|
||||
: []
|
||||
const modifierIds =
|
||||
databaseFunctions.length > 0
|
||||
? find(databaseFunctions, {
|
||||
id: 'using-modifiers',
|
||||
}) &&
|
||||
find(databaseFunctions, {
|
||||
id: 'using-modifiers',
|
||||
})
|
||||
.items.filter((x) => allowedKeys.includes(x.id))
|
||||
.map((x) => x.id)
|
||||
: []
|
||||
|
||||
const authServerIds =
|
||||
databaseFunctions.length > 0
|
||||
? find(authFunctions, {
|
||||
id: 'admin-api',
|
||||
}) &&
|
||||
find(authFunctions, {
|
||||
id: 'admin-api',
|
||||
}).items.map((x) => x.id)
|
||||
: []
|
||||
|
||||
const level = useMenuLevelId()
|
||||
|
||||
return (
|
||||
<div
|
||||
className={[
|
||||
'transition-all ml-8 duration-150 ease-out',
|
||||
// enabled
|
||||
level === id && 'opacity-100 ml-0 delay-150 h-auto',
|
||||
active && 'opacity-100 ml-0 delay-150 h-auto',
|
||||
// move menu back to margin-left
|
||||
level === 'home' && 'ml-12',
|
||||
// level === 'home' && 'ml-12',
|
||||
// disabled
|
||||
level !== 'home' && level !== id ? '-ml-8' : '',
|
||||
level !== id ? 'opacity-0 invisible absolute h-0 overflow-hidden' : '',
|
||||
// level !== 'home' && level !== id ? '-ml-8' : '',
|
||||
!active ? 'opacity-0 invisible absolute h-0 overflow-hidden' : '',
|
||||
].join(' ')}
|
||||
>
|
||||
<div className={'w-full flex flex-col gap-0 sticky top-8'}>
|
||||
<Link href="/" passHref>
|
||||
<a
|
||||
className={[
|
||||
'flex items-center gap-1 text-xs group mb-3',
|
||||
'text-base transition-all duration-200 text-scale-1100 hover:text-brand-1200 hover:cursor-pointer ',
|
||||
].join(' ')}
|
||||
>
|
||||
<div className="relative w-2">
|
||||
<div className="transition-all ease-out ml-0 group-hover:-ml-1">
|
||||
<IconChevronLeft size={10} strokeWidth={3} />
|
||||
</div>
|
||||
</div>
|
||||
<span>Back to Main Menu</span>
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
<div className="flex items-center gap-3 my-3">
|
||||
<Image
|
||||
alt={id}
|
||||
width={24}
|
||||
height={24}
|
||||
src={`${router.basePath}/img/icons/menu/${menu.icon}${isDarkMode ? '' : '-light'}.svg`}
|
||||
className="rounded"
|
||||
/>
|
||||
<span className={['text-base text-brand-1200 ', !menu.title && 'capitalize'].join(' ')}>
|
||||
{menu.title}
|
||||
</span>
|
||||
<RevVersionDropdown />
|
||||
</div>
|
||||
{/* )} */}
|
||||
|
||||
<ul className="function-link-list">
|
||||
{sections.map((fn: any, fnIndex) => {
|
||||
if (isFuncNotInLibraryOrVersion(fn.id, fn.type, allowedKeys)) {
|
||||
return
|
||||
}
|
||||
|
||||
const RenderLink = (props) => {
|
||||
const activeAccordianItem = useMenuActiveRefId()
|
||||
let active = false
|
||||
|
||||
const isFilter =
|
||||
filterIds && filterIds.length > 0 && filterIds.includes(activeAccordianItem)
|
||||
const isModifier =
|
||||
modifierIds && modifierIds.length > 0 && modifierIds.includes(activeAccordianItem)
|
||||
const isAuthServer =
|
||||
authServerIds &&
|
||||
authServerIds.length > 0 &&
|
||||
authServerIds.includes(activeAccordianItem)
|
||||
|
||||
if (
|
||||
(isFilter && !isModifier && !isAuthServer && props.id === 'using-filters') ||
|
||||
(activeAccordianItem === 'using-filters' && props.id === 'using-filters')
|
||||
) {
|
||||
active = true
|
||||
} else if (
|
||||
(isModifier && !isFilter && !isAuthServer && props.id === 'using-modifiers') ||
|
||||
(activeAccordianItem === 'using-modifiers' && props.id === 'using-modifiers')
|
||||
) {
|
||||
active = true
|
||||
} else if (
|
||||
(isAuthServer && !isFilter && !isModifier && props.id === 'admin-api') ||
|
||||
(activeAccordianItem === 'admin-api' && props.id === 'admin-api')
|
||||
) {
|
||||
active = true
|
||||
} else {
|
||||
active = false
|
||||
}
|
||||
|
||||
return (
|
||||
<Accordion.Root
|
||||
collapsible
|
||||
key={props.id + '-accordian-root-for-func-' + fnIndex}
|
||||
type="single"
|
||||
value={active ? props.id : ''}
|
||||
>
|
||||
<Accordion.Item key={props.id + '-accordian-item'} value={props.id}>
|
||||
<FunctionLink {...props} library={lib} />
|
||||
<Accordion.Content
|
||||
key={props.id + '-sub-items-accordion-container'}
|
||||
className="transition data-open:animate-slide-down data-closed:animate-slide-up ml-2"
|
||||
>
|
||||
{props.items &&
|
||||
props.items
|
||||
.filter((item) => allowedKeys.includes(item.id))
|
||||
.map((item) => {
|
||||
return <FunctionLink {...item} library={lib} key={item.id} />
|
||||
})}
|
||||
</Accordion.Content>
|
||||
</Accordion.Item>
|
||||
</Accordion.Root>
|
||||
)
|
||||
}
|
||||
|
||||
return fn.id ? (
|
||||
<Fragment key={fn.id}>
|
||||
<RenderLink {...fn} library={menu.title} key={menu.title} />
|
||||
{fn.items &&
|
||||
fn.items.map((item) => (
|
||||
<RenderLink {...item} library={menu.title} key={menu.title} />
|
||||
))}
|
||||
</Fragment>
|
||||
) : (
|
||||
<Fragment key={fn.title}>
|
||||
<Divider />
|
||||
<SideMenuTitle title={fn.title} />
|
||||
{fn.items &&
|
||||
fn.items.map((item, i) =>
|
||||
isFuncNotInLibraryOrVersion(item.id, item.type, allowedKeys) ? (
|
||||
<Fragment key={item.id + i}></Fragment>
|
||||
) : (
|
||||
<RenderLink {...item} library={menu.title} key={item.id + i} />
|
||||
)
|
||||
)}
|
||||
</Fragment>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
<NavigationMenuRefListItems id={id} lib={lib} commonSections={commonSections} spec={spec} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default NavigationMenuRefList
|
||||
export default React.memo(NavigationMenuRefList)
|
||||
@@ -0,0 +1,324 @@
|
||||
import * as Accordion from '@radix-ui/react-accordion'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { IconChevronLeft } from 'ui'
|
||||
import * as NavItems from './NavigationMenu.constants'
|
||||
|
||||
import { find } from 'lodash'
|
||||
import Image from 'next/image'
|
||||
import { useTheme } from 'common/Providers'
|
||||
|
||||
import RevVersionDropdown from '~/components/RefVersionDropdown'
|
||||
import { useMenuActiveRefId } from '~/hooks/useMenuState'
|
||||
import { RefIdOptions, RefKeyOptions } from './NavigationMenu'
|
||||
|
||||
import React from 'react'
|
||||
import { generateAllowedClientLibKeys } from '~/lib/refGenerator/helpers'
|
||||
|
||||
const HeaderImage = React.memo(function HeaderImage(props: any) {
|
||||
const router = useRouter()
|
||||
const { isDarkMode } = useTheme()
|
||||
|
||||
return (
|
||||
<Image
|
||||
alt={props.icon}
|
||||
width={15}
|
||||
height={15}
|
||||
src={`${router.basePath}` + `/img/icons/menu/${props.icon}${isDarkMode ? '' : '-light'}.svg`}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
const HeaderLink = React.memo(function HeaderLink(props: any) {
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<span className={['text-base text-brand-1200 ', !props.title && 'capitalize'].join(' ')}>
|
||||
{props.title ?? props.id}
|
||||
</span>
|
||||
)
|
||||
})
|
||||
|
||||
const FunctionLink = React.memo(function FunctionLink({
|
||||
title,
|
||||
id,
|
||||
icon,
|
||||
library,
|
||||
slug,
|
||||
}: {
|
||||
title: string
|
||||
name?: string
|
||||
id: string
|
||||
icon?: string
|
||||
product?: string
|
||||
library: string
|
||||
slug: string
|
||||
}) {
|
||||
const router = useRouter()
|
||||
const activeAccordianItem = useMenuActiveRefId()
|
||||
|
||||
// check if we're on a versioned page
|
||||
let version = ''
|
||||
if (router.asPath.includes('v1')) {
|
||||
version = 'v1'
|
||||
}
|
||||
|
||||
if (router.asPath.includes('v0')) {
|
||||
version = 'v0'
|
||||
}
|
||||
|
||||
const active = activeAccordianItem === id
|
||||
return (
|
||||
<li key={id} className="function-link-item">
|
||||
<Link href={`/reference/${library}/${version ? version + '/' : ''}${slug}`} passHref>
|
||||
<a
|
||||
className={[
|
||||
'cursor-pointer transition text-sm hover:text-brand-900 flex gap-3',
|
||||
active ? 'text-brand-900' : 'text-scale-1000',
|
||||
].join(' ')}
|
||||
>
|
||||
{icon && <Image width={16} height={16} alt={icon} src={`${router.basePath}${icon}`} />}
|
||||
{title}
|
||||
</a>
|
||||
</Link>
|
||||
</li>
|
||||
)
|
||||
})
|
||||
|
||||
const RenderLink = React.memo(function RenderLink(props: any) {
|
||||
const activeAccordianItem = useMenuActiveRefId()
|
||||
let active = false
|
||||
|
||||
const isFilter = props.filterIds?.includes(activeAccordianItem)
|
||||
const isModifier = props.modifierIds?.includes(activeAccordianItem)
|
||||
const isAuthServer = props.authServerIds?.includes(activeAccordianItem)
|
||||
|
||||
if (
|
||||
(isFilter && props.id === 'using-filters') ||
|
||||
(activeAccordianItem === 'using-filters' && props.id === 'using-filters')
|
||||
) {
|
||||
active = true
|
||||
} else if (
|
||||
(isModifier && props.id === 'using-modifiers') ||
|
||||
(activeAccordianItem === 'using-modifiers' && props.id === 'using-modifiers')
|
||||
) {
|
||||
active = true
|
||||
} else if (
|
||||
(isAuthServer && props.id === 'admin-api') ||
|
||||
(activeAccordianItem === 'admin-api' && props.id === 'admin-api')
|
||||
) {
|
||||
active = true
|
||||
} else {
|
||||
active = false
|
||||
}
|
||||
|
||||
return (
|
||||
<Accordion.Root
|
||||
collapsible
|
||||
key={props.id + '-accordian-root-for-func-' + props.index}
|
||||
type="single"
|
||||
value={active ? props.id : ''}
|
||||
>
|
||||
<Accordion.Item key={props.id + '-accordian-item'} value={props.id}>
|
||||
<FunctionLink library={props.lib} title={props.title} id={props.id} slug={props.slug} />
|
||||
<Accordion.Content
|
||||
key={props.id + '-sub-items-accordion-container'}
|
||||
className="transition data-open:animate-slide-down data-closed:animate-slide-up ml-2"
|
||||
>
|
||||
{props.items &&
|
||||
props.items
|
||||
.filter((item) => props.allowedKeys.includes(item.id))
|
||||
.map((item) => {
|
||||
return (
|
||||
<FunctionLink
|
||||
library={props.lib}
|
||||
title={item.title}
|
||||
id={item.id}
|
||||
slug={item.slug}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</Accordion.Content>
|
||||
</Accordion.Item>
|
||||
</Accordion.Root>
|
||||
)
|
||||
})
|
||||
|
||||
const SideMenuTitle = ({ title }: { title: string }) => {
|
||||
return (
|
||||
<span className="font-mono text-xs uppercase text-scale-1200 font-medium tracking-wider mb-3">
|
||||
{title}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
const Divider = () => {
|
||||
return <div className="h-px w-full bg-blackA-300 dark:bg-whiteA-300 my-3"></div>
|
||||
}
|
||||
|
||||
interface INavigationMenuRefList {
|
||||
id: RefIdOptions
|
||||
lib: RefKeyOptions
|
||||
commonSections: any[] // to do type up
|
||||
|
||||
// the keys of menu items that are allowed to be shown on the side menu
|
||||
// if undefined, we show all the menu items
|
||||
allowedClientKeys?: string[]
|
||||
spec?: any
|
||||
}
|
||||
|
||||
const Content: React.FC<INavigationMenuRefList> = ({ id, lib, commonSections, spec }) => {
|
||||
const allowedClientKeys = spec ? generateAllowedClientLibKeys(commonSections, spec) : undefined
|
||||
|
||||
let sections = commonSections
|
||||
|
||||
const allowedKeys = allowedClientKeys
|
||||
|
||||
if (!sections) console.error('no common sections imported')
|
||||
|
||||
const menu = NavItems[id]
|
||||
|
||||
const databaseFunctions = find(sections, { title: 'Database' })
|
||||
? find(sections, { title: 'Database' }).items
|
||||
: []
|
||||
|
||||
const authFunctions = find(sections, { title: 'Auth' })
|
||||
? find(sections, { title: 'Auth' }).items
|
||||
: []
|
||||
|
||||
const filterIds =
|
||||
databaseFunctions.length > 0
|
||||
? find(databaseFunctions, {
|
||||
id: 'using-filters',
|
||||
}) &&
|
||||
find(databaseFunctions, {
|
||||
id: 'using-filters',
|
||||
})
|
||||
.items.filter((x) => allowedKeys.includes(x.id))
|
||||
.map((x) => x.id)
|
||||
: []
|
||||
const modifierIds =
|
||||
databaseFunctions.length > 0
|
||||
? find(databaseFunctions, {
|
||||
id: 'using-modifiers',
|
||||
}) &&
|
||||
find(databaseFunctions, {
|
||||
id: 'using-modifiers',
|
||||
})
|
||||
.items.filter((x) => allowedKeys.includes(x.id))
|
||||
.map((x) => x.id)
|
||||
: []
|
||||
|
||||
const authServerIds =
|
||||
databaseFunctions.length > 0
|
||||
? find(authFunctions, {
|
||||
id: 'admin-api',
|
||||
}) &&
|
||||
find(authFunctions, {
|
||||
id: 'admin-api',
|
||||
}).items.map((x) => x.id)
|
||||
: []
|
||||
|
||||
return (
|
||||
<div className={'w-full flex flex-col gap-0 sticky top-8'}>
|
||||
<Link href="/" passHref>
|
||||
<a
|
||||
className={[
|
||||
'flex items-center gap-1 text-xs group mb-3',
|
||||
'text-base transition-all duration-200 text-scale-1100 hover:text-brand-1200 hover:cursor-pointer ',
|
||||
].join(' ')}
|
||||
>
|
||||
<div className="relative w-2">
|
||||
<div className="transition-all ease-out ml-0 group-hover:-ml-1">
|
||||
<IconChevronLeft size={10} strokeWidth={3} />
|
||||
</div>
|
||||
</div>
|
||||
<span>Back to Main Menu</span>
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
<div className="flex items-center gap-3 my-3">
|
||||
<HeaderImage icon={menu.icon} />
|
||||
<HeaderLink title={menu.title} url={menu.url} id={id} />
|
||||
<RevVersionDropdown />
|
||||
</div>
|
||||
|
||||
<ul className="function-link-list">
|
||||
{sections.map((fn: any, fnIndex) => {
|
||||
//
|
||||
// check if the link is allowed to be displayed
|
||||
function isFuncNotInLibraryOrVersion(id, type) {
|
||||
if (id && allowedKeys && !allowedKeys.includes(id) && type !== 'markdown') {
|
||||
/*
|
||||
* Remove this menu link from side bar, as it does not exist for either
|
||||
* this language, or for this lib version
|
||||
*
|
||||
* */
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// run allow check
|
||||
if (isFuncNotInLibraryOrVersion(fn.id, fn.type)) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
// handle subtitles with subitems
|
||||
if (!fn.id) {
|
||||
return (
|
||||
<>
|
||||
<Divider />
|
||||
<SideMenuTitle title={fn.title} />
|
||||
{fn.items &&
|
||||
fn.items
|
||||
//.filter((item) => item.libs && item.libs.includes(lib))
|
||||
.map((item) => {
|
||||
// run allow check
|
||||
if (isFuncNotInLibraryOrVersion(item.id, item.type)) return <></>
|
||||
return (
|
||||
<RenderLink
|
||||
{...item}
|
||||
library={menu.title}
|
||||
index={fnIndex}
|
||||
modifierIds={modifierIds}
|
||||
filterIds={filterIds}
|
||||
authServerIds={authServerIds}
|
||||
lib={lib}
|
||||
allowedKeys={allowedKeys}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</>
|
||||
)
|
||||
} else {
|
||||
// handle normal links
|
||||
return (
|
||||
<>
|
||||
<RenderLink {...fn} lib={lib} />
|
||||
{fn.items &&
|
||||
fn.items
|
||||
//.filter((item) => item.libs.includes(lib))
|
||||
.map((item) => (
|
||||
<RenderLink
|
||||
{...item}
|
||||
library={menu.title}
|
||||
index={fnIndex}
|
||||
modifierIds={modifierIds}
|
||||
filterIds={filterIds}
|
||||
authServerIds={authServerIds}
|
||||
lib={lib}
|
||||
allowedKeys={allowedKeys}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(Content)
|
||||
@@ -7,7 +7,7 @@ export const menuState = proxy({
|
||||
setMenuActiveRefId: (value) => {
|
||||
menuState.menuActiveRefId = value
|
||||
},
|
||||
menuLevelId: '',
|
||||
menuLevelId: 'home',
|
||||
setMenuLevelId: (value) => {
|
||||
menuState.menuMobileOpen = false
|
||||
menuState.menuLevelId = value
|
||||
|
||||
+293
-261
@@ -1,18 +1,293 @@
|
||||
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, useMenuLevelId, useMenuMobileOpen } from '~/hooks/useMenuState'
|
||||
import { useEffect } from 'react'
|
||||
import { memo, useEffect } from 'react'
|
||||
import Footer from '~/components/Navigation/Footer'
|
||||
import { menuState, useMenuLevelId, useMenuMobileOpen } from '~/hooks/useMenuState'
|
||||
|
||||
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',
|
||||
},
|
||||
self_hosting: {
|
||||
icon: '/docs/img/icons/menu/self-hosting',
|
||||
name: 'Self-Hosting',
|
||||
},
|
||||
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',
|
||||
},
|
||||
}
|
||||
|
||||
const MobileHeader = memo(function MobileHeader() {
|
||||
const mobileMenuOpen = useMenuMobileOpen()
|
||||
const menuLevel = useMenuLevelId()
|
||||
|
||||
return (
|
||||
<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>
|
||||
)
|
||||
})
|
||||
|
||||
const MobileMenuBackdrop = memo(function MobileMenuBackdrop() {
|
||||
const mobileMenuOpen = useMenuMobileOpen()
|
||||
return (
|
||||
<div
|
||||
className={[
|
||||
'h-full',
|
||||
'left-0',
|
||||
'right-0',
|
||||
'z-10',
|
||||
'backdrop-blur-sm backdrop-filter bg-white-1200 dark:bg-blackA-600',
|
||||
mobileMenuOpen ? 'absolute h-full w-full top-0 left-0' : 'hidden h-0',
|
||||
// always hide on desktop
|
||||
'lg:hidden',
|
||||
].join(' ')}
|
||||
onClick={() => menuState.setMenuMobileOpen(!mobileMenuOpen)}
|
||||
></div>
|
||||
)
|
||||
})
|
||||
|
||||
const SideMenu = memo(function SideMenu() {
|
||||
return (
|
||||
<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',
|
||||
// desktop styles
|
||||
'lg:relative lg:top-0 lg:left-0 lg:pb-10 lg:px-10 lg:pt-0 lg:flex',
|
||||
'lg:opacity-100 lg:visible',
|
||||
].join(' ')}
|
||||
>
|
||||
<NavigationMenu />
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
const HeaderLogo = memo(function HeaderLogo() {
|
||||
const { isDarkMode } = useTheme()
|
||||
return (
|
||||
<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>
|
||||
)
|
||||
})
|
||||
|
||||
const Container = memo(function Container(props) {
|
||||
const mobileMenuOpen = useMenuMobileOpen()
|
||||
|
||||
return (
|
||||
<div
|
||||
// #docs-content-container is used by layout to scroll to top
|
||||
id="docs-content-container"
|
||||
className={[
|
||||
// 'overflow-x-auto',
|
||||
'w-full h-screen transition-all ease-out',
|
||||
'absolute lg:relative',
|
||||
mobileMenuOpen
|
||||
? '!w-auto ml-[75%] sm:ml-[50%] md:ml-[33%] overflow-hidden'
|
||||
: 'overflow-auto',
|
||||
// desktop override any margin styles
|
||||
'lg:ml-0',
|
||||
].join(' ')}
|
||||
>
|
||||
<div className="flex flex-col relative">{props.children}</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
const NavContainer = memo(function NavContainer() {
|
||||
const mobileMenuOpen = useMenuMobileOpen()
|
||||
|
||||
return (
|
||||
<div
|
||||
className={[
|
||||
// 'hidden',
|
||||
'absolute lg:relative',
|
||||
mobileMenuOpen ? 'w-[75%] sm:w-[50%] md:w-[33%] left-0' : 'w-0 -left-[280px]',
|
||||
'lg:w-[420px] !lg:left-0',
|
||||
// desktop override any left styles
|
||||
'lg:left-0',
|
||||
'transition-all',
|
||||
'top-0',
|
||||
'h-screen',
|
||||
'flex flex-col ml-0',
|
||||
].join(' ')}
|
||||
>
|
||||
<div
|
||||
className={[
|
||||
'top-0',
|
||||
'relative',
|
||||
'w-auto',
|
||||
'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 lg:flex lg:height-auto',
|
||||
'pt-8 bg-scale-200 flex-col gap-8',
|
||||
].join(' ')}
|
||||
>
|
||||
<HeaderLogo />
|
||||
</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>
|
||||
<SideMenu />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
const SiteLayout = ({ children }) => {
|
||||
const { isDarkMode } = useTheme()
|
||||
// const mobileMenuOpen = useMenuMobileOpen()
|
||||
|
||||
useEffect(() => {
|
||||
const key = localStorage.getItem('supabaseDarkMode')
|
||||
@@ -24,275 +299,32 @@ const SiteLayout = ({ children }) => {
|
||||
}
|
||||
}, [])
|
||||
|
||||
const menuLevel = useMenuLevelId()
|
||||
const mobileMenuOpen = useMenuMobileOpen()
|
||||
|
||||
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',
|
||||
},
|
||||
self_hosting: {
|
||||
icon: '/docs/img/icons/menu/self-hosting',
|
||||
name: 'Self-Hosting',
|
||||
},
|
||||
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(' ')}
|
||||
>
|
||||
<NavContainer />
|
||||
<Container>
|
||||
<div className={['lg:sticky top-0 z-10 overflow-hidden'].join(' ')}>
|
||||
<TopNavBarRef />
|
||||
</div>
|
||||
<div
|
||||
className={[
|
||||
'top-0',
|
||||
'relative',
|
||||
'w-auto',
|
||||
'sticky transition-all top-0',
|
||||
'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 context="side" />
|
||||
<div className={['lg:hidden', 'px-5 ', 'border-b z-10'].join(' ')}>
|
||||
<MobileHeader />
|
||||
</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">
|
||||
<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 context="mobile" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grow px-5 max-w-7xl mx-auto py-16">
|
||||
{children}
|
||||
<FooterHelpCallout />
|
||||
<Footer />
|
||||
</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 className="grow px-5 max-w-7xl mx-auto py-16">
|
||||
{children}
|
||||
<FooterHelpCallout />
|
||||
<Footer />
|
||||
</div>
|
||||
</div>
|
||||
<MobileMenuBackdrop />
|
||||
</Container>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
|
||||
@@ -2,6 +2,7 @@ import { TsDoc } from '../../generator/legacy/definitions'
|
||||
|
||||
import { values, mapValues } from 'lodash'
|
||||
import { OpenAPIV3 } from 'openapi-types'
|
||||
import { flattenSections } from '../helpers'
|
||||
|
||||
export function extractTsDocNode(nodeToFind: string, definition: any) {
|
||||
const nodePath = nodeToFind.split('.')
|
||||
@@ -285,3 +286,23 @@ export const toArrayWithKey = (obj: object, keyAs: string) =>
|
||||
return value
|
||||
})
|
||||
)
|
||||
|
||||
export function generateAllowedClientLibKeys(sections, spec) {
|
||||
// Filter parent sections first
|
||||
|
||||
const specIds = spec.functions.map((func) => {
|
||||
return func.id
|
||||
})
|
||||
|
||||
const newShape = flattenSections(sections).filter((section) => {
|
||||
if (specIds.includes(section.id)) {
|
||||
return section
|
||||
}
|
||||
})
|
||||
|
||||
const final = newShape.map((func) => {
|
||||
return func.id
|
||||
})
|
||||
|
||||
return final
|
||||
}
|
||||
@@ -13,7 +13,6 @@ import '../styles/main.scss?v=1.0.0'
|
||||
import '../styles/new-docs.scss'
|
||||
import '../styles/prism-okaidia.scss'
|
||||
import { post } from '~/lib/fetchWrappers'
|
||||
import { menuState } from '~/hooks/useMenuState'
|
||||
|
||||
function MyApp({ Component, pageProps }: AppPropsWithLayout) {
|
||||
const router = useRouter()
|
||||
|
||||
@@ -55,7 +55,7 @@ You can enable third-party providers with the click of a button by navigating to
|
||||
|
||||
### Redirect URLs and wildcards
|
||||
|
||||
When using third-party providers, the [Supabase client library](/docs/reference/javascript/auth-signinwithoauth#sign-in-using-a-third-party-provider-with-redirect) redirects the user to the provider. When the third-party provider successfully authenticates the user, the provider redirects the user to the Supabase Auth callback URL where they are further redirected to the URL specified in the `redirectTo` parameter. This parameter defaults to the [`SITE_URL`](/docs/reference/auth/config#site_url). You can modify the `SITE_URL` or [add additional redirect URLs](https://app.supabase.com/project/_/auth/settings).
|
||||
When using third-party providers, the [Supabase client library](/docs/reference/javascript/auth-signinwithoauth#sign-in-using-a-third-party-provider-with-redirect) redirects the user to the provider. When the third-party provider successfully authenticates the user, the provider redirects the user to the Supabase Auth callback URL where they are further redirected to the URL specified in the `redirectTo` parameter. This parameter defaults to the [`SITE_URL`](/docs/reference/auth/config#site_url). You can modify the `SITE_URL` or add additional [redirect URLs](https://app.supabase.com/project/_/auth/url-configuration).
|
||||
|
||||
You can use wildcard match patterns to support preview URLs from providers like Netlify and Vercel. See the [full list of supported patterns](https://pkg.go.dev/github.com/gobwas/glob#Compile). Use [this tool](https://www.digitalocean.com/community/tools/glob?comments=true&glob=http%3A%2F%2Flocalhost%3A3000%2F%2A%2A&matches=false&tests=http%3A%2F%2Flocalhost%3A3000&tests=http%3A%2F%2Flocalhost%3A3000%2F&tests=http%3A%2F%2Flocalhost%3A3000%2F%3Ftest%3Dtest&tests=http%3A%2F%2Flocalhost%3A3000%2Ftest-test%3Ftest%3Dtest&tests=http%3A%2F%2Flocalhost%3A3000%2Ftest%2Ftest%3Ftest%3Dtest) to test your patterns.
|
||||
|
||||
|
||||
@@ -63,21 +63,38 @@ This project comes with TypeScript configured and has the following structure.
|
||||
|
||||
### Configuring the project to use PostgreSQL
|
||||
|
||||
Go ahead and delete the `prisma/dev.db` file because we will be switching to PostgreSQL.
|
||||
Next, inside the `prisma/.env` file, update the value of the `DATABASE_URL` variable to the connection string you got in **step 1**. The URL might look as follows:
|
||||
By default, Prisma migrations will try to drop the `postgres` database, which can lead to conflicts with Supabase databases. For this scenario, use [Prisma Shadow Databases](https://www.prisma.io/docs/concepts/components/prisma-migrate/shadow-database#cloud-hosted-shadow-databases-must-be-created-manually).
|
||||
|
||||
```env
|
||||
# prisma/.env
|
||||
postgres://postgres:[YOUR-PASSWORD]@db.vdbnhqozmlzdsaejdxwr.supabase.co:5432/postgres
|
||||
Create a shadow database in your PostgreSQL server within the same Supabase project using the `psql` CLI and the `DATABASE_URL` from the previous steps (or use the local database).
|
||||
|
||||
```bash
|
||||
psql postgresql://postgres:[YOUR-PASSWORD]@db.vdbnhqozmlzdsaejdxwr.supabase.red:5432
|
||||
```
|
||||
|
||||
Finally, inside your `schema.prisma` file, change the `provider` from “sqlite” to `“postgresql”`.
|
||||
After you connect to your project's PostgreSQL instance, create another database (e.g., `postgres_shadow`):
|
||||
|
||||
```bash
|
||||
postgres=> CREATE DATABASE postgres_shadow;
|
||||
postgres=> exit
|
||||
```
|
||||
|
||||
Go ahead and delete the `prisma/dev.db` file because we will be switching to PostgreSQL.
|
||||
In the `.env` file, update `DATABASE_URL` and `SHADOW_DATABASE_URL` to the connection string from **step 1**. The `.env` file should look like:
|
||||
|
||||
```env
|
||||
# .env
|
||||
DATABASE_URL="postgres://postgres:[YOUR-PASSWORD]@db.vdbnhqozmlzdsaejdxwr.supabase.co:5432/postgres"
|
||||
SHADOW_DATABASE_URL="postgres://postgres:[YOUR-PASSWORD]@db.vdbnhqozmlzdsaejdxwr.supabase.co:5432/postgres_shadow"
|
||||
```
|
||||
|
||||
In the `schema.prisma` file, change the `provider` from "sqlite" to `"postgresql"` and add the `shadowDatabaseUrl` property.
|
||||
This is what your `schema.prisma` file should look like:
|
||||
|
||||
```go
|
||||
datasource db {
|
||||
provider = “postgresql”
|
||||
url = env(“DATABASE_URL”)
|
||||
shadowDatabaseUrl = env("SHADOW_DATABASE_URL")
|
||||
}
|
||||
generator client {
|
||||
provider = “prisma-client-js”
|
||||
@@ -124,11 +141,12 @@ This will create a `prisma/migrations` folder inside your `prisma` directory and
|
||||
If you’re working in a serverless environment (for example Node.js functions hosted on AWS Lambda, Vercel or Netlify Functions), you need to set up [connection pooling](https://www.prisma.io/docs/guides/performance-and-optimization/connection-management#serverless-environments-faas) using a tool like [PgBouncer](https://www.pgbouncer.org/). That’s because every function invocation may result in a [new connection to the database](https://www.prisma.io/docs/guides/performance-and-optimization/connection-management#the-serverless-challenge). Supabase [supports connection management using PgBouncer](https://supabase.io/blog/2021/04/02/supabase-pgbouncer#what-is-connection-pooling) and are enabled by default.
|
||||
Go to the **Database** page from the sidebar in the Supabase dashboard and navigate to **connection pool** settings
|
||||

|
||||
When running migrations you need to use the non pooled connection URL (like the one we used in **step 1**). However, when deploying your app, you’ll use the pooled connection URL and add the `?pgbouncer=true` flag to the PostgreSQL connection URL. To minimize the number of concurrent connections, setting the `connection_limit` to `1` is also recommended. So the URL might look as follows:
|
||||
When migrating, you need to use the non-pooled connection URL (like the one used in **step 1**). However, when deploying your app, use the pooled connection URL and add the `?pgbouncer=true` flag to the PostgreSQL connection URL. It's also recommended to minimize the number of concurrent connections by setting the `connection_limit` to `1`. The `.env` file should look like:
|
||||
|
||||
```env
|
||||
# prisma/.env
|
||||
postgres://postgres:[YOUR-PASSWORD]@db.vdbnhqozmlzdsaejdxwr.supabase.co:6543/postgres?pgbouncer=true&connection_limit=1
|
||||
# .env
|
||||
DATABASE_URL="postgres://postgres:[YOUR-PASSWORD]@db.vdbnhqozmlzdsaejdxwr.supabase.co:6543/postgres?pgbouncer=true&connection_limit=1"
|
||||
SHADOW_DATABASE_URL="postgres://postgres:[YOUR-PASSWORD]@db.vdbnhqozmlzdsaejdxwr.supabase.co:5432/postgres_shadow"
|
||||
```
|
||||
|
||||
Prisma Migrate uses database transactions to check out the current state of the database and the migrations table. However, the Migration Engine is designed to use a single connection to the database, and does not support connection pooling with PgBouncer. If you attempt to run Prisma Migrate commands in any environment that uses PgBouncer for connection pooling, you might see the following error:
|
||||
|
||||
@@ -48,7 +48,7 @@ The new hCpatcha integration allows you to implement captcha functionality for a
|
||||
|
||||

|
||||
|
||||
We've started updating our settings UI, starting with the Auth settings. You'll now see updated UI for setting up your Auth providers, Email templates and SMTP config. [Auth settings](https://app.supabase.com/project/_/auth/settings)
|
||||
We've started updating our settings UI, starting with the Auth settings. You'll now see updated UI for setting up your [Auth providers](https://app.supabase.com/project/_/auth/providers), [Email templates](https://app.supabase.com/project/_/auth/templates), and [SMTP config](https://app.supabase.com/project/_/auth/url-configuration).
|
||||
|
||||
## Quick product announcements
|
||||
|
||||
|
||||
@@ -113,3 +113,16 @@ Don't forget to checkout the new feature's being announced as part of [Launch We
|
||||
- Any intellectual property developed during the hackathon will belong to the team that developed it. We expect that each team will have an agreement between themselves regarding the IP, but this is not required
|
||||
- By making a submission you grant Supabase permission to use screenshots, code-snippets and/or links to your project or content of your README on our Twitter, blog, website, email updates, and in the Supabase discord server. Supabase does not make any claims over your IP.
|
||||
- $1500 prize will be paid by making a GitHub sponsorship to the winning repo, $500/month for 3 months. The goal here is to create a sustainable project that will be continue to be maintained for the duration of the sponsorship period (and hopefully beyond :) )
|
||||
|
||||
## More Launch Week 6
|
||||
|
||||
- [Day 1: New Supabase Docs, built with Next.js](https://supabase.com/blog/new-supabase-docs-built-with-nextjs)
|
||||
- [Day 2: Supabase Storage v2: Image resizing and Smart CDN](https://supabase.com/blog/storage-image-resizing-smart-cdn)
|
||||
- [Day 3: Multi-factor Authentication via Row Level Security Enforcement](https://supabase.com/blog/mfa-auth-via-rls)
|
||||
- [Day 4: Supabase Wrappers, a Postgres FDW framework written in Rust](https://supabase.com/blog/postgres-foreign-data-wrappers-rust)
|
||||
- [Day 5: Supabase Vault is now in Beta](https://supabase.com/blog/vault-now-in-beta)
|
||||
- [Community Day](https://supabase.com/blog/launch-week-6-community-day)
|
||||
- [Point in Time Recovery is now available](https://supabase.com/blog/postgres-point-in-time-recovery)
|
||||
- [Custom Domain Names are now available](https://supabase.com/blog/custom-domain-names)
|
||||
- [Wrap Up: everything we shipped](https://supabase.com/blog/launch-week-6-wrap-up)
|
||||
|
||||
@@ -145,3 +145,15 @@ We're likely to discover more (no doubt from a few friendly HN comments).
|
||||
## Next steps
|
||||
|
||||
If you want to help with `pg_crdt` the best way is to get involved in the GitHub repo. We have enabled [Discussions](https://github.com/supabase/pg_crdt/discussions) for any and all ideas. If you have experience with CRDTs and you like this approach, don't hesitate to contact one of the team.
|
||||
|
||||
## More Launch Week 6
|
||||
|
||||
- [Day 1: New Supabase Docs, built with Next.js](https://supabase.com/blog/new-supabase-docs-built-with-nextjs)
|
||||
- [Day 2: Supabase Storage v2: Image resizing and Smart CDN](https://supabase.com/blog/storage-image-resizing-smart-cdn)
|
||||
- [Day 3: Multi-factor Authentication via Row Level Security Enforcement](https://supabase.com/blog/mfa-auth-via-rls)
|
||||
- [Day 4: Supabase Wrappers, a Postgres FDW framework written in Rust](https://supabase.com/blog/postgres-foreign-data-wrappers-rust)
|
||||
- [Day 5: Supabase Vault is now in Beta](https://supabase.com/blog/vault-now-in-beta)
|
||||
- [Community Day](https://supabase.com/blog/launch-week-6-community-day)
|
||||
- [Point in Time Recovery is now available](https://supabase.com/blog/postgres-point-in-time-recovery)
|
||||
- [Custom Domain Names are now available](https://supabase.com/blog/custom-domain-names)
|
||||
- [Wrap Up: everything we shipped](https://supabase.com/blog/launch-week-6-wrap-up)
|
||||
@@ -94,6 +94,12 @@ Docs are more than just the tech behind them. The goal of docs is to give you, t
|
||||
|
||||
## More Launch Week 6
|
||||
|
||||
- [Launch Week 6 Hackathon](https://supabase.com/blog/launch-week-6-hackathon)
|
||||
- [Who We Hire at Supabase](https://supabase.com/blog/who-we-hire)
|
||||
- [pg_crdt - an experimental CRDT extension for Postgres](https://supabase.com/blog/postgres-crdt)
|
||||
- [Day 2: Supabase Storage v2: Image resizing and Smart CDN](https://supabase.com/blog/storage-image-resizing-smart-cdn)
|
||||
- [Day 3: Multi-factor Authentication via Row Level Security Enforcement](https://supabase.com/blog/mfa-auth-via-rls)
|
||||
- [Day 4: Supabase Wrappers, a Postgres FDW framework written in Rust](https://supabase.com/blog/postgres-foreign-data-wrappers-rust)
|
||||
- [Day 5: Supabase Vault is now in Beta](https://supabase.com/blog/vault-now-in-beta)
|
||||
- [Community Day](https://supabase.com/blog/launch-week-6-community-day)
|
||||
- [Point in Time Recovery is now available](https://supabase.com/blog/postgres-point-in-time-recovery)
|
||||
- [Custom Domain Names are now available](https://supabase.com/blog/custom-domain-names)
|
||||
- [Wrap Up: everything we shipped](https://supabase.com/blog/launch-week-6-wrap-up)
|
||||
|
||||
@@ -205,3 +205,14 @@ A few features to look out for in the future:
|
||||
- Check out the Docs for [Image Resizing](https://supabase.com/docs/guides/storage/image-transformations).
|
||||
- Check out the Docs for the [Storage CDN](https://supabase.com/docs/guides/storage/cdn).
|
||||
- Get Started today with the [JavaScript](https://supabase.com/docs/reference/javascript/storage-from-download) and [Dart](https://supabase.com/docs/reference/dart/storage-from-list) client libraries.
|
||||
|
||||
## More Launch Week 6
|
||||
|
||||
- [Day 1: New Supabase Docs, built with Next.js](https://supabase.com/blog/new-supabase-docs-built-with-nextjs)
|
||||
- [Day 3: Multi-factor Authentication via Row Level Security Enforcement](https://supabase.com/blog/mfa-auth-via-rls)
|
||||
- [Day 4: Supabase Wrappers, a Postgres FDW framework written in Rust](https://supabase.com/blog/postgres-foreign-data-wrappers-rust)
|
||||
- [Day 5: Supabase Vault is now in Beta](https://supabase.com/blog/vault-now-in-beta)
|
||||
- [Community Day](https://supabase.com/blog/launch-week-6-community-day)
|
||||
- [Point in Time Recovery is now available](https://supabase.com/blog/postgres-point-in-time-recovery)
|
||||
- [Custom Domain Names are now available](https://supabase.com/blog/custom-domain-names)
|
||||
- [Wrap Up: everything we shipped](https://supabase.com/blog/launch-week-6-wrap-up)
|
||||
@@ -128,10 +128,14 @@ For starters, we are looking to support WebAuthn and FIDO2 compliant devices suc
|
||||
|
||||
We are grateful to our early MFA users for the support and feedback provided throughout this period. In particular, we would like to thank [Fabian Beer](https://madebyfabian.com), [Cogram](https://www.cogram.com), and [Happl](https://happl.com) whose detailed feedback helped to shape our implementation. We would also like to specially thank the community behind the [pquerna/otp](https://github.com/pquerna/otp) and [ajstarks/svgo](https://github.com/ajstarks/svgo) libraries - their work is indispensable to this implementation.
|
||||
|
||||
|
||||
## More Launch Week 6
|
||||
|
||||
- [Day 1: New Supabase Docs, built with Next.js](https://supabase.com/blog/new-supabase-docs-built-with-nextjs)
|
||||
- [Day 2: Supabase Storage v2: Image resizing and Smart CDN](https://supabase.com/blog/storage-image-resizing-smart-cdn)
|
||||
- [Launch Week 6 Hackathon](https://supabase.com/blog/launch-week-6-hackathon)
|
||||
- [Who We Hire at Supabase](https://supabase.com/blog/who-we-hire)
|
||||
- [pg_crdt - an experimental CRDT extension for Postgres](https://supabase.com/blog/postgres-crdt)
|
||||
- [Day 4: Supabase Wrappers, a Postgres FDW framework written in Rust](https://supabase.com/blog/postgres-foreign-data-wrappers-rust)
|
||||
- [Day 5: Supabase Vault is now in Beta](https://supabase.com/blog/vault-now-in-beta)
|
||||
- [Community Day](https://supabase.com/blog/launch-week-6-community-day)
|
||||
- [Point in Time Recovery is now available](https://supabase.com/blog/postgres-point-in-time-recovery)
|
||||
- [Custom Domain Names are now available](https://supabase.com/blog/custom-domain-names)
|
||||
- [Wrap Up: everything we shipped](https://supabase.com/blog/launch-week-6-wrap-up)
|
||||
@@ -259,6 +259,8 @@ If you're interested in getting involved or building your own Wrapper, don't hes
|
||||
- [Day 1: New Supabase Docs, built with Next.js](https://supabase.com/blog/new-supabase-docs-built-with-nextjs)
|
||||
- [Day 2: Supabase Storage v2: Image resizing and Smart CDN](https://supabase.com/blog/storage-image-resizing-smart-cdn)
|
||||
- [Day 3: Multi-factor Authentication via Row Level Security Enforcement](https://supabase.com/blog/mfa-auth-via-rls)
|
||||
- [Launch Week 6 Hackathon](https://supabase.com/blog/launch-week-6-hackathon)
|
||||
- [Who We Hire at Supabase](https://supabase.com/blog/who-we-hire)
|
||||
- [pg_crdt - an experimental CRDT extension for Postgres](https://supabase.com/blog/postgres-crdt)
|
||||
- [Day 5: Supabase Vault is now in Beta](https://supabase.com/blog/vault-now-in-beta)
|
||||
- [Community Day](https://supabase.com/blog/launch-week-6-community-day)
|
||||
- [Point in Time Recovery is now available](https://supabase.com/blog/postgres-point-in-time-recovery)
|
||||
- [Custom Domain Names are now available](https://supabase.com/blog/custom-domain-names)
|
||||
- [Wrap Up: everything we shipped](https://supabase.com/blog/launch-week-6-wrap-up)
|
||||
@@ -62,6 +62,8 @@ We're working hard to fix these limitations, so stay tuned for future updates.
|
||||
- [Day 1: New Supabase Docs, built with Next.js](https://supabase.com/blog/new-supabase-docs-built-with-nextjs)
|
||||
- [Day 2: Supabase Storage v2: Image resizing and Smart CDN](https://supabase.com/blog/storage-image-resizing-smart-cdn)
|
||||
- [Day 3: Multi-factor Authentication via Row Level Security Enforcement](https://supabase.com/blog/mfa-auth-via-rls)
|
||||
- [Launch Week 6 Hackathon](https://supabase.com/blog/launch-week-6-hackathon)
|
||||
- [Who We Hire at Supabase](https://supabase.com/blog/who-we-hire)
|
||||
- [pg_crdt - an experimental CRDT extension for Postgres](https://supabase.com/blog/postgres-crdt)
|
||||
- [Day 4: Supabase Wrappers, a Postgres FDW framework written in Rust](https://supabase.com/blog/postgres-foreign-data-wrappers-rust)
|
||||
- [Day 5: Supabase Vault is now in Beta](https://supabase.com/blog/vault-now-in-beta)
|
||||
- [Point in Time Recovery is now available](https://supabase.com/blog/postgres-point-in-time-recovery)
|
||||
- [Custom Domain Names are now available](https://supabase.com/blog/custom-domain-names)
|
||||
- [Wrap Up: everything we shipped](https://supabase.com/blog/launch-week-6-wrap-up)
|
||||
@@ -237,4 +237,7 @@ We plan to continue our open and collaborative trend. There are many companies w
|
||||
- [Day 2: Supabase Storage v2: Image resizing and Smart CDN](https://supabase.com/blog/storage-image-resizing-smart-cdn)
|
||||
- [Day 3: Multi-factor Authentication via Row Level Security Enforcement](https://supabase.com/blog/mfa-auth-via-rls)
|
||||
- [Day 4: Supabase Wrappers, a Postgres FDW framework written in Rust](https://supabase.com/blog/postgres-foreign-data-wrappers-rust)
|
||||
- [Who We Hire at Supabase](https://supabase.com/blog/who-we-hire)
|
||||
- [Day 5: Supabase Vault is now in Beta](https://supabase.com/blog/vault-now-in-beta)
|
||||
- [Point in Time Recovery is now available](https://supabase.com/blog/postgres-point-in-time-recovery)
|
||||
- [Custom Domain Names are now available](https://supabase.com/blog/custom-domain-names)
|
||||
- [Wrap Up: everything we shipped](https://supabase.com/blog/launch-week-6-wrap-up)
|
||||
@@ -68,3 +68,15 @@ Before choosing to upgrade, don't forget to check the list of rare cases that ne
|
||||
- If you're self-hosting, upgrading between major PostgreSQL is easily done with [pg_upgrade](https://www.postgresql.org/docs/current/pgupgrade.html) utility or a set of recommended practices in the [official docs](https://www.postgresql.org/docs/current/upgrading.html).
|
||||
- If you're starting a new project on Supabase, you'll already be on PG15.
|
||||
- If you want to upgrade an existing project, check out our [Upgrading](https://supabase.com/docs/guides/platform/migrating-and-upgrading-projects#upgrade-your-project) documentation.
|
||||
|
||||
## More Launch Week 6
|
||||
|
||||
- [Day 1: New Supabase Docs, built with Next.js](https://supabase.com/blog/new-supabase-docs-built-with-nextjs)
|
||||
- [Day 2: Supabase Storage v2: Image resizing and Smart CDN](https://supabase.com/blog/storage-image-resizing-smart-cdn)
|
||||
- [Day 3: Multi-factor Authentication via Row Level Security Enforcement](https://supabase.com/blog/mfa-auth-via-rls)
|
||||
- [Day 4: Supabase Wrappers, a Postgres FDW framework written in Rust](https://supabase.com/blog/postgres-foreign-data-wrappers-rust)
|
||||
- [Day 5: Supabase Vault is now in Beta](https://supabase.com/blog/vault-now-in-beta)
|
||||
- [Community Day](https://supabase.com/blog/launch-week-6-community-day)
|
||||
- [Point in Time Recovery is now available](https://supabase.com/blog/postgres-point-in-time-recovery)
|
||||
- [Custom Domain Names are now available](https://supabase.com/blog/custom-domain-names)
|
||||
- [Wrap Up: everything we shipped](https://supabase.com/blog/launch-week-6-wrap-up)
|
||||
@@ -98,6 +98,9 @@ Longer term we look forward to experimenting with more ambitions features like a
|
||||
- [Day 1: New Supabase Docs, built with Next.js](https://supabase.com/blog/new-supabase-docs-built-with-nextjs)
|
||||
- [Day 2: Supabase Storage v2: Image resizing and Smart CDN](https://supabase.com/blog/storage-image-resizing-smart-cdn)
|
||||
- [Day 3: Multi-factor Authentication via Row Level Security Enforcement](https://supabase.com/blog/mfa-auth-via-rls)
|
||||
- [Launch Week 6 Hackathon](https://supabase.com/blog/launch-week-6-hackathon)
|
||||
- [Who We Hire at Supabase](https://supabase.com/blog/who-we-hire)
|
||||
- [pg_crdt - an experimental CRDT extension for Postgres](https://supabase.com/blog/postgres-crdt)
|
||||
- [Day 4: Supabase Wrappers, a Postgres FDW framework written in Rust](https://supabase.com/blog/postgres-foreign-data-wrappers-rust)
|
||||
- [Day 5: Supabase Vault is now in Beta](https://supabase.com/blog/vault-now-in-beta)
|
||||
- [Community Day](https://supabase.com/blog/launch-week-6-community-day)
|
||||
- [Point in Time Recovery is now available](https://supabase.com/blog/postgres-point-in-time-recovery)
|
||||
- [Custom Domain Names are now available](https://supabase.com/blog/custom-domain-names)
|
||||
- [Wrap Up: everything we shipped](https://supabase.com/blog/launch-week-6-wrap-up)
|
||||
@@ -45,6 +45,8 @@ Enabling Point in Time Recovery could be done [in the Dashboard](https://app.sup
|
||||
- [Day 1: New Supabase Docs, built with Next.js](https://supabase.com/blog/new-supabase-docs-built-with-nextjs)
|
||||
- [Day 2: Supabase Storage v2: Image resizing and Smart CDN](https://supabase.com/blog/storage-image-resizing-smart-cdn)
|
||||
- [Day 3: Multi-factor Authentication via Row Level Security Enforcement](https://supabase.com/blog/mfa-auth-via-rls)
|
||||
- [Launch Week 6 Hackathon](https://supabase.com/blog/launch-week-6-hackathon)
|
||||
- [Who We Hire at Supabase](https://supabase.com/blog/who-we-hire)
|
||||
- [pg_crdt - an experimental CRDT extension for Postgres](https://supabase.com/blog/postgres-crdt)
|
||||
- [Day 4: Supabase Wrappers, a Postgres FDW framework written in Rust](https://supabase.com/blog/postgres-foreign-data-wrappers-rust)
|
||||
- [Day 5: Supabase Vault is now in Beta](https://supabase.com/blog/vault-now-in-beta)
|
||||
- [Community Day](https://supabase.com/blog/launch-week-6-community-day)
|
||||
- [Custom Domain Names are now available](https://supabase.com/blog/custom-domain-names)
|
||||
- [Wrap Up: everything we shipped](https://supabase.com/blog/launch-week-6-wrap-up)
|
||||
@@ -224,3 +224,15 @@ $ supabase start
|
||||
```
|
||||
|
||||
Please try it and report any bugs, suggestions or ideas!
|
||||
|
||||
## More Launch Week 6
|
||||
|
||||
- [Day 1: New Supabase Docs, built with Next.js](https://supabase.com/blog/new-supabase-docs-built-with-nextjs)
|
||||
- [Day 2: Supabase Storage v2: Image resizing and Smart CDN](https://supabase.com/blog/storage-image-resizing-smart-cdn)
|
||||
- [Day 3: Multi-factor Authentication via Row Level Security Enforcement](https://supabase.com/blog/mfa-auth-via-rls)
|
||||
- [Day 4: Supabase Wrappers, a Postgres FDW framework written in Rust](https://supabase.com/blog/postgres-foreign-data-wrappers-rust)
|
||||
- [Day 5: Supabase Vault is now in Beta](https://supabase.com/blog/vault-now-in-beta)
|
||||
- [Community Day](https://supabase.com/blog/launch-week-6-community-day)
|
||||
- [Point in Time Recovery is now available](https://supabase.com/blog/postgres-point-in-time-recovery)
|
||||
- [Custom Domain Names are now available](https://supabase.com/blog/custom-domain-names)
|
||||
- [Wrap Up: everything we shipped](https://supabase.com/blog/launch-week-6-wrap-up)
|
||||
@@ -91,6 +91,8 @@ You'll see the Vault appear in the Dashboard over the next month. If you want to
|
||||
- [Day 1: New Supabase Docs, built with Next.js](https://supabase.com/blog/new-supabase-docs-built-with-nextjs)
|
||||
- [Day 2: Supabase Storage v2: Image resizing and Smart CDN](https://supabase.com/blog/storage-image-resizing-smart-cdn)
|
||||
- [Day 3: Multi-factor Authentication via Row Level Security Enforcement](https://supabase.com/blog/mfa-auth-via-rls)
|
||||
- [Launch Week 6 Hackathon](https://supabase.com/blog/launch-week-6-hackathon)
|
||||
- [Who We Hire at Supabase](https://supabase.com/blog/who-we-hire)
|
||||
- [pg_crdt - an experimental CRDT extension for Postgres](https://supabase.com/blog/postgres-crdt)
|
||||
- [Day 4: Supabase Wrappers, a Postgres FDW framework written in Rust](https://supabase.com/blog/postgres-foreign-data-wrappers-rust)
|
||||
- [Community Day](https://supabase.com/blog/launch-week-6-community-day)
|
||||
- [Point in Time Recovery is now available](https://supabase.com/blog/postgres-point-in-time-recovery)
|
||||
- [Custom Domain Names are now available](https://supabase.com/blog/custom-domain-names)
|
||||
- [Wrap Up: everything we shipped](https://supabase.com/blog/launch-week-6-wrap-up)
|
||||
+128
-11
@@ -71,17 +71,134 @@ Supabase es una [plataforma alojada](https://app.supabase.com). Te puedes regist
|
||||
|
||||
Nuestra librería de cliente es modular. Cada sub-librería es una implementación independiente para cada sistema externo. Esta es una de las formas de apoyar las herramientas existentes.
|
||||
|
||||
- **`supabase-{lang}`**: Combina librerías y agrega mejoras.
|
||||
- `postgrest-{lang}`: Librería de cliente para trabajar con [PostgREST](https://github.com/postgrest/postgrest)
|
||||
- `realtime-{lang}`: Librería de cliente para trabajar con [Realtime](https://github.com/supabase/realtime)
|
||||
- `gotrue-{lang}`: Librería de cliente para trabajar con [GoTrue](https://github.com/netlify/gotrue)
|
||||
|
||||
| Repositorio | Oficial | Comunidad |
|
||||
| --------------------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`supabase-{lang}`** | [`JS`](https://github.com/supabase/supabase-js) | [`C#`](https://github.com/supabase/supabase-csharp) \| [`Flutter`](https://github.com/supabase/supabase-flutter) \| [`Python`](https://github.com/supabase/supabase-py) \| `Rust` |
|
||||
| `postgrest-{lang}` | [`JS`](https://github.com/supabase/postgrest-js) | [`C#`](https://github.com/supabase/postgrest-csharp) \| [`Dart`](https://github.com/supabase/postgrest-dart) \| [`Python`](https://github.com/supabase/postgrest-py) \| [`Rust`](https://github.com/supabase/postgrest-rs) |
|
||||
| `realtime-{lang}` | [`JS`](https://github.com/supabase/realtime-js) | [`C#`](https://github.com/supabase/realtime-csharp) \| [`Dart`](https://github.com/supabase/realtime-dart) \| [`Python`](https://github.com/supabase/realtime-py) \| `Rust` |
|
||||
| `gotrue-{lang}` | [`JS`](https://github.com/supabase/gotrue-js) | [`C#`](https://github.com/supabase/gotrue-csharp) \| [`Dart`](https://github.com/supabase/gotrue-dart) \| [`Python`](https://github.com/supabase/gotrue-py) \| `Rust` |
|
||||
<table style="table-layout:fixed; white-space: nowrap;">
|
||||
<tr>
|
||||
<th>Lenguaje</th>
|
||||
<th>Cliente</th>
|
||||
<th colspan="5">Característica - Clientes (incluido en el cliente de Supabase)</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<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/realtime" target="_blank" rel="noopener noreferrer">Realtime</a></th>
|
||||
<th><a href="https://github.com/supabase/storage-api" target="_blank" rel="noopener noreferrer">Storage</a></th>
|
||||
<th>Functions</th>
|
||||
</tr>
|
||||
<!-- TEMPLATE FOR NEW ROW -->
|
||||
<!-- START ROW
|
||||
<tr>
|
||||
<td>lang</td>
|
||||
<td><a href="https://github.com/supabase-community/supabase-lang" target="_blank" rel="noopener noreferrer">supabase-lang</a></td>
|
||||
<td><a href="https://github.com/supabase-community/postgrest-lang" target="_blank" rel="noopener noreferrer">postgrest-lang</a></td>
|
||||
<td><a href="https://github.com/supabase-community/gotrue-lang" target="_blank" rel="noopener noreferrer">gotrue-lang</a></td>
|
||||
<td><a href="https://github.com/supabase-community/realtime-lang" target="_blank" rel="noopener noreferrer">realtime-lang</a></td>
|
||||
<td><a href="https://github.com/supabase-community/storage-lang" target="_blank" rel="noopener noreferrer">storage-lang</a></td>
|
||||
</tr>
|
||||
END ROW -->
|
||||
<th colspan="7">⚡️ Oficial ⚡️</th>
|
||||
<tr>
|
||||
<td>JavaScript (TypeScript)</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/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/realtime-js" target="_blank" rel="noopener noreferrer">realtime-js</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/functions-js" target="_blank" rel="noopener noreferrer">functions-js</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Flutter</td>
|
||||
<td><a href="https://github.com/supabase/supabase-flutter" target="_blank" rel="noopener noreferrer">supabase-flutter</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/realtime-dart" target="_blank" rel="noopener noreferrer">realtime-dart</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/functions-dart" target="_blank" rel="noopener noreferrer">functions-dart</a></td>
|
||||
</tr>
|
||||
<th colspan="7">💚 Comunidad 💚</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/realtime-csharp" target="_blank" rel="noopener noreferrer">realtime-csharp</a></td>
|
||||
<td><a href="https://github.com/supabase-community/storage-csharp" target="_blank" rel="noopener noreferrer">storage-csharp</a></td>
|
||||
<td><a href="https://github.com/supabase-community/functions-csharp" target="_blank" rel="noopener noreferrer">functions-csharp</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Go</td>
|
||||
<td>-</td>
|
||||
<td><a href="https://github.com/supabase-community/postgrest-go" target="_blank" rel="noopener noreferrer">postgrest-go</a></td>
|
||||
<td><a href="https://github.com/supabase-community/gotrue-go" target="_blank" rel="noopener noreferrer">gotrue-go</a></td>
|
||||
<td>-</td>
|
||||
<td><a href="https://github.com/supabase-community/storage-go" target="_blank" rel="noopener noreferrer">storage-go</a></td>
|
||||
<td><a href="https://github.com/supabase-community/functions-go" target="_blank" rel="noopener noreferrer">functions-go</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Java</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>-</td>
|
||||
<td><a href="https://github.com/supabase-community/storage-java" target="_blanke" rel="noopener noreferrer">storage-java</a></td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Kotlin</td>
|
||||
<td><a href="https://github.com/supabase-community/supabase-kt" target="_blank" rel="noopener noreferrer">supabase-kt</a></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/supabase-kt/tree/master/Realtime" target="_blank" rel="noopener noreferrer">realtime-kt</a></td>
|
||||
<td><a href="https://github.com/supabase-community/supabase-kt/tree/master/Storage" target="_blank" rel="noopener noreferrer">storage-kt</a></td>
|
||||
<td><a href="https://github.com/supabase-community/supabase-kt/tree/master/Functions" target="_blank" rel="noopener noreferrer">functions-kt</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Python</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/storage-py" target="_blank" rel="noopener noreferrer">storage-py</a></td>
|
||||
<td><a href="https://github.com/supabase-community/functions-py" target="_blank" rel="noopener noreferrer">functions-py</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Ruby</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/postgrest-rb" target="_blank" rel="noopener noreferrer">postgrest-rb</a></td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Rust</td>
|
||||
<td>-</td>
|
||||
<td><a href="https://github.com/supabase-community/postgrest-rs" target="_blank" rel="noopener noreferrer">postgrest-rs</a></td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Swift</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/realtime-swift" target="_blank" rel="noopener noreferrer">realtime-swift</a></td>
|
||||
<td><a href="https://github.com/supabase-community/storage-swift" target="_blank" rel="noopener noreferrer">storage-swift</a></td>
|
||||
<td><a href="https://github.com/supabase-community/functions-swift" target="_blank" rel="noopener noreferrer">functions-swift</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Godot Engine (GDScript)</td>
|
||||
<td><a href="https://github.com/supabase-community/godot-engine.supabase" target="_blank" rel="noopener noreferrer">supabase-gdscript</a></td>
|
||||
<td><a href="https://github.com/supabase-community/postgrest-gdscript" target="_blank" rel="noopener noreferrer">postgrest-gdscript</a></td>
|
||||
<td><a href="https://github.com/supabase-community/gotrue-gdscript" target="_blank" rel="noopener noreferrer">gotrue-gdscript</a></td>
|
||||
<td><a href="https://github.com/supabase-community/realtime-gdscript" target="_blank" rel="noopener noreferrer">realtime-gdscript</a></td>
|
||||
<td><a href="https://github.com/supabase-community/storage-gdscript" target="_blank" rel="noopener noreferrer">storage-gdscript</a></td>
|
||||
<td><a href="https://github.com/supabase-community/functions-gdscript" target="_blank" rel="noopener noreferrer">functions-gdscript</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!--- Remove this list if you're traslating to another language, it's hard to keep updated across multiple files-->
|
||||
<!--- Keep only the link to the list of translation files-->
|
||||
|
||||
@@ -616,107 +616,103 @@
|
||||
"product": "auth",
|
||||
"type": "function",
|
||||
"libs": ["js"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Auth Admin",
|
||||
"libs": ["js", "js_v1"],
|
||||
"items": [
|
||||
},
|
||||
{
|
||||
"id": "admin-api",
|
||||
"title": "Overview",
|
||||
"title": "Auth Admin",
|
||||
"slug": "admin-api",
|
||||
"libs": ["js", "js_v1"],
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"id": "get-user-by-id",
|
||||
"title": "Retrieve a user",
|
||||
"slug": "auth-admin-getuserbyid",
|
||||
"product": "auth-admin",
|
||||
"type": "function",
|
||||
"libs": ["js"]
|
||||
},
|
||||
{
|
||||
"id": "list-users",
|
||||
"title": "List all users",
|
||||
"slug": "auth-admin-listusers",
|
||||
"product": "auth-admin",
|
||||
"type": "function",
|
||||
"libs": ["js", "js_v1"]
|
||||
},
|
||||
{
|
||||
"id": "create-user",
|
||||
"title": "Create a user",
|
||||
"slug": "auth-admin-createuser",
|
||||
"product": "auth-admin",
|
||||
"type": "function",
|
||||
"libs": ["js", "js_v1"]
|
||||
},
|
||||
{
|
||||
"id": "delete-user",
|
||||
"title": "Delete a user",
|
||||
"slug": "auth-admin-deleteuser",
|
||||
"product": "auth-admin",
|
||||
"type": "function",
|
||||
"libs": ["js", "js_v1"]
|
||||
},
|
||||
{
|
||||
"id": "invite-user-by-email",
|
||||
"title": "Send an email invite link",
|
||||
"slug": "auth-admin-inviteuserbyemail",
|
||||
"product": "auth-admin",
|
||||
"type": "function",
|
||||
"libs": ["js", "js_v1"]
|
||||
},
|
||||
{
|
||||
"id": "reset-password-for-email",
|
||||
"title": "Send a password reset request",
|
||||
"slug": "auth-admin-resetpasswordforemail",
|
||||
"product": "auth-admin",
|
||||
"type": "function",
|
||||
"libs": ["js"]
|
||||
},
|
||||
{
|
||||
"id": "generate-link",
|
||||
"title": "Generate an email link",
|
||||
"slug": "auth-admin-generatelink",
|
||||
"product": "auth-admin",
|
||||
"type": "function",
|
||||
"libs": ["js"]
|
||||
},
|
||||
{
|
||||
"id": "send-mobile-otp",
|
||||
"title": "Send a one-time passcode",
|
||||
"slug": "auth-api-sendmobileotp",
|
||||
"product": "auth-server",
|
||||
"type": "function",
|
||||
"libs": ["js_v1"]
|
||||
},
|
||||
{
|
||||
"id": "update-user-by-id",
|
||||
"title": "Update a user",
|
||||
"slug": "auth-admin-updateuserbyid",
|
||||
"product": "auth-admin",
|
||||
"type": "function",
|
||||
"libs": ["js", "js_v1"]
|
||||
},
|
||||
{
|
||||
"id": "mfa-list-factors",
|
||||
"title": "List all factors for a user",
|
||||
"slug": "auth-admin-mfa-listfactors",
|
||||
"product": "auth-admin",
|
||||
"type": "function",
|
||||
"libs": ["js"]
|
||||
},
|
||||
{
|
||||
"id": "mfa-delete-factor",
|
||||
"title": "Delete a factor for a user",
|
||||
"slug": "auth-admin-mfa-deletefactor",
|
||||
"product": "auth-admin",
|
||||
"type": "function",
|
||||
"libs": ["js"]
|
||||
"items": [
|
||||
{
|
||||
"id": "get-user-by-id",
|
||||
"title": "Retrieve a user",
|
||||
"slug": "auth-admin-getuserbyid",
|
||||
"product": "auth-admin",
|
||||
"type": "function",
|
||||
"libs": ["js"]
|
||||
},
|
||||
{
|
||||
"id": "list-users",
|
||||
"title": "List all users",
|
||||
"slug": "auth-admin-listusers",
|
||||
"product": "auth-admin",
|
||||
"type": "function",
|
||||
"libs": ["js", "js_v1"]
|
||||
},
|
||||
{
|
||||
"id": "create-user",
|
||||
"title": "Create a user",
|
||||
"slug": "auth-admin-createuser",
|
||||
"product": "auth-admin",
|
||||
"type": "function",
|
||||
"libs": ["js", "js_v1"]
|
||||
},
|
||||
{
|
||||
"id": "delete-user",
|
||||
"title": "Delete a user",
|
||||
"slug": "auth-admin-deleteuser",
|
||||
"product": "auth-admin",
|
||||
"type": "function",
|
||||
"libs": ["js", "js_v1"]
|
||||
},
|
||||
{
|
||||
"id": "invite-user-by-email",
|
||||
"title": "Send an email invite link",
|
||||
"slug": "auth-admin-inviteuserbyemail",
|
||||
"product": "auth-admin",
|
||||
"type": "function",
|
||||
"libs": ["js", "js_v1"]
|
||||
},
|
||||
{
|
||||
"id": "reset-password-for-email",
|
||||
"title": "Send a password reset request",
|
||||
"slug": "auth-admin-resetpasswordforemail",
|
||||
"product": "auth-admin",
|
||||
"type": "function",
|
||||
"libs": ["js"]
|
||||
},
|
||||
{
|
||||
"id": "generate-link",
|
||||
"title": "Generate an email link",
|
||||
"slug": "auth-admin-generatelink",
|
||||
"product": "auth-admin",
|
||||
"type": "function",
|
||||
"libs": ["js"]
|
||||
},
|
||||
{
|
||||
"id": "send-mobile-otp",
|
||||
"title": "Send a one-time passcode",
|
||||
"slug": "auth-api-sendmobileotp",
|
||||
"product": "auth-server",
|
||||
"type": "function",
|
||||
"libs": ["js_v1"]
|
||||
},
|
||||
{
|
||||
"id": "update-user-by-id",
|
||||
"title": "Update a user",
|
||||
"slug": "auth-admin-updateuserbyid",
|
||||
"product": "auth-admin",
|
||||
"type": "function",
|
||||
"libs": ["js", "js_v1"]
|
||||
},
|
||||
{
|
||||
"id": "mfa-list-factors",
|
||||
"title": "List all factors for a user",
|
||||
"slug": "auth-admin-mfa-listfactors",
|
||||
"product": "auth-admin",
|
||||
"type": "function",
|
||||
"libs": ["js"]
|
||||
},
|
||||
{
|
||||
"id": "mfa-delete-factor",
|
||||
"title": "Delete a factor for a user",
|
||||
"slug": "auth-admin-mfa-deletefactor",
|
||||
"product": "auth-admin",
|
||||
"type": "function",
|
||||
"libs": ["js"]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -114,13 +114,13 @@ functions:
|
||||
title: 'signUp()'
|
||||
$ref: '@supabase/gotrue-js.GoTrueClient.signUp'
|
||||
notes: |
|
||||
- By default, the user needs to verify their email address before logging in. To turn this off, disable **Confirm email** in [your project](https://app.supabase.com/project/_/auth/settings).
|
||||
- By default, the user needs to verify their email address before logging in. To turn this off, disable **Confirm email** in [your project](https://app.supabase.com/project/_/auth/providers).
|
||||
- **Confirm email** determines if users need to confirm their email address after signing up.
|
||||
- If **Confirm email** is enabled, a `user` is returned but `session` is null.
|
||||
- If **Confirm email** is disabled, both a `user` and a `session` are returned.
|
||||
- When the user confirms their email address, they are redirected to the [`SITE_URL`](https://supabase.com/docs/reference/auth/config#site_url) by default. You can modify your `SITE_URL` or add additional redirect URLs in [your project](https://app.supabase.com/project/_/auth/settings).
|
||||
- By default, when the user confirms their email address, they are redirected to the [`SITE_URL`](https://supabase.com/docs/reference/auth/config#site_url). You can modify your `SITE_URL` or add additional redirect URLs in [your project](https://app.supabase.com/project/_/auth/url-configuration).
|
||||
- If signUp() is called for an existing confirmed user:
|
||||
- If **Confirm email** is enabled in [your project](https://app.supabase.com/project/_/auth/settings), an obfuscated/fake user object is returned.
|
||||
- If **Confirm email** is enabled in [your project](https://app.supabase.com/project/_/auth/providers), an obfuscated/fake user object is returned.
|
||||
- If **Confirm email** is disabled, the error message, `User already registered` is returned.
|
||||
- To fetch the currently logged-in user, refer to [`getUser()`](/docs/reference/javascript/auth-getuser).
|
||||
examples:
|
||||
@@ -192,7 +192,7 @@ functions:
|
||||
- This method is used for passwordless sign-ins where a OTP is sent to the user's email or phone number.
|
||||
- If you're using an email, you can configure whether you want the user to receive a magiclink or a OTP.
|
||||
- If you're using phone, you can configure whether you want the user to receive a OTP.
|
||||
- The magic link's destination URL is determined by the [`SITE_URL`](https://supabase.com/docs/reference/auth/config#site_url). You can modify the `SITE_URL` or add additional redirect urls in [your project](https://app.supabase.com/project/_/auth/settings).
|
||||
- The magic link's destination URL is determined by the [`SITE_URL`](https://supabase.com/docs/reference/auth/config#site_url). You can modify the `SITE_URL` or add additional redirect URLs in [your project](https://app.supabase.com/project/_/auth/url-configuration).
|
||||
examples:
|
||||
- id: sign-in-with-email.
|
||||
name: Sign in with email.
|
||||
@@ -236,7 +236,7 @@ functions:
|
||||
isSpotlight: false
|
||||
description: |
|
||||
When the third-party provider successfully authenticates the user, the provider will redirect the user to the URL specified in the `redirectTo` parameter. This parameter defaults to the [`SITE_URL`](https://supabase.com/docs/reference/auth/config#site_url). It does not redirect the user immediately after invoking this method.
|
||||
You can modify the `SITE_URL` or add additional redirect urls in [your project](https://app.supabase.com/project/_/auth/settings).
|
||||
You can modify the `SITE_URL` or add additional redirect URLs in [your project](https://app.supabase.com/project/_/auth/url-configuration).
|
||||
js: |
|
||||
```js
|
||||
const { data, error } = await supabase.auth.signInWithOAuth({
|
||||
@@ -334,7 +334,7 @@ functions:
|
||||
notes: |
|
||||
- In order to use the `updateUser()` method, the user needs to be signed in first.
|
||||
- By Default, email updates sends a confirmation link to both the user's current and new email.
|
||||
To only send a confirmation link to the user's new email, disable **Secure email change** in your project's [email auth provider settings](https://app.supabase.com/project/_/auth/settings).
|
||||
To only send a confirmation link to the user's new email, disable **Secure email change** in your project's [email auth provider settings](https://app.supabase.com/project/_/auth/providers).
|
||||
examples:
|
||||
- id: update-the-email-for-an-authenticated-user
|
||||
name: Update the email for an authenticated user
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -21,13 +21,13 @@ functions:
|
||||
description: |
|
||||
Creates a new user.
|
||||
notes: |
|
||||
- By default, the user needs to verify their email address before logging in. To turn this off, disable **Confirm email** in [your project](https://app.supabase.com/project/_/auth/settings).
|
||||
- By default, the user needs to verify their email address before logging in. To turn this off, disable **Confirm email** in [your project](https://app.supabase.com/project/_/auth/providers).
|
||||
- **Confirm email** determines if users need to confirm their email address after signing up.
|
||||
- If **Confirm email** is enabled, a `user` is returned but `session` is null.
|
||||
- If **Confirm email** is disabled, both a `user` and a `session` are returned.
|
||||
- When the user confirms their email address, they are redirected to the [`SITE_URL`](https://supabase.com/docs/reference/auth/config#site_url) by default. You can modify your `SITE_URL` or add additional redirect URLs in [your project](https://app.supabase.com/project/_/auth/settings).
|
||||
- When the user confirms their email address, they are redirected to the [`SITE_URL`](https://supabase.com/docs/reference/auth/config#site_url) by default. You can modify your `SITE_URL` or add additional redirect URLs in [your project](https://app.supabase.com/project/_/auth/url-configuration).
|
||||
- If signUp() is called for an existing confirmed user:
|
||||
- If **Confirm email** is enabled in [your project](https://app.supabase.com/project/_/auth/settings), an obfuscated/fake user object is returned.
|
||||
- If **Confirm email** is enabled in [your project](https://app.supabase.com/project/_/auth/providers), an obfuscated/fake user object is returned.
|
||||
- If **Confirm email** is disabled, the error message, `User already registered` is returned.
|
||||
examples:
|
||||
- id: sign-up
|
||||
@@ -85,7 +85,7 @@ functions:
|
||||
- This method is used for passwordless sign-ins where a OTP is sent to the user's email or phone number.
|
||||
- If you're using an email, you can configure whether you want the user to receive a magiclink or a OTP.
|
||||
- If you're using phone, you can configure whether you want the user to receive a OTP.
|
||||
- The magic link's destination URL is determined by the [`SITE_URL`](https://supabase.com/docs/reference/auth/config#site_url). You can modify the `SITE_URL` or add additional redirect urls in [your project](https://app.supabase.com/project/_/auth/settings).
|
||||
- The magic link's destination URL is determined by the [`SITE_URL`](https://supabase.com/docs/reference/auth/config#site_url). You can modify the `SITE_URL` or add additional redirect urls in [your project](https://app.supabase.com/project/_/auth/url-configuration).
|
||||
examples:
|
||||
- id: sign-in-with-email
|
||||
name: Sign in with email.
|
||||
@@ -229,7 +229,7 @@ functions:
|
||||
notes: |
|
||||
- In order to use the `updateUser()` method, the user needs to be signed in first.
|
||||
- By Default, email updates sends a confirmation link to both the user's current and new email.
|
||||
To only send a confirmation link to the user's new email, disable **Secure email change** in your project's [email auth provider settings](https://app.supabase.com/project/_/auth/settings).
|
||||
To only send a confirmation link to the user's new email, disable **Secure email change** in your project's [email auth provider settings](https://app.supabase.com/project/_/auth/providers).
|
||||
examples:
|
||||
- id: update-the-email-for-an-authenticated-user
|
||||
name: Update the email for an authenticated user
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -285,7 +285,7 @@ functions:
|
||||
$ref: '@supabase/gotrue-js.GoTrueClient.update'
|
||||
notes: |
|
||||
User email: By Default, email updates sends a confirmation link to both the user's current and new email.
|
||||
To only send a confirmation link to the user's new email, disable **Secure email change** in your project's [email auth provider settings](https://app.supabase.com/project/_/auth/settings).
|
||||
To only send a confirmation link to the user's new email, disable **Secure email change** in your project's [email auth provider settings](https://app.supabase.com/project/_/auth/providers).
|
||||
|
||||
User metadata: It's generally better to store user data in a table within your public schema (i.e., `public.users`).
|
||||
Use the `update()` method if you have data which rarely changes or is specific only to the logged in user.
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -136,13 +136,13 @@ functions:
|
||||
title: 'signUp()'
|
||||
$ref: '@supabase/gotrue-js.GoTrueClient.signUp'
|
||||
notes: |
|
||||
- By default, the user needs to verify their email address before logging in. To turn this off, disable **Confirm email** in [your project](https://app.supabase.com/project/_/auth/settings).
|
||||
- By default, the user needs to verify their email address before logging in. To turn this off, disable **Confirm email** in [your project](https://app.supabase.com/project/_/auth/providers).
|
||||
- **Confirm email** determines if users need to confirm their email address after signing up.
|
||||
- If **Confirm email** is enabled, a `user` is returned but `session` is null.
|
||||
- If **Confirm email** is disabled, both a `user` and a `session` are returned.
|
||||
- When the user confirms their email address, they are redirected to the [`SITE_URL`](https://supabase.com/docs/reference/auth/config#site_url) by default. You can modify your `SITE_URL` or add additional redirect URLs in [your project](https://app.supabase.com/project/_/auth/settings).
|
||||
- When the user confirms their email address, they are redirected to the [`SITE_URL`](https://supabase.com/docs/reference/auth/config#site_url) by default. You can modify your `SITE_URL` or add additional redirect URLs in [your project](https://app.supabase.com/project/_/auth/url-configuration).
|
||||
- If signUp() is called for an existing confirmed user:
|
||||
- If **Confirm email** is enabled in [your project](https://app.supabase.com/project/_/auth/settings), an obfuscated/fake user object is returned.
|
||||
- If **Confirm email** is enabled in [your project](https://app.supabase.com/project/_/auth/providers), an obfuscated/fake user object is returned.
|
||||
- If **Confirm email** is disabled, the error message, `User already registered` is returned.
|
||||
- To fetch the currently logged-in user, refer to [`getUser()`](/docs/reference/javascript/auth-getuser).
|
||||
examples:
|
||||
@@ -360,7 +360,7 @@ functions:
|
||||
notes: |
|
||||
- In order to use the `updateUser()` method, the user needs to be signed in first.
|
||||
- By Default, email updates sends a confirmation link to both the user's current and new email.
|
||||
To only send a confirmation link to the user's new email, disable **Secure email change** in your project's [email auth provider settings](https://app.supabase.com/project/_/auth/settings).
|
||||
To only send a confirmation link to the user's new email, disable **Secure email change** in your project's [email auth provider settings](https://app.supabase.com/project/_/auth/providers).
|
||||
examples:
|
||||
- id: update-the-email-for-an-authenticated-user
|
||||
name: Update the email for an authenticated user
|
||||
|
||||
@@ -52,8 +52,7 @@ export const formSubscriptionUpdatePayload = (
|
||||
},
|
||||
nonChangeableAddons: SubscriptionAddon[],
|
||||
selectedPaymentMethod: string,
|
||||
region: string,
|
||||
hcaptchaToken: string | undefined
|
||||
region: string
|
||||
) => {
|
||||
const { computeSize, pitrDuration, customDomains } = selectedAddons
|
||||
|
||||
@@ -78,8 +77,7 @@ export const formSubscriptionUpdatePayload = (
|
||||
...(tierPriceId && { tier: tierPriceId.id }),
|
||||
addons,
|
||||
proration_date,
|
||||
payment_method: selectedPaymentMethod,
|
||||
hcaptchaToken
|
||||
payment_method: selectedPaymentMethod
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,8 +114,7 @@ const EnterpriseUpdate: FC<Props> = ({
|
||||
selectedAddons,
|
||||
nonChangeableAddons,
|
||||
selectedPaymentMethodId,
|
||||
projectRegion,
|
||||
undefined
|
||||
projectRegion
|
||||
),
|
||||
tier: currentSubscription.tier.price_id,
|
||||
}
|
||||
@@ -178,8 +177,7 @@ const EnterpriseUpdate: FC<Props> = ({
|
||||
selectedAddons,
|
||||
nonChangeableAddons,
|
||||
selectedPaymentMethodId,
|
||||
projectRegion,
|
||||
token ?? undefined
|
||||
projectRegion
|
||||
),
|
||||
tier: currentSubscription.tier.price_id,
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ const ExitSurvey: FC<Props> = ({ freeTier, subscription, onSelectBack }) => {
|
||||
setMessage(values.message)
|
||||
return setShowConfirmModal(true)
|
||||
} else {
|
||||
downgradeProject(values, token as string)
|
||||
downgradeProject(values)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ const ExitSurvey: FC<Props> = ({ freeTier, subscription, onSelectBack }) => {
|
||||
captchaRef.current?.resetCaptcha()
|
||||
}
|
||||
|
||||
const downgradeProject = async (values?: any, hcaptchaToken?: string) => {
|
||||
const downgradeProject = async (values?: any) => {
|
||||
const downgradeMessage = values?.message ?? message
|
||||
|
||||
try {
|
||||
@@ -132,7 +132,6 @@ const ExitSurvey: FC<Props> = ({ freeTier, subscription, onSelectBack }) => {
|
||||
tier,
|
||||
addons,
|
||||
proration_date,
|
||||
hcaptchaToken: captchaToken ?? hcaptchaToken,
|
||||
})
|
||||
|
||||
resetCaptcha()
|
||||
|
||||
@@ -137,8 +137,7 @@ const ProUpgrade: FC<Props> = ({
|
||||
selectedAddons,
|
||||
nonChangeableAddons,
|
||||
selectedPaymentMethodId,
|
||||
projectRegion,
|
||||
undefined
|
||||
projectRegion
|
||||
)
|
||||
|
||||
setIsRefreshingPreview(true)
|
||||
@@ -184,8 +183,7 @@ const ProUpgrade: FC<Props> = ({
|
||||
selectedAddons,
|
||||
nonChangeableAddons,
|
||||
selectedPaymentMethodId,
|
||||
projectRegion,
|
||||
captchaToken ?? undefined
|
||||
projectRegion
|
||||
)
|
||||
const res = await patch(`${API_URL}/projects/${projectRef}/subscription`, payload)
|
||||
resetCaptcha()
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# Supabase
|
||||
.branches
|
||||
.temp
|
||||
@@ -0,0 +1,40 @@
|
||||
# Open Graph (OG) Image Generator
|
||||
|
||||
Generate OG Images for the sites at supabase.
|
||||
|
||||
## How to use
|
||||
|
||||
To use the og image generator, you will need to visit the site with the following parameters:
|
||||
|
||||
`site`: indicating which site you want to generate an image for. Currently, the only available option is docs.
|
||||
|
||||
`title`: representing the title of the image you want to generate.
|
||||
|
||||
`description`: representing the description of the image you want to generate.
|
||||
|
||||
`type` (optional): indicating the type of image you want to generate. This is optional and is only used for the docs site.
|
||||
|
||||
`icon` (optional): indicating the icon you want to use for the image. This is optional and is only used for the docs site.
|
||||
|
||||
If any of the required parameters are missing, you will receive a 404 response with a message indicating that some parameters are missing. If the site parameter is not recognized, you will receive a 404 response with a message indicating that the site was not found.
|
||||
|
||||
Here is an example link that you can use to test the website:
|
||||
|
||||
https://obuldanrptloktxcffvn.functions.supabase.co/og-images?site=docs&title=Example%20Title&description=Example%20Description&type=Auth&icon=google
|
||||
|
||||
This link will generate an image for the docs site with the title "Example Title", the description "Example Description", the Auth type, and the Google icon.
|
||||
|
||||
## Run locally
|
||||
|
||||
First we need to start up supabase using the [supabase cli](https://supabase.com/docs/reference/cli/introduction)
|
||||
|
||||
```bash
|
||||
supabase start
|
||||
```
|
||||
|
||||
Then run the function
|
||||
```bash
|
||||
supabase functions serve og-images
|
||||
```
|
||||
|
||||
Now we can visit [localhost:54321/functions/v1/og-images/?site=docs&title=Title&description=Description&type=Auth](http://localhost:54321/functions/v1/og-images/?site=docs&title=Title&description=Description&type=Auth) to see your changes localy.
|
||||
@@ -0,0 +1,57 @@
|
||||
import React from 'https://esm.sh/react@18.2.0?deno-std=0.140.0'
|
||||
|
||||
type Props = {
|
||||
type?: string | null
|
||||
title: string
|
||||
description: string
|
||||
icon?: string | null
|
||||
}
|
||||
|
||||
const Docs = (props: Props) => {
|
||||
const { type, title, description, icon } = props
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
color: 'white',
|
||||
backgroundColor: '#1c1c1c',
|
||||
fontFamily: 'Circular',
|
||||
backgroundImage: 'url(https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/og-images/gradient.svg)',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
}}
|
||||
>
|
||||
<div tw="flex flex-row items-center justify-center absolute top-[60px] left-[64px]">
|
||||
{icon && (
|
||||
<img src={`https://raw.githubusercontent.com/supabase/supabase/master/apps/docs/public/img/icons/${icon}-icon.svg`} width="50px" height="50px" />
|
||||
)}
|
||||
{type && icon && (
|
||||
<div tw="h-[50px] border-[1px] border-white mx-4"></div>
|
||||
)}
|
||||
{type && (
|
||||
<>
|
||||
<div tw="w-[50px] h-[50px] bg-[#164430] rounded-md flex items-center justify-center">
|
||||
<img src={`https://raw.githubusercontent.com/supabase/supabase/master/apps/docs/public/img/icons/menu/${type.toLowerCase()}.svg`} width="80%" height="80%" />
|
||||
</div>
|
||||
<span tw="text-[36px] text-[#ededed] ml-[16px]">{type}</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div tw="flex flex-col">
|
||||
<div tw="flex flex-col absolute left-[64px] top-[154px] w-[1072px]">
|
||||
<h1 tw="my-0 mb-2 text-[60px]">{title}</h1>
|
||||
<p tw="my-0 mt-2 text-[40px] text-[#f2fff9] opacity-50">{description}</p>
|
||||
</div>
|
||||
<div tw="flex flex-row items-center justify-center absolute left-[64px] top-[500px]">
|
||||
<img src="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.png" width={180} height={34} />
|
||||
<span tw="text-lg font-normal text-[#3ecf8e] ml-2">DOCS</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Docs
|
||||
@@ -0,0 +1,59 @@
|
||||
import React from 'https://esm.sh/react@18.2.0?deno-std=0.140.0'
|
||||
import { ImageResponse } from 'https://deno.land/x/og_edge@0.0.4/mod.ts'
|
||||
import Docs from './component/Docs.tsx'
|
||||
|
||||
const corsHeaders = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
|
||||
// Load custom font
|
||||
const FONT_URL = 'https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/lw6/CircularStd-Book.otf'
|
||||
const font = fetch(new URL(FONT_URL, import.meta.url)).then((res) => res.arrayBuffer())
|
||||
const fontData = await font
|
||||
|
||||
export async function handler(req: Request) {
|
||||
const url = new URL(req.url)
|
||||
const site = url.searchParams.get('site')?.toLowerCase() ?? url.searchParams.get('amp;site')?.toLowerCase()
|
||||
const icon = url.searchParams.get('icon')?.toLowerCase() ?? url.searchParams.get('amp;icon')?.toLowerCase()
|
||||
const type = url.searchParams.get('type') ?? url.searchParams.get('amp;type')
|
||||
const title = url.searchParams.get('title') ?? url.searchParams.get('amp;title')
|
||||
const description = url.searchParams.get('description') ?? url.searchParams.get('amp;description')
|
||||
|
||||
if(!site || !title || !description) {
|
||||
return new Response(JSON.stringify({ message: 'missing params' }), {
|
||||
headers: { ...corsHeaders },
|
||||
status: 404,
|
||||
})
|
||||
}
|
||||
|
||||
switch (site) {
|
||||
case 'docs':
|
||||
return new ImageResponse(( <Docs title={title} description={description} type={type} icon={icon} /> ),
|
||||
{
|
||||
width: 1200,
|
||||
height: 630,
|
||||
fonts: [
|
||||
{
|
||||
name: 'Circular',
|
||||
data: fontData,
|
||||
style: 'normal',
|
||||
},
|
||||
],
|
||||
headers: {
|
||||
'content-type': 'image/png',
|
||||
'cache-control': 'public, max-age=31536000, s-maxage=31536000, no-transform, immutable',
|
||||
'cdn-cache-control': 'max-age=31536000',
|
||||
},
|
||||
})
|
||||
break;
|
||||
|
||||
default:
|
||||
return new Response(JSON.stringify({message: 'site not found'}), {
|
||||
headers: { ...corsHeaders },
|
||||
status: 404,
|
||||
})
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
import { serve } from 'https://deno.land/std@0.170.0/http/server.ts'
|
||||
import { handler } from './handler.tsx'
|
||||
|
||||
serve(handler)
|
||||
Reference in new issue
Block a user