mirror of
https://github.com/supabase/supabase.git
synced 2026-10-13 13:19:09 +03:00
Merge branch 'master' into feature/braintrust
This commit is contained in:
commit
ca8d0defd8
283 files changed
+12932
-1561
No files matched your search
@@ -147,7 +147,7 @@ If you're a library maintainer, follow these steps when updating function parame
|
||||
|
||||
## Content reuse
|
||||
|
||||
If you copy the same content multiple times across different files, create a **partial** for content reuse instead. Partials are MDX files contained in [`apps/docs/components/MDX`](https://github.com/supabase/supabase/tree/master/apps/docs/components/MDX). They contain reusable snippets that can be inserted in multiple pages. For example, you can create a partial to define a common setup step for a group of tutorials.
|
||||
If you copy the same content multiple times across different files, create a **partial** for content reuse instead. Partials are MDX files contained in [`apps/docs/content/_partials`](https://github.com/supabase/supabase/tree/master/apps/docs/content/_partials). They contain reusable snippets that can be inserted in multiple pages. For example, you can create a partial to define a common setup step for a group of tutorials.
|
||||
|
||||
To use a partial, import it into your MDX file. You can also set up a partial to automatically import by including it in the `components` within [`apps/docs/components/index.tsx`](https://github.com/supabase/supabase/blob/master/apps/docs/components/index.tsx).
|
||||
|
||||
|
||||
@@ -1,28 +1,30 @@
|
||||
import matter from 'gray-matter'
|
||||
import Link from 'next/link'
|
||||
import { notFound } from 'next/navigation'
|
||||
import { readFile } from 'node:fs/promises'
|
||||
import { join, relative } from 'node:path'
|
||||
import rehypeSlug from 'rehype-slug'
|
||||
import emoji from 'remark-emoji'
|
||||
import Link from 'next/link'
|
||||
// End of third-party imports
|
||||
|
||||
import { IS_PROD, isFeatureEnabled } from 'common'
|
||||
import { Button } from 'ui'
|
||||
import { Admonition } from 'ui-patterns'
|
||||
|
||||
import { Guide, GuideArticle, GuideHeader, GuideFooter, GuideMdxContent } from '~/features/ui/guide'
|
||||
import { newEditLink } from '~/features/helpers.edit-link'
|
||||
import {
|
||||
genGuideMeta,
|
||||
genGuidesStaticParams,
|
||||
removeRedundantH1,
|
||||
} from '~/features/docs/GuidesMdx.utils'
|
||||
import { newEditLink } from '~/features/helpers.edit-link'
|
||||
import { REVALIDATION_TAGS } from '~/features/helpers.fetch'
|
||||
import { Guide, GuideArticle, GuideFooter, GuideHeader, GuideMdxContent } from '~/features/ui/guide'
|
||||
import { GUIDES_DIRECTORY, isValidGuideFrontmatter } from '~/lib/docs'
|
||||
import { UrlTransformFunction, linkTransform } from '~/lib/mdx/plugins/rehypeLinkTransform'
|
||||
import { linkTransform, type UrlTransformFunction } from '~/lib/mdx/plugins/rehypeLinkTransform'
|
||||
import remarkMkDocsAdmonition from '~/lib/mdx/plugins/remarkAdmonition'
|
||||
import { removeTitle } from '~/lib/mdx/plugins/remarkRemoveTitle'
|
||||
import remarkPyMdownTabs from '~/lib/mdx/plugins/remarkTabs'
|
||||
import { octokit } from '~/lib/octokit'
|
||||
import { SerializeOptions } from '~/types/next-mdx-remote-serialize'
|
||||
import { IS_PROD } from 'common'
|
||||
import type { SerializeOptions } from '~/types/next-mdx-remote-serialize'
|
||||
|
||||
// We fetch these docs at build time from an external repo
|
||||
const org = 'supabase'
|
||||
@@ -85,7 +87,10 @@ async function getLatestRelease(after: string | null = null) {
|
||||
after,
|
||||
request: {
|
||||
fetch: (url: RequestInfo | URL, options?: RequestInit) =>
|
||||
fetch(url, { ...options, next: { tags: [REVALIDATION_TAGS.WRAPPERS] } }),
|
||||
fetch(url, {
|
||||
...options,
|
||||
next: { tags: [REVALIDATION_TAGS.WRAPPERS] },
|
||||
}),
|
||||
},
|
||||
})
|
||||
|
||||
@@ -243,6 +248,10 @@ interface Params {
|
||||
}
|
||||
|
||||
const WrappersDocs = async (props: { params: Promise<Params> }) => {
|
||||
if (!isFeatureEnabled('docs:fdw')) {
|
||||
notFound()
|
||||
}
|
||||
|
||||
const params = await props.params
|
||||
const { isExternal, meta, assetsBaseUrl, ...data } = await getContent(params)
|
||||
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
|
||||
import { ChevronRight, Play, Sparkles } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
// End of third-party imports
|
||||
|
||||
import { isFeatureEnabled, useBreakpoint } from 'common'
|
||||
import { cn, IconBackground } from 'ui'
|
||||
import { IconPanel } from 'ui-patterns/IconPanel'
|
||||
|
||||
import { useCustomContent } from '../hooks/custom-content/useCustomContent'
|
||||
import DocsCoverLogo from './DocsCoverLogo'
|
||||
|
||||
const { sdkDart: sdkDartEnabled, sdkKotlin: sdkKotlinEnabled } = isFeatureEnabled([
|
||||
@@ -36,6 +37,7 @@ function AiPrompt({ className }: { className?: string }) {
|
||||
const HomePageCover = (props) => {
|
||||
const isXs = useBreakpoint(639)
|
||||
const iconSize = isXs ? 'sm' : 'lg'
|
||||
const { homepageHeading } = useCustomContent(['homepage:heading'])
|
||||
|
||||
const frameworks = [
|
||||
{
|
||||
@@ -141,7 +143,9 @@ const HomePageCover = (props) => {
|
||||
<div className="flex flex-col sm:flex-row gap-4 sm:gap-8 items-start sm:items-center w-full max-w-xl xl:max-w-[33rem]">
|
||||
<DocsCoverLogo aria-hidden="true" />
|
||||
<div className="flex flex-col">
|
||||
<h1 className="m-0 mb-3 text-2xl sm:text-3xl text-foreground">{props.title}</h1>
|
||||
<h1 className="m-0 mb-3 text-2xl sm:text-3xl text-foreground">
|
||||
{homepageHeading || props.title}
|
||||
</h1>
|
||||
<p className="m-0 text-foreground-light">
|
||||
Learn how to get up and running with Supabase through tutorials, APIs and platform
|
||||
resources.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { ComponentProps } from 'react'
|
||||
// End of third-party imports
|
||||
|
||||
import { isFeatureEnabled } from 'common/enabled-features'
|
||||
import type { IconPanel } from 'ui-patterns/IconPanel'
|
||||
@@ -14,13 +15,14 @@ const {
|
||||
docsAuthTroubleshooting: authTroubleshootingEnabled,
|
||||
docsCompliance: complianceEnabled,
|
||||
docsContribution: contributionEnabled,
|
||||
'docsSelf-hosting': selfHostingEnabled,
|
||||
docsFdw: fdwEnabled,
|
||||
docsFrameworkQuickstarts: frameworkQuickstartsEnabled,
|
||||
docsFullPlatform: fullPlatformEnabled,
|
||||
docsLocalDevelopment: localDevelopmentEnabled,
|
||||
docsMobileTutorials: mobileTutorialsEnabled,
|
||||
docsPgtap: pgTapEnabled,
|
||||
docsProductionChecklist: productionChecklistEnabled,
|
||||
'docsSelf-hosting': selfHostingEnabled,
|
||||
docsWebApps: webAppsEnabled,
|
||||
integrationsPartners: integrationsEnabled,
|
||||
sdkCsharp: sdkCsharpEnabled,
|
||||
@@ -38,6 +40,7 @@ const {
|
||||
'docs:auth_troubleshooting',
|
||||
'docs:compliance',
|
||||
'docs:contribution',
|
||||
'docs:fdw',
|
||||
'docs:self-hosting',
|
||||
'docs:framework_quickstarts',
|
||||
'docs:full_platform',
|
||||
@@ -1260,6 +1263,7 @@ export const database: NavMenuConstant = {
|
||||
{
|
||||
name: 'Foreign Data Wrappers',
|
||||
url: undefined,
|
||||
enabled: fdwEnabled,
|
||||
items: [
|
||||
{
|
||||
name: 'Overview',
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { memo, useState } from 'react'
|
||||
import { Command, Menu, Search } from 'lucide-react'
|
||||
import dynamic from 'next/dynamic'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import { Command, Search, Menu } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { memo, useState } from 'react'
|
||||
// End of third-party imports
|
||||
|
||||
import { useIsLoggedIn, useIsUserLoading, useUser } from 'common'
|
||||
import { Button, buttonVariants, cn } from 'ui'
|
||||
import { AuthenticatedDropdownMenu, CommandMenuTrigger } from 'ui-patterns'
|
||||
import { useCustomContent } from '../../../hooks/custom-content/useCustomContent'
|
||||
import GlobalNavigationMenu from './GlobalNavigationMenu'
|
||||
import useDropdownMenu from './useDropdownMenu'
|
||||
|
||||
import type { FC } from 'react'
|
||||
|
||||
const GlobalMobileMenu = dynamic(() => import('./GlobalMobileMenu'))
|
||||
const TopNavDropdown = dynamic(() => import('./TopNavDropdown'))
|
||||
|
||||
@@ -55,7 +56,8 @@ const TopNavBar: FC = () => {
|
||||
<div className="flex items-center space-x-2 text-foreground-muted">
|
||||
<Search size={18} strokeWidth={2} />
|
||||
<p className="flex text-sm pr-2">
|
||||
Search<span className="hidden xl:inline ml-1"> docs...</span>
|
||||
Search
|
||||
<span className="hidden xl:inline ml-1"> docs...</span>
|
||||
</p>
|
||||
</div>
|
||||
<div className="hidden md:flex items-center space-x-1">
|
||||
@@ -108,6 +110,8 @@ const TopNavBar: FC = () => {
|
||||
}
|
||||
|
||||
const HeaderLogo = memo(() => {
|
||||
const { navigationLogoUrl } = useCustomContent(['navigation:logo_url'])
|
||||
|
||||
return (
|
||||
<Link
|
||||
href="/"
|
||||
@@ -118,7 +122,7 @@ const HeaderLogo = memo(() => {
|
||||
>
|
||||
<Image
|
||||
className="hidden dark:block !m-0"
|
||||
src="/docs/supabase-dark.svg"
|
||||
src={navigationLogoUrl?.dark ?? '/docs/supabase-dark.svg'}
|
||||
priority={true}
|
||||
loading="eager"
|
||||
width={96}
|
||||
@@ -127,7 +131,7 @@ const HeaderLogo = memo(() => {
|
||||
/>
|
||||
<Image
|
||||
className="block dark:hidden !m-0"
|
||||
src="/docs/supabase-light.svg"
|
||||
src={navigationLogoUrl?.light ?? '/docs/supabase-light.svg'}
|
||||
priority={true}
|
||||
loading="eager"
|
||||
width={96}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
title = "Enabling the IPv4 add-on FAQ"
|
||||
topics = [ "database", "platform", "supavisor" ]
|
||||
---
|
||||
|
||||
Enabling the IPv4 add-on will attach an IPv4 address to your project's compute instance, while preserving the existing IPv6 address. Both DNS records `ref.supabase.co` and `db.ref.supabase.co` will be updated to point to the IPv4 address.
|
||||
|
||||
## How much downtime can be expected when enabling the IPv4 add-on?
|
||||
|
||||
Enabling the IPv4 add-on will not cause any downtime since existing connections will not be dropped. New inbound connections (both direct connections on ports 5432 and 6543, as well as PostgREST requests) will use the newly allocated IPv4 address.
|
||||
|
||||
## Will the project instance will be restarted?
|
||||
|
||||
No, the IPv4 add-on will not require a restart of the instance.
|
||||
|
||||
## Will IPv6 address change?
|
||||
|
||||
The IPv6 address will be preserved. New inbound connections (both direct connections on ports 5432 and 6543, as well as PostgREST requests) will use the newly allocated IPv4 address.
|
||||
|
||||
## Will existing connections be dropped?
|
||||
|
||||
DNS changes do not affect already-established connections, and only new connections will resolve the updated record. For `db.ref.supabase.co` (i.e database connections through ports 5432 and 6543), the existing AAAA record will be updated to an A record pointing to the IPv4 address. This is essentially an in-place update for `db.ref.supabase.co`'s value and record type which would externally translate to an AAAA removal and an A record creation, which mitigates against split moments in time where no record would be available.
|
||||
|
||||
## Is it the case that the new IPv4 address cannot be connected until DNS is updated?
|
||||
|
||||
Clients will use the new IPv4 address only after DNS propagation; until then, IPv6 continues to resolve and work for connectivity.
|
||||
|
||||
## Removing the IPv4 add-on
|
||||
|
||||
Removing the IPv4 add-on does tend to result in 'downtime' at a sub-minute time interval for database connections, given clients would've resolved the A record which now points to an unassigned IP address, and would need to wait for DNS propagation to go through in order for the AAAA record to be available
|
||||
@@ -0,0 +1,7 @@
|
||||
export type CustomContentTypes = {
|
||||
homepageHeading: string
|
||||
navigationLogoUrl: {
|
||||
light: string
|
||||
dark: string
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"homepage:heading": "Supabase Documentation",
|
||||
"navigation:logo_url": {
|
||||
"light": "/docs/supabase-light.svg",
|
||||
"dark": "/docs/supabase-dark.svg"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* @vitest-environment jsdom
|
||||
*/
|
||||
|
||||
import { cleanup, renderHook } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
vi.resetModules()
|
||||
cleanup()
|
||||
})
|
||||
|
||||
describe('useCustomContent', () => {
|
||||
it('should return null if content is not found in the custom-content.json file', async () => {
|
||||
vi.doMock('./custom-content.json', () => ({
|
||||
default: {
|
||||
'navigation:logo_url': null,
|
||||
},
|
||||
}))
|
||||
|
||||
const { useCustomContent } = await import('./useCustomContent')
|
||||
const { result } = renderHook(() => useCustomContent(['navigation:logo_url']))
|
||||
expect(result.current.navigationLogoUrl).toEqual(null)
|
||||
})
|
||||
|
||||
it('should return the content for the key passed in if it exists in the custom-content.json file', async () => {
|
||||
vi.doMock('./custom-content.json', () => ({
|
||||
default: {
|
||||
'navigation:logo_url': {
|
||||
light: 'https://example.com/logo-light.svg',
|
||||
dark: 'https://example.com/logo-dark.svg',
|
||||
},
|
||||
'homepage:heading': 'Custom Heading',
|
||||
},
|
||||
}))
|
||||
|
||||
const { useCustomContent } = await import('./useCustomContent')
|
||||
const { result } = renderHook(() =>
|
||||
useCustomContent(['navigation:logo_url', 'homepage:heading'])
|
||||
)
|
||||
expect(result.current.navigationLogoUrl).toEqual({
|
||||
light: 'https://example.com/logo-light.svg',
|
||||
dark: 'https://example.com/logo-dark.svg',
|
||||
})
|
||||
expect(result.current.homepageHeading).toEqual('Custom Heading')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* [Charis 2025-09-29] This file is a duplicate of studio's useCustomContent.ts
|
||||
* for now.
|
||||
*
|
||||
* We should probably consolidate these two files in the future, but we want to
|
||||
* get this change shipped quickly without worrying about smoke testing all the
|
||||
* components affected by a refactor.
|
||||
*/
|
||||
|
||||
import type { CustomContentTypes } from './CustomContent.types'
|
||||
import customContentRaw from './custom-content.json'
|
||||
|
||||
const customContentStaticObj = customContentRaw as Omit<typeof customContentRaw, '$schema'>
|
||||
type CustomContent = keyof typeof customContentStaticObj
|
||||
|
||||
type SnakeToCamelCase<S extends string> = S extends `${infer First}_${infer Rest}`
|
||||
? `${First}${SnakeToCamelCase<Capitalize<Rest>>}`
|
||||
: S
|
||||
|
||||
type CustomContentToCamelCase<S extends CustomContent> = S extends `${infer P}:${infer R}`
|
||||
? `${SnakeToCamelCase<P>}${Capitalize<SnakeToCamelCase<R>>}`
|
||||
: SnakeToCamelCase<S>
|
||||
|
||||
function contentToCamelCase(feature: CustomContent) {
|
||||
return feature
|
||||
.replace(/:/g, '_')
|
||||
.split('_')
|
||||
.map((word, index) => (index === 0 ? word : word[0].toUpperCase() + word.slice(1)))
|
||||
.join('') as CustomContentToCamelCase<typeof feature>
|
||||
}
|
||||
|
||||
const useCustomContent = <T extends CustomContent[]>(
|
||||
contents: T
|
||||
): {
|
||||
[key in CustomContentToCamelCase<T[number]>]:
|
||||
| CustomContentTypes[CustomContentToCamelCase<T[number]>]
|
||||
| null
|
||||
} => {
|
||||
// [Joshen] Running into some TS errors without the `as` here - must be overlooking something super simple
|
||||
return Object.fromEntries(
|
||||
contents.map((content) => [contentToCamelCase(content), customContentStaticObj[content]])
|
||||
) as {
|
||||
[key in CustomContentToCamelCase<T[number]>]:
|
||||
| CustomContentTypes[CustomContentToCamelCase<T[number]>]
|
||||
| null
|
||||
}
|
||||
}
|
||||
|
||||
export { useCustomContent }
|
||||
@@ -2,13 +2,14 @@
|
||||
|
||||
import dynamic from 'next/dynamic'
|
||||
import { usePathname } from 'next/navigation'
|
||||
import { memo, useEffect, type PropsWithChildren, type ReactNode } from 'react'
|
||||
import { memo, type PropsWithChildren, type ReactNode, useEffect } from 'react'
|
||||
// End of third-party imports
|
||||
|
||||
import { isFeatureEnabled } from 'common'
|
||||
import { cn } from 'ui'
|
||||
|
||||
import { type NavMenuSection } from '~/components/Navigation/Navigation.types'
|
||||
import type { NavMenuSection } from '~/components/Navigation/Navigation.types'
|
||||
import DefaultNavigationMenu, {
|
||||
MenuId,
|
||||
type MenuId,
|
||||
} from '~/components/Navigation/NavigationMenu/NavigationMenu'
|
||||
import { getMenuId } from '~/components/Navigation/NavigationMenu/NavigationMenu.utils'
|
||||
import TopNavBar from '~/components/Navigation/NavigationMenu/TopNavBar'
|
||||
@@ -17,6 +18,8 @@ import { menuState, useMenuMobileOpen } from '~/hooks/useMenuState'
|
||||
|
||||
const Footer = dynamic(() => import('~/components/Navigation/Footer'))
|
||||
|
||||
const footerEnabled = isFeatureEnabled('docs:footer')
|
||||
|
||||
const levelsData = {
|
||||
home: {
|
||||
icon: 'home',
|
||||
@@ -375,7 +378,7 @@ function SidebarSkeleton({
|
||||
menuId: _menuId,
|
||||
menuName,
|
||||
NavigationMenu,
|
||||
hideFooter = false,
|
||||
hideFooter = !footerEnabled,
|
||||
className,
|
||||
hideSideNav,
|
||||
additionalNavItems,
|
||||
|
||||
@@ -128,6 +128,7 @@
|
||||
"@graphql-codegen/typescript": "4.1.6",
|
||||
"@graphql-codegen/typescript-resolvers": "4.5.0",
|
||||
"@supabase/supa-mdx-lint": "0.3.1",
|
||||
"@testing-library/react": "^16.0.0",
|
||||
"@types/common-tags": "^1.8.4",
|
||||
"@types/estree": "1.0.5",
|
||||
"@types/graphql-validation-complexity": "^0.4.4",
|
||||
|
||||
@@ -95,6 +95,7 @@ Luca Forstner
|
||||
Manan Gupta
|
||||
Margarita Sandomirskaia
|
||||
Mark Burggraf
|
||||
Matt Johnston
|
||||
Matt Rossman
|
||||
Monica Khoury
|
||||
Mykhailo Mischa Lieibenson
|
||||
|
||||
@@ -168,7 +168,7 @@ const Pagination = () => {
|
||||
onKeyDown={(e) => {
|
||||
const parsedValue = Number(value)
|
||||
if (
|
||||
e.code === 'Enter' &&
|
||||
(e.code === 'Enter' || e.code === 'NumpadEnter') &&
|
||||
!Number.isNaN(parsedValue) &&
|
||||
parsedValue >= 1 &&
|
||||
parsedValue <= maxPages
|
||||
|
||||
@@ -11,6 +11,7 @@ import { tableRowKeys } from 'data/table-rows/keys'
|
||||
import { useTableRowUpdateMutation } from 'data/table-rows/table-row-update-mutation'
|
||||
import type { TableRowsData } from 'data/table-rows/table-rows-query'
|
||||
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { useGetImpersonatedRoleState } from 'state/role-impersonation-state'
|
||||
import { useTableEditorTableStateSnapshot } from 'state/table-editor-table'
|
||||
import { Dictionary } from 'types'
|
||||
@@ -115,7 +116,7 @@ export function useOnRowsChange(rows: SupaRow[]) {
|
||||
each row before updating or deleting the row.
|
||||
</p>
|
||||
<div className="mt-3">
|
||||
<DocsButton href="https://supabase.com/docs/guides/database/tables#primary-keys" />
|
||||
<DocsButton href={`${DOCS_URL}/guides/database/tables#primary-keys`} />
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
|
||||
@@ -17,6 +17,7 @@ import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
|
||||
import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions'
|
||||
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
|
||||
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { RoleImpersonationState } from 'lib/role-impersonation'
|
||||
import {
|
||||
useRoleImpersonationStateSnapshot,
|
||||
@@ -47,7 +48,7 @@ export const MAX_EXPORT_ROW_COUNT_MESSAGE = (
|
||||
<>
|
||||
Sorry! We're unable to support exporting row counts larger than $
|
||||
{MAX_EXPORT_ROW_COUNT.toLocaleString()} at the moment. Alternatively, you may consider using
|
||||
<Link href="https://supabase.com/docs/reference/cli/supabase-db-dump" target="_blank">
|
||||
<Link href={`${DOCS_URL}/reference/cli/supabase-db-dump`} target="_blank">
|
||||
pg_dump
|
||||
</Link>{' '}
|
||||
via our CLI instead.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Image from 'next/image'
|
||||
|
||||
import { InlineLink } from 'components/ui/InlineLink'
|
||||
import { BASE_PATH } from 'lib/constants'
|
||||
import { BASE_PATH, DOCS_URL } from 'lib/constants'
|
||||
|
||||
export const Branching2Preview = () => {
|
||||
return (
|
||||
@@ -16,7 +16,7 @@ export const Branching2Preview = () => {
|
||||
<p className="text-sm text-foreground-light mb-4">
|
||||
Create branches, review changes, and merge back into production all through the dashboard.
|
||||
Read the below limitations and our{' '}
|
||||
<InlineLink href="https://supabase.com/docs/guides/platform/branching">
|
||||
<InlineLink href={`${DOCS_URL}/guides/platform/branching`}>
|
||||
branching documentation
|
||||
</InlineLink>{' '}
|
||||
before opting in.
|
||||
|
||||
@@ -3,7 +3,7 @@ import Image from 'next/image'
|
||||
import { useParams } from 'common'
|
||||
import { Markdown } from 'components/interfaces/Markdown'
|
||||
import { InlineLink } from 'components/ui/InlineLink'
|
||||
import { BASE_PATH } from 'lib/constants'
|
||||
import { BASE_PATH, DOCS_URL } from 'lib/constants'
|
||||
import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, WarningIcon } from 'ui'
|
||||
|
||||
export const CLSPreview = () => {
|
||||
@@ -14,11 +14,11 @@ export const CLSPreview = () => {
|
||||
<div className="mb-4 flex flex-col gap-y-2">
|
||||
<Markdown
|
||||
className="text-foreground-light max-w-full"
|
||||
content={`[Postgres Column-Level Privileges](https://supabase.com/docs/guides/auth/column-level-security) is a feature of Postgres that allows you to grant or revoke privileges on tables and columns based on user roles.`}
|
||||
content={`[Postgres Column-Level Privileges](${DOCS_URL}/guides/auth/column-level-security) is a feature of Postgres that allows you to grant or revoke privileges on tables and columns based on user roles.`}
|
||||
/>
|
||||
<Markdown
|
||||
className="text-foreground-light max-w-full"
|
||||
content={`This is an advanced feature and should be used with caution. Unless you have a very specific use case, we recommend just using [Row-Level Security](https://supabase.com/docs/guides/auth/row-level-security).`}
|
||||
content={`This is an advanced feature and should be used with caution. Unless you have a very specific use case, we recommend just using [Row-Level Security](${DOCS_URL}/guides/auth/row-level-security).`}
|
||||
/>
|
||||
<Alert_Shadcn_ variant="warning" className="mt-2">
|
||||
<WarningIcon />
|
||||
|
||||
@@ -2,6 +2,7 @@ import { ExternalLink } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
|
||||
import { useParams } from 'common'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import {
|
||||
Alert_Shadcn_,
|
||||
AlertDescription_Shadcn_,
|
||||
@@ -31,7 +32,7 @@ export const AuthAlert = ({
|
||||
below. Developers using this provider should move over to the new provider. Please refer
|
||||
to our{' '}
|
||||
<a
|
||||
href="https://supabase.com/docs/guides/auth/social-login/auth-slack"
|
||||
href={`${DOCS_URL}/guides/auth/social-login/auth-slack`}
|
||||
className="underline"
|
||||
target="_blank"
|
||||
>
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
import { ResourceList } from 'components/ui/Resource/ResourceList'
|
||||
import { HorizontalShimmerWithIcon } from 'components/ui/Shimmers/Shimmers'
|
||||
import { useAuthConfigQuery } from 'data/auth/auth-config-query'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import {
|
||||
Alert_Shadcn_,
|
||||
AlertDescription_Shadcn_,
|
||||
@@ -53,7 +54,7 @@ export const AuthProvidersForm = () => {
|
||||
to more than an hour. It is recommended to set this value to less than an hour.
|
||||
</p>
|
||||
<Button asChild type="default" className="w-min" icon={<ExternalLink />}>
|
||||
<Link href="https://supabase.com/docs/guides/platform/going-into-prod#security">
|
||||
<Link href={`${DOCS_URL}/guides/platform/going-into-prod#security`}>
|
||||
View security recommendations
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { NO_REQUIRED_CHARACTERS, urlRegex } from 'components/interfaces/Auth/Auth.constants'
|
||||
import { ProjectAuthConfigData } from 'data/auth/auth-config-query'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { boolean, number, object, string } from 'yup'
|
||||
|
||||
const parseBase64URL = (b64url: string) => {
|
||||
@@ -12,7 +13,7 @@ const PROVIDER_EMAIL = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'Email',
|
||||
link: 'https://supabase.com/docs/guides/auth/passwords',
|
||||
link: `${DOCS_URL}/guides/auth/passwords`,
|
||||
properties: {
|
||||
EXTERNAL_EMAIL_ENABLED: {
|
||||
title: 'Enable Email provider',
|
||||
@@ -95,7 +96,7 @@ const PROVIDER_EMAIL = {
|
||||
misc: {
|
||||
iconKey: 'email-icon2',
|
||||
helper: `To complete setup, add this authorisation callback URL to your app's configuration in the Apple Developer Console.
|
||||
[Learn more](https://supabase.com/docs/guides/auth/social-login/auth-apple#configure-your-services-id)`,
|
||||
[Learn more](${DOCS_URL}/guides/auth/social-login/auth-apple#configure-your-services-id)`,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -217,7 +218,7 @@ export const PROVIDER_PHONE = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'Phone',
|
||||
link: 'https://supabase.com/docs/guides/auth/phone-login',
|
||||
link: `${DOCS_URL}/guides/auth/phone-login`,
|
||||
properties: {
|
||||
EXTERNAL_PHONE_ENABLED: {
|
||||
title: 'Enable Phone provider',
|
||||
@@ -418,7 +419,7 @@ export const PROVIDER_PHONE = {
|
||||
misc: {
|
||||
iconKey: 'phone-icon4',
|
||||
helper: `To complete setup, add this authorisation callback URL to your app's configuration in the Apple Developer Console.
|
||||
[Learn more](https://supabase.com/docs/guides/auth/social-login/auth-apple#configure-your-services-id)`,
|
||||
[Learn more](${DOCS_URL}/guides/auth/social-login/auth-apple#configure-your-services-id)`,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -426,7 +427,7 @@ const EXTERNAL_PROVIDER_APPLE = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'Apple',
|
||||
link: 'https://supabase.com/docs/guides/auth/social-login/auth-apple',
|
||||
link: `${DOCS_URL}/guides/auth/social-login/auth-apple`,
|
||||
properties: {
|
||||
EXTERNAL_APPLE_ENABLED: {
|
||||
title: 'Enable Sign in with Apple',
|
||||
@@ -441,7 +442,7 @@ const EXTERNAL_PROVIDER_APPLE = {
|
||||
},
|
||||
EXTERNAL_APPLE_SECRET: {
|
||||
title: 'Secret Key (for OAuth)',
|
||||
description: `Secret key used in the OAuth flow. [Learn more](https://supabase.com/docs/guides/auth/social-login/auth-apple#generate-a-client_secret)`,
|
||||
description: `Secret key used in the OAuth flow. [Learn more](${DOCS_URL}/guides/auth/social-login/auth-apple#generate-a-client_secret)`,
|
||||
type: 'string',
|
||||
isSecret: true,
|
||||
},
|
||||
@@ -527,7 +528,7 @@ const EXTERNAL_PROVIDER_APPLE = {
|
||||
iconKey: 'apple-icon',
|
||||
requiresRedirect: true,
|
||||
helper: `Register this callback URL when using Sign in with Apple on the web in the Apple Developer Center.
|
||||
[Learn more](https://supabase.com/docs/guides/auth/social-login/auth-apple#configure-your-services-id)`,
|
||||
[Learn more](${DOCS_URL}/guides/auth/social-login/auth-apple#configure-your-services-id)`,
|
||||
alert: {
|
||||
title: `Apple OAuth secret keys expire every 6 months`,
|
||||
description: `A new secret should be generated every 6 months, otherwise users on the web will not be able to sign in.`,
|
||||
@@ -539,7 +540,7 @@ const EXTERNAL_PROVIDER_AZURE = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'Azure',
|
||||
link: 'https://supabase.com/docs/guides/auth/social-login/auth-azure',
|
||||
link: `${DOCS_URL}/guides/auth/social-login/auth-azure`,
|
||||
properties: {
|
||||
EXTERNAL_AZURE_ENABLED: {
|
||||
title: 'Azure enabled',
|
||||
@@ -553,7 +554,7 @@ const EXTERNAL_PROVIDER_AZURE = {
|
||||
EXTERNAL_AZURE_SECRET: {
|
||||
// [TODO] Change docs
|
||||
title: 'Secret Value',
|
||||
description: `Enter the data from Value, not the Secret ID. [Learn more](https://supabase.com/docs/guides/auth/social-login/auth-azure#obtain-a-secret-id)`,
|
||||
description: `Enter the data from Value, not the Secret ID. [Learn more](${DOCS_URL}/guides/auth/social-login/auth-azure#obtain-a-secret-id)`,
|
||||
type: 'string',
|
||||
isSecret: true,
|
||||
},
|
||||
@@ -588,7 +589,7 @@ const EXTERNAL_PROVIDER_BITBUCKET = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'Bitbucket',
|
||||
link: 'https://supabase.com/docs/guides/auth/social-login/auth-bitbucket',
|
||||
link: `${DOCS_URL}/guides/auth/social-login/auth-bitbucket`,
|
||||
properties: {
|
||||
EXTERNAL_BITBUCKET_ENABLED: {
|
||||
title: 'Bitbucket enabled',
|
||||
@@ -627,7 +628,7 @@ const EXTERNAL_PROVIDER_DISCORD = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'Discord',
|
||||
link: 'https://supabase.com/docs/guides/auth/social-login/auth-discord?',
|
||||
link: `${DOCS_URL}/guides/auth/social-login/auth-discord?`,
|
||||
properties: {
|
||||
EXTERNAL_DISCORD_ENABLED: {
|
||||
title: 'Discord enabled',
|
||||
@@ -666,7 +667,7 @@ const EXTERNAL_PROVIDER_FACEBOOK = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'Facebook',
|
||||
link: 'https://supabase.com/docs/guides/auth/social-login/auth-facebook',
|
||||
link: `${DOCS_URL}/guides/auth/social-login/auth-facebook`,
|
||||
properties: {
|
||||
EXTERNAL_FACEBOOK_ENABLED: {
|
||||
title: 'Facebook enabled',
|
||||
@@ -705,7 +706,7 @@ const EXTERNAL_PROVIDER_FIGMA = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'Figma',
|
||||
link: 'https://supabase.com/docs/guides/auth/social-login/auth-figma',
|
||||
link: `${DOCS_URL}/guides/auth/social-login/auth-figma`,
|
||||
properties: {
|
||||
EXTERNAL_FIGMA_ENABLED: {
|
||||
title: 'Figma enabled',
|
||||
@@ -744,7 +745,7 @@ const EXTERNAL_PROVIDER_GITHUB = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'GitHub',
|
||||
link: 'https://supabase.com/docs/guides/auth/social-login/auth-github',
|
||||
link: `${DOCS_URL}/guides/auth/social-login/auth-github`,
|
||||
properties: {
|
||||
EXTERNAL_GITHUB_ENABLED: {
|
||||
title: 'GitHub enabled',
|
||||
@@ -783,7 +784,7 @@ const EXTERNAL_PROVIDER_GITLAB = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'GitLab',
|
||||
link: 'https://supabase.com/docs/guides/auth/social-login/auth-gitlab',
|
||||
link: `${DOCS_URL}/guides/auth/social-login/auth-gitlab`,
|
||||
properties: {
|
||||
EXTERNAL_GITLAB_ENABLED: {
|
||||
title: 'GitLab enabled',
|
||||
@@ -830,7 +831,7 @@ const EXTERNAL_PROVIDER_GOOGLE = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'Google',
|
||||
link: 'https://supabase.com/docs/guides/auth/social-login/auth-google',
|
||||
link: `${DOCS_URL}/guides/auth/social-login/auth-google`,
|
||||
properties: {
|
||||
EXTERNAL_GOOGLE_ENABLED: {
|
||||
title: 'Enable Sign in with Google',
|
||||
@@ -884,7 +885,7 @@ const EXTERNAL_PROVIDER_GOOGLE = {
|
||||
iconKey: 'google-icon',
|
||||
requiresRedirect: true,
|
||||
helper: `Register this callback URL when using Sign-in with Google on the web using OAuth.
|
||||
[Learn more](https://supabase.com/docs/guides/auth/social-login/auth-google#configure-your-services-id)`,
|
||||
[Learn more](${DOCS_URL}/guides/auth/social-login/auth-google#configure-your-services-id)`,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -892,7 +893,7 @@ const EXTERNAL_PROVIDER_KAKAO = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'Kakao',
|
||||
link: 'https://supabase.com/docs/guides/auth/social-login/auth-kakao',
|
||||
link: `${DOCS_URL}/guides/auth/social-login/auth-kakao`,
|
||||
properties: {
|
||||
EXTERNAL_KAKAO_ENABLED: {
|
||||
title: 'Kakao enabled',
|
||||
@@ -934,7 +935,7 @@ const EXTERNAL_PROVIDER_KEYCLOAK = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'KeyCloak',
|
||||
link: 'https://supabase.com/docs/guides/auth/social-login/auth-keycloak',
|
||||
link: `${DOCS_URL}/guides/auth/social-login/auth-keycloak`,
|
||||
properties: {
|
||||
EXTERNAL_KEYCLOAK_ENABLED: {
|
||||
title: 'Keycloak enabled',
|
||||
@@ -985,7 +986,7 @@ const EXTERNAL_PROVIDER_LINKEDIN_OIDC = {
|
||||
type: 'object',
|
||||
key: 'linkedin_oidc',
|
||||
title: 'LinkedIn (OIDC)',
|
||||
link: 'https://supabase.com/docs/guides/auth/social-login/auth-linkedin',
|
||||
link: `${DOCS_URL}/guides/auth/social-login/auth-linkedin`,
|
||||
properties: {
|
||||
EXTERNAL_LINKEDIN_OIDC_ENABLED: {
|
||||
title: 'LinkedIn enabled',
|
||||
@@ -1024,7 +1025,7 @@ const EXTERNAL_PROVIDER_NOTION = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'Notion',
|
||||
link: 'https://supabase.com/docs/guides/auth/social-login/auth-notion',
|
||||
link: `${DOCS_URL}/guides/auth/social-login/auth-notion`,
|
||||
properties: {
|
||||
EXTERNAL_NOTION_ENABLED: {
|
||||
title: 'Notion enabled',
|
||||
@@ -1063,7 +1064,7 @@ const EXTERNAL_PROVIDER_TWITCH = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'Twitch',
|
||||
link: 'https://supabase.com/docs/guides/auth/social-login/auth-twitch',
|
||||
link: `${DOCS_URL}/guides/auth/social-login/auth-twitch`,
|
||||
properties: {
|
||||
EXTERNAL_TWITCH_ENABLED: {
|
||||
title: 'Twitch enabled',
|
||||
@@ -1102,7 +1103,7 @@ const EXTERNAL_PROVIDER_TWITTER = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'Twitter',
|
||||
link: 'https://supabase.com/docs/guides/auth/social-login/auth-twitter',
|
||||
link: `${DOCS_URL}/guides/auth/social-login/auth-twitter`,
|
||||
properties: {
|
||||
EXTERNAL_TWITTER_ENABLED: {
|
||||
title: 'Twitter enabled',
|
||||
@@ -1141,7 +1142,7 @@ const EXTERNAL_PROVIDER_SLACK = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'Slack (Deprecated)',
|
||||
link: 'https://supabase.com/docs/guides/auth/social-login/auth-slack',
|
||||
link: `${DOCS_URL}/guides/auth/social-login/auth-slack`,
|
||||
properties: {
|
||||
EXTERNAL_SLACK_ENABLED: {
|
||||
title: 'Slack enabled',
|
||||
@@ -1181,7 +1182,7 @@ const EXTERNAL_PROVIDER_SLACK_OIDC = {
|
||||
type: 'object',
|
||||
title: 'Slack (OIDC)',
|
||||
key: 'slack_oidc',
|
||||
link: 'https://supabase.com/docs/guides/auth/social-login/auth-slack',
|
||||
link: `${DOCS_URL}/guides/auth/social-login/auth-slack`,
|
||||
properties: {
|
||||
EXTERNAL_SLACK_OIDC_ENABLED: {
|
||||
title: 'Slack enabled',
|
||||
@@ -1220,7 +1221,7 @@ const EXTERNAL_PROVIDER_SPOTIFY = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'Spotify',
|
||||
link: 'https://supabase.com/docs/guides/auth/social-login/auth-spotify',
|
||||
link: `${DOCS_URL}/guides/auth/social-login/auth-spotify`,
|
||||
properties: {
|
||||
EXTERNAL_SPOTIFY_ENABLED: {
|
||||
title: 'Spotify enabled',
|
||||
@@ -1259,7 +1260,7 @@ const EXTERNAL_PROVIDER_WORKOS = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'WorkOS',
|
||||
link: 'https://supabase.com/docs/guides/auth/social-login/auth-workos',
|
||||
link: `${DOCS_URL}/guides/auth/social-login/auth-workos`,
|
||||
properties: {
|
||||
EXTERNAL_WORKOS_ENABLED: {
|
||||
title: 'WorkOS enabled',
|
||||
@@ -1309,7 +1310,7 @@ const EXTERNAL_PROVIDER_ZOOM = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'Zoom',
|
||||
link: 'https://supabase.com/docs/guides/auth/social-login/auth-zoom',
|
||||
link: `${DOCS_URL}/guides/auth/social-login/auth-zoom`,
|
||||
properties: {
|
||||
EXTERNAL_ZOOM_ENABLED: {
|
||||
title: 'Zoom enabled',
|
||||
@@ -1348,12 +1349,11 @@ const PROVIDER_SAML = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'SAML 2.0',
|
||||
link: 'https://supabase.com/docs/guides/auth/enterprise-sso/auth-sso-saml',
|
||||
link: `${DOCS_URL}/guides/auth/enterprise-sso/auth-sso-saml`,
|
||||
properties: {
|
||||
SAML_ENABLED: {
|
||||
title: 'Enable SAML 2.0 Single Sign-on',
|
||||
description:
|
||||
'You will need to use the [Supabase CLI](https://supabase.com/docs/guides/auth/sso/auth-sso-saml#managing-saml-20-connections) to set up SAML after enabling it',
|
||||
description: `You will need to use the [Supabase CLI](${DOCS_URL}/guides/auth/sso/auth-sso-saml#managing-saml-20-connections) to set up SAML after enabling it`,
|
||||
type: 'boolean',
|
||||
},
|
||||
SAML_EXTERNAL_URL: {
|
||||
@@ -1385,7 +1385,7 @@ const PROVIDER_WEB3 = {
|
||||
$schema: JSON_SCHEMA_VERSION,
|
||||
type: 'object',
|
||||
title: 'Web3 Wallet',
|
||||
link: 'https://supabase.com/docs/guides/auth/auth-web3',
|
||||
link: `${DOCS_URL}/guides/auth/auth-web3`,
|
||||
properties: {
|
||||
EXTERNAL_WEB3_ETHEREUM_ENABLED: {
|
||||
title: 'Enable Sign in with Ethereum',
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import type { FormSchema } from 'types'
|
||||
import { object, string } from 'yup'
|
||||
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import type { FormSchema } from 'types'
|
||||
|
||||
const JSON_SCHEMA_VERSION = 'http://json-schema.org/draft-07/schema#'
|
||||
|
||||
const CONFIRMATION: FormSchema = {
|
||||
@@ -34,7 +36,7 @@ const CONFIRMATION: FormSchema = {
|
||||
misc: {
|
||||
iconKey: 'email-icon2',
|
||||
helper: `To complete setup, add this authorisation callback URL to your app's configuration in the Apple Developer Console.
|
||||
[Learn more](https://supabase.com/docs/guides/auth/social-login/auth-apple#configure-your-services-id)`,
|
||||
[Learn more](${DOCS_URL}/guides/auth/social-login/auth-apple#configure-your-services-id)`,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -69,7 +71,7 @@ const INVITE: FormSchema = {
|
||||
misc: {
|
||||
iconKey: 'email-icon2',
|
||||
helper: `To complete setup, add this authorisation callback URL to your app's configuration in the Apple Developer Console.
|
||||
[Learn more](https://supabase.com/docs/guides/auth/social-login/auth-apple#configure-your-services-id)`,
|
||||
[Learn more](${DOCS_URL}/guides/auth/social-login/auth-apple#configure-your-services-id)`,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -104,7 +106,7 @@ const MAGIC_LINK: FormSchema = {
|
||||
misc: {
|
||||
iconKey: 'email-icon2',
|
||||
helper: `To complete setup, add this authorisation callback URL to your app's configuration in the Apple Developer Console.
|
||||
[Learn more](https://supabase.com/docs/guides/auth/social-login/auth-apple#configure-your-services-id)`,
|
||||
[Learn more](${DOCS_URL}/guides/auth/social-login/auth-apple#configure-your-services-id)`,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -140,7 +142,7 @@ const EMAIL_CHANGE: FormSchema = {
|
||||
misc: {
|
||||
iconKey: 'email-icon2',
|
||||
helper: `To complete setup, add this authorisation callback URL to your app's configuration in the Apple Developer Console.
|
||||
[Learn more](https://supabase.com/docs/guides/auth/social-login/auth-apple#configure-your-services-id)`,
|
||||
[Learn more](${DOCS_URL}/guides/auth/social-login/auth-apple#configure-your-services-id)`,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -175,7 +177,7 @@ const RECOVERY: FormSchema = {
|
||||
misc: {
|
||||
iconKey: 'email-icon2',
|
||||
helper: `To complete setup, add this authorisation callback URL to your app's configuration in the Apple Developer Console.
|
||||
[Learn more](https://supabase.com/docs/guides/auth/social-login/auth-apple#configure-your-services-id)`,
|
||||
[Learn more](${DOCS_URL}/guides/auth/social-login/auth-apple#configure-your-services-id)`,
|
||||
},
|
||||
}
|
||||
const REAUTHENTICATION: FormSchema = {
|
||||
@@ -206,7 +208,7 @@ const REAUTHENTICATION: FormSchema = {
|
||||
misc: {
|
||||
iconKey: 'email-icon2',
|
||||
helper: `To complete setup, add this authorisation callback URL to your app's configuration in the Apple Developer Console.
|
||||
[Learn more](https://supabase.com/docs/guides/auth/social-login/auth-apple#configure-your-services-id)`,
|
||||
[Learn more](${DOCS_URL}/guides/auth/social-login/auth-apple#configure-your-services-id)`,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -15,6 +15,7 @@ import { useAuthConfigQuery } from 'data/auth/auth-config-query'
|
||||
import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation'
|
||||
import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions'
|
||||
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import {
|
||||
AlertDescription_Shadcn_,
|
||||
AlertTitle_Shadcn_,
|
||||
@@ -186,7 +187,7 @@ export const BasicAuthSettingsForm = () => {
|
||||
Enable{' '}
|
||||
<InlineLink
|
||||
className="text-foreground-light hover:text-foreground"
|
||||
href="https://supabase.com/docs/guides/auth/auth-identity-linking#manual-linking-beta"
|
||||
href={`${DOCS_URL}/guides/auth/auth-identity-linking#manual-linking-beta`}
|
||||
>
|
||||
manual linking APIs
|
||||
</InlineLink>{' '}
|
||||
@@ -219,7 +220,7 @@ export const BasicAuthSettingsForm = () => {
|
||||
Enable{' '}
|
||||
<InlineLink
|
||||
className="text-foreground-light hover:text-foreground"
|
||||
href="https://supabase.com/docs/guides/auth/auth-anonymous"
|
||||
href={`${DOCS_URL}/guides/auth/auth-anonymous`}
|
||||
>
|
||||
anonymous sign-ins
|
||||
</InlineLink>{' '}
|
||||
@@ -263,7 +264,7 @@ export const BasicAuthSettingsForm = () => {
|
||||
to ensure that access to your data is restricted where required.
|
||||
</p>
|
||||
<Button asChild type="default" className="w-min" icon={<ExternalLink />}>
|
||||
<Link href="https://supabase.com/docs/guides/auth/auth-anonymous#access-control">
|
||||
<Link href={`${DOCS_URL}/guides/auth/auth-anonymous#access-control`}>
|
||||
View access control docs
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
+2
-1
@@ -2,6 +2,7 @@ import Link from 'next/link'
|
||||
|
||||
import { useParams } from 'common'
|
||||
import { InlineLink } from 'components/ui/InlineLink'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import {
|
||||
AlertDescription_Shadcn_,
|
||||
AlertTitle_Shadcn_,
|
||||
@@ -20,7 +21,7 @@ export function EmailRateLimitsAlert() {
|
||||
<AlertDescription_Shadcn_>
|
||||
You're using the built-in email service. The service has rate limits and it's not meant to
|
||||
be used for production apps. Check the{' '}
|
||||
<InlineLink href="https://supabase.com/docs/guides/platform/going-into-prod#auth-rate-limits">
|
||||
<InlineLink href={`${DOCS_URL}/guides/platform/going-into-prod#auth-rate-limits`}>
|
||||
documentation
|
||||
</InlineLink>{' '}
|
||||
for an up-to-date information on the current rate limits.
|
||||
|
||||
@@ -17,6 +17,7 @@ import { AuthConfigResponse } from 'data/auth/auth-config-query'
|
||||
import { useAuthHooksUpdateMutation } from 'data/auth/auth-hooks-update-mutation'
|
||||
import { executeSql } from 'data/sql/execute-sql-query'
|
||||
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import {
|
||||
Button,
|
||||
FormControl_Shadcn_,
|
||||
@@ -290,7 +291,7 @@ export const CreateHookSheet = ({
|
||||
{isCreating ? `Add ${title}` : `Update ${title}`}
|
||||
</SheetTitle>
|
||||
</div>
|
||||
<DocsButton href={'https://supabase.com/docs/guides/auth/auth-hooks/' + hook.docSlug} />
|
||||
<DocsButton href={`${DOCS_URL}/guides/auth/auth-hooks/${hook.docSlug}`} />
|
||||
</SheetHeader>
|
||||
<Separator />
|
||||
<SheetSection className="overflow-auto flex-grow px-0">
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Check, Webhook } from 'lucide-react'
|
||||
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
|
||||
import { DocsButton } from 'components/ui/DocsButton'
|
||||
import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { Badge, Input, copyToClipboard } from 'ui'
|
||||
import { Hook } from './hooks.constants'
|
||||
|
||||
@@ -108,7 +109,7 @@ export const HookCard = ({ hook, onSelect }: HookCardProps) => {
|
||||
>
|
||||
Configure hook
|
||||
</ButtonTooltip>
|
||||
<DocsButton href={'https://supabase.com/docs/guides/auth/auth-hooks/' + hook.docSlug} />
|
||||
<DocsButton href={`${DOCS_URL}/guides/auth/auth-hooks/${hook.docSlug}`} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
|
||||
+2
-4
@@ -2,6 +2,7 @@ import { noop } from 'lodash'
|
||||
import { ChevronLeft, FlaskConical } from 'lucide-react'
|
||||
|
||||
import { DocsButton } from 'components/ui/DocsButton'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { Button } from 'ui'
|
||||
import { POLICY_MODAL_VIEWS } from '../Policies.constants'
|
||||
|
||||
@@ -59,10 +60,7 @@ const PolicyEditorModalTitle = ({
|
||||
Try Supabase Assistant
|
||||
</Button>
|
||||
)}
|
||||
<DocsButton
|
||||
className="mt-[-4px]"
|
||||
href="https://supabase.com/docs/learn/auth-deep-dive/auth-policies"
|
||||
/>
|
||||
<DocsButton className="mt-[-4px]" href={`${DOCS_URL}/learn/auth-deep-dive/auth-policies`} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
+3
-2
@@ -13,6 +13,7 @@ import NoPermission from 'components/ui/NoPermission'
|
||||
import { useAuthConfigQuery } from 'data/auth/auth-config-query'
|
||||
import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation'
|
||||
import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import {
|
||||
AlertDescription_Shadcn_,
|
||||
AlertTitle_Shadcn_,
|
||||
@@ -214,9 +215,9 @@ export const ProtectionAuthSettingsForm = () => {
|
||||
<InlineLink
|
||||
href={
|
||||
field.value === 'hcaptcha'
|
||||
? 'https://supabase.com/docs/guides/auth/auth-captcha?queryGroups=captcha-method&captcha-method=hcaptcha-1'
|
||||
? `${DOCS_URL}/guides/auth/auth-captcha?queryGroups=captcha-method&captcha-method=hcaptcha-1`
|
||||
: field.value === 'turnstile'
|
||||
? 'https://supabase.com/docs/guides/auth/auth-captcha?queryGroups=captcha-method&captcha-method=turnstile-1'
|
||||
? `${DOCS_URL}/guides/auth/auth-captcha?queryGroups=captcha-method&captcha-method=turnstile-1`
|
||||
: '/'
|
||||
}
|
||||
className="mt-2 text-xs text-foreground-light hover:text-foreground no-underline"
|
||||
|
||||
@@ -11,6 +11,7 @@ import { DocsButton } from 'components/ui/DocsButton'
|
||||
import { HorizontalShimmerWithIcon } from 'components/ui/Shimmers/Shimmers'
|
||||
import { useAuthConfigQuery } from 'data/auth/auth-config-query'
|
||||
import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import {
|
||||
AlertDescription_Shadcn_,
|
||||
AlertTitle_Shadcn_,
|
||||
@@ -82,7 +83,7 @@ export const RedirectUrls = () => {
|
||||
allowed, for example, https://*.domain.com
|
||||
</ScaffoldDescription>
|
||||
</div>
|
||||
<DocsButton href="https://supabase.com/docs/guides/auth/concepts/redirect-urls" />
|
||||
<DocsButton href={`${DOCS_URL}/guides/auth/concepts/redirect-urls`} />
|
||||
</div>
|
||||
|
||||
{isLoading && (
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Check } from 'lucide-react'
|
||||
import Image from 'next/image'
|
||||
|
||||
import { useParams } from 'common'
|
||||
import { ThirdPartyAuthIntegration } from 'data/third-party-auth/integrations-query'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { Badge, Button } from 'ui'
|
||||
import { AWS_IDP_REGIONS } from './AwsRegionSelector'
|
||||
import {
|
||||
@@ -29,7 +29,7 @@ export const getIntegrationTypeDescription = (type: INTEGRATION_TYPES) => {
|
||||
users. You can read more in the{' '}
|
||||
<a
|
||||
className="hover:decoration-brand underline hover:text-foreground transition"
|
||||
href="https://supabase.com/docs/guides/auth"
|
||||
href={`${DOCS_URL}/guides/auth`}
|
||||
>
|
||||
documentation
|
||||
</a>
|
||||
@@ -44,7 +44,7 @@ export const getIntegrationTypeDescription = (type: INTEGRATION_TYPES) => {
|
||||
read more in the{' '}
|
||||
<a
|
||||
className="hover:decoration-brand underline hover:text-foreground transition"
|
||||
href="https://supabase.com/docs/guides/auth"
|
||||
href={`${DOCS_URL}/guides/auth`}
|
||||
>
|
||||
documentation
|
||||
</a>
|
||||
@@ -58,7 +58,7 @@ export const getIntegrationTypeDescription = (type: INTEGRATION_TYPES) => {
|
||||
can read more in the{' '}
|
||||
<a
|
||||
className="hover:decoration-brand underline hover:text-foreground transition"
|
||||
href="https://supabase.com/docs/guides/auth/third-party/aws-cognito"
|
||||
href={`${DOCS_URL}/guides/auth/third-party/aws-cognito`}
|
||||
>
|
||||
documentation
|
||||
</a>
|
||||
@@ -73,7 +73,7 @@ export const getIntegrationTypeDescription = (type: INTEGRATION_TYPES) => {
|
||||
more in the{' '}
|
||||
<a
|
||||
className="hover:decoration-brand underline hover:text-foreground transition"
|
||||
href="https://supabase.com/docs/guides/auth/third-party/clerk"
|
||||
href={`${DOCS_URL}/guides/auth/third-party/clerk`}
|
||||
>
|
||||
documentation
|
||||
</a>
|
||||
@@ -88,7 +88,7 @@ export const getIntegrationTypeDescription = (type: INTEGRATION_TYPES) => {
|
||||
more in the{' '}
|
||||
<a
|
||||
className="hover:decoration-brand underline hover:text-foreground transition"
|
||||
href="https://supabase.com/docs/guides/auth/third-party/workos"
|
||||
href={`${DOCS_URL}/guides/auth/third-party/workos`}
|
||||
>
|
||||
documentation
|
||||
</a>
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
useThirdPartyAuthIntegrationsQuery,
|
||||
} from 'data/third-party-auth/integrations-query'
|
||||
import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { cn } from 'ui'
|
||||
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
|
||||
import { AddIntegrationDropdown } from './AddIntegrationDropdown'
|
||||
@@ -73,14 +74,16 @@ export const ThirdPartyAuthForm = () => {
|
||||
<br />
|
||||
Billing is based on the number of monthly active users (MAUs) requesting your API
|
||||
throughout the billing period. Refer to our{' '}
|
||||
<InlineLink href="https://supabase.com/docs/guides/platform/manage-your-usage/monthly-active-users-third-party">
|
||||
<InlineLink
|
||||
href={`${DOCS_URL}/guides/platform/manage-your-usage/monthly-active-users-third-party`}
|
||||
>
|
||||
billing docs
|
||||
</InlineLink>{' '}
|
||||
for more information.
|
||||
</ScaffoldSectionDescription>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 ">
|
||||
<DocsButton href="https://supabase.com/docs/guides/auth/third-party/overview" />
|
||||
<DocsButton href={`${DOCS_URL}/guides/auth/third-party/overview`} />
|
||||
{integrations.length !== 0 && (
|
||||
<AddIntegrationDropdown onSelectIntegrationType={setSelectedIntegration} />
|
||||
)}
|
||||
|
||||
@@ -317,7 +317,7 @@ export const UsersV2 = () => {
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.code === 'Enter') {
|
||||
if (e.code === 'Enter' || e.code === 'NumpadEnter') {
|
||||
setSearch(search.trim())
|
||||
setFilterKeywords(search.trim().toLocaleLowerCase())
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { DocsButton } from 'components/ui/DocsButton'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { Button, Modal, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from 'ui'
|
||||
|
||||
interface SpendCapModalProps {
|
||||
@@ -15,7 +16,7 @@ const SpendCapModal = ({ visible, onHide }: SpendCapModalProps) => {
|
||||
header={
|
||||
<div className="flex justify-between items-center">
|
||||
<span>Spend Cap</span>
|
||||
<DocsButton href="https://supabase.com/docs/guides/platform/cost-control#spend-cap" />
|
||||
<DocsButton href={`${DOCS_URL}/guides/platform/cost-control#spend-cap`} />
|
||||
</div>
|
||||
}
|
||||
showCloseButton={false}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { AlertTitle } from '@ui/components/shadcn/ui/alert'
|
||||
import { AlertCircle } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
|
||||
import { AlertTitle } from '@ui/components/shadcn/ui/alert'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { AlertDescription_Shadcn_, Alert_Shadcn_, Button } from 'ui'
|
||||
|
||||
interface CPUWarningsProps {
|
||||
@@ -22,9 +24,7 @@ const CPUWarnings = ({ isFreePlan, upgradeUrl, severity }: CPUWarningsProps) =>
|
||||
</AlertDescription_Shadcn_>
|
||||
<div className="mt-3 flex items-center space-x-2">
|
||||
<Button asChild type="default">
|
||||
<Link href="https://supabase.com/docs/guides/troubleshooting/high-cpu-usage">
|
||||
Learn more
|
||||
</Link>
|
||||
<Link href={`${DOCS_URL}/guides/troubleshooting/high-cpu-usage`}>Learn more</Link>
|
||||
</Button>
|
||||
<Button asChild type="warning">
|
||||
<Link href={upgradeUrl}>
|
||||
@@ -48,9 +48,7 @@ const CPUWarnings = ({ isFreePlan, upgradeUrl, severity }: CPUWarningsProps) =>
|
||||
</AlertDescription_Shadcn_>
|
||||
<div className="mt-3 flex items-center space-x-2">
|
||||
<Button asChild type="default">
|
||||
<Link href="https://supabase.com/docs/guides/troubleshooting/high-cpu-usage">
|
||||
Learn more
|
||||
</Link>
|
||||
<Link href={`${DOCS_URL}/guides/troubleshooting/high-cpu-usage`}>Learn more</Link>
|
||||
</Button>
|
||||
<Button asChild type="danger">
|
||||
<Link href={upgradeUrl}>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { AlertTitle } from '@ui/components/shadcn/ui/alert'
|
||||
import { AlertCircle } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
|
||||
import { AlertTitle } from '@ui/components/shadcn/ui/alert'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { AlertDescription_Shadcn_, Alert_Shadcn_, Button } from 'ui'
|
||||
|
||||
interface RAMWarningsProps {
|
||||
@@ -22,9 +24,7 @@ const RAMWarnings = ({ isFreePlan, upgradeUrl, severity }: RAMWarningsProps) =>
|
||||
</AlertDescription_Shadcn_>
|
||||
<div className="mt-3 flex items-center space-x-2">
|
||||
<Button asChild type="default">
|
||||
<Link href="https://supabase.com/docs/guides/troubleshooting/exhaust-ram">
|
||||
Learn more
|
||||
</Link>
|
||||
<Link href={`${DOCS_URL}/guides/troubleshooting/exhaust-ram`}>Learn more</Link>
|
||||
</Button>
|
||||
<Button asChild type="warning">
|
||||
<Link href={upgradeUrl}>
|
||||
@@ -48,9 +48,7 @@ const RAMWarnings = ({ isFreePlan, upgradeUrl, severity }: RAMWarningsProps) =>
|
||||
</AlertDescription_Shadcn_>
|
||||
<div className="mt-3 flex items-center space-x-2">
|
||||
<Button asChild type="default">
|
||||
<Link href="https://supabase.com/docs/guides/troubleshooting/high-cpu-usage">
|
||||
Learn more
|
||||
</Link>
|
||||
<Link href={`${DOCS_URL}/guides/troubleshooting/high-cpu-usage`}>Learn more</Link>
|
||||
</Button>
|
||||
<Button asChild type="danger">
|
||||
<Link href={upgradeUrl}>
|
||||
|
||||
@@ -4,6 +4,7 @@ import Link from 'next/link'
|
||||
import { BranchSelector } from './BranchSelector'
|
||||
|
||||
import { DocsButton } from 'components/ui/DocsButton'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { Button } from 'ui'
|
||||
|
||||
const EMPTY_STATE_CONTAINER = 'flex items-center flex-col justify-center w-full py-10 px-4'
|
||||
@@ -69,7 +70,7 @@ export const PreviewBranchesEmptyState = ({
|
||||
your database schema without affecting your main database.
|
||||
</p>
|
||||
<div className="flex items-center space-x-2">
|
||||
<DocsButton href="https://supabase.com/docs/guides/platform/branching" />
|
||||
<DocsButton href={`${DOCS_URL}/guides/platform/branching`} />
|
||||
<Button type="primary" onClick={() => onSelectCreateBranch()}>
|
||||
Create your first branch
|
||||
</Button>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { CodeBlockLang } from 'ui'
|
||||
|
||||
export type DatabaseConnectionType =
|
||||
@@ -75,7 +76,7 @@ export const FRAMEWORKS: ConnectionType[] = [
|
||||
key: 'nextjs',
|
||||
label: 'Next.js',
|
||||
icon: 'nextjs',
|
||||
guideLink: 'https://supabase.com/docs/guides/getting-started/quickstarts/nextjs',
|
||||
guideLink: `${DOCS_URL}/guides/getting-started/quickstarts/nextjs`,
|
||||
children: [
|
||||
{
|
||||
key: 'app',
|
||||
@@ -109,8 +110,7 @@ export const FRAMEWORKS: ConnectionType[] = [
|
||||
key: 'remix',
|
||||
label: 'Remix',
|
||||
icon: 'remix',
|
||||
guideLink:
|
||||
'https://supabase.com/docs/guides/auth/server-side/creating-a-client?framework=remix&environment=remix-loader',
|
||||
guideLink: `${DOCS_URL}/guides/auth/server-side/creating-a-client?framework=remix&environment=remix-loader`,
|
||||
children: [
|
||||
{
|
||||
key: 'supabasejs',
|
||||
@@ -124,7 +124,7 @@ export const FRAMEWORKS: ConnectionType[] = [
|
||||
key: 'react',
|
||||
label: 'React',
|
||||
icon: 'react',
|
||||
guideLink: 'https://supabase.com/docs/guides/getting-started/quickstarts/reactjs',
|
||||
guideLink: `${DOCS_URL}/guides/getting-started/quickstarts/reactjs`,
|
||||
children: [
|
||||
{
|
||||
key: 'create-react-app',
|
||||
@@ -158,7 +158,7 @@ export const FRAMEWORKS: ConnectionType[] = [
|
||||
key: 'nuxt',
|
||||
label: 'Nuxt',
|
||||
icon: 'nuxt',
|
||||
guideLink: 'https://supabase.com/docs/guides/getting-started/quickstarts/nuxtjs',
|
||||
guideLink: `${DOCS_URL}/guides/getting-started/quickstarts/nuxtjs`,
|
||||
children: [
|
||||
{
|
||||
key: 'supabasejs',
|
||||
@@ -172,7 +172,7 @@ export const FRAMEWORKS: ConnectionType[] = [
|
||||
key: 'vuejs',
|
||||
label: 'Vue.JS',
|
||||
icon: 'vuejs',
|
||||
guideLink: 'https://supabase.com/docs/guides/getting-started/quickstarts/vue',
|
||||
guideLink: `${DOCS_URL}/guides/getting-started/quickstarts/vue`,
|
||||
children: [
|
||||
{
|
||||
key: 'supabasejs',
|
||||
@@ -187,7 +187,7 @@ export const FRAMEWORKS: ConnectionType[] = [
|
||||
key: 'sveltekit',
|
||||
label: 'SvelteKit',
|
||||
icon: 'sveltekit',
|
||||
guideLink: 'https://supabase.com/docs/guides/getting-started/quickstarts/sveltekit',
|
||||
guideLink: `${DOCS_URL}/guides/getting-started/quickstarts/sveltekit`,
|
||||
children: [
|
||||
{
|
||||
key: 'supabasejs',
|
||||
@@ -201,7 +201,7 @@ export const FRAMEWORKS: ConnectionType[] = [
|
||||
key: 'solidjs',
|
||||
label: 'Solid.js',
|
||||
icon: 'solidjs',
|
||||
guideLink: 'https://supabase.com/docs/guides/getting-started/quickstarts/solidjs',
|
||||
guideLink: `${DOCS_URL}/guides/getting-started/quickstarts/solidjs`,
|
||||
children: [
|
||||
{
|
||||
key: 'supabasejs',
|
||||
@@ -229,7 +229,7 @@ export const FRAMEWORKS: ConnectionType[] = [
|
||||
key: 'refine',
|
||||
label: 'refine',
|
||||
icon: 'refine',
|
||||
guideLink: 'https://supabase.com/docs/guides/getting-started/quickstarts/refine',
|
||||
guideLink: `${DOCS_URL}/guides/getting-started/quickstarts/refine`,
|
||||
children: [
|
||||
{
|
||||
key: 'supabasejs',
|
||||
@@ -246,7 +246,7 @@ export const MOBILES: ConnectionType[] = [
|
||||
key: 'exporeactnative',
|
||||
label: 'Expo React Native',
|
||||
icon: 'expo',
|
||||
guideLink: 'https://supabase.com/docs/guides/getting-started/tutorials/with-expo-react-native',
|
||||
guideLink: `${DOCS_URL}/guides/getting-started/tutorials/with-expo-react-native`,
|
||||
children: [
|
||||
{
|
||||
key: 'supabasejs',
|
||||
@@ -260,7 +260,7 @@ export const MOBILES: ConnectionType[] = [
|
||||
key: 'flutter',
|
||||
label: 'Flutter',
|
||||
icon: 'flutter',
|
||||
guideLink: 'https://supabase.com/docs/guides/getting-started/tutorials/with-flutter',
|
||||
guideLink: `${DOCS_URL}/guides/getting-started/tutorials/with-flutter`,
|
||||
children: [
|
||||
{
|
||||
key: 'supabaseflutter',
|
||||
@@ -274,7 +274,7 @@ export const MOBILES: ConnectionType[] = [
|
||||
key: 'ionicreact',
|
||||
label: 'Ionic React',
|
||||
icon: 'react',
|
||||
guideLink: 'https://supabase.com/docs/guides/getting-started/tutorials/with-ionic-react',
|
||||
guideLink: `${DOCS_URL}/guides/getting-started/tutorials/with-ionic-react`,
|
||||
children: [
|
||||
{
|
||||
key: 'supabasejs',
|
||||
@@ -288,7 +288,7 @@ export const MOBILES: ConnectionType[] = [
|
||||
key: 'swift',
|
||||
label: 'Swift',
|
||||
icon: 'swift',
|
||||
guideLink: 'https://supabase.com/docs/guides/getting-started/tutorials/with-swift',
|
||||
guideLink: `${DOCS_URL}/guides/getting-started/tutorials/with-swift`,
|
||||
children: [
|
||||
{
|
||||
key: 'supabaseswift',
|
||||
@@ -302,7 +302,7 @@ export const MOBILES: ConnectionType[] = [
|
||||
key: 'androidkotlin',
|
||||
label: 'Android Kotlin',
|
||||
icon: 'kotlin',
|
||||
guideLink: 'https://supabase.com/docs/guides/getting-started/tutorials/with-kotlin',
|
||||
guideLink: `${DOCS_URL}/guides/getting-started/tutorials/with-kotlin`,
|
||||
children: [
|
||||
{
|
||||
key: 'supabasekt',
|
||||
@@ -316,7 +316,7 @@ export const MOBILES: ConnectionType[] = [
|
||||
key: 'ionicangular',
|
||||
label: 'Ionic Angular',
|
||||
icon: 'ionic-angular',
|
||||
guideLink: 'https://supabase.com/docs/guides/getting-started/tutorials/with-ionic-angular',
|
||||
guideLink: `${DOCS_URL}/guides/getting-started/tutorials/with-ionic-angular`,
|
||||
children: [
|
||||
{
|
||||
key: 'supabasejs',
|
||||
@@ -340,8 +340,7 @@ export const ORMS: ConnectionType[] = [
|
||||
key: 'drizzle',
|
||||
label: 'Drizzle',
|
||||
icon: 'drizzle',
|
||||
guideLink:
|
||||
'https://supabase.com/docs/guides/database/connecting-to-postgres#connecting-with-drizzle',
|
||||
guideLink: `${DOCS_URL}/guides/database/connecting-to-postgres#connecting-with-drizzle`,
|
||||
children: [],
|
||||
},
|
||||
]
|
||||
|
||||
@@ -7,6 +7,7 @@ import { InlineLink } from 'components/ui/InlineLink'
|
||||
import { useBackupDownloadMutation } from 'data/database/backup-download-mutation'
|
||||
import type { DatabaseBackup } from 'data/database/backups-query'
|
||||
import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { Badge, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
|
||||
import { TimestampInfo } from 'ui-patterns'
|
||||
|
||||
@@ -75,7 +76,9 @@ export const BackupItem = ({ index, isHealthy, backup, onSelectBackup }: BackupI
|
||||
<>
|
||||
Physical backups cannot be downloaded through the dashboard. You can still
|
||||
download it via pgdump by following our guide{' '}
|
||||
<InlineLink href="https://supabase.com/docs/guides/troubleshooting/download-logical-backups">
|
||||
<InlineLink
|
||||
href={`${DOCS_URL}/guides/troubleshooting/download-logical-backups`}
|
||||
>
|
||||
here
|
||||
</InlineLink>
|
||||
.
|
||||
|
||||
@@ -10,6 +10,7 @@ import { useSchemasQuery } from 'data/database/schemas-query'
|
||||
import { executeSql } from 'data/sql/execute-sql-query'
|
||||
import { useIsOrioleDb, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
||||
import { useProtectedSchemas } from 'hooks/useProtectedSchemas'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import {
|
||||
AlertDescription_Shadcn_,
|
||||
AlertTitle_Shadcn_,
|
||||
@@ -146,7 +147,7 @@ const EnableExtensionModal = ({ visible, extension, onCancel }: EnableExtensionM
|
||||
{extension.name} cannot be accelerated by indexes on tables that are using the
|
||||
OrioleDB access method
|
||||
</span>
|
||||
<DocsButton abbrev={false} className="mt-2" href="https://supabase.com/docs" />
|
||||
<DocsButton abbrev={false} className="mt-2" href={`${DOCS_URL}`} />
|
||||
</Admonition>
|
||||
)}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import { useDatabaseExtensionDisableMutation } from 'data/database-extensions/da
|
||||
import { DatabaseExtension } from 'data/database-extensions/database-extensions-query'
|
||||
import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions'
|
||||
import { useIsOrioleDb, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { extensions } from 'shared-data'
|
||||
import { Button, Switch, TableCell, TableRow, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
|
||||
import { Admonition } from 'ui-patterns'
|
||||
@@ -37,7 +38,7 @@ export const ExtensionRow = ({ extension }: ExtensionRowProps) => {
|
||||
|
||||
const extensionMeta = extensions.find((item) => item.name === extension.name)
|
||||
const docsUrl = extensionMeta?.link.startsWith('/guides')
|
||||
? `https://supabase.com/docs${extensionMeta?.link}`
|
||||
? `${DOCS_URL}${extensionMeta?.link}`
|
||||
: extensionMeta?.link ?? undefined
|
||||
|
||||
const { mutate: disableExtension, isLoading: isDisabling } = useDatabaseExtensionDisableMutation({
|
||||
|
||||
@@ -11,6 +11,7 @@ import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
|
||||
import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query'
|
||||
import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions'
|
||||
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import {
|
||||
Card,
|
||||
Input,
|
||||
@@ -72,7 +73,7 @@ export const Extensions = () => {
|
||||
className="w-52"
|
||||
icon={<Search size={14} />}
|
||||
/>
|
||||
<DocsButton href="https://supabase.com/docs/guides/database/extensions" />
|
||||
<DocsButton href={`${DOCS_URL}/guides/database/extensions`} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
|
||||
import { useDatabaseHooksQuery } from 'data/database-triggers/database-triggers-query'
|
||||
import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions'
|
||||
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { noop } from 'lib/void'
|
||||
import { Input } from 'ui'
|
||||
import { HooksListEmpty } from './HooksListEmpty'
|
||||
@@ -63,7 +64,7 @@ export const HooksList = ({
|
||||
onChange={(e) => setFilterString(e.target.value)}
|
||||
/>
|
||||
<div className="flex items-center gap-x-2">
|
||||
<DocsButton href="https://supabase.com/docs/guides/database/webhooks" />
|
||||
<DocsButton href={`${DOCS_URL}/guides/database/webhooks`} />
|
||||
<ButtonTooltip
|
||||
onClick={() => createHook()}
|
||||
disabled={!isPermissionsLoaded || !canCreateWebhooks}
|
||||
|
||||
@@ -11,6 +11,7 @@ import { useSchemasQuery } from 'data/database/schemas-query'
|
||||
import { useTableColumnsQuery } from 'data/database/table-columns-query'
|
||||
import { useEntityTypesQuery } from 'data/entity-types/entity-types-infinite-query'
|
||||
import { useIsOrioleDb, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import {
|
||||
Button,
|
||||
CommandEmpty_Shadcn_,
|
||||
@@ -379,7 +380,7 @@ CREATE INDEX ON "${selectedSchema}"."${selectedEntity}" USING ${selectedIndexTyp
|
||||
description="More index types may be supported when OrioleDB is no longer in preview"
|
||||
>
|
||||
{/* [Joshen Oriole] Hook up proper docs URL */}
|
||||
<DocsButton className="mt-2" abbrev={false} href="https://supabase.com/docs" />
|
||||
<DocsButton className="mt-2" abbrev={false} href={`${DOCS_URL}`} />
|
||||
</Admonition>
|
||||
)}
|
||||
</SidePanel.Content>
|
||||
|
||||
@@ -5,12 +5,15 @@ import { toast } from 'sonner'
|
||||
import * as z from 'zod'
|
||||
|
||||
import { useParams } from 'common'
|
||||
import { InlineLink } from 'components/ui/InlineLink'
|
||||
import { useCheckPrimaryKeysExists } from 'data/database/primary-keys-exists-query'
|
||||
import { useCreateDestinationPipelineMutation } from 'data/replication/create-destination-pipeline-mutation'
|
||||
import { useReplicationDestinationByIdQuery } from 'data/replication/destination-by-id-query'
|
||||
import { useReplicationPipelineByIdQuery } from 'data/replication/pipeline-by-id-query'
|
||||
import { useReplicationPublicationsQuery } from 'data/replication/publications-query'
|
||||
import { useStartPipelineMutation } from 'data/replication/start-pipeline-mutation'
|
||||
import { useUpdateDestinationPipelineMutation } from 'data/replication/update-destination-pipeline-mutation'
|
||||
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
||||
import {
|
||||
PipelineStatusRequestStatus,
|
||||
usePipelineRequestStatus,
|
||||
@@ -44,6 +47,7 @@ import { Admonition } from 'ui-patterns'
|
||||
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
|
||||
import NewPublicationPanel from './NewPublicationPanel'
|
||||
import PublicationsComboBox from './PublicationsComboBox'
|
||||
import { ReplicationDisclaimerDialog } from './ReplicationDisclaimerDialog'
|
||||
|
||||
const formId = 'destination-editor'
|
||||
const types = ['BigQuery'] as const
|
||||
@@ -80,10 +84,15 @@ export const DestinationPanel = ({
|
||||
existingDestination,
|
||||
}: DestinationPanelProps) => {
|
||||
const { ref: projectRef } = useParams()
|
||||
const { data: project } = useSelectedProjectQuery()
|
||||
const { setRequestStatus } = usePipelineRequestStatus()
|
||||
|
||||
const editMode = !!existingDestination
|
||||
const [publicationPanelVisible, setPublicationPanelVisible] = useState(false)
|
||||
const [showDisclaimerDialog, setShowDisclaimerDialog] = useState(false)
|
||||
const [pendingFormValues, setPendingFormValues] = useState<z.infer<typeof FormSchema> | null>(
|
||||
null
|
||||
)
|
||||
|
||||
const { mutateAsync: createDestinationPipeline, isLoading: creatingDestinationPipeline } =
|
||||
useCreateDestinationPipelineMutation({
|
||||
@@ -142,9 +151,21 @@ export const DestinationPanel = ({
|
||||
const isSelectedPublicationMissing =
|
||||
isSuccessPublications && !!publicationName && !publicationNames.includes(publicationName)
|
||||
|
||||
const isSubmitDisabled = isSaving || isSelectedPublicationMissing
|
||||
const selectedPublication = publications.find((pub) => pub.name === publicationName)
|
||||
const { data: checkPrimaryKeysExistsData, isLoading: isLoadingCheck } = useCheckPrimaryKeysExists(
|
||||
{
|
||||
projectRef: project?.ref,
|
||||
connectionString: project?.connectionString,
|
||||
tables: selectedPublication?.tables ?? [],
|
||||
},
|
||||
{ enabled: visible && !!selectedPublication }
|
||||
)
|
||||
const hasTablesWithNoPrimaryKeys = (checkPrimaryKeysExistsData?.offendingTables ?? []).length > 0
|
||||
|
||||
const onSubmit = async (data: z.infer<typeof FormSchema>) => {
|
||||
const isSubmitDisabled =
|
||||
isSaving || isSelectedPublicationMissing || isLoadingCheck || hasTablesWithNoPrimaryKeys
|
||||
|
||||
const submitPipeline = async (data: z.infer<typeof FormSchema>) => {
|
||||
if (!projectRef) return console.error('Project ref is required')
|
||||
if (!sourceId) return console.error('Source id is required')
|
||||
if (isSelectedPublicationMissing) {
|
||||
@@ -236,6 +257,32 @@ export const DestinationPanel = ({
|
||||
}
|
||||
}
|
||||
|
||||
const onSubmit = async (data: z.infer<typeof FormSchema>) => {
|
||||
if (!editMode) {
|
||||
setPendingFormValues(data)
|
||||
setShowDisclaimerDialog(true)
|
||||
return
|
||||
}
|
||||
|
||||
await submitPipeline(data)
|
||||
}
|
||||
|
||||
const handleDisclaimerDialogChange = (open: boolean) => {
|
||||
setShowDisclaimerDialog(open)
|
||||
if (!open) {
|
||||
setPendingFormValues(null)
|
||||
}
|
||||
}
|
||||
|
||||
const handleDisclaimerConfirm = async () => {
|
||||
if (!pendingFormValues) return
|
||||
|
||||
const values = pendingFormValues
|
||||
setPendingFormValues(null)
|
||||
setShowDisclaimerDialog(false)
|
||||
await submitPipeline(values)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (editMode && destinationData && pipelineData) {
|
||||
form.reset(defaultValues)
|
||||
@@ -303,12 +350,13 @@ export const DestinationPanel = ({
|
||||
<FormControl_Shadcn_>
|
||||
<PublicationsComboBox
|
||||
publications={publicationNames}
|
||||
loading={isLoadingPublications}
|
||||
isLoadingPublications={isLoadingPublications}
|
||||
isLoadingCheck={!!selectedPublication && isLoadingCheck}
|
||||
field={field}
|
||||
onNewPublicationClick={() => setPublicationPanelVisible(true)}
|
||||
/>
|
||||
</FormControl_Shadcn_>
|
||||
{isSelectedPublicationMissing && (
|
||||
{isSelectedPublicationMissing ? (
|
||||
<Admonition type="warning" className="mt-2 mb-0">
|
||||
<p className="!leading-normal">
|
||||
The publication{' '}
|
||||
@@ -317,7 +365,29 @@ export const DestinationPanel = ({
|
||||
another one.
|
||||
</p>
|
||||
</Admonition>
|
||||
)}
|
||||
) : hasTablesWithNoPrimaryKeys ? (
|
||||
<Admonition type="warning" className="mt-2 mb-0">
|
||||
<p className="!leading-normal">
|
||||
Replication requires every table in the publication to have a
|
||||
primary key to work, which these tables are missing:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 mb-2">
|
||||
{(checkPrimaryKeysExistsData?.offendingTables ?? []).map((x) => {
|
||||
const value = `${x.schema}.${x.name}`
|
||||
return (
|
||||
<li key={value} className="!leading-normal">
|
||||
<InlineLink href={`/project/${projectRef}/editor/${x.id}`}>
|
||||
{value}
|
||||
</InlineLink>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
<p className="!leading-normal">
|
||||
Ensure that these tables have primary keys first.
|
||||
</p>
|
||||
</Admonition>
|
||||
) : null}
|
||||
</FormItemLayout>
|
||||
)}
|
||||
/>
|
||||
@@ -487,6 +557,13 @@ export const DestinationPanel = ({
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
|
||||
<ReplicationDisclaimerDialog
|
||||
open={showDisclaimerDialog}
|
||||
onOpenChange={handleDisclaimerDialogChange}
|
||||
isLoading={isSaving}
|
||||
onConfirm={handleDisclaimerConfirm}
|
||||
/>
|
||||
|
||||
<NewPublicationPanel
|
||||
visible={publicationPanelVisible}
|
||||
sourceId={sourceId}
|
||||
|
||||
@@ -11,6 +11,7 @@ import { replicationKeys } from 'data/replication/keys'
|
||||
import { fetchReplicationPipelineVersion } from 'data/replication/pipeline-version-query'
|
||||
import { useReplicationPipelinesQuery } from 'data/replication/pipelines-query'
|
||||
import { useReplicationSourcesQuery } from 'data/replication/sources-query'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { Button, cn, Input_Shadcn_ } from 'ui'
|
||||
import { GenericSkeletonLoader } from 'ui-patterns'
|
||||
import { DestinationPanel } from './DestinationPanel'
|
||||
@@ -136,7 +137,7 @@ export const Destinations = () => {
|
||||
<div className="flex gap-x-2">
|
||||
<EnableReplicationModal />
|
||||
{/* [Joshen] Placeholder for when we have documentation */}
|
||||
<DocsButton href="https://supabase.com/docs" />
|
||||
<DocsButton href={`${DOCS_URL}`} />
|
||||
</div>
|
||||
</div>
|
||||
) : hasDestinations ? (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useParams } from 'common'
|
||||
import { InlineLink } from 'components/ui/InlineLink'
|
||||
import { TableState } from './ReplicationPipelineStatus.types'
|
||||
import { isValidRetryPolicy } from './ReplicationPipelineStatus.utils'
|
||||
import { TableState } from './ReplicationPipelineStatus/ReplicationPipelineStatus.types'
|
||||
import { isValidRetryPolicy } from './ReplicationPipelineStatus/ReplicationPipelineStatus.utils'
|
||||
import { RetryCountdown } from './RetryCountdown'
|
||||
import { RetryOptionsDropdown } from './RetryOptionsDropdown'
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { Check, ChevronsUpDown, Loader2, Plus } from 'lucide-react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { ControllerRenderProps } from 'react-hook-form'
|
||||
import {
|
||||
Button,
|
||||
cn,
|
||||
Command_Shadcn_,
|
||||
CommandEmpty_Shadcn_,
|
||||
CommandGroup_Shadcn_,
|
||||
@@ -14,18 +16,19 @@ import {
|
||||
PopoverTrigger_Shadcn_,
|
||||
ScrollArea,
|
||||
} from 'ui'
|
||||
import { ControllerRenderProps } from 'react-hook-form'
|
||||
|
||||
interface PublicationsComboBoxProps {
|
||||
publications: string[]
|
||||
loading: boolean
|
||||
isLoadingPublications: boolean
|
||||
isLoadingCheck: boolean
|
||||
onNewPublicationClick: () => void
|
||||
field: ControllerRenderProps<any, 'publicationName'>
|
||||
}
|
||||
|
||||
const PublicationsComboBox = ({
|
||||
publications,
|
||||
loading,
|
||||
isLoadingPublications,
|
||||
isLoadingCheck,
|
||||
onNewPublicationClick,
|
||||
field,
|
||||
}: PublicationsComboBoxProps) => {
|
||||
@@ -62,13 +65,16 @@ const PublicationsComboBox = ({
|
||||
<Button
|
||||
type="default"
|
||||
size="medium"
|
||||
className={`w-full [&>span]:w-full text-left`}
|
||||
className={cn(
|
||||
'w-full [&>span]:w-full text-left',
|
||||
!selectedPublication && 'text-foreground-muted'
|
||||
)}
|
||||
iconRight={
|
||||
<ChevronsUpDown
|
||||
className="text-foreground-muted"
|
||||
strokeWidth={2}
|
||||
size={14}
|
||||
></ChevronsUpDown>
|
||||
isLoadingCheck ? (
|
||||
<Loader2 className="animate-spin" size={14} />
|
||||
) : (
|
||||
<ChevronsUpDown className="text-foreground-muted" strokeWidth={2} size={14} />
|
||||
)
|
||||
}
|
||||
name={field.name}
|
||||
onBlur={field.onBlur}
|
||||
@@ -82,10 +88,10 @@ const PublicationsComboBox = ({
|
||||
placeholder="Find publication..."
|
||||
value={searchTerm}
|
||||
onValueChange={handleSearchChange}
|
||||
></CommandInput_Shadcn_>
|
||||
/>
|
||||
<CommandList_Shadcn_>
|
||||
<CommandEmpty_Shadcn_>
|
||||
{loading ? (
|
||||
{isLoadingPublications ? (
|
||||
<div className="flex items-center gap-2 text-center justify-center">
|
||||
<Loader2 size={12} className="animate-spin" />
|
||||
Loading...
|
||||
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogSection,
|
||||
DialogSectionSeparator,
|
||||
DialogTitle,
|
||||
} from 'ui'
|
||||
|
||||
interface ReplicationDisclaimerDialogProps {
|
||||
open: boolean
|
||||
isLoading: boolean
|
||||
onOpenChange: (value: boolean) => void
|
||||
onConfirm: () => void
|
||||
}
|
||||
|
||||
export const ReplicationDisclaimerDialog = ({
|
||||
open,
|
||||
isLoading,
|
||||
onOpenChange,
|
||||
onConfirm,
|
||||
}: ReplicationDisclaimerDialogProps) => {
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="sm:max-w-lg">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Replication limitations</DialogTitle>
|
||||
</DialogHeader>
|
||||
<DialogSectionSeparator />
|
||||
<DialogSection className="space-y-4 text-sm">
|
||||
<p className="text-foreground">
|
||||
Creating this replication pipeline will immediately start syncing data from your
|
||||
publication into the destination. Make sure you understand the limitations of the system
|
||||
before proceeding.
|
||||
</p>
|
||||
|
||||
<div className="text-foreground-light">
|
||||
<ul className="list-disc flex flex-col gap-y-1.5 pl-5 text-sm leading-snug">
|
||||
<li>
|
||||
<strong className="text-foreground">Custom data types replicate as strings.</strong>{' '}
|
||||
Check that the destination can interpret those string values correctly.
|
||||
</li>
|
||||
<li>
|
||||
<strong className="text-foreground">Generated columns are skipped.</strong> Replace
|
||||
them with triggers or materialized views if you need the derived values downstream.
|
||||
</li>
|
||||
<li>
|
||||
<strong className="text-foreground">
|
||||
FULL replica identity is strongly recommended.
|
||||
</strong>{' '}
|
||||
With FULL replica identity deletes and updates include the payload that is needed to
|
||||
correctly apply those changes.
|
||||
</li>
|
||||
<li>
|
||||
<strong className="text-foreground">Schema changes aren’t supported yet.</strong>{' '}
|
||||
Plan for manual adjustments if you need to alter replicated tables.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</DialogSection>
|
||||
|
||||
<DialogSectionSeparator />
|
||||
|
||||
<DialogFooter>
|
||||
<Button type="default" disabled={isLoading} onClick={() => onOpenChange(false)}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button loading={isLoading} onClick={onConfirm}>
|
||||
Understood, start replication
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
+110
-43
@@ -4,10 +4,12 @@ import {
|
||||
Ban,
|
||||
ChevronLeft,
|
||||
ExternalLink,
|
||||
Info,
|
||||
Pause,
|
||||
Play,
|
||||
RotateCcw,
|
||||
Search,
|
||||
WifiOff,
|
||||
X,
|
||||
} from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
@@ -31,17 +33,18 @@ import {
|
||||
import { Badge, Button, cn } from 'ui'
|
||||
import { GenericSkeletonLoader } from 'ui-patterns'
|
||||
import { Input } from 'ui-patterns/DataInputs/Input'
|
||||
import { ErroredTableDetails } from './ErroredTableDetails'
|
||||
import { ErroredTableDetails } from '../ErroredTableDetails'
|
||||
import {
|
||||
PIPELINE_ACTIONABLE_STATES,
|
||||
PIPELINE_ERROR_MESSAGES,
|
||||
getStatusName,
|
||||
} from './Pipeline.utils'
|
||||
import { PipelineStatus, PipelineStatusName } from './PipelineStatus'
|
||||
import { STATUS_REFRESH_FREQUENCY_MS } from './Replication.constants'
|
||||
import { TableState } from './ReplicationPipelineStatus.types'
|
||||
} from '../Pipeline.utils'
|
||||
import { PipelineStatus, PipelineStatusName } from '../PipelineStatus'
|
||||
import { STATUS_REFRESH_FREQUENCY_MS } from '../Replication.constants'
|
||||
import { UpdateVersionModal } from '../UpdateVersionModal'
|
||||
import { SlotLagMetrics, TableState } from './ReplicationPipelineStatus.types'
|
||||
import { getDisabledStateConfig, getStatusConfig } from './ReplicationPipelineStatus.utils'
|
||||
import { UpdateVersionModal } from './UpdateVersionModal'
|
||||
import { SlotLagMetricsInline, SlotLagMetricsList } from './SlotLagMetrics'
|
||||
|
||||
/**
|
||||
* Component for displaying replication pipeline status and table replication details.
|
||||
@@ -82,7 +85,6 @@ export const ReplicationPipelineStatus = () => {
|
||||
|
||||
const {
|
||||
data: replicationStatusData,
|
||||
error: statusError,
|
||||
isLoading: isStatusLoading,
|
||||
isError: isStatusError,
|
||||
} = useReplicationPipelineReplicationStatusQuery(
|
||||
@@ -107,12 +109,14 @@ export const ReplicationPipelineStatus = () => {
|
||||
const config = getDisabledStateConfig({ requestStatus, statusName })
|
||||
|
||||
const tableStatuses = replicationStatusData?.table_statuses || []
|
||||
const applyLagMetrics = replicationStatusData?.apply_lag
|
||||
const filteredTableStatuses =
|
||||
filterString.length === 0
|
||||
? tableStatuses
|
||||
: tableStatuses.filter((table: TableState) =>
|
||||
: tableStatuses.filter((table) =>
|
||||
table.table_name.toLowerCase().includes(filterString.toLowerCase())
|
||||
)
|
||||
const tablesWithLag = tableStatuses.filter((table) => Boolean(table.table_sync_lag))
|
||||
|
||||
const isPipelineRunning = statusName === 'started'
|
||||
const hasTableData = tableStatuses.length > 0
|
||||
@@ -121,6 +125,10 @@ export const ReplicationPipelineStatus = () => {
|
||||
requestStatus === PipelineStatusRequestStatus.StopRequested ||
|
||||
requestStatus === PipelineStatusRequestStatus.RestartRequested
|
||||
const showDisabledState = !isPipelineRunning || isEnablingDisabling
|
||||
const refreshIntervalLabel =
|
||||
STATUS_REFRESH_FREQUENCY_MS >= 1000
|
||||
? `${Math.round(STATUS_REFRESH_FREQUENCY_MS / 1000)}s`
|
||||
: `${STATUS_REFRESH_FREQUENCY_MS}ms`
|
||||
|
||||
const logsUrl = `/project/${projectRef}/logs/etl-replication-logs${
|
||||
pipelineId ? `?f=${encodeURIComponent(JSON.stringify({ pipeline_id: pipelineId }))}` : ''
|
||||
@@ -242,46 +250,105 @@ export const ReplicationPipelineStatus = () => {
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{(isPipelineLoading || isStatusLoading) && <GenericSkeletonLoader />}
|
||||
|
||||
{isPipelineError && (
|
||||
<AlertError error={pipelineError} subject={PIPELINE_ERROR_MESSAGES.RETRIEVE_PIPELINE} />
|
||||
)}
|
||||
|
||||
{isStatusError && (
|
||||
<AlertError
|
||||
error={statusError}
|
||||
subject={PIPELINE_ERROR_MESSAGES.RETRIEVE_REPLICATION_STATUS}
|
||||
/>
|
||||
<div className="flex items-center gap-2 rounded-lg border border-warning-400 bg-warning-50 px-3 py-2 text-xs text-warning-800">
|
||||
<WifiOff size={14} />
|
||||
<span className="font-medium">Live updates paused</span>
|
||||
<span className="text-warning-700">Retrying automatically</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{showDisabledState && (
|
||||
<div
|
||||
className={cn(
|
||||
'p-4 border border-default rounded-lg flex items-center justify-between',
|
||||
config.colors.bg
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center gap-x-3">
|
||||
<div
|
||||
className={cn(
|
||||
'w-10 h-10 rounded-full flex items-center justify-center',
|
||||
config.colors.iconBg
|
||||
)}
|
||||
>
|
||||
<div className={config.colors.icon}>{config.icon}</div>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h4 className={`text-sm font-medium ${config.colors.text}`}>{config.title}</h4>
|
||||
<p className={`text-sm ${config.colors.subtext}`}>{config.message}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{(isPipelineLoading || isStatusLoading) && (
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center gap-x-3">
|
||||
<div className="h-6 w-40 rounded bg-surface-200" />
|
||||
<div className="h-5 w-24 rounded bg-surface-200" />
|
||||
</div>
|
||||
<GenericSkeletonLoader />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{applyLagMetrics && (
|
||||
<div className="border border-default rounded-lg bg-surface-100 px-4 py-4 space-y-3">
|
||||
<div className="flex flex-wrap items-baseline justify-between gap-y-1">
|
||||
<div>
|
||||
<h4 className="text-sm font-semibold text-foreground">Replication lag</h4>
|
||||
<p className="text-xs text-foreground-light">
|
||||
Snapshot of how far this pipeline is trailing behind right now.
|
||||
</p>
|
||||
</div>
|
||||
<p className="text-xs text-foreground-lighter">
|
||||
Updates every {refreshIntervalLabel}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{isStatusError && (
|
||||
<p className="text-xs text-warning-700">
|
||||
Unable to refresh data. Showing the last values we received.
|
||||
</p>
|
||||
)}
|
||||
|
||||
<SlotLagMetricsList metrics={applyLagMetrics} />
|
||||
|
||||
{tablesWithLag.length > 0 && (
|
||||
<>
|
||||
<div className="border-t border-default/40" />
|
||||
<div className="space-y-3 text-xs text-foreground">
|
||||
<div className="flex items-start gap-2 rounded-md border border-default/50 bg-surface-200/60 px-3 py-2 text-foreground-light">
|
||||
<Info size={14} className="mt-0.5" />
|
||||
<span>
|
||||
During initial sync, tables can copy and stream independently before
|
||||
reconciling with the overall pipeline.
|
||||
</span>
|
||||
</div>
|
||||
<div className="rounded border border-default/50 bg-surface-200/40">
|
||||
<ul className="divide-y divide-default/40">
|
||||
{tablesWithLag.map((table) => (
|
||||
<li key={`${table.table_id}-${table.table_name}`} className="px-3 py-2">
|
||||
<SlotLagMetricsInline
|
||||
tableName={table.table_name}
|
||||
metrics={table.table_sync_lag as SlotLagMetrics}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{hasTableData && (
|
||||
<div className="flex flex-col gap-y-4">
|
||||
{showDisabledState && (
|
||||
<div
|
||||
className={cn(
|
||||
'p-4 border border-default rounded-lg flex items-center justify-between',
|
||||
config.colors.bg
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center gap-x-3">
|
||||
<div
|
||||
className={cn(
|
||||
'w-10 h-10 rounded-full flex items-center justify-center',
|
||||
config.colors.iconBg
|
||||
)}
|
||||
>
|
||||
<div className={config.colors.icon}>{config.icon}</div>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h4 className={`text-sm font-medium ${config.colors.text}`}>{config.title}</h4>
|
||||
<p className={`text-sm ${config.colors.subtext}`}>{config.message}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex flex-col gap-y-3">
|
||||
<div className="w-full overflow-hidden overflow-x-auto">
|
||||
{/* [Joshen] Should update to use new Table components next time */}
|
||||
<Table
|
||||
@@ -304,8 +371,8 @@ export const ReplicationPipelineStatus = () => {
|
||||
</Table.td>
|
||||
</Table.tr>
|
||||
)}
|
||||
{filteredTableStatuses.map((table: TableState, index: number) => {
|
||||
const statusConfig = getStatusConfig(table.state)
|
||||
{filteredTableStatuses.map((table, index) => {
|
||||
const statusConfig = getStatusConfig(table.state as TableState['state'])
|
||||
return (
|
||||
<Table.tr key={`${table.table_name}-${index}`} className="border-t">
|
||||
<Table.td className="align-top">
|
||||
@@ -342,7 +409,7 @@ export const ReplicationPipelineStatus = () => {
|
||||
Status unavailable while pipeline is {config.badge.toLowerCase()}
|
||||
</p>
|
||||
) : (
|
||||
<div className="space-y-1">
|
||||
<div className="space-y-3">
|
||||
<div className="text-sm text-foreground">
|
||||
{statusConfig.description}
|
||||
</div>
|
||||
+11
@@ -3,6 +3,16 @@ export type RetryPolicy =
|
||||
| { policy: 'manual_retry' }
|
||||
| { policy: 'timed_retry'; next_retry: string }
|
||||
|
||||
export type SlotLagMetrics = {
|
||||
restart_lsn_bytes: number
|
||||
confirmed_flush_lsn_bytes: number
|
||||
safe_wal_size_bytes: number
|
||||
write_lag?: number
|
||||
flush_lag?: number
|
||||
}
|
||||
|
||||
export type SlotLagMetricKey = keyof SlotLagMetrics
|
||||
|
||||
export type TableState = {
|
||||
table_id: number
|
||||
table_name: string
|
||||
@@ -12,4 +22,5 @@ export type TableState = {
|
||||
| { name: 'copied_table' }
|
||||
| { name: 'following_wal'; lag: number }
|
||||
| { name: 'error'; reason: string; solution?: string; retry_policy: RetryPolicy }
|
||||
table_sync_lag?: SlotLagMetrics
|
||||
}
|
||||
+73
-8
@@ -1,46 +1,57 @@
|
||||
import { ReplicationPipelineStatusData } from 'data/replication/pipeline-status-query'
|
||||
import dayjs from 'dayjs'
|
||||
import { Activity, Clock, HelpCircle, Loader2, XCircle } from 'lucide-react'
|
||||
|
||||
import { ReplicationPipelineStatusData } from 'data/replication/pipeline-status-query'
|
||||
import { formatBytes } from 'lib/helpers'
|
||||
import { PipelineStatusRequestStatus } from 'state/replication-pipeline-request-status'
|
||||
import { Badge } from 'ui'
|
||||
import { getPipelineStateMessages } from './Pipeline.utils'
|
||||
import { getPipelineStateMessages } from '../Pipeline.utils'
|
||||
import { RetryPolicy, TableState } from './ReplicationPipelineStatus.types'
|
||||
|
||||
const numberFormatter = new Intl.NumberFormat()
|
||||
|
||||
export const getStatusConfig = (state: TableState['state']) => {
|
||||
switch (state.name) {
|
||||
case 'queued':
|
||||
return {
|
||||
badge: <Badge variant="warning">Queued</Badge>,
|
||||
description: 'Waiting to start replication',
|
||||
description: 'Table is waiting for ETL to pick it up for replication.',
|
||||
tooltip: 'Table is waiting for ETL to pick it up for replication.',
|
||||
color: 'text-warning',
|
||||
}
|
||||
case 'copying_table':
|
||||
return {
|
||||
badge: <Badge variant="brand">Copying</Badge>,
|
||||
description: 'Initial data copy in progress',
|
||||
description: "Table's existing rows are being copied before live streaming begins.",
|
||||
tooltip: "Table's existing rows are being copied before live streaming begins.",
|
||||
color: 'text-brand-600',
|
||||
}
|
||||
case 'copied_table':
|
||||
return {
|
||||
badge: <Badge variant="success">Copied</Badge>,
|
||||
description: 'Initial copy completed',
|
||||
description: "Table copy is complete and it's preparing to follow WAL changes.",
|
||||
tooltip: "Table copy is complete and it's preparing to follow WAL changes.",
|
||||
color: 'text-success-600',
|
||||
}
|
||||
case 'following_wal':
|
||||
return {
|
||||
badge: <Badge variant="success">Live</Badge>,
|
||||
description: `Replicating live changes`,
|
||||
description: 'Table is streaming new changes in real time from the WAL.',
|
||||
tooltip: 'Table is streaming new changes in real time from the WAL.',
|
||||
color: 'text-success-600',
|
||||
}
|
||||
case 'error':
|
||||
return {
|
||||
badge: <Badge variant="destructive">Error</Badge>,
|
||||
description: <pre className="text-xs font-mono">{state.reason}</pre>,
|
||||
description: 'Replication is paused because the table encountered an error.',
|
||||
tooltip: 'Replication is paused because the table encountered an error.',
|
||||
color: 'text-destructive-600',
|
||||
}
|
||||
default:
|
||||
return {
|
||||
badge: <Badge variant="warning">Unknown</Badge>,
|
||||
description: 'Unknown status',
|
||||
description: 'Table status is unavailable.',
|
||||
tooltip: 'Table status is unavailable.',
|
||||
color: 'text-warning',
|
||||
}
|
||||
}
|
||||
@@ -122,3 +133,57 @@ export const isValidRetryPolicy = (policy: any): policy is RetryPolicy => {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
const formatLagBytesValue = (value?: number) => {
|
||||
if (typeof value !== 'number' || Number.isNaN(value)) {
|
||||
return { display: '—', detail: undefined }
|
||||
}
|
||||
|
||||
const decimals = value < 1024 ? 0 : value < 1024 * 1024 ? 1 : 2
|
||||
const display = formatBytes(value, decimals)
|
||||
const detail = `${numberFormatter.format(value)} bytes`
|
||||
|
||||
return { display, detail }
|
||||
}
|
||||
|
||||
const formatLagDurationValue = (value?: number) => {
|
||||
if (typeof value !== 'number' || Number.isNaN(value)) {
|
||||
return { display: '—', detail: undefined }
|
||||
}
|
||||
|
||||
const sign = value < 0 ? '-' : ''
|
||||
const absMilliseconds = Math.abs(value)
|
||||
const duration = dayjs.duration(absMilliseconds, 'milliseconds')
|
||||
|
||||
if (absMilliseconds < 1000) {
|
||||
return { display: `${value} ms`, detail: undefined }
|
||||
}
|
||||
|
||||
const seconds = duration.asSeconds()
|
||||
if (seconds < 60) {
|
||||
const decimals = seconds >= 10 ? 1 : 2
|
||||
return {
|
||||
display: `${sign}${seconds.toFixed(decimals)} s`,
|
||||
detail: `${numberFormatter.format(value)} ms`,
|
||||
}
|
||||
}
|
||||
|
||||
const minutes = duration.asMinutes()
|
||||
if (minutes < 60) {
|
||||
const roundedSeconds = Math.round(seconds)
|
||||
return {
|
||||
display: `${sign}${minutes.toFixed(minutes >= 10 ? 1 : 2)} min`,
|
||||
detail: `${numberFormatter.format(roundedSeconds)} s`,
|
||||
}
|
||||
}
|
||||
|
||||
const hours = duration.asHours()
|
||||
const roundedMinutes = Math.round(minutes)
|
||||
return {
|
||||
display: `${sign}${hours.toFixed(hours >= 10 ? 1 : 2)} h`,
|
||||
detail: `${numberFormatter.format(roundedMinutes)} min`,
|
||||
}
|
||||
}
|
||||
|
||||
export const getFormattedLagValue = (type: 'bytes' | 'duration', value?: number) =>
|
||||
type === 'bytes' ? formatLagBytesValue(value) : formatLagDurationValue(value)
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
import { Info } from 'lucide-react'
|
||||
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from 'ui'
|
||||
import { SlotLagMetricKey, SlotLagMetrics } from './ReplicationPipelineStatus.types'
|
||||
import { getFormattedLagValue } from './ReplicationPipelineStatus.utils'
|
||||
|
||||
const SLOT_LAG_FIELDS: {
|
||||
key: SlotLagMetricKey
|
||||
label: string
|
||||
type: 'bytes' | 'duration'
|
||||
description: string
|
||||
}[] = [
|
||||
{
|
||||
key: 'confirmed_flush_lsn_bytes',
|
||||
label: 'WAL Flush lag (size)',
|
||||
type: 'bytes',
|
||||
description:
|
||||
'Bytes between the newest WAL record applied locally and the latest flushed WAL record acknowledged by ETL.',
|
||||
},
|
||||
{
|
||||
key: 'flush_lag',
|
||||
label: 'WAL Flush lag (time)',
|
||||
type: 'duration',
|
||||
description:
|
||||
'Time between flushing recent WAL locally and receiving notification that ETL has written and flushed it.',
|
||||
},
|
||||
{
|
||||
key: 'safe_wal_size_bytes',
|
||||
label: 'Remaining WAL size',
|
||||
type: 'bytes',
|
||||
description:
|
||||
'Bytes still available to write to WAL before this slot risks entering the "lost" state.',
|
||||
},
|
||||
]
|
||||
|
||||
export const SlotLagMetricsInline = ({
|
||||
tableName,
|
||||
metrics,
|
||||
}: {
|
||||
tableName: string
|
||||
metrics: SlotLagMetrics
|
||||
}) => {
|
||||
return (
|
||||
<div className="flex flex-wrap items-center gap-x-3 gap-y-1.5 text-xs text-foreground">
|
||||
<span className="truncate font-medium" title={tableName}>
|
||||
{tableName}
|
||||
</span>
|
||||
<span className="text-foreground-lighter">•</span>
|
||||
<div className="flex flex-wrap items-center gap-x-3 gap-y-1.5 text-[11px] text-foreground-light">
|
||||
{SLOT_LAG_FIELDS.map(({ key, label, type }) => {
|
||||
const { display } = getFormattedLagValue(type, metrics[key])
|
||||
return (
|
||||
<span key={`${tableName}-${key}`} className="flex items-center gap-1">
|
||||
<span className="uppercase tracking-wide text-[10px] text-foreground-lighter">
|
||||
{label}
|
||||
</span>
|
||||
<span className="text-foreground">{display}</span>
|
||||
</span>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const SlotLagMetricsList = ({
|
||||
metrics,
|
||||
size = 'default',
|
||||
showMetricInfo = true,
|
||||
}: {
|
||||
metrics: SlotLagMetrics
|
||||
size?: 'default' | 'compact'
|
||||
showMetricInfo?: boolean
|
||||
}) => {
|
||||
const gridClasses =
|
||||
size === 'default'
|
||||
? 'grid-cols-1 sm:grid-cols-2 xl:grid-cols-3 gap-y-4 gap-x-6'
|
||||
: 'grid-cols-2 gap-y-2 gap-x-4'
|
||||
|
||||
const labelClasses =
|
||||
size === 'default' ? 'text-xs text-foreground-light' : 'text-[11px] text-foreground-lighter'
|
||||
|
||||
const valueClasses =
|
||||
size === 'default'
|
||||
? 'text-sm font-medium text-foreground'
|
||||
: 'text-xs font-medium text-foreground'
|
||||
|
||||
return (
|
||||
<dl className={`grid ${gridClasses}`}>
|
||||
{SLOT_LAG_FIELDS.map(({ key, label, type, description }) => (
|
||||
<div key={key} className="flex flex-col gap-0.5">
|
||||
<dt className={labelClasses}>
|
||||
<span className="inline-flex items-center gap-1">
|
||||
{label}
|
||||
{showMetricInfo && (
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
aria-label={`What is ${label}`}
|
||||
className="inline-flex h-4 w-4 items-center justify-center rounded-full bg-surface-200 text-foreground-lighter transition-colors hover:bg-surface-300 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:ring-foreground-lighter"
|
||||
>
|
||||
<Info size={12} />
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="top" align="start" className="max-w-xs text-xs">
|
||||
{description}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</span>
|
||||
</dt>
|
||||
{(() => {
|
||||
const { display, detail } = getFormattedLagValue(type, metrics[key])
|
||||
return (
|
||||
<dd className={`flex flex-col ${valueClasses}`}>
|
||||
<span>{display}</span>
|
||||
{detail && <span className="text-[11px] text-foreground-lighter">{detail}</span>}
|
||||
</dd>
|
||||
)
|
||||
})()}
|
||||
</div>
|
||||
))}
|
||||
</dl>
|
||||
)
|
||||
}
|
||||
@@ -32,7 +32,7 @@ import {
|
||||
useIsAwsK8sCloudProvider,
|
||||
useSelectedProjectQuery,
|
||||
} from 'hooks/misc/useSelectedProject'
|
||||
import { GB, PROJECT_STATUS } from 'lib/constants'
|
||||
import { DOCS_URL, GB, PROJECT_STATUS } from 'lib/constants'
|
||||
import { CloudProvider } from 'shared-data'
|
||||
import {
|
||||
Button,
|
||||
@@ -372,7 +372,7 @@ export function DiskManagementForm() {
|
||||
<DocsButton
|
||||
abbrev={false}
|
||||
className="mt-2"
|
||||
href="https://supabase.com/docs/guides/platform/database-size#read-only-mode"
|
||||
href={`${DOCS_URL}/guides/platform/database-size#read-only-mode`}
|
||||
/>
|
||||
</Admonition>
|
||||
)}
|
||||
@@ -385,7 +385,7 @@ export function DiskManagementForm() {
|
||||
<DocsButton
|
||||
abbrev={false}
|
||||
className="mt-2"
|
||||
href="https://supabase.com/docs/guides/platform/database-size#disabling-read-only-mode"
|
||||
href={`${DOCS_URL}/guides/platform/database-size#disabling-read-only-mode`}
|
||||
/>
|
||||
</Admonition>
|
||||
)}
|
||||
|
||||
@@ -2,6 +2,7 @@ import Link from 'next/link'
|
||||
|
||||
import { useParams } from 'common'
|
||||
import { FormHeader } from 'components/ui/Forms/FormHeader'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { Button } from 'ui'
|
||||
import { NoticeBar } from './ui/NoticeBar'
|
||||
|
||||
@@ -13,7 +14,7 @@ export function DiskManagementPanelForm() {
|
||||
<div id="disk-management">
|
||||
<FormHeader
|
||||
title="Disk Management"
|
||||
docsUrl="https://supabase.com/docs/guides/platform/database-size#disk-management"
|
||||
docsUrl={`${DOCS_URL}/guides/platform/database-size#disk-management`}
|
||||
/>
|
||||
<NoticeBar
|
||||
visible={true}
|
||||
|
||||
@@ -6,10 +6,11 @@ import { useParams } from 'common'
|
||||
import { DocsButton } from 'components/ui/DocsButton'
|
||||
import { InlineLink } from 'components/ui/InlineLink'
|
||||
import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query'
|
||||
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
|
||||
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
|
||||
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
||||
import { getCloudProviderArchitecture } from 'lib/cloudprovider-utils'
|
||||
import { InstanceSpecs } from 'lib/constants'
|
||||
import { DOCS_URL, InstanceSpecs } from 'lib/constants'
|
||||
import Link from 'next/link'
|
||||
import {
|
||||
cn,
|
||||
@@ -33,7 +34,6 @@ import {
|
||||
import { BillingChangeBadge } from '../ui/BillingChangeBadge'
|
||||
import FormMessage from '../ui/FormMessage'
|
||||
import { NoticeBar } from '../ui/NoticeBar'
|
||||
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
|
||||
|
||||
/**
|
||||
* to do: this could be a type from api-types
|
||||
@@ -139,7 +139,7 @@ export function ComputeSizeField({ form, disabled }: ComputeSizeFieldProps) {
|
||||
<div className="mt-3">
|
||||
<DocsButton
|
||||
abbrev={false}
|
||||
href="https://supabase.com/docs/guides/platform/compute-and-disk"
|
||||
href={`${DOCS_URL}/guides/platform/compute-and-disk`}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useDiskUtilizationQuery } from 'data/config/disk-utilization-query'
|
||||
import dayjs from 'dayjs'
|
||||
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
|
||||
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
||||
import { GB } from 'lib/constants'
|
||||
import { DOCS_URL, GB } from 'lib/constants'
|
||||
import { Button, FormControl_Shadcn_, FormField_Shadcn_, Input_Shadcn_, Skeleton, cn } from 'ui'
|
||||
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
|
||||
import { DiskStorageSchemaType } from '../DiskManagement.schema'
|
||||
@@ -156,10 +156,7 @@ export function DiskSizeField({
|
||||
`Your plan includes ${includedDiskGB} GB of disk size for ${watchedStorageType}.`}
|
||||
|
||||
<div className="mt-3">
|
||||
<DocsButton
|
||||
abbrev={false}
|
||||
href="https://supabase.com/docs/guides/platform/database-size"
|
||||
/>
|
||||
<DocsButton abbrev={false} href={`${DOCS_URL}/guides/platform/database-size`} />
|
||||
</div>
|
||||
</span>
|
||||
<DiskTypeRecommendationSection
|
||||
|
||||
@@ -8,6 +8,7 @@ import CodeSnippet from 'components/interfaces/Docs/CodeSnippet'
|
||||
import { DocsButton } from 'components/ui/DocsButton'
|
||||
import { useProjectPostgrestConfigQuery } from 'data/config/project-postgrest-config-query'
|
||||
import { generateTypes } from 'data/projects/project-type-generation-query'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { Button } from 'ui'
|
||||
|
||||
interface Props {
|
||||
@@ -43,7 +44,7 @@ export default function GeneratingTypes({ selectedLang }: Props) {
|
||||
<>
|
||||
<h2 className="doc-heading flex items-center justify-between">
|
||||
<span>Generating types</span>
|
||||
<DocsButton href="https://supabase.com/docs/guides/database/api/generating-types" />
|
||||
<DocsButton href={`${DOCS_URL}/guides/database/api/generating-types`} />
|
||||
</h2>
|
||||
<div className="doc-section">
|
||||
<article className="code-column text-foreground">
|
||||
@@ -53,10 +54,8 @@ export default function GeneratingTypes({ selectedLang }: Props) {
|
||||
</p>
|
||||
<p>
|
||||
You can generate types from your database either through the{' '}
|
||||
<Link href="https://supabase.com/docs/guides/database/api/generating-types">
|
||||
Supabase CLI
|
||||
</Link>
|
||||
, or by downloading the types file via the button on the right and importing it in your
|
||||
<Link href={`${DOCS_URL}/guides/database/api/generating-types`}>Supabase CLI</Link>, or
|
||||
by downloading the types file via the button on the right and importing it in your
|
||||
application within <code>src/index.ts</code>.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useRouter } from 'next/router'
|
||||
import { useParams } from 'common'
|
||||
import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query'
|
||||
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { makeRandomString } from 'lib/helpers'
|
||||
import CodeSnippet from '../CodeSnippet'
|
||||
import Snippets from '../Snippets'
|
||||
@@ -179,11 +180,7 @@ export const UserManagement = ({ selectedLang, showApiKey }: UserManagementProps
|
||||
</p>
|
||||
<p>
|
||||
View all the available{' '}
|
||||
<a
|
||||
href="https://supabase.com/docs/guides/auth#providers"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<a href={`${DOCS_URL}/guides/auth#providers`} target="_blank" rel="noreferrer">
|
||||
Third Party OAuth providers
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -8,6 +8,7 @@ import Snippets from 'components/interfaces/Docs/Snippets'
|
||||
import { useCustomDomainsQuery } from 'data/custom-domains/custom-domains-query'
|
||||
import { useProjectJsonSchemaQuery } from 'data/docs/project-json-schema-query'
|
||||
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
|
||||
interface ResourceContentProps {
|
||||
apiEndpoint: string
|
||||
@@ -120,7 +121,7 @@ const ResourceContent = ({
|
||||
</p>
|
||||
<p>
|
||||
<a
|
||||
href="https://supabase.com/docs/reference/javascript/select"
|
||||
href={`${DOCS_URL}/reference/javascript/select`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
@@ -157,7 +158,7 @@ const ResourceContent = ({
|
||||
<p>Supabase provides a wide range of filters.</p>
|
||||
<p>
|
||||
<a
|
||||
href="https://supabase.com/docs/reference/javascript/using-filters"
|
||||
href={`${DOCS_URL}/reference/javascript/using-filters`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
@@ -188,7 +189,7 @@ const ResourceContent = ({
|
||||
</p>
|
||||
<p>
|
||||
<a
|
||||
href="https://supabase.com/docs/reference/javascript/insert"
|
||||
href={`${DOCS_URL}/reference/javascript/insert`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
@@ -228,7 +229,7 @@ const ResourceContent = ({
|
||||
</p>
|
||||
<p>
|
||||
<a
|
||||
href="https://supabase.com/docs/reference/javascript/update"
|
||||
href={`${DOCS_URL}/reference/javascript/update`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
@@ -256,7 +257,7 @@ const ResourceContent = ({
|
||||
</p>
|
||||
<p>
|
||||
<a
|
||||
href="https://supabase.com/docs/reference/javascript/delete"
|
||||
href={`${DOCS_URL}/reference/javascript/delete`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
@@ -285,7 +286,7 @@ const ResourceContent = ({
|
||||
</p>
|
||||
<p>
|
||||
<a
|
||||
href="https://supabase.com/docs/reference/javascript/subscribe"
|
||||
href={`${DOCS_URL}/reference/javascript/subscribe`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
|
||||
+2
-1
@@ -19,6 +19,7 @@ import { useEdgeFunctionQuery } from 'data/edge-functions/edge-function-query'
|
||||
import { useEdgeFunctionDeleteMutation } from 'data/edge-functions/edge-functions-delete-mutation'
|
||||
import { useEdgeFunctionUpdateMutation } from 'data/edge-functions/edge-functions-update-mutation'
|
||||
import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import {
|
||||
Alert_Shadcn_,
|
||||
AlertDescription_Shadcn_,
|
||||
@@ -378,7 +379,7 @@ export const EdgeFunctionDetails = () => {
|
||||
icon={<ExternalLink strokeWidth={1.5} />}
|
||||
>
|
||||
<Link
|
||||
href="https://supabase.com/docs/guides/functions/dependencies"
|
||||
href={`${DOCS_URL}/guides/functions/dependencies`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Code, Github, Lock, Play, Server, Terminal } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import { useParams } from 'common'
|
||||
import { ScaffoldSectionTitle } from 'components/layouts/Scaffold'
|
||||
@@ -8,7 +9,9 @@ import { DocsButton } from 'components/ui/DocsButton'
|
||||
import { ResourceItem } from 'components/ui/Resource/ResourceItem'
|
||||
import { ResourceList } from 'components/ui/Resource/ResourceList'
|
||||
import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
|
||||
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
|
||||
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state'
|
||||
import {
|
||||
AiIconAnimation,
|
||||
@@ -39,6 +42,16 @@ export const FunctionsEmptyState = () => {
|
||||
const { mutate: sendEvent } = useSendEventMutation()
|
||||
const { data: org } = useSelectedOrganizationQuery()
|
||||
|
||||
const showStripeExample = useIsFeatureEnabled('edge_functions:show_stripe_example')
|
||||
const templates = useMemo(() => {
|
||||
if (showStripeExample) {
|
||||
return EDGE_FUNCTION_TEMPLATES
|
||||
}
|
||||
|
||||
// Filter out Stripe template
|
||||
return EDGE_FUNCTION_TEMPLATES.filter((template) => template.value !== 'stripe-webhook')
|
||||
}, [showStripeExample])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card>
|
||||
@@ -157,7 +170,7 @@ export const FunctionsEmptyState = () => {
|
||||
Start with a template
|
||||
</ScaffoldSectionTitle>
|
||||
<ResourceList>
|
||||
{EDGE_FUNCTION_TEMPLATES.map((template) => (
|
||||
{templates.map((template) => (
|
||||
<ResourceItem
|
||||
key={template.name}
|
||||
media={<Code strokeWidth={1.5} size={16} className="-translate-y-[9px]" />}
|
||||
@@ -181,6 +194,16 @@ export const FunctionsEmptyState = () => {
|
||||
}
|
||||
|
||||
export const FunctionsEmptyStateLocal = () => {
|
||||
const showStripeExample = useIsFeatureEnabled('edge_functions:show_stripe_example')
|
||||
const templates = useMemo(() => {
|
||||
if (showStripeExample) {
|
||||
return EDGE_FUNCTION_TEMPLATES
|
||||
}
|
||||
|
||||
// Filter out Stripe template
|
||||
return EDGE_FUNCTION_TEMPLATES.filter((template) => template.value !== 'stripe-webhook')
|
||||
}, [showStripeExample])
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col gap-y-4">
|
||||
@@ -214,7 +237,9 @@ export const FunctionsEmptyStateLocal = () => {
|
||||
value="supabase functions new hello-world"
|
||||
/>
|
||||
</div>
|
||||
<DocsButton href="https://supabase.com/docs/guides/functions/local-quickstart#create-an-edge-function" />
|
||||
<DocsButton
|
||||
href={`${DOCS_URL}/guides/functions/local-quickstart#create-an-edge-function`}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="p-8">
|
||||
@@ -237,7 +262,9 @@ supabase start # start the supabase stack
|
||||
supabase functions serve # start the Functions watcher`.trim()}
|
||||
/>
|
||||
</div>
|
||||
<DocsButton href="https://supabase.com/docs/guides/functions/local-quickstart#running-edge-functions-locally" />
|
||||
<DocsButton
|
||||
href={`${DOCS_URL}/guides/functions/local-quickstart#running-edge-functions-locally`}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="p-8">
|
||||
@@ -263,7 +290,9 @@ curl --request POST 'http://localhost:54321/functions/v1/hello-world' \\
|
||||
--data '{ "name":"Functions" }'`.trim()}
|
||||
/>
|
||||
</div>
|
||||
<DocsButton href="https://supabase.com/docs/guides/functions/local-quickstart#invoking-edge-functions-locally" />
|
||||
<DocsButton
|
||||
href={`${DOCS_URL}/guides/functions/local-quickstart#invoking-edge-functions-locally`}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -284,7 +313,7 @@ curl --request POST 'http://localhost:54321/functions/v1/hello-world' \\
|
||||
on providers like Fly.io, Digital Ocean, or AWS.
|
||||
</p>
|
||||
<div className="flex items-center gap-x-2">
|
||||
<DocsButton href="https://supabase.com/docs/reference/self-hosting-functions/introduction" />
|
||||
<DocsButton href={`${DOCS_URL}/reference/self-hosting-functions/introduction`} />
|
||||
<Button asChild type="default" icon={<Github />}>
|
||||
<a href="https://github.com/supabase/edge-runtime/">GitHub</a>
|
||||
</Button>
|
||||
@@ -295,7 +324,7 @@ curl --request POST 'http://localhost:54321/functions/v1/hello-world' \\
|
||||
|
||||
<ScaffoldSectionTitle className="text-xl mt-12">Explore our templates</ScaffoldSectionTitle>
|
||||
<ResourceList>
|
||||
{EDGE_FUNCTION_TEMPLATES.map((template) => (
|
||||
{templates.map((template) => (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<ResourceItem
|
||||
@@ -361,7 +390,7 @@ export const FunctionsSecretsEmptyStateLocal = () => {
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<DocsButton href="https://supabase.com/docs/guides/functions/secrets#using-the-cli" />
|
||||
<DocsButton href={`${DOCS_URL}/guides/functions/secrets#using-the-cli`} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
@@ -9,6 +9,7 @@ import { useAccessTokensQuery } from 'data/access-tokens/access-tokens-query'
|
||||
import { getKeys, useAPIKeysQuery } from 'data/api-keys/api-keys-query'
|
||||
import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query'
|
||||
import { useCustomDomainsQuery } from 'data/custom-domains/custom-domains-query'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import {
|
||||
Button,
|
||||
CollapsibleContent_Shadcn_,
|
||||
@@ -140,7 +141,7 @@ export const TerminalInstructions = forwardRef<
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<DocsButton href="https://supabase.com/docs/guides/functions" />
|
||||
<DocsButton href={`${DOCS_URL}/guides/functions`} />
|
||||
<Button asChild type="default" icon={<ExternalLink />}>
|
||||
<a
|
||||
target="_blank"
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
useProjectByRefQuery,
|
||||
useSelectedProjectQuery,
|
||||
} from 'hooks/misc/useSelectedProject'
|
||||
import { IS_PLATFORM, PROJECT_STATUS } from 'lib/constants'
|
||||
import { DOCS_URL, IS_PLATFORM, PROJECT_STATUS } from 'lib/constants'
|
||||
import { useAppStateSnapshot } from 'state/app-state'
|
||||
import {
|
||||
Badge,
|
||||
@@ -127,7 +127,7 @@ export const Home = () => {
|
||||
<TooltipContent side="bottom" align="start" className="max-w-80 text-center">
|
||||
This project is using Postgres with OrioleDB which is currently in preview and
|
||||
not suitable for production workloads. View our{' '}
|
||||
<InlineLink href="https://supabase.com/docs/guides/database/orioledb">
|
||||
<InlineLink href={`${DOCS_URL}/guides/database/orioledb`}>
|
||||
documentation
|
||||
</InlineLink>{' '}
|
||||
for all limitations.
|
||||
|
||||
@@ -6,6 +6,7 @@ import Panel from 'components/ui/Panel'
|
||||
import { EditorIndexPageLink } from 'data/prefetchers/project.$ref.editor'
|
||||
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
|
||||
import { Auth, EdgeFunctions, Realtime, SqlEditor, Storage, TableEditor } from 'icons'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { Button } from 'ui'
|
||||
import { APIKeys } from './APIKeys'
|
||||
import { GetStartedHero } from './GetStartedHero'
|
||||
@@ -51,11 +52,7 @@ export const NewProjectPanel = () => {
|
||||
<Link href={`/project/${ref}/sql/new`}>SQL Editor</Link>
|
||||
</Button>
|
||||
<Button asChild type="default" icon={<ExternalLink />}>
|
||||
<Link
|
||||
href="https://supabase.com/docs/guides/database"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Link href={`${DOCS_URL}/guides/database`} target="_blank" rel="noreferrer">
|
||||
About Database
|
||||
</Link>
|
||||
</Button>
|
||||
@@ -100,11 +97,7 @@ export const NewProjectPanel = () => {
|
||||
type="default"
|
||||
asChild
|
||||
>
|
||||
<Link
|
||||
href="https://supabase.com/docs/guides/auth"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Link href={`${DOCS_URL}/guides/auth`} target="_blank" rel="noreferrer">
|
||||
About Auth
|
||||
</Link>
|
||||
</Button>
|
||||
@@ -136,11 +129,7 @@ export const NewProjectPanel = () => {
|
||||
type="default"
|
||||
asChild
|
||||
>
|
||||
<Link
|
||||
href="https://supabase.com/docs/guides/storage"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Link href={`${DOCS_URL}/guides/storage`} target="_blank" rel="noreferrer">
|
||||
About Storage
|
||||
</Link>
|
||||
</Button>
|
||||
@@ -173,7 +162,7 @@ export const NewProjectPanel = () => {
|
||||
asChild
|
||||
>
|
||||
<Link
|
||||
href="https://supabase.com/docs/guides/functions"
|
||||
href={`${DOCS_URL}/guides/functions`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
@@ -206,11 +195,7 @@ export const NewProjectPanel = () => {
|
||||
type="default"
|
||||
asChild
|
||||
>
|
||||
<Link
|
||||
href="https://supabase.com/docs/guides/realtime"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Link href={`${DOCS_URL}/guides/realtime`} target="_blank" rel="noreferrer">
|
||||
About Realtime
|
||||
</Link>
|
||||
</Button>
|
||||
@@ -229,7 +214,7 @@ export const NewProjectPanel = () => {
|
||||
<h2>Connecting to your new project</h2>
|
||||
<p className="text-base text-foreground-light lg:max-w-sm">
|
||||
Interact with your database through the{' '}
|
||||
<Link href="https://supabase.com/docs/reference" className="text-brand">
|
||||
<Link href={`${DOCS_URL}/reference`} className="text-brand">
|
||||
Supabase client libraries
|
||||
</Link>{' '}
|
||||
with your API keys.
|
||||
@@ -244,11 +229,7 @@ export const NewProjectPanel = () => {
|
||||
<Link href={`/project/${ref}/settings/api`}>View API settings</Link>
|
||||
</Button>
|
||||
<Button asChild className="translate-y-[1px]" type="default" icon={<ExternalLink />}>
|
||||
<Link
|
||||
href="https://supabase.com/docs/guides/database/api"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Link href={`${DOCS_URL}/guides/database/api`} target="_blank" rel="noreferrer">
|
||||
About APIs
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
} from 'data/service-status/service-status-query'
|
||||
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
|
||||
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import {
|
||||
Button,
|
||||
InfoIcon,
|
||||
@@ -213,7 +214,7 @@ export const ServiceStatus = () => {
|
||||
{
|
||||
name: 'Edge Functions',
|
||||
error: undefined,
|
||||
docsUrl: 'https://supabase.com/docs/guides/functions/troubleshooting',
|
||||
docsUrl: `${DOCS_URL}/guides/functions/troubleshooting`,
|
||||
isLoading,
|
||||
isHealthy: !!edgeFunctionsStatus?.healthy,
|
||||
status: edgeFunctionsStatus?.healthy
|
||||
|
||||
@@ -20,7 +20,7 @@ import { useTablesQuery } from 'data/tables/tables-query'
|
||||
import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
|
||||
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
|
||||
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
||||
import { BASE_PATH } from 'lib/constants'
|
||||
import { BASE_PATH, DOCS_URL } from 'lib/constants'
|
||||
import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state'
|
||||
import {
|
||||
AiIconAnimation,
|
||||
@@ -167,7 +167,7 @@ export function GettingStartedSection({
|
||||
actions: [
|
||||
{
|
||||
label: 'Create schema file',
|
||||
href: 'https://supabase.com/docs/guides/local-development/declarative-database-schemas',
|
||||
href: `${DOCS_URL}/guides/local-development/declarative-database-schemas`,
|
||||
variant: 'default',
|
||||
},
|
||||
{
|
||||
@@ -192,7 +192,7 @@ export function GettingStartedSection({
|
||||
actions: [
|
||||
{
|
||||
label: 'Create a seed file',
|
||||
href: 'https://supabase.com/docs/guides/local-development/seeding-your-database',
|
||||
href: `${DOCS_URL}/guides/local-development/seeding-your-database`,
|
||||
variant: 'default',
|
||||
},
|
||||
{
|
||||
@@ -262,7 +262,7 @@ export function GettingStartedSection({
|
||||
actions: [
|
||||
{
|
||||
label: 'Read docs',
|
||||
href: 'https://supabase.com/docs/guides/auth',
|
||||
href: `${DOCS_URL}/guides/auth`,
|
||||
variant: 'default',
|
||||
},
|
||||
],
|
||||
@@ -426,7 +426,7 @@ export function GettingStartedSection({
|
||||
actions: [
|
||||
{
|
||||
label: 'Read docs',
|
||||
href: 'https://supabase.com/docs/guides/auth',
|
||||
href: `${DOCS_URL}/guides/auth`,
|
||||
variant: 'default',
|
||||
},
|
||||
],
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
} from 'data/service-status/service-status-query'
|
||||
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
|
||||
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { InfoIcon, PopoverContent_Shadcn_, PopoverTrigger_Shadcn_, Popover_Shadcn_, cn } from 'ui'
|
||||
|
||||
/**
|
||||
@@ -200,7 +201,7 @@ export const ServiceStatus = () => {
|
||||
{
|
||||
name: 'Edge Functions',
|
||||
error: undefined,
|
||||
docsUrl: 'https://supabase.com/docs/guides/functions/troubleshooting',
|
||||
docsUrl: `${DOCS_URL}/guides/functions/troubleshooting`,
|
||||
isLoading,
|
||||
isHealthy: !!edgeFunctionsStatus?.healthy,
|
||||
status: edgeFunctionsStatus?.healthy
|
||||
|
||||
@@ -5,6 +5,7 @@ import { ProjectPausedState } from 'components/layouts/ProjectLayout/PausedState
|
||||
import { ComputeBadgeWrapper } from 'components/ui/ComputeBadgeWrapper'
|
||||
import { InlineLink } from 'components/ui/InlineLink'
|
||||
import { ProjectUpgradeFailedBanner } from 'components/ui/ProjectUpgradeFailedBanner'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { ReactFlowProvider } from 'reactflow'
|
||||
import { Badge, cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
|
||||
import { InstanceConfiguration } from '../Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration'
|
||||
@@ -54,7 +55,7 @@ export const TopSection = ({
|
||||
<TooltipContent side="bottom" align="start" className="max-w-80 text-center">
|
||||
This project is using Postgres with OrioleDB which is currently in preview and
|
||||
not suitable for production workloads. View our{' '}
|
||||
<InlineLink href="https://supabase.com/docs/guides/database/orioledb">
|
||||
<InlineLink href={`${DOCS_URL}/guides/database/orioledb`}>
|
||||
documentation
|
||||
</InlineLink>{' '}
|
||||
for all limitations.
|
||||
|
||||
@@ -144,7 +144,7 @@ export const CronjobsTab = () => {
|
||||
value={search ?? ''}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.code === 'Enter') setSearchQuery(search.trim())
|
||||
if (e.code === 'Enter' || e.code === 'NumpadEnter') setSearchQuery(search.trim())
|
||||
}}
|
||||
actions={[
|
||||
search && (
|
||||
|
||||
@@ -4,7 +4,7 @@ import Image from 'next/image'
|
||||
import { ComponentType, ReactNode } from 'react'
|
||||
|
||||
import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
|
||||
import { BASE_PATH } from 'lib/constants'
|
||||
import { BASE_PATH, DOCS_URL } from 'lib/constants'
|
||||
import { cn } from 'ui'
|
||||
import { UpgradeDatabaseAlert } from '../Queues/UpgradeDatabaseAlert'
|
||||
import { WRAPPERS } from '../Wrappers/Wrappers.constants'
|
||||
@@ -177,7 +177,7 @@ const supabaseIntegrations: IntegrationDefinition[] = [
|
||||
<Vault className={cn('inset-0 p-2 text-black w-full h-full', className)} {...props} />
|
||||
),
|
||||
description: 'Application level encryption for your project',
|
||||
docsUrl: 'https://supabase.com/docs',
|
||||
docsUrl: DOCS_URL,
|
||||
author: authorSupabase,
|
||||
navigation: [
|
||||
{
|
||||
@@ -221,7 +221,7 @@ const supabaseIntegrations: IntegrationDefinition[] = [
|
||||
),
|
||||
description:
|
||||
'Send real-time data from your database to another system when a table event occurs',
|
||||
docsUrl: 'https://supabase.com/docs',
|
||||
docsUrl: DOCS_URL,
|
||||
author: authorSupabase,
|
||||
requiredExtensions: [],
|
||||
navigation: [
|
||||
@@ -275,7 +275,7 @@ const supabaseIntegrations: IntegrationDefinition[] = [
|
||||
/>
|
||||
),
|
||||
description: 'Run GraphQL queries through our interactive in-browser IDE',
|
||||
docsUrl: 'https://supabase.com/docs',
|
||||
docsUrl: DOCS_URL,
|
||||
author: authorSupabase,
|
||||
navigation: [
|
||||
{
|
||||
|
||||
@@ -66,7 +66,7 @@ export const QueuesTab = () => {
|
||||
value={search ?? ''}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.code === 'Enter') setSearchQuery(search.trim())
|
||||
if (e.code === 'Enter' || e.code === 'NumpadEnter') setSearchQuery(search.trim())
|
||||
}}
|
||||
actions={[
|
||||
search && (
|
||||
|
||||
@@ -10,6 +10,7 @@ import { DocsButton } from 'components/ui/DocsButton'
|
||||
import { useVaultSecretsQuery } from 'data/vault/vault-secrets-query'
|
||||
import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions'
|
||||
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import type { VaultSecret } from 'types'
|
||||
import {
|
||||
Button,
|
||||
@@ -127,7 +128,7 @@ export const SecretsManagement = () => {
|
||||
>
|
||||
Refresh
|
||||
</Button>
|
||||
<DocsButton href="https://supabase.com/docs/guides/database/vault" />
|
||||
<DocsButton href={`${DOCS_URL}/guides/database/vault`} />
|
||||
<ButtonTooltip
|
||||
type="primary"
|
||||
disabled={!canManageSecrets}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BASE_PATH } from 'lib/constants'
|
||||
import { BASE_PATH, DOCS_URL } from 'lib/constants'
|
||||
import { CreateIcebergWrapperSheet } from './CreateIcebergWrapperSheet'
|
||||
import type { ServerOption, WrapperMeta } from './Wrappers.types'
|
||||
|
||||
@@ -46,7 +46,7 @@ export const WRAPPERS: WrapperMeta[] = [
|
||||
description: 'Payment processing and subscription management',
|
||||
extensionName: 'StripeFdw',
|
||||
label: 'Stripe',
|
||||
docsUrl: 'https://supabase.com/docs/guides/database/extensions/wrappers/stripe',
|
||||
docsUrl: `${DOCS_URL}/guides/database/extensions/wrappers/stripe`,
|
||||
server: {
|
||||
options: [
|
||||
{
|
||||
@@ -1213,7 +1213,7 @@ export const WRAPPERS: WrapperMeta[] = [
|
||||
description: 'Backend-as-a-Service with real-time database',
|
||||
extensionName: 'FirebaseFdw',
|
||||
label: 'Firebase',
|
||||
docsUrl: 'https://supabase.com/docs/guides/database/extensions/wrappers/firebase',
|
||||
docsUrl: `${DOCS_URL}/guides/database/extensions/wrappers/firebase`,
|
||||
server: {
|
||||
options: [
|
||||
{
|
||||
@@ -1340,7 +1340,7 @@ export const WRAPPERS: WrapperMeta[] = [
|
||||
description: 'Cloud object storage service',
|
||||
extensionName: 'S3Fdw',
|
||||
label: 'S3',
|
||||
docsUrl: 'https://supabase.com/docs/guides/database/extensions/wrappers/s3',
|
||||
docsUrl: `${DOCS_URL}/guides/database/extensions/wrappers/s3`,
|
||||
server: {
|
||||
options: [
|
||||
{
|
||||
@@ -1424,7 +1424,7 @@ export const WRAPPERS: WrapperMeta[] = [
|
||||
description: 'Column-oriented analytics database',
|
||||
extensionName: 'ClickHouseFdw',
|
||||
label: 'ClickHouse',
|
||||
docsUrl: 'https://supabase.com/docs/guides/database/extensions/wrappers/clickhouse',
|
||||
docsUrl: `${DOCS_URL}/guides/database/extensions/wrappers/clickhouse`,
|
||||
server: {
|
||||
options: [
|
||||
{
|
||||
@@ -1469,7 +1469,7 @@ export const WRAPPERS: WrapperMeta[] = [
|
||||
description: 'Serverless data warehouse and analytics',
|
||||
extensionName: 'BigQueryFdw',
|
||||
label: 'BigQuery',
|
||||
docsUrl: 'https://supabase.com/docs/guides/database/extensions/wrappers/bigquery',
|
||||
docsUrl: `${DOCS_URL}/guides/database/extensions/wrappers/bigquery`,
|
||||
server: {
|
||||
options: [
|
||||
{
|
||||
@@ -1544,7 +1544,7 @@ export const WRAPPERS: WrapperMeta[] = [
|
||||
description: 'No-code database and spreadsheet platform',
|
||||
extensionName: 'airtableFdw',
|
||||
label: 'Airtable',
|
||||
docsUrl: 'https://supabase.com/docs/guides/database/extensions/wrappers/airtable',
|
||||
docsUrl: `${DOCS_URL}/guides/database/extensions/wrappers/airtable`,
|
||||
server: {
|
||||
options: [
|
||||
{
|
||||
@@ -1587,7 +1587,7 @@ export const WRAPPERS: WrapperMeta[] = [
|
||||
description: 'Log management and analytics service',
|
||||
extensionName: 'logflareFdw',
|
||||
label: 'Logflare',
|
||||
docsUrl: 'https://supabase.com/docs/guides/database/extensions/wrappers/logflare',
|
||||
docsUrl: `${DOCS_URL}/guides/database/extensions/wrappers/logflare`,
|
||||
server: {
|
||||
options: [
|
||||
{
|
||||
@@ -1623,7 +1623,7 @@ export const WRAPPERS: WrapperMeta[] = [
|
||||
description: 'Identity and access management platform',
|
||||
extensionName: 'Auth0Fdw',
|
||||
label: 'Auth0',
|
||||
docsUrl: 'https://supabase.com/docs/guides/database/extensions/wrappers/auth0',
|
||||
docsUrl: `${DOCS_URL}/guides/database/extensions/wrappers/auth0`,
|
||||
minimumExtensionVersion: '0.3.0',
|
||||
server: {
|
||||
options: [
|
||||
@@ -1754,7 +1754,7 @@ export const WRAPPERS: WrapperMeta[] = [
|
||||
description: 'AWS user authentication and authorization',
|
||||
extensionName: 'CognitoFdw',
|
||||
label: 'Cognito',
|
||||
docsUrl: 'https://supabase.com/docs/guides/database/extensions/wrappers/cognito',
|
||||
docsUrl: `${DOCS_URL}/guides/database/extensions/wrappers/cognito`,
|
||||
minimumExtensionVersion: '0.3.0',
|
||||
server: {
|
||||
options: [
|
||||
@@ -1849,7 +1849,7 @@ export const WRAPPERS: WrapperMeta[] = [
|
||||
description: 'Microsoft SQL Server database',
|
||||
extensionName: 'mssqlFdw',
|
||||
label: 'Microsoft SQL Server',
|
||||
docsUrl: 'https://supabase.com/docs/guides/database/extensions/wrappers/mssql',
|
||||
docsUrl: `${DOCS_URL}/guides/database/extensions/wrappers/mssql`,
|
||||
minimumExtensionVersion: '0.3.0',
|
||||
server: {
|
||||
options: [
|
||||
@@ -1886,7 +1886,7 @@ export const WRAPPERS: WrapperMeta[] = [
|
||||
description: 'In-memory data structure store',
|
||||
extensionName: 'redisFdw',
|
||||
label: 'Redis',
|
||||
docsUrl: 'https://supabase.com/docs/guides/database/extensions/wrappers/redis',
|
||||
docsUrl: `${DOCS_URL}/guides/database/extensions/wrappers/redis`,
|
||||
minimumExtensionVersion: '0.3.0',
|
||||
server: {
|
||||
options: [
|
||||
@@ -1969,7 +1969,7 @@ export const WRAPPERS: WrapperMeta[] = [
|
||||
description: 'Subscription billing and payments platform',
|
||||
extensionName: 'paddleFdw',
|
||||
label: 'Paddle',
|
||||
docsUrl: 'https://supabase.com/docs/guides/database/extensions/wrappers/paddle',
|
||||
docsUrl: `${DOCS_URL}/guides/database/extensions/wrappers/paddle`,
|
||||
minimumExtensionVersion: '0.4.0',
|
||||
server: {
|
||||
options: [
|
||||
@@ -2070,7 +2070,7 @@ export const WRAPPERS: WrapperMeta[] = [
|
||||
description: 'Cloud data warehouse platform',
|
||||
extensionName: 'snowflakeFdw',
|
||||
label: 'Snowflake',
|
||||
docsUrl: 'https://supabase.com/docs/guides/database/extensions/wrappers/snowflake',
|
||||
docsUrl: `${DOCS_URL}/guides/database/extensions/wrappers/snowflake`,
|
||||
minimumExtensionVersion: '0.4.0',
|
||||
server: {
|
||||
options: [
|
||||
@@ -2173,7 +2173,7 @@ export const WRAPPERS: WrapperMeta[] = [
|
||||
description: 'Iceberg is a data warehouse',
|
||||
extensionName: 'icebergFdw',
|
||||
label: 'Iceberg',
|
||||
docsUrl: 'https://supabase.com/docs/guides/database/extensions/wrappers/iceberg',
|
||||
docsUrl: `${DOCS_URL}/guides/database/extensions/wrappers/iceberg`,
|
||||
minimumExtensionVersion: '0.5.3',
|
||||
createComponent: CreateIcebergWrapperSheet,
|
||||
server: {
|
||||
@@ -2259,7 +2259,7 @@ export const WRAPPERS: WrapperMeta[] = [
|
||||
icon: `${BASE_PATH}/img/icons/cal-com-icon.svg`,
|
||||
extensionName: 'calFdw',
|
||||
label: 'Cal.com',
|
||||
docsUrl: 'https://supabase.com/docs/guides/database/extensions/wrappers/cal',
|
||||
docsUrl: `${DOCS_URL}/guides/database/extensions/wrappers/cal`,
|
||||
minimumExtensionVersion: '0.4.0',
|
||||
server: {
|
||||
options: [
|
||||
@@ -2466,7 +2466,7 @@ export const WRAPPERS: WrapperMeta[] = [
|
||||
icon: `${BASE_PATH}/img/icons/calendly-icon.svg`,
|
||||
extensionName: 'calendlyFdw',
|
||||
label: 'Calendly',
|
||||
docsUrl: 'https://supabase.com/docs/guides/database/extensions/wrappers/calendly',
|
||||
docsUrl: `${DOCS_URL}/guides/database/extensions/wrappers/calendly`,
|
||||
minimumExtensionVersion: '0.4.0',
|
||||
server: {
|
||||
options: [
|
||||
@@ -2703,7 +2703,7 @@ export const WRAPPERS: WrapperMeta[] = [
|
||||
icon: `${BASE_PATH}/img/icons/clerk-icon.svg`,
|
||||
extensionName: 'clerkFdw',
|
||||
label: 'Clerk',
|
||||
docsUrl: 'https://supabase.com/docs/guides/database/extensions/wrappers/clerk',
|
||||
docsUrl: `${DOCS_URL}/guides/database/extensions/wrappers/clerk`,
|
||||
minimumExtensionVersion: '0.4.0',
|
||||
server: {
|
||||
options: [
|
||||
|
||||
@@ -2,11 +2,12 @@ import Link from 'next/link'
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
|
||||
import { createLintSummaryPrompt, lintInfoMap } from 'components/interfaces/Linter/Linter.utils'
|
||||
import { EntityTypeIcon, LintCTA, LintCategoryBadge, LintEntity } from './Linter.utils'
|
||||
import { Lint } from 'data/lint/lint-query'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { ExternalLink } from 'lucide-react'
|
||||
import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state'
|
||||
import { AiIconAnimation, Button } from 'ui'
|
||||
import { ExternalLink } from 'lucide-react'
|
||||
import { EntityTypeIcon, LintCTA, LintEntity } from './Linter.utils'
|
||||
|
||||
interface LintDetailProps {
|
||||
lint: Lint
|
||||
@@ -54,7 +55,7 @@ const LintDetail = ({ lint, projectRef, onAskAssistant }: LintDetailProps) => {
|
||||
<Link
|
||||
href={
|
||||
lintInfoMap.find((item) => item.name === lint.name)?.docsLink ||
|
||||
'https://supabase.com/docs/guides/database/database-linter'
|
||||
`${DOCS_URL}/guides/database/database-linter`
|
||||
}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
|
||||
@@ -14,6 +14,7 @@ import Link from 'next/link'
|
||||
|
||||
import { LINTER_LEVELS, LintInfo } from 'components/interfaces/Linter/Linter.constants'
|
||||
import { LINT_TYPES, Lint } from 'data/lint/lint-query'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { Badge, Button } from 'ui'
|
||||
|
||||
export const lintInfoMap: LintInfo[] = [
|
||||
@@ -24,8 +25,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
link: ({ projectRef, metadata }) =>
|
||||
`/project/${projectRef}/database/indexes?schema=${metadata?.schema}`,
|
||||
linkText: 'Create an index',
|
||||
docsLink:
|
||||
'https://supabase.com/docs/guides/database/database-linter?queryGroups=lint&lint=0001_unindexed_foreign_keys',
|
||||
docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0001_unindexed_foreign_keys`,
|
||||
category: 'performance',
|
||||
},
|
||||
{
|
||||
@@ -34,8 +34,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
icon: <Lock className="text-foreground-muted" size={15} strokeWidth={1.5} />,
|
||||
link: ({ projectRef }) => `/project/${projectRef}/editor`,
|
||||
linkText: 'View table',
|
||||
docsLink:
|
||||
'https://supabase.com/docs/guides/database/database-linter?queryGroups=lint&lint=0002_auth_users_exposed',
|
||||
docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0002_auth_users_exposed`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
@@ -44,8 +43,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
icon: <Table2 className="text-foreground-muted" size={15} strokeWidth={1} />,
|
||||
link: ({ projectRef }) => `/project/${projectRef}/auth/policies`,
|
||||
linkText: 'View policies',
|
||||
docsLink:
|
||||
'https://supabase.com/docs/guides/database/database-linter?queryGroups=lint&lint=0003_auth_rls_initplan',
|
||||
docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0003_auth_rls_initplan`,
|
||||
category: 'performance',
|
||||
},
|
||||
{
|
||||
@@ -54,8 +52,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
icon: <Table2 className="text-foreground-muted" size={15} strokeWidth={1} />,
|
||||
link: ({ projectRef }) => `/project/${projectRef}/editor`,
|
||||
linkText: 'View table',
|
||||
docsLink:
|
||||
'https://supabase.com/docs/guides/database/database-linter?queryGroups=lint&lint=0004_no_primary_key',
|
||||
docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0004_no_primary_key`,
|
||||
category: 'performance',
|
||||
},
|
||||
{
|
||||
@@ -65,8 +62,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
link: ({ projectRef, metadata }) =>
|
||||
`/project/${projectRef}/database/indexes?schema=${metadata?.schema}&table=${metadata?.name}`,
|
||||
linkText: 'View index',
|
||||
docsLink:
|
||||
'https://supabase.com/docs/guides/database/database-linter?queryGroups=lint&lint=0005_unused_index',
|
||||
docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0005_unused_index`,
|
||||
category: 'performance',
|
||||
},
|
||||
{
|
||||
@@ -76,8 +72,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
link: ({ projectRef, metadata }) =>
|
||||
`/project/${projectRef}/auth/policies?schema=${metadata?.schema}&search=${metadata?.name}`,
|
||||
linkText: 'View policies',
|
||||
docsLink:
|
||||
'https://supabase.com/docs/guides/database/database-linter?queryGroups=lint&lint=0006_multiple_permissive_policies',
|
||||
docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0006_multiple_permissive_policies`,
|
||||
category: 'performance',
|
||||
},
|
||||
{
|
||||
@@ -87,8 +82,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
link: ({ projectRef, metadata }) =>
|
||||
`/project/${projectRef}/auth/policies?schema=${metadata?.schema}&search=${metadata?.name}`,
|
||||
linkText: 'View policies',
|
||||
docsLink:
|
||||
'https://supabase.com/docs/guides/database/database-linter?queryGroups=lint&lint=0007_policy_exists_rls_disabled',
|
||||
docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0007_policy_exists_rls_disabled`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
@@ -98,8 +92,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
link: ({ projectRef, metadata }) =>
|
||||
`/project/${projectRef}/auth/policies?schema=${metadata?.schema}&search=${metadata?.name}`,
|
||||
linkText: 'View table',
|
||||
docsLink:
|
||||
'https://supabase.com/docs/guides/database/database-linter?queryGroups=lint&lint=0008_rls_enabled_no_policy',
|
||||
docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0008_rls_enabled_no_policy`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
@@ -109,8 +102,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
link: ({ projectRef, metadata }) =>
|
||||
`/project/${projectRef}/database/indexes?schema=${metadata?.schema}&table=${metadata?.name}`,
|
||||
linkText: 'View index',
|
||||
docsLink:
|
||||
'https://supabase.com/docs/guides/database/database-linter?queryGroups=lint&lint=0009_duplicate_index',
|
||||
docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0009_duplicate_index`,
|
||||
category: 'performance',
|
||||
},
|
||||
{
|
||||
@@ -118,10 +110,9 @@ export const lintInfoMap: LintInfo[] = [
|
||||
title: 'Security Definer View',
|
||||
icon: <Eye className="text-foreground-muted" size={15} strokeWidth={1.5} />,
|
||||
link: () =>
|
||||
'https://supabase.com/docs/guides/database/database-linter?queryGroups=lint&lint=0010_security_definer_view',
|
||||
`${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0010_security_definer_view`,
|
||||
linkText: 'View docs',
|
||||
docsLink:
|
||||
'https://supabase.com/docs/guides/database/database-linter?queryGroups=lint&lint=0010_security_definer_view',
|
||||
docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0010_security_definer_view`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
@@ -131,8 +122,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
link: ({ projectRef, metadata }) =>
|
||||
`/project/${projectRef}/database/functions?schema=${metadata?.schema}&search=${metadata?.name}`,
|
||||
linkText: 'View functions',
|
||||
docsLink:
|
||||
'https://supabase.com/docs/guides/database/database-linter?queryGroups=lint&lint=0011_function_search_path_mutable',
|
||||
docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0011_function_search_path_mutable`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
@@ -142,8 +132,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
link: ({ projectRef, metadata }) =>
|
||||
`/project/${projectRef}/auth/policies?schema=${metadata?.schema}&search=${metadata?.name}`,
|
||||
linkText: 'View policies',
|
||||
docsLink:
|
||||
'https://supabase.com/docs/guides/database/database-linter?queryGroups=lint&lint=0013_rls_disabled_in_public',
|
||||
docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0013_rls_disabled_in_public`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
@@ -153,8 +142,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
link: ({ projectRef, metadata }) =>
|
||||
`/project/${projectRef}/database/extensions?filter=${metadata?.name}`,
|
||||
linkText: 'View extension',
|
||||
docsLink:
|
||||
'https://supabase.com/docs/guides/database/database-linter?queryGroups=lint&lint=0014_extension_in_public',
|
||||
docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0014_extension_in_public`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
@@ -163,7 +151,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
icon: <Clock className="text-foreground-muted" size={15} strokeWidth={1} />,
|
||||
link: ({ projectRef }) => `/project/${projectRef}/auth/providers`,
|
||||
linkText: 'View settings',
|
||||
docsLink: 'https://supabase.com/docs/guides/platform/going-into-prod#security',
|
||||
docsLink: `${DOCS_URL}/guides/platform/going-into-prod#security`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
@@ -172,7 +160,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
icon: <Ruler className="text-foreground-muted" size={15} strokeWidth={1} />,
|
||||
link: ({ projectRef }) => `/project/${projectRef}/auth/providers`,
|
||||
linkText: 'View settings',
|
||||
docsLink: 'https://supabase.com/docs/guides/platform/going-into-prod#security',
|
||||
docsLink: `${DOCS_URL}/guides/platform/going-into-prod#security`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
@@ -181,30 +169,25 @@ export const lintInfoMap: LintInfo[] = [
|
||||
icon: <User className="text-foreground-muted" size={15} strokeWidth={1} />,
|
||||
link: ({ projectRef }) => `/project/${projectRef}/auth/policies`,
|
||||
linkText: 'View policies',
|
||||
docsLink:
|
||||
'https://supabase.com/docs/guides/database/database-linter?queryGroups=lint&lint=0015_rls_references_user_metadata',
|
||||
docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0015_rls_references_user_metadata`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
name: 'materialized_view_in_api',
|
||||
title: 'Materialized View in API',
|
||||
icon: <Eye className="text-foreground-muted" size={15} strokeWidth={1.5} />,
|
||||
link: () =>
|
||||
`https://supabase.com/docs/guides/database/database-advisors?lint=0016_materialized_view_in_api`,
|
||||
link: () => `${DOCS_URL}/guides/database/database-advisors?lint=0016_materialized_view_in_api`,
|
||||
linkText: 'View docs',
|
||||
docsLink:
|
||||
'https://supabase.com/docs/guides/database/database-advisors?lint=0016_materialized_view_in_api',
|
||||
docsLink: `${DOCS_URL}/guides/database/database-advisors?lint=0016_materialized_view_in_api`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
name: 'foreign_table_in_api',
|
||||
title: 'Foreign Table in API',
|
||||
icon: <Table2 className="text-foreground-muted" size={15} strokeWidth={1.5} />,
|
||||
link: () =>
|
||||
`https://supabase.com/docs/guides/database/database-linter?lint=0017_foreign_table_in_api`,
|
||||
link: () => `${DOCS_URL}/guides/database/database-linter?lint=0017_foreign_table_in_api`,
|
||||
linkText: 'View docs',
|
||||
docsLink:
|
||||
'https://supabase.com/docs/guides/database/database-linter?lint=0017_foreign_table_in_api',
|
||||
docsLink: `${DOCS_URL}/guides/database/database-linter?lint=0017_foreign_table_in_api`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
@@ -212,10 +195,9 @@ export const lintInfoMap: LintInfo[] = [
|
||||
title: 'Unsupported reg types',
|
||||
icon: <Table2 className="text-foreground-muted" size={15} strokeWidth={1.5} />,
|
||||
link: () =>
|
||||
`https://supabase.com/docs/guides/database/database-advisors?lint=0018_unsupported_reg_types&queryGroups=lint`,
|
||||
`${DOCS_URL}/guides/database/database-advisors?lint=0018_unsupported_reg_types&queryGroups=lint`,
|
||||
linkText: 'View docs',
|
||||
docsLink:
|
||||
'https://supabase.com/docs/guides/database/database-advisors?lint=0018_unsupported_reg_types&queryGroups=lint',
|
||||
docsLink: `${DOCS_URL}/guides/database/database-advisors?lint=0018_unsupported_reg_types&queryGroups=lint`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
@@ -224,7 +206,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
icon: <Ruler className="text-foreground-muted" size={15} strokeWidth={1} />,
|
||||
link: ({ projectRef }) => `/project/${projectRef}/database/settings`,
|
||||
linkText: 'View settings',
|
||||
docsLink: 'https://supabase.com/docs/guides/platform/ssl-enforcement',
|
||||
docsLink: `${DOCS_URL}/guides/platform/ssl-enforcement`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
@@ -233,7 +215,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
icon: <Ruler className="text-foreground-muted" size={15} strokeWidth={1} />,
|
||||
link: ({ projectRef }) => `/project/${projectRef}/database/settings`,
|
||||
linkText: 'View settings',
|
||||
docsLink: 'https://supabase.com/docs/guides/platform/network-restrictions',
|
||||
docsLink: `${DOCS_URL}/guides/platform/network-restrictions`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
@@ -242,7 +224,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
icon: <Ruler className="text-foreground-muted" size={15} strokeWidth={1} />,
|
||||
link: ({ projectRef }) => `/project/${projectRef}/auth/providers?provider=Email`,
|
||||
linkText: 'View settings',
|
||||
docsLink: 'https://supabase.com/docs/guides/platform/going-into-prod#security',
|
||||
docsLink: `${DOCS_URL}/guides/platform/going-into-prod#security`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
@@ -251,7 +233,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
icon: <Ruler className="text-foreground-muted" size={15} strokeWidth={1} />,
|
||||
link: ({ projectRef }) => `/project/${projectRef}/database/backups/pitr`,
|
||||
linkText: 'View settings',
|
||||
docsLink: 'https://supabase.com/docs/guides/platform/backups#point-in-time-recovery',
|
||||
docsLink: `${DOCS_URL}/guides/platform/backups#point-in-time-recovery`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
@@ -260,8 +242,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
icon: <LockIcon className="text-foreground-muted" size={15} strokeWidth={1} />,
|
||||
link: ({ projectRef }) => `/project/${projectRef}/auth/providers?provider=Email`,
|
||||
linkText: 'View settings',
|
||||
docsLink:
|
||||
'https://supabase.com/docs/guides/auth/password-security#password-strength-and-leaked-password-protection',
|
||||
docsLink: `${DOCS_URL}/guides/auth/password-security#password-strength-and-leaked-password-protection`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
@@ -270,7 +251,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
icon: <LockIcon className="text-foreground-muted" size={15} strokeWidth={1} />,
|
||||
link: ({ projectRef }) => `/project/${projectRef}/auth/mfa`,
|
||||
linkText: 'View settings',
|
||||
docsLink: 'https://supabase.com/docs/guides/auth/auth-mfa',
|
||||
docsLink: `${DOCS_URL}/guides/auth/auth-mfa`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
@@ -279,7 +260,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
icon: <LockIcon className="text-foreground-muted" size={15} strokeWidth={1} />,
|
||||
link: ({ projectRef }) => `/project/${projectRef}/auth/providers?provider=Email`,
|
||||
linkText: 'View settings',
|
||||
docsLink: 'https://supabase.com/docs/guides/auth/password-security',
|
||||
docsLink: `${DOCS_URL}/guides/auth/password-security`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
@@ -288,7 +269,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
icon: <LockIcon className="text-foreground-muted" size={15} strokeWidth={1} />,
|
||||
link: ({ projectRef }) => `/project/${projectRef}/settings/api`,
|
||||
linkText: 'View settings',
|
||||
docsLink: 'https://supabase.com/docs/guides/api/api-keys#the-servicerole-key',
|
||||
docsLink: `${DOCS_URL}/guides/api/api-keys#the-servicerole-key`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
@@ -297,7 +278,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
icon: <LockIcon className="text-foreground-muted" size={15} strokeWidth={1} />,
|
||||
link: ({ projectRef }) => `/project/${projectRef}/auth/mfa`,
|
||||
linkText: 'View settings',
|
||||
docsLink: 'https://supabase.com/docs/guides/auth/auth-mfa',
|
||||
docsLink: `${DOCS_URL}/guides/auth/auth-mfa`,
|
||||
category: 'security',
|
||||
},
|
||||
{
|
||||
@@ -306,7 +287,7 @@ export const lintInfoMap: LintInfo[] = [
|
||||
icon: <LockIcon className="text-foreground-muted" size={15} strokeWidth={1} />,
|
||||
link: ({ projectRef }) => `/project/${projectRef}/settings/infrastructure`,
|
||||
linkText: 'View settings',
|
||||
docsLink: 'https://supabase.com/docs/guides/platform/upgrading',
|
||||
docsLink: `${DOCS_URL}/guides/platform/upgrading`,
|
||||
category: 'security',
|
||||
},
|
||||
]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { X } from 'lucide-react'
|
||||
import { LOCAL_STORAGE_KEYS } from 'common'
|
||||
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { X } from 'lucide-react'
|
||||
import { Button, cn } from 'ui'
|
||||
import { Markdown } from '../Markdown'
|
||||
|
||||
@@ -75,8 +76,8 @@ const LinterPageFooter = ({
|
||||
<p>Inspect your database for potential issues</p>
|
||||
<Markdown
|
||||
className="text-xs"
|
||||
content="The Supabase CLI comes with a range of tools to help inspect your Postgres instances for
|
||||
potential issues. [Learn more here](https://supabase.com/docs/guides/database/inspect)."
|
||||
content={`The Supabase CLI comes with a range of tools to help inspect your Postgres instances for
|
||||
potential issues. [Learn more here](${DOCS_URL}/guides/database/inspect).`}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -6,9 +6,9 @@ import { toast } from 'sonner'
|
||||
import { z } from 'zod'
|
||||
|
||||
import { useParams } from 'common'
|
||||
import { LogDrainData, useLogDrainsQuery } from 'data/log-drains/log-drains-query'
|
||||
|
||||
import { DocsButton } from 'components/ui/DocsButton'
|
||||
import { LogDrainData, useLogDrainsQuery } from 'data/log-drains/log-drains-query'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import {
|
||||
Button,
|
||||
Form_Shadcn_,
|
||||
@@ -533,7 +533,7 @@ export function LogDrainDestinationSheetForm({
|
||||
<DocsButton
|
||||
abbrev={false}
|
||||
className="w-min"
|
||||
href="https://supabase.com/docs/guides/platform/log-drains"
|
||||
href={`${DOCS_URL}/guides/platform/log-drains`}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,4 +1,5 @@
|
||||
import { PricingMetric } from 'data/analytics/org-daily-stats-query'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
|
||||
export const USAGE_APPROACHING_THRESHOLD = 0.8
|
||||
|
||||
@@ -111,7 +112,7 @@ export const BILLING_BREAKDOWN_METRICS: Metric[] = [
|
||||
tip: 'Each project gets provisioned with 8 GB of GP3 disk for free. When you get close to the disk size limit, we autoscale your disk by 1.5x. Each GB of provisioned disk size beyond 8 GB incurs a GB-Hr every hour. Each extra GB is billed at $0.125/month ($0.000171/GB-Hr), prorated down to the hour.',
|
||||
docLink: {
|
||||
title: 'Read more',
|
||||
url: 'https://supabase.com/docs/guides/platform/manage-your-usage/disk-size',
|
||||
url: `${DOCS_URL}/guides/platform/manage-your-usage/disk-size`,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
+3
-2
@@ -2,6 +2,7 @@ import Link from 'next/link'
|
||||
|
||||
import { ComputeUsageMetric, PricingMetric } from 'data/analytics/org-daily-stats-query'
|
||||
import type { OrgUsageResponse } from 'data/usage/org-usage-query'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { formatCurrency } from 'lib/helpers'
|
||||
import { ChevronRight } from 'lucide-react'
|
||||
import { useMemo } from 'react'
|
||||
@@ -74,7 +75,7 @@ export const ComputeMetric = ({
|
||||
Each Preview branch is a separate environment with all Supabase services (Database,
|
||||
Auth, Storage, etc.).{' '}
|
||||
<Link
|
||||
href="https://supabase.com/docs/guides/platform/manage-your-usage/branching"
|
||||
href={`${DOCS_URL}/guides/platform/manage-your-usage/branching`}
|
||||
target="_blank"
|
||||
className="transition text-brand hover:text-brand-600 underline"
|
||||
>
|
||||
@@ -87,7 +88,7 @@ export const ComputeMetric = ({
|
||||
active, it incurs compute costs based on the compute size of your project. Paused
|
||||
projects do not incur compute costs.{' '}
|
||||
<Link
|
||||
href="https://supabase.com/docs/guides/platform/manage-your-usage/compute"
|
||||
href={`${DOCS_URL}/guides/platform/manage-your-usage/compute`}
|
||||
target="_blank"
|
||||
className="transition text-brand hover:text-brand-600 underline"
|
||||
>
|
||||
|
||||
+30
-54
@@ -2,70 +2,50 @@ import Link from 'next/link'
|
||||
|
||||
import AlertError from 'components/ui/AlertError'
|
||||
import ShimmeringLoader from 'components/ui/ShimmeringLoader'
|
||||
import { PricingMetric } from 'data/analytics/org-daily-stats-query'
|
||||
import {
|
||||
UpcomingInvoiceResponse,
|
||||
useOrgUpcomingInvoiceQuery,
|
||||
} from 'data/invoices/org-invoice-upcoming-query'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { formatCurrency } from 'lib/helpers'
|
||||
import { Table, TableBody, TableCell, TableFooter, TableRow } from 'ui'
|
||||
import { billingMetricUnit, formatUsage } from '../helpers'
|
||||
import { InfoTooltip } from 'ui-patterns/info-tooltip'
|
||||
import { PricingMetric } from 'data/analytics/org-daily-stats-query'
|
||||
import _ from 'lodash'
|
||||
import React from 'react'
|
||||
import { Table, TableBody, TableCell, TableFooter, TableRow } from 'ui'
|
||||
import { InfoTooltip } from 'ui-patterns/info-tooltip'
|
||||
import { billingMetricUnit, formatUsage } from '../helpers'
|
||||
|
||||
export interface UpcomingInvoiceProps {
|
||||
slug?: string
|
||||
}
|
||||
|
||||
const usageBillingDocsLink: { [K in PricingMetric]?: string } = {
|
||||
[PricingMetric.MONTHLY_ACTIVE_USERS]:
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/monthly-active-users',
|
||||
[PricingMetric.MONTHLY_ACTIVE_SSO_USERS]:
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/monthly-active-users-sso',
|
||||
[PricingMetric.MONTHLY_ACTIVE_THIRD_PARTY_USERS]:
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/monthly-active-users-third-party',
|
||||
[PricingMetric.AUTH_MFA_PHONE]:
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/advanced-mfa-phone',
|
||||
[PricingMetric.MONTHLY_ACTIVE_USERS]: `${DOCS_URL}/guides/platform/manage-your-usage/monthly-active-users`,
|
||||
[PricingMetric.MONTHLY_ACTIVE_SSO_USERS]: `${DOCS_URL}/guides/platform/manage-your-usage/monthly-active-users-sso`,
|
||||
[PricingMetric.MONTHLY_ACTIVE_THIRD_PARTY_USERS]: `${DOCS_URL}/guides/platform/manage-your-usage/monthly-active-users-third-party`,
|
||||
[PricingMetric.AUTH_MFA_PHONE]: `${DOCS_URL}/guides/platform/manage-your-usage/advanced-mfa-phone`,
|
||||
|
||||
[PricingMetric.EGRESS]: 'https://supabase.com/docs/guides/platform/manage-your-usage/egress',
|
||||
[PricingMetric.CACHED_EGRESS]:
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/egress',
|
||||
[PricingMetric.EGRESS]: `${DOCS_URL}/guides/platform/manage-your-usage/egress`,
|
||||
[PricingMetric.CACHED_EGRESS]: `${DOCS_URL}/guides/platform/manage-your-usage/egress`,
|
||||
|
||||
[PricingMetric.FUNCTION_INVOCATIONS]:
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/edge-function-invocations',
|
||||
[PricingMetric.FUNCTION_INVOCATIONS]: `${DOCS_URL}/guides/platform/manage-your-usage/edge-function-invocations`,
|
||||
|
||||
[PricingMetric.STORAGE_SIZE]:
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/storage-size',
|
||||
[PricingMetric.STORAGE_IMAGES_TRANSFORMED]:
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/storage-image-transformations',
|
||||
[PricingMetric.STORAGE_SIZE]: `${DOCS_URL}/guides/platform/manage-your-usage/storage-size`,
|
||||
[PricingMetric.STORAGE_IMAGES_TRANSFORMED]: `${DOCS_URL}/guides/platform/manage-your-usage/storage-image-transformations`,
|
||||
|
||||
[PricingMetric.REALTIME_MESSAGE_COUNT]:
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/realtime-messages',
|
||||
[PricingMetric.REALTIME_PEAK_CONNECTIONS]:
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/realtime-peak-connections',
|
||||
[PricingMetric.REALTIME_MESSAGE_COUNT]: `${DOCS_URL}/guides/platform/manage-your-usage/realtime-messages`,
|
||||
[PricingMetric.REALTIME_PEAK_CONNECTIONS]: `${DOCS_URL}/guides/platform/manage-your-usage/realtime-peak-connections`,
|
||||
|
||||
[PricingMetric.CUSTOM_DOMAIN]:
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/custom-domains',
|
||||
[PricingMetric.IPV4]: 'https://supabase.com/docs/guides/platform/manage-your-usage/ipv4',
|
||||
[PricingMetric.PITR_7]:
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/point-in-time-recovery',
|
||||
[PricingMetric.PITR_14]:
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/point-in-time-recovery',
|
||||
[PricingMetric.PITR_28]:
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/point-in-time-recovery',
|
||||
[PricingMetric.DISK_SIZE_GB_HOURS_GP3]:
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/disk-size',
|
||||
[PricingMetric.DISK_SIZE_GB_HOURS_IO2]:
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/disk-size',
|
||||
[PricingMetric.DISK_IOPS_GP3]:
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/disk-iops',
|
||||
[PricingMetric.DISK_IOPS_IO2]:
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/disk-iops',
|
||||
[PricingMetric.DISK_THROUGHPUT_GP3]:
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/disk-throughput',
|
||||
[PricingMetric.LOG_DRAIN]:
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/log-drains',
|
||||
[PricingMetric.CUSTOM_DOMAIN]: `${DOCS_URL}/guides/platform/manage-your-usage/custom-domains`,
|
||||
[PricingMetric.IPV4]: `${DOCS_URL}/guides/platform/manage-your-usage/ipv4`,
|
||||
[PricingMetric.PITR_7]: `${DOCS_URL}/guides/platform/manage-your-usage/point-in-time-recovery`,
|
||||
[PricingMetric.PITR_14]: `${DOCS_URL}/guides/platform/manage-your-usage/point-in-time-recovery`,
|
||||
[PricingMetric.PITR_28]: `${DOCS_URL}/guides/platform/manage-your-usage/point-in-time-recovery`,
|
||||
[PricingMetric.DISK_SIZE_GB_HOURS_GP3]: `${DOCS_URL}/guides/platform/manage-your-usage/disk-size`,
|
||||
[PricingMetric.DISK_SIZE_GB_HOURS_IO2]: `${DOCS_URL}/guides/platform/manage-your-usage/disk-size`,
|
||||
[PricingMetric.DISK_IOPS_GP3]: `${DOCS_URL}/guides/platform/manage-your-usage/disk-iops`,
|
||||
[PricingMetric.DISK_IOPS_IO2]: `${DOCS_URL}/guides/platform/manage-your-usage/disk-iops`,
|
||||
[PricingMetric.DISK_THROUGHPUT_GP3]: `${DOCS_URL}/guides/platform/manage-your-usage/disk-throughput`,
|
||||
[PricingMetric.LOG_DRAIN]: `${DOCS_URL}/guides/platform/manage-your-usage/log-drains`,
|
||||
}
|
||||
|
||||
const UpcomingInvoice = ({ slug }: UpcomingInvoiceProps) => {
|
||||
@@ -147,7 +127,7 @@ const UpcomingInvoice = ({ slug }: UpcomingInvoiceProps) => {
|
||||
compute costs starting at <span translate="no">$10</span>/month, independent
|
||||
of activity. See{' '}
|
||||
<Link
|
||||
href={'https://supabase.com/docs/guides/platform/manage-your-usage/compute'}
|
||||
href={`${DOCS_URL}/guides/platform/manage-your-usage/compute`}
|
||||
target="_blank"
|
||||
>
|
||||
docs
|
||||
@@ -167,9 +147,7 @@ const UpcomingInvoice = ({ slug }: UpcomingInvoiceProps) => {
|
||||
Compute, Disk Size, provisioned Disk IOPS, provisioned Disk Throughput, and
|
||||
IPv4. See{' '}
|
||||
<Link
|
||||
href={
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/read-replicas'
|
||||
}
|
||||
href={`${DOCS_URL}/guides/platform/manage-your-usage/read-replicas`}
|
||||
target="_blank"
|
||||
>
|
||||
docs
|
||||
@@ -200,9 +178,7 @@ const UpcomingInvoice = ({ slug }: UpcomingInvoiceProps) => {
|
||||
See{' '}
|
||||
<Link
|
||||
className="underline"
|
||||
href={
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/branching'
|
||||
}
|
||||
href={`${DOCS_URL}/guides/platform/manage-your-usage/branching`}
|
||||
target="_blank"
|
||||
>
|
||||
docs
|
||||
|
||||
+3
-4
@@ -12,17 +12,16 @@ import {
|
||||
} from 'components/layouts/Scaffold'
|
||||
import AlertError from 'components/ui/AlertError'
|
||||
import NoPermission from 'components/ui/NoPermission'
|
||||
import PartnerIcon from 'components/ui/PartnerIcon'
|
||||
import { PARTNER_TO_NAME } from 'components/ui/PartnerManagedResource'
|
||||
import ShimmeringLoader from 'components/ui/ShimmeringLoader'
|
||||
import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query'
|
||||
import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions'
|
||||
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
|
||||
import { BASE_PATH } from 'lib/constants'
|
||||
import { BASE_PATH, DOCS_URL } from 'lib/constants'
|
||||
import { MANAGED_BY } from 'lib/constants/infrastructure'
|
||||
import { useOrgSettingsPageStateSnapshot } from 'state/organization-settings'
|
||||
import { Alert, AlertTitle_Shadcn_, Alert_Shadcn_, Button } from 'ui'
|
||||
|
||||
import PartnerIcon from 'components/ui/PartnerIcon'
|
||||
import ProjectUpdateDisabledTooltip from '../ProjectUpdateDisabledTooltip'
|
||||
import SpendCapSidePanel from './SpendCapSidePanel'
|
||||
|
||||
@@ -78,7 +77,7 @@ const CostControl = ({}: CostControlProps) => {
|
||||
<p className="text-sm text-foreground-light m-0">More information</p>
|
||||
<div>
|
||||
<Link
|
||||
href="https://supabase.com/docs/guides/platform/cost-control#spend-cap"
|
||||
href={`${DOCS_URL}/guides/platform/cost-control#spend-cap`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ import Table from 'components/to-be-cleaned/Table'
|
||||
import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query'
|
||||
import { useOrgSubscriptionUpdateMutation } from 'data/subscriptions/org-subscription-update-mutation'
|
||||
import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions'
|
||||
import { BASE_PATH, PRICING_TIER_PRODUCT_IDS } from 'lib/constants'
|
||||
import { BASE_PATH, DOCS_URL, PRICING_TIER_PRODUCT_IDS } from 'lib/constants'
|
||||
import { ChevronRight, ExternalLink } from 'lucide-react'
|
||||
import { pricing } from 'shared-data/pricing'
|
||||
import { useOrgSettingsPageStateSnapshot } from 'state/organization-settings'
|
||||
@@ -108,7 +108,7 @@ const SpendCapSidePanel = () => {
|
||||
<h4>Spend cap</h4>
|
||||
<Button asChild type="default" icon={<ExternalLink strokeWidth={1.5} />}>
|
||||
<Link
|
||||
href="https://supabase.com/docs/guides/platform/cost-control#spend-cap"
|
||||
href={`${DOCS_URL}/guides/platform/cost-control#spend-cap`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
|
||||
@@ -6,6 +6,7 @@ import { PricingMetric } from 'data/analytics/org-daily-stats-query'
|
||||
import { VIOLATION_TYPE_LABELS } from 'data/usage/constants'
|
||||
import { useOrgUsageQuery } from 'data/usage/org-usage-query'
|
||||
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { usePathname } from 'next/navigation'
|
||||
import {
|
||||
AlertDescription_Shadcn_,
|
||||
@@ -94,9 +95,7 @@ export const Restriction = () => {
|
||||
</Button>
|
||||
)}
|
||||
<Button asChild type="default" icon={<ExternalLink />}>
|
||||
<a href="https://supabase.com/docs/guides/platform/cost-control#spend-cap">
|
||||
About spend cap
|
||||
</a>
|
||||
<a href={`${DOCS_URL}/guides/platform/cost-control#spend-cap`}>About spend cap</a>
|
||||
</Button>
|
||||
</div>
|
||||
</AlertDescription_Shadcn_>
|
||||
@@ -139,7 +138,7 @@ export const Restriction = () => {
|
||||
)}
|
||||
|
||||
<Button asChild type="default" icon={<ExternalLink />}>
|
||||
<a href="https://supabase.com/docs/guides/platform/billing-faq#fair-use-policy">
|
||||
<a href={`${DOCS_URL}/guides/platform/billing-faq#fair-use-policy`}>
|
||||
About Fair Use Policy
|
||||
</a>
|
||||
</Button>
|
||||
@@ -179,7 +178,7 @@ export const Restriction = () => {
|
||||
</Button>
|
||||
)}
|
||||
<Button asChild type="default" icon={<ExternalLink />}>
|
||||
<a href="https://supabase.com/docs/guides/platform/billing-faq#fair-use-policy">
|
||||
<a href={`${DOCS_URL}/guides/platform/billing-faq#fair-use-policy`}>
|
||||
About Fair Use Policy
|
||||
</a>
|
||||
</Button>
|
||||
@@ -217,7 +216,7 @@ export const Restriction = () => {
|
||||
</Button>
|
||||
)}
|
||||
<Button asChild type="default" icon={<ExternalLink />}>
|
||||
<a href="https://supabase.com/docs/guides/platform/billing-faq#fair-use-policy">
|
||||
<a href={`${DOCS_URL}/guides/platform/billing-faq#fair-use-policy`}>
|
||||
About Fair Use Policy
|
||||
</a>
|
||||
</Button>
|
||||
|
||||
+8
-5
@@ -19,7 +19,12 @@ import { useConfirmPendingSubscriptionChangeMutation } from 'data/subscriptions/
|
||||
import { useOrgSubscriptionUpdateMutation } from 'data/subscriptions/org-subscription-update-mutation'
|
||||
import { SubscriptionTier } from 'data/subscriptions/types'
|
||||
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
|
||||
import { PRICING_TIER_PRODUCT_IDS, PROJECT_STATUS, STRIPE_PUBLIC_KEY } from 'lib/constants'
|
||||
import {
|
||||
DOCS_URL,
|
||||
PRICING_TIER_PRODUCT_IDS,
|
||||
PROJECT_STATUS,
|
||||
STRIPE_PUBLIC_KEY,
|
||||
} from 'lib/constants'
|
||||
import { formatCurrency } from 'lib/helpers'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { plans as subscriptionsPlans } from 'shared-data/plans'
|
||||
@@ -351,9 +356,7 @@ export const SubscriptionPlanUpdateDialog = ({
|
||||
Credits; additional projects start at <span translate="no">$10</span>
|
||||
/month regardless of usage.{' '}
|
||||
<Link
|
||||
href={
|
||||
'https://supabase.com/docs/guides/platform/manage-your-usage/compute'
|
||||
}
|
||||
href={`${DOCS_URL}/guides/platform/manage-your-usage/compute`}
|
||||
target="_blank"
|
||||
>
|
||||
Learn more
|
||||
@@ -589,7 +592,7 @@ export const SubscriptionPlanUpdateDialog = ({
|
||||
/month regardless of usage.{' '}
|
||||
</div>
|
||||
<Link
|
||||
href={'https://supabase.com/docs/guides/platform/manage-your-usage/compute'}
|
||||
href={`${DOCS_URL}/guides/platform/manage-your-usage/compute`}
|
||||
target="_blank"
|
||||
className="underline"
|
||||
>
|
||||
|
||||
+12
-14
@@ -1,20 +1,22 @@
|
||||
import { useAwsManagedOrganizationCreateMutation } from '../../../../data/organizations/organization-create-mutation'
|
||||
import { toast } from 'sonner'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { SubmitHandler } from 'react-hook-form'
|
||||
import NewAwsMarketplaceOrgForm, {
|
||||
CREATE_AWS_MANAGED_ORG_FORM_ID,
|
||||
NewMarketplaceOrgForm,
|
||||
} from './NewAwsMarketplaceOrgForm'
|
||||
import { toast } from 'sonner'
|
||||
|
||||
import { useAwsManagedOrganizationCreateMutation } from 'data/organizations/organization-create-mutation'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { Button } from 'ui'
|
||||
import {
|
||||
ScaffoldSection,
|
||||
ScaffoldSectionContent,
|
||||
ScaffoldSectionDetail,
|
||||
} from '../../../layouts/Scaffold'
|
||||
import Link from 'next/link'
|
||||
import { Button } from 'ui'
|
||||
import { useRouter } from 'next/router'
|
||||
import AwsMarketplaceAutoRenewalWarning from './AwsMarketplaceAutoRenewalWarning'
|
||||
import { CloudMarketplaceOnboardingInfo } from './cloud-marketplace-query'
|
||||
import NewAwsMarketplaceOrgForm, {
|
||||
CREATE_AWS_MANAGED_ORG_FORM_ID,
|
||||
NewMarketplaceOrgForm,
|
||||
} from './NewAwsMarketplaceOrgForm'
|
||||
|
||||
interface Props {
|
||||
onboardingInfo?: CloudMarketplaceOnboardingInfo | undefined
|
||||
@@ -61,11 +63,7 @@ const AwsMarketplaceCreateNewOrg = ({ onboardingInfo }: Props) => {
|
||||
<p>
|
||||
You can read more on billing through AWS in our {''}
|
||||
{/*TODO(thomas): Update docs link once the new docs exist*/}
|
||||
<Link
|
||||
href="https://supabase.com/docs/guides/platform"
|
||||
target="_blank"
|
||||
className="underline"
|
||||
>
|
||||
<Link href={`${DOCS_URL}/guides/platform`} target="_blank" className="underline">
|
||||
Billing Docs.
|
||||
</Link>
|
||||
</p>
|
||||
|
||||
+8
-10
@@ -1,5 +1,4 @@
|
||||
import { zodResolver } from '@hookform/resolvers/zod'
|
||||
import { RadioGroupCard, RadioGroupCardItem } from '@ui/components/radio-group-card'
|
||||
import { cn } from '@ui/lib/utils'
|
||||
import { Boxes, ChevronRight } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
@@ -7,6 +6,13 @@ import { useRouter } from 'next/router'
|
||||
import { useMemo, useState } from 'react'
|
||||
import { SubmitHandler, useForm } from 'react-hook-form'
|
||||
import { toast } from 'sonner'
|
||||
import { z } from 'zod'
|
||||
|
||||
import { RadioGroupCard, RadioGroupCardItem } from '@ui/components/radio-group-card'
|
||||
import { useOrganizationLinkAwsMarketplaceMutation } from 'data/organizations/organization-link-aws-marketplace-mutation'
|
||||
import { useProjectsQuery } from 'data/projects/projects-query'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { Organization } from 'types'
|
||||
import {
|
||||
Button,
|
||||
Collapsible_Shadcn_,
|
||||
@@ -17,10 +23,6 @@ import {
|
||||
Skeleton,
|
||||
} from 'ui'
|
||||
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
|
||||
import { z } from 'zod'
|
||||
import { useOrganizationLinkAwsMarketplaceMutation } from '../../../../data/organizations/organization-link-aws-marketplace-mutation'
|
||||
import { useProjectsQuery } from '../../../../data/projects/projects-query'
|
||||
import { Organization } from '../../../../types'
|
||||
import {
|
||||
ScaffoldSection,
|
||||
ScaffoldSectionContent,
|
||||
@@ -139,11 +141,7 @@ const AwsMarketplaceLinkExistingOrg = ({
|
||||
<p>
|
||||
You can read more on billing through AWS in our {''}
|
||||
{/*TODO(thomas): Update docs link once the new docs exist*/}
|
||||
<Link
|
||||
href="https://supabase.com/docs/guides/platform"
|
||||
target="_blank"
|
||||
className="underline"
|
||||
>
|
||||
<Link href={`${DOCS_URL}/guides/platform`} target="_blank" className="underline">
|
||||
Billing Docs.
|
||||
</Link>
|
||||
</p>
|
||||
|
||||
+4
-1
@@ -8,6 +8,7 @@ import { useClientSecretCreateMutation } from 'data/oauth-secrets/client-secret-
|
||||
import { CreatedSecret, useClientSecretsQuery } from 'data/oauth-secrets/client-secrets-query'
|
||||
import { OAuthApp } from 'data/oauth/oauth-apps-query'
|
||||
import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { Alert_Shadcn_, AlertTitle_Shadcn_, InfoIcon } from 'ui'
|
||||
import { SecretRow } from './SecretRow'
|
||||
|
||||
@@ -42,7 +43,9 @@ export const OAuthSecrets = ({ selectedApp }: Props) => {
|
||||
<span className="text-sm text-foreground">Client secrets</span>
|
||||
<span className="text-sm text-foreground-light">
|
||||
For handling callbacks in the OAuth 2.0 flow. Learn more{' '}
|
||||
<InlineLink href="https://supabase.com/docs/guides/integrations/build-a-supabase-integration#handling-the-callback">
|
||||
<InlineLink
|
||||
href={`${DOCS_URL}/guides/integrations/build-a-supabase-integration#handling-the-callback`}
|
||||
>
|
||||
here
|
||||
</InlineLink>
|
||||
.
|
||||
|
||||
+2
-1
@@ -11,6 +11,7 @@ import {
|
||||
} from 'data/oauth/oauth-app-create-mutation'
|
||||
import { useOAuthAppUpdateMutation } from 'data/oauth/oauth-app-update-mutation'
|
||||
import type { OAuthApp } from 'data/oauth/oauth-apps-query'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { isValidHttpUrl, uuidv4 } from 'lib/helpers'
|
||||
import { uploadAttachment } from 'lib/upload'
|
||||
import {
|
||||
@@ -349,7 +350,7 @@ export const PublishAppSidePanel = ({
|
||||
projects.
|
||||
</span>
|
||||
</div>
|
||||
<DocsButton href="https://supabase.com/docs/guides/platform/oauth-apps/oauth-scopes" />
|
||||
<DocsButton href={`${DOCS_URL}/guides/platform/oauth-apps/oauth-scopes`} />
|
||||
</div>
|
||||
|
||||
<ScopesPanel scopes={scopes} setScopes={setScopes} />
|
||||
|
||||
@@ -12,6 +12,7 @@ import { useSSOConfigCreateMutation } from 'data/sso/sso-config-create-mutation'
|
||||
import { useOrgSSOConfigQuery } from 'data/sso/sso-config-query'
|
||||
import { useSSOConfigUpdateMutation } from 'data/sso/sso-config-update-mutation'
|
||||
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import {
|
||||
AlertDescription_Shadcn_,
|
||||
AlertTitle_Shadcn_,
|
||||
@@ -219,7 +220,7 @@ export const SSOConfig = () => {
|
||||
Enable and configure SSO for your organization. Learn more about SSO{' '}
|
||||
<InlineLink
|
||||
className="text-foreground-lighter hover:text-foreground"
|
||||
href="https://supabase.com/docs/guides/platform/sso"
|
||||
href={`${DOCS_URL}/guides/platform/sso`}
|
||||
>
|
||||
here
|
||||
</InlineLink>
|
||||
|
||||
@@ -17,6 +17,7 @@ import { useHasAccessToProjectLevelPermissions } from 'data/subscriptions/org-su
|
||||
import { doPermissionsCheck, useGetPermissions } from 'hooks/misc/useCheckPermissions'
|
||||
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
|
||||
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { useProfile } from 'lib/profile'
|
||||
import {
|
||||
Button,
|
||||
@@ -300,7 +301,7 @@ export const InviteMemberButton = () => {
|
||||
<div className="flex items-center space-x-2">
|
||||
<Button asChild type="default">
|
||||
<Link
|
||||
href="https://supabase.com/docs/guides/platform/sso"
|
||||
href={`${DOCS_URL}/guides/platform/sso`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
|
||||
@@ -5,22 +5,23 @@ import AlertError from 'components/ui/AlertError'
|
||||
import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
|
||||
import { useOrganizationRolesV2Query } from 'data/organization-members/organization-roles-query'
|
||||
import { useOrganizationMembersQuery } from 'data/organizations/organization-members-query'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { useProfile } from 'lib/profile'
|
||||
import { partition } from 'lodash'
|
||||
import { useMemo } from 'react'
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Loading,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
Table,
|
||||
TableHeader,
|
||||
TableHead,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableRow,
|
||||
Card,
|
||||
} from 'ui'
|
||||
import { Admonition } from 'ui-patterns'
|
||||
import { MemberRow } from './MemberRow'
|
||||
@@ -108,7 +109,7 @@ const MembersView = ({ searchString }: MembersViewProps) => {
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href="https://supabase.com/docs/guides/platform/access-control"
|
||||
href={`${DOCS_URL}/guides/platform/access-control`}
|
||||
>
|
||||
<HelpCircle size={14} className="text-foreground-light" />
|
||||
</a>
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
ScaffoldTitle,
|
||||
} from 'components/layouts/Scaffold'
|
||||
import { DocsButton } from 'components/ui/DocsButton'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { Input } from 'ui-patterns/DataInputs/Input'
|
||||
import { InviteMemberButton } from './InviteMemberButton'
|
||||
import MembersView from './MembersView'
|
||||
@@ -33,7 +34,7 @@ export const TeamSettings = () => {
|
||||
placeholder="Filter members"
|
||||
/>
|
||||
<ScaffoldActionsGroup className="w-full md:w-auto">
|
||||
<DocsButton href="https://supabase.com/docs/guides/platform/access-control" />
|
||||
<DocsButton href={`${DOCS_URL}/guides/platform/access-control`} />
|
||||
<InviteMemberButton />
|
||||
</ScaffoldActionsGroup>
|
||||
</ScaffoldActionsContainer>
|
||||
|
||||
+2
-1
@@ -11,6 +11,7 @@ import { usePermissionsQuery } from 'data/permissions/permissions-query'
|
||||
import { useProjectsQuery } from 'data/projects/projects-query'
|
||||
import { useHasAccessToProjectLevelPermissions } from 'data/subscriptions/org-subscription-query'
|
||||
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import {
|
||||
AlertDescription_Shadcn_,
|
||||
AlertTitle_Shadcn_,
|
||||
@@ -186,7 +187,7 @@ export const UpdateRolesPanel = ({ visible, member, onClose }: UpdateRolesPanelP
|
||||
<p className="truncate" title={`Manage access for ${member.username}`}>
|
||||
Manage access for {member.username}
|
||||
</p>
|
||||
<DocsButton href="https://supabase.com/docs/guides/platform/access-control" />
|
||||
<DocsButton href={`${DOCS_URL}/guides/platform/access-control`} />
|
||||
</SheetHeader>
|
||||
|
||||
<SheetSection className="h-full overflow-auto flex flex-col gap-y-4">
|
||||
|
||||
@@ -9,6 +9,7 @@ import { useOrgDailyComputeStatsQuery } from 'data/analytics/org-daily-compute-s
|
||||
import { ComputeUsageMetric, computeUsageMetricLabel } from 'data/analytics/org-daily-stats-query'
|
||||
import type { OrgSubscription } from 'data/subscriptions/types'
|
||||
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { SectionContent } from './SectionContent'
|
||||
import { Attribute, AttributeColor } from './Usage.constants'
|
||||
import UsageBarChart from './UsageBarChart'
|
||||
@@ -86,11 +87,11 @@ const Compute = ({ orgSlug, projectRef, startDate, endDate }: ComputeProps) => {
|
||||
? [
|
||||
{
|
||||
name: 'Compute Add-ons',
|
||||
url: 'https://supabase.com/docs/guides/platform/compute-add-ons',
|
||||
url: `${DOCS_URL}/guides/platform/compute-add-ons`,
|
||||
},
|
||||
{
|
||||
name: 'Usage-billing for Compute',
|
||||
url: 'https://supabase.com/docs/guides/platform/manage-your-usage/compute',
|
||||
url: `${DOCS_URL}/guides/platform/manage-your-usage/compute`,
|
||||
},
|
||||
]
|
||||
: [],
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
import type { OrgSubscription } from 'data/subscriptions/types'
|
||||
import { useOrgUsageQuery } from 'data/usage/org-usage-query'
|
||||
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { cn } from 'ui'
|
||||
import { BILLING_BREAKDOWN_METRICS } from '../BillingSettings/BillingBreakdown/BillingBreakdown.constants'
|
||||
import { BillingMetric } from '../BillingSettings/BillingBreakdown/BillingMetric'
|
||||
@@ -125,7 +126,7 @@ export const TotalUsage = ({
|
||||
? [
|
||||
{
|
||||
name: 'How billing works',
|
||||
url: 'https://supabase.com/docs/guides/platform/billing-on-supabase',
|
||||
url: `${DOCS_URL}/guides/platform/billing-on-supabase`,
|
||||
},
|
||||
{
|
||||
name: 'Supabase Plans',
|
||||
|
||||
@@ -2,6 +2,7 @@ import { USAGE_APPROACHING_THRESHOLD } from 'components/interfaces/Billing/Billi
|
||||
import { EgressType, PricingMetric } from 'data/analytics/org-daily-stats-query'
|
||||
import type { OrgSubscription } from 'data/subscriptions/types'
|
||||
import type { OrgUsageResponse } from 'data/usage/org-usage-query'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { Admonition } from 'ui-patterns'
|
||||
|
||||
export const COLOR_MAP = {
|
||||
@@ -97,7 +98,7 @@ export const USAGE_CATEGORIES: (subscription?: OrgSubscription) => CategoryMeta[
|
||||
links: [
|
||||
{
|
||||
name: 'Documentation',
|
||||
url: 'https://supabase.com/docs/guides/platform/manage-your-usage/egress',
|
||||
url: `${DOCS_URL}/guides/platform/manage-your-usage/egress`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -116,7 +117,7 @@ export const USAGE_CATEGORIES: (subscription?: OrgSubscription) => CategoryMeta[
|
||||
links: [
|
||||
{
|
||||
name: 'Documentation',
|
||||
url: 'https://supabase.com/docs/guides/platform/manage-your-usage/egress',
|
||||
url: `${DOCS_URL}/guides/platform/manage-your-usage/egress`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@@ -147,7 +148,7 @@ export const USAGE_CATEGORIES: (subscription?: OrgSubscription) => CategoryMeta[
|
||||
links: [
|
||||
{
|
||||
name: 'Documentation',
|
||||
url: 'https://supabase.com/docs/guides/platform/database-size',
|
||||
url: `${DOCS_URL}/guides/platform/database-size`,
|
||||
},
|
||||
],
|
||||
chartDescription: 'The data refreshes every 24 hours.',
|
||||
@@ -205,11 +206,11 @@ export const USAGE_CATEGORIES: (subscription?: OrgSubscription) => CategoryMeta[
|
||||
links: [
|
||||
{
|
||||
name: 'Documentation',
|
||||
url: 'https://supabase.com/docs/guides/platform/manage-your-usage/disk-size',
|
||||
url: `${DOCS_URL}/guides/platform/manage-your-usage/disk-size`,
|
||||
},
|
||||
{
|
||||
name: 'Disk Management',
|
||||
url: 'https://supabase.com/docs/guides/platform/database-size#disk-management',
|
||||
url: `${DOCS_URL}/guides/platform/database-size#disk-management`,
|
||||
},
|
||||
],
|
||||
chartDescription: '',
|
||||
@@ -227,7 +228,7 @@ export const USAGE_CATEGORIES: (subscription?: OrgSubscription) => CategoryMeta[
|
||||
links: [
|
||||
{
|
||||
name: 'Storage',
|
||||
url: 'https://supabase.com/docs/guides/storage',
|
||||
url: `${DOCS_URL}/guides/storage`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -253,7 +254,7 @@ export const USAGE_CATEGORIES: (subscription?: OrgSubscription) => CategoryMeta[
|
||||
links: [
|
||||
{
|
||||
name: 'Auth',
|
||||
url: 'https://supabase.com/docs/guides/auth',
|
||||
url: `${DOCS_URL}/guides/auth`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -274,7 +275,7 @@ export const USAGE_CATEGORIES: (subscription?: OrgSubscription) => CategoryMeta[
|
||||
links: [
|
||||
{
|
||||
name: 'SSO with SAML 2.0',
|
||||
url: 'https://supabase.com/docs/guides/auth/sso/auth-sso-saml',
|
||||
url: `${DOCS_URL}/guides/auth/sso/auth-sso-saml`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -295,7 +296,7 @@ export const USAGE_CATEGORIES: (subscription?: OrgSubscription) => CategoryMeta[
|
||||
links: [
|
||||
{
|
||||
name: 'Documentation',
|
||||
url: 'https://supabase.com/docs/guides/storage/image-transformations',
|
||||
url: `${DOCS_URL}/guides/storage/image-transformations`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -311,7 +312,7 @@ export const USAGE_CATEGORIES: (subscription?: OrgSubscription) => CategoryMeta[
|
||||
links: [
|
||||
{
|
||||
name: 'Edge Functions',
|
||||
url: 'https://supabase.com/docs/guides/functions',
|
||||
url: `${DOCS_URL}/guides/functions`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -327,7 +328,7 @@ export const USAGE_CATEGORIES: (subscription?: OrgSubscription) => CategoryMeta[
|
||||
links: [
|
||||
{
|
||||
name: 'Realtime Quotas',
|
||||
url: 'https://supabase.com/docs/guides/realtime/quotas',
|
||||
url: `${DOCS_URL}/guides/realtime/quotas`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -346,7 +347,7 @@ export const USAGE_CATEGORIES: (subscription?: OrgSubscription) => CategoryMeta[
|
||||
links: [
|
||||
{
|
||||
name: 'Realtime Quotas',
|
||||
url: 'https://supabase.com/docs/guides/realtime/quotas',
|
||||
url: `${DOCS_URL}/guides/realtime/quotas`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Download } from 'lucide-react'
|
||||
import { useState } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
|
||||
@@ -5,7 +6,7 @@ import { useParams } from 'common'
|
||||
import { DocsButton } from 'components/ui/DocsButton'
|
||||
import { useProjectPostgrestConfigQuery } from 'data/config/project-postgrest-config-query'
|
||||
import { generateTypes } from 'data/projects/project-type-generation-query'
|
||||
import { Download } from 'lucide-react'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { Button } from 'ui'
|
||||
import ContentSnippet from '../ContentSnippet'
|
||||
import { DOCS_CONTENT } from '../ProjectAPIDocs.constants'
|
||||
@@ -42,7 +43,7 @@ const Entities = ({ language }: ContentProps) => {
|
||||
<div>
|
||||
<ContentSnippet selectedLanguage={language} snippet={DOCS_CONTENT.generatingTypes} />
|
||||
<div className="flex items-center gap-x-2 px-4 mt-3">
|
||||
<DocsButton href="https://supabase.com/docs/guides/database/api/generating-types" />
|
||||
<DocsButton href={`${DOCS_URL}/guides/database/api/generating-types`} />
|
||||
<Button
|
||||
type="default"
|
||||
disabled={isGeneratingTypes}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { useEdgeFunctionsQuery } from 'data/edge-functions/edge-functions-query'
|
||||
import { useOpenAPISpecQuery } from 'data/open-api/api-spec-query'
|
||||
import { useBucketsQuery } from 'data/storage/buckets-query'
|
||||
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
|
||||
import { BASE_PATH } from 'lib/constants'
|
||||
import { BASE_PATH, DOCS_URL } from 'lib/constants'
|
||||
import { Book, BookOpen } from 'lucide-react'
|
||||
import { useAppStateSnapshot } from 'state/app-state'
|
||||
import { Button } from 'ui'
|
||||
@@ -171,7 +171,7 @@ const FirstLevelNav = () => {
|
||||
</Button>
|
||||
<Button block asChild type="text" size="small" icon={<BookOpen />}>
|
||||
<Link
|
||||
href="https://supabase.com/docs/guides/graphql"
|
||||
href={`${DOCS_URL}/guides/graphql`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="!justify-start"
|
||||
@@ -183,18 +183,13 @@ const FirstLevelNav = () => {
|
||||
|
||||
<div className="px-2 py-4">
|
||||
<Button block asChild type="text" size="small" icon={<Book />}>
|
||||
<Link
|
||||
href="https://supabase.com/docs"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="!justify-start"
|
||||
>
|
||||
<Link href={`${DOCS_URL}`} target="_blank" rel="noreferrer" className="!justify-start">
|
||||
Documentation
|
||||
</Link>
|
||||
</Button>
|
||||
<Button block asChild type="text" size="small" icon={<BookOpen />}>
|
||||
<Link
|
||||
href="https://supabase.com/docs/guides/api"
|
||||
href={`${DOCS_URL}/guides/api`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="!justify-start"
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
|
||||
export const DOCS_MENU = [
|
||||
{ name: 'Connect', key: 'introduction' },
|
||||
{ name: 'User Management', key: 'user-management' },
|
||||
@@ -345,11 +347,11 @@ Edge Functions are server-side TypeScript functions, distributed globally at the
|
||||
description: `
|
||||
Follow the steps to prepare your Supabase project on your local machine.
|
||||
|
||||
- Install the Supabase [CLI](https://supabase.com/docs/guides/cli).
|
||||
- [Login to the CLI](https://supabase.com/docs/reference/cli/usage#supabase-login) using the command: \`supabase login\`..
|
||||
- [Initialize Supabase](https://supabase.com/docs/guides/getting-started/local-development#getting-started) inside your project using the command: \`supabase init\`..
|
||||
- [Link to your Remote Project](https://supabase.com/docs/reference/cli/usage#supabase-link) using the command \`supabase link --project-ref [ref]\`..
|
||||
- Setup your environment: Follow the steps [here](https://supabase.com/docs/guides/functions/quickstart#setting-up-your-environment).
|
||||
- Install the Supabase [CLI](${DOCS_URL}/guides/cli).
|
||||
- [Login to the CLI](${DOCS_URL}/reference/cli/usage#supabase-login) using the command: \`supabase login\`..
|
||||
- [Initialize Supabase](${DOCS_URL}/guides/getting-started/local-development#getting-started) inside your project using the command: \`supabase init\`..
|
||||
- [Link to your Remote Project](${DOCS_URL}/reference/cli/usage#supabase-link) using the command \`supabase link --project-ref [ref]\`..
|
||||
- Setup your environment: Follow the steps [here](${DOCS_URL}/guides/functions/quickstart#setting-up-your-environment).
|
||||
`,
|
||||
js: undefined,
|
||||
bash: undefined,
|
||||
@@ -397,7 +399,7 @@ If you don't want to expose tables in your API, simply add them to a different s
|
||||
description: `
|
||||
Supabase APIs are generated from your database, which means that we can use database introspection to generate type-safe API definitions.
|
||||
|
||||
You can generate types from your database either through the [Supabase CLI](https://supabase.com/docs/guides/database/api/generating-types), or by downloading the types file via the button on the right and importing it in your application within \`src/index.ts\`.
|
||||
You can generate types from your database either through the [Supabase CLI](${DOCS_URL}/guides/database/api/generating-types), or by downloading the types file via the button on the right and importing it in your application within \`src/index.ts\`.
|
||||
`,
|
||||
js: undefined,
|
||||
bash: undefined,
|
||||
@@ -480,9 +482,9 @@ The API endpoint supports POST (and in some cases GET) to execute the function.
|
||||
description: `
|
||||
Supabase provides a globally distributed cluster of Realtime servers that enable the following functionality:
|
||||
|
||||
- [Broadcast](https://supabase.com/docs/guides/realtime/broadcast): Send ephemeral messages from client to clients with low latency.
|
||||
- [Presence](https://supabase.com/docs/guides/realtime/presence): Track and synchronize shared state between clients.
|
||||
- [Postgres Changes](https://supabase.com/docs/guides/realtime/postgres-changes): Listen to Postgres database changes and send them to authorized clients.
|
||||
- [Broadcast](${DOCS_URL}/guides/realtime/broadcast): Send ephemeral messages from client to clients with low latency.
|
||||
- [Presence](${DOCS_URL}/guides/realtime/presence): Track and synchronize shared state between clients.
|
||||
- [Postgres Changes](${DOCS_URL}/guides/realtime/postgres-changes): Listen to Postgres database changes and send them to authorized clients.
|
||||
`,
|
||||
js: undefined,
|
||||
bash: undefined,
|
||||
@@ -495,7 +497,7 @@ Supabase provides a globally distributed cluster of Realtime servers that enable
|
||||
Creates an event handler that listens to changes.
|
||||
|
||||
- By default, Broadcast and Presence are enabled for all projects.
|
||||
- By default, listening to database changes is disabled for new projects due to database performance and security concerns. You can turn it on by managing Realtime's [replication](https://supabase.com/docs/guides/api#realtime-api-overview).
|
||||
- By default, listening to database changes is disabled for new projects due to database performance and security concerns. You can turn it on by managing Realtime's [replication](${DOCS_URL}/guides/api#realtime-api-overview).
|
||||
- You can receive the "previous" data for updates and deletes by setting the table's \`REPLICA IDENTITY\` to \`FULL\` (e.g., \`ALTER TABLE your_table REPLICA IDENTITY FULL;\`).
|
||||
- Row level security is not applied to delete statements. When RLS is enabled and replica identity is set to full, only the primary key is sent to clients.
|
||||
`,
|
||||
@@ -568,7 +570,7 @@ export const DOCS_RESOURCE_CONTENT: {
|
||||
title: 'Invoke function',
|
||||
category: 'stored-procedures',
|
||||
description: undefined,
|
||||
docsUrl: 'https://supabase.com/docs/reference/javascript/rpc',
|
||||
docsUrl: `${DOCS_URL}/reference/javascript/rpc`,
|
||||
code: ({
|
||||
rpcName,
|
||||
rpcParams,
|
||||
@@ -624,7 +626,7 @@ else console.log(data)
|
||||
key: 'read-rows',
|
||||
title: `Read rows`,
|
||||
category: 'entities',
|
||||
docsUrl: 'https://supabase.com/docs/reference/javascript/select',
|
||||
docsUrl: `${DOCS_URL}/reference/javascript/select`,
|
||||
description: `To read rows in this table, use the \`select\` method.`,
|
||||
code: ({
|
||||
resourceId,
|
||||
@@ -707,7 +709,7 @@ let { data: ${resourceId}, error } = await supabase
|
||||
category: 'entities',
|
||||
title: 'Filtering',
|
||||
description: `Supabase provides a wide range of filters`,
|
||||
docsUrl: 'https://supabase.com/docs/reference/javascript/using-filters',
|
||||
docsUrl: `${DOCS_URL}/reference/javascript/using-filters`,
|
||||
code: ({
|
||||
resourceId,
|
||||
endpoint,
|
||||
@@ -786,7 +788,7 @@ let { data: ${resourceId}, error } = await supabase
|
||||
|
||||
\`insert\` will also return the replaced values for UPSERT.
|
||||
`,
|
||||
docsUrl: 'https://supabase.com/docs/reference/javascript/insert',
|
||||
docsUrl: `${DOCS_URL}/reference/javascript/insert`,
|
||||
code: ({
|
||||
resourceId,
|
||||
endpoint,
|
||||
@@ -867,7 +869,7 @@ const { data, error } = await supabase
|
||||
|
||||
\`update\` will also return the replaced values for UPDATE.
|
||||
`,
|
||||
docsUrl: 'https://supabase.com/docs/reference/javascript/update',
|
||||
docsUrl: `${DOCS_URL}/reference/javascript/update`,
|
||||
code: ({
|
||||
resourceId,
|
||||
endpoint,
|
||||
@@ -907,7 +909,7 @@ const { data, error } = await supabase
|
||||
description: `
|
||||
\`delete\` lets you delete rows. \`delete\` will match all rows by default, so remember to specify your filters!
|
||||
`,
|
||||
docsUrl: 'https://supabase.com/docs/reference/javascript/delete',
|
||||
docsUrl: `${DOCS_URL}/reference/javascript/delete`,
|
||||
code: ({
|
||||
resourceId,
|
||||
endpoint,
|
||||
@@ -943,7 +945,7 @@ const { error } = await supabase
|
||||
description: `
|
||||
Supabase provides realtime functionality and broadcasts database changes to authorized users depending on Row Level Security (RLS) policies.
|
||||
`,
|
||||
docsUrl: 'https://supabase.com/docs/reference/javascript/subscribe',
|
||||
docsUrl: `${DOCS_URL}/reference/javascript/subscribe`,
|
||||
code: ({ resourceId }: { resourceId: string }) => {
|
||||
return [
|
||||
{
|
||||
@@ -1028,7 +1030,7 @@ const channels = supabase.channel('custom-filter-channel')
|
||||
key: 'upload-file',
|
||||
category: 'storage',
|
||||
title: 'Upload a file',
|
||||
docsUrl: 'https://supabase.com/docs/reference/javascript/storage-from-upload',
|
||||
docsUrl: `${DOCS_URL}/reference/javascript/storage-from-upload`,
|
||||
description: `
|
||||
Upload a file to an existing bucket. RLS policy permissions required:
|
||||
- \`buckets\` table permissions: none
|
||||
@@ -1064,7 +1066,7 @@ const { data, error } = await supabase
|
||||
key: 'delete-files',
|
||||
category: 'storage',
|
||||
title: 'Delete files',
|
||||
docsUrl: 'https://supabase.com/docs/reference/javascript/storage-from-remove',
|
||||
docsUrl: `${DOCS_URL}/reference/javascript/storage-from-remove`,
|
||||
description: `
|
||||
Delete files within the bucket. RLS policy permissions required:
|
||||
- \`buckets\` table permissions: none
|
||||
@@ -1093,7 +1095,7 @@ const { data, error } = await supabase
|
||||
key: 'list-files',
|
||||
category: 'storage',
|
||||
title: 'List all files',
|
||||
docsUrl: 'https://supabase.com/docs/reference/javascript/storage-from-list',
|
||||
docsUrl: `${DOCS_URL}/reference/javascript/storage-from-list`,
|
||||
description: `
|
||||
List all files within the bucket. RLS policy permissions required:
|
||||
- \`buckets\` table permissions: none
|
||||
@@ -1125,7 +1127,7 @@ const { data, error } = await supabase
|
||||
key: 'download-file',
|
||||
category: 'storage',
|
||||
title: 'Download a file',
|
||||
docsUrl: 'https://supabase.com/docs/reference/javascript/storage-from-download',
|
||||
docsUrl: `${DOCS_URL}/reference/javascript/storage-from-download`,
|
||||
description: `
|
||||
Downloads a file from a private bucket. For public buckets, make a request to the URL returned from getPublicUrl instead. RLS policy permissions required:
|
||||
- \`buckets\` table permissions: none
|
||||
@@ -1154,7 +1156,7 @@ const { data, error } = await supabase
|
||||
key: 'create-signed-url',
|
||||
category: 'storage',
|
||||
title: 'Create a signed URL',
|
||||
docsUrl: 'https://supabase.com/docs/reference/javascript/storage-from-createsignedurl',
|
||||
docsUrl: `${DOCS_URL}/reference/javascript/storage-from-createsignedurl`,
|
||||
description: `
|
||||
Create a signed URL which can be used to share a file for a fixed amount of time. RLS policy permissions required:
|
||||
- \`buckets\` table permissions: none
|
||||
@@ -1183,7 +1185,7 @@ const { data, error } = await supabase
|
||||
key: 'retrieve-public-url',
|
||||
category: 'storage',
|
||||
title: 'Retrieve public URL',
|
||||
docsUrl: 'https://supabase.com/docs/reference/javascript/storage-from-getpublicurl',
|
||||
docsUrl: `${DOCS_URL}/reference/javascript/storage-from-getpublicurl`,
|
||||
description: `
|
||||
A simple convenience function to get the URL for an asset in a public bucket. If you do not want to use this function, you can construct the public URL by concatenating the bucket URL with the path to the asset.
|
||||
|
||||
@@ -1216,7 +1218,7 @@ const { data } = supabase
|
||||
key: 'invoke-edge-function',
|
||||
category: 'edge-functions',
|
||||
title: 'Invoke an edge function',
|
||||
docsUrl: 'https://supabase.com/docs/reference/javascript/functions-invoke',
|
||||
docsUrl: `${DOCS_URL}/reference/javascript/functions-invoke`,
|
||||
description: `
|
||||
Invokes a Supabase Edge Function. Requires an Authorization header, and invoke params generally match the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) spec.
|
||||
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
import { useParams } from 'common'
|
||||
import Link from 'next/link'
|
||||
import { useState } from 'react'
|
||||
|
||||
import { DocsButton } from 'components/ui/DocsButton'
|
||||
import { useEdgeFunctionsQuery } from 'data/edge-functions/edge-functions-query'
|
||||
import { useOpenAPISpecQuery } from 'data/open-api/api-spec-query'
|
||||
import { useBucketsQuery } from 'data/storage/buckets-query'
|
||||
import { DOCS_URL } from 'lib/constants'
|
||||
import { ChevronLeft, Code } from 'lucide-react'
|
||||
import { useAppStateSnapshot } from 'state/app-state'
|
||||
import {
|
||||
AlertDescription_Shadcn_,
|
||||
AlertTitle_Shadcn_,
|
||||
@@ -14,16 +21,9 @@ import {
|
||||
PopoverTrigger_Shadcn_,
|
||||
Popover_Shadcn_,
|
||||
} from 'ui'
|
||||
|
||||
import { useEdgeFunctionsQuery } from 'data/edge-functions/edge-functions-query'
|
||||
import { useOpenAPISpecQuery } from 'data/open-api/api-spec-query'
|
||||
import { useBucketsQuery } from 'data/storage/buckets-query'
|
||||
import { useAppStateSnapshot } from 'state/app-state'
|
||||
import { useIsAPIDocsSidePanelEnabled } from '../App/FeaturePreview/FeaturePreviewContext'
|
||||
import { navigateToSection } from './Content/Content.utils'
|
||||
import { DOCS_RESOURCE_CONTENT } from './ProjectAPIDocs.constants'
|
||||
import { ChevronLeft, Code, ExternalLink } from 'lucide-react'
|
||||
import { DocsButton } from 'components/ui/DocsButton'
|
||||
|
||||
const SecondLevelNav = () => {
|
||||
const { ref } = useParams()
|
||||
@@ -44,22 +44,22 @@ const SecondLevelNav = () => {
|
||||
entities: {
|
||||
title: 'Tables & Views',
|
||||
options: tables,
|
||||
docsUrl: 'https://supabase.com/docs/reference/javascript/select',
|
||||
docsUrl: `${DOCS_URL}/reference/javascript/select`,
|
||||
},
|
||||
'stored-procedures': {
|
||||
title: 'Stored Procedures',
|
||||
options: functions,
|
||||
docsUrl: 'https://supabase.com/docs/reference/javascript/rpc',
|
||||
docsUrl: `${DOCS_URL}/reference/javascript/rpc`,
|
||||
},
|
||||
storage: {
|
||||
title: 'Storage',
|
||||
options: buckets ?? [],
|
||||
docsUrl: 'https://supabase.com/docs/reference/javascript/storage-createbucket',
|
||||
docsUrl: `${DOCS_URL}/reference/javascript/storage-createbucket`,
|
||||
},
|
||||
'edge-functions': {
|
||||
title: 'Edge Functions',
|
||||
options: edgeFunctions ?? [],
|
||||
docsUrl: 'https://supabase.com/docs/reference/javascript/functions-invoke',
|
||||
docsUrl: `${DOCS_URL}/reference/javascript/functions-invoke`,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
Loaded 100 of 283 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user