mirror of
https://github.com/supabase/supabase.git
synced 2026-05-06 08:56:46 -04:00
56de26fe22
This PR migrates the whole monorepo to use Tailwind v4: - Removed `@tailwindcss/container-queries` plugin since it's included by default in v4, - Bump all instances of Tailwind to v4. Made minimal changes to the shared config to remove non-supported features (`alpha` mentions), - Migrate all apps to be compatible with v4 configs, - Fix the `typography.css` import in 3 apps, - Add missing rules which were included by default in v3, - Run `pnpm dlx @tailwindcss/upgrade` on all apps, which renames a lot of classes - Rename all misnamed classes according to https://tailwindcss.com/docs/upgrade-guide#renamed-utilities in all apps. --------- Co-authored-by: Jordi Enric <jordi.err@gmail.com>
187 lines
6.2 KiB
TypeScript
187 lines
6.2 KiB
TypeScript
import { capitalize } from 'lodash-es'
|
||
import rehypeSlug from 'rehype-slug'
|
||
import { Heading } from 'ui'
|
||
import { Admonition } from 'ui-patterns'
|
||
|
||
import { GuideTemplate, newEditLink } from '~/features/docs/GuidesMdx.template'
|
||
import { genGuideMeta } from '~/features/docs/GuidesMdx.utils'
|
||
import { MDXRemoteBase } from '~/features/docs/MdxBase'
|
||
import { OCTOKIT_RETRY_OPTIONS, getGitHubFileContents, octokit } from '~/lib/octokit'
|
||
import { TabPanel, Tabs } from '~/features/ui/Tabs'
|
||
import { UrlTransformFunction, linkTransform } 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 { SerializeOptions } from '~/types/next-mdx-remote-serialize'
|
||
|
||
// We fetch these docs at build time from an external repo
|
||
const org = 'supabase'
|
||
const repo = 'splinter'
|
||
const branch = 'main'
|
||
const docsDir = 'docs'
|
||
|
||
const meta = {
|
||
title: 'Performance and Security Advisors',
|
||
subtitle: 'Check your database for performance and security issues',
|
||
}
|
||
|
||
const generateMetadata = genGuideMeta(() => ({
|
||
pathname: '/guides/database/database-linter',
|
||
meta,
|
||
}))
|
||
|
||
const editLink = newEditLink('supabase/splinter/tree/main/docs')
|
||
|
||
const markdownIntro = `
|
||
You can use the Database Performance and Security Advisors to check your database for issues such as missing indexes and improperly set-up RLS policies.
|
||
|
||
## Using the Advisors
|
||
|
||
In the dashboard, navigate to [Security Advisor](https://supabase.com/dashboard/project/_/database/security-advisor) and [Performance Advisor](https://supabase.com/dashboard/project/_/database/performance-advisor) under Database. The advisors run automatically. You can also manually rerun them after you've resolved issues.
|
||
`.trim()
|
||
|
||
const getBasename = (path: string) => path.split('/').at(-1)!.replace(/\.md$/, '')
|
||
|
||
const DatabaseAdvisorDocs = async () => {
|
||
let lints: Awaited<ReturnType<typeof getLints>>['lints'] = []
|
||
let lintsList: Awaited<ReturnType<typeof getLints>>['lintsList'] = []
|
||
let fetchError: Error | null = null
|
||
|
||
try {
|
||
const data = await getLints()
|
||
lints = data.lints
|
||
lintsList = data.lintsList
|
||
} catch (error) {
|
||
fetchError = error instanceof Error ? error : new Error('Unknown error fetching advisor docs')
|
||
console.error('[database-advisors] Failed to fetch advisor docs from GitHub', fetchError)
|
||
}
|
||
|
||
const options = {
|
||
mdxOptions: {
|
||
remarkPlugins: [remarkMkDocsAdmonition, remarkPyMdownTabs, [removeTitle, meta.title]],
|
||
rehypePlugins: [[linkTransform, urlTransform(lintsList)], rehypeSlug],
|
||
},
|
||
} as SerializeOptions
|
||
|
||
return (
|
||
<GuideTemplate meta={meta} editLink={editLink}>
|
||
<MDXRemoteBase source={markdownIntro} />
|
||
<Heading tag="h2">Available checks</Heading>
|
||
|
||
{fetchError ? (
|
||
<Admonition type="note" title="Couldn’t load the full Advisor library">
|
||
We fetch remediation guides straight from the <code>supabase/splinter</code> repository
|
||
during the build. GitHub timed out just now, so we’re showing the overview only.
|
||
<br />
|
||
<br />
|
||
You can check back in a few minutes or browse the
|
||
{` `}
|
||
<a
|
||
className="underline decoration-dashed underline-offset-2"
|
||
href="https://github.com/supabase/splinter/tree/main/docs"
|
||
target="_blank"
|
||
rel="noreferrer"
|
||
>
|
||
latest Markdown on GitHub (opens in a new tab)
|
||
</a>
|
||
.
|
||
</Admonition>
|
||
) : (
|
||
<Tabs listClassNames="flex flex-wrap gap-2 [&>button]:m-0!" queryGroup="lint">
|
||
{lints.map((lint) => (
|
||
<TabPanel
|
||
key={lint.path}
|
||
id={lint.path}
|
||
label={capitalize(getBasename(lint.path).replace(/_/g, ' '))}
|
||
>
|
||
<section id={getBasename(lint.path)}>
|
||
<MDXRemoteBase source={lint.content} options={options} />
|
||
</section>
|
||
</TabPanel>
|
||
))}
|
||
</Tabs>
|
||
)}
|
||
</GuideTemplate>
|
||
)
|
||
}
|
||
|
||
/**
|
||
* The GitHub repo uses relative links, which don't lead to the right locations
|
||
* in docs.
|
||
*
|
||
* @param url The original link, as written in the Markdown file
|
||
* @returns The rewritten link
|
||
*/
|
||
const urlTransform: (lints: Array<{ path: string }>) => UrlTransformFunction = (lints) => (url) => {
|
||
try {
|
||
const placeholderHostname = 'placeholder'
|
||
const { hostname, pathname, hash } = new URL(url, `http://${placeholderHostname}`)
|
||
|
||
// Don't modify a url with a FQDN or a url that's only a hash
|
||
if (hostname !== placeholderHostname || pathname === '/') {
|
||
return url
|
||
}
|
||
|
||
const relativePath = getBasename(pathname)
|
||
const section = lints.find(({ path }) => path === relativePath)
|
||
|
||
if (section) {
|
||
const url = new URL(window.location.href)
|
||
url.searchParams.set('lint', relativePath)
|
||
return url.toString()
|
||
}
|
||
|
||
// If we don't have this page in our docs, link to GitHub repo
|
||
return `https://github.com/${org}/${repo}/blob/${branch}${pathname}${hash}`
|
||
} catch (err) {
|
||
console.error('Error transforming markdown URL', err)
|
||
return url
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Fetch lint remediation Markdown from external repo
|
||
*/
|
||
const getLints = async () => {
|
||
const response = await octokit().request('GET /repos/{owner}/{repo}/contents/{path}', {
|
||
owner: org,
|
||
repo: repo,
|
||
path: docsDir,
|
||
ref: branch,
|
||
headers: {
|
||
'X-GitHub-Api-Version': '2022-11-28',
|
||
},
|
||
request: OCTOKIT_RETRY_OPTIONS,
|
||
})
|
||
|
||
if (response.status >= 400) {
|
||
throw new Error(
|
||
`Failed to fetch ${org}/${repo}/contents/${docsDir} docs from GitHub: ${response.status}`
|
||
)
|
||
}
|
||
|
||
if (!Array.isArray(response.data)) {
|
||
throw Error(
|
||
'Reading a directory, not a file. Should not reach this, solely to appease Typescript.'
|
||
)
|
||
}
|
||
|
||
const lintsList = response.data.filter(({ path }) => /docs\/\d+.+\.md$/.test(path))
|
||
|
||
const lints = await Promise.all(
|
||
lintsList.map(async ({ path }) => {
|
||
const content = await getGitHubFileContents({ org, repo, path, branch })
|
||
|
||
return {
|
||
path: getBasename(path),
|
||
content,
|
||
}
|
||
})
|
||
)
|
||
|
||
return { lints, lintsList }
|
||
}
|
||
|
||
export default DatabaseAdvisorDocs
|
||
export { generateMetadata }
|