mirror of
https://github.com/supabase/supabase.git
synced 2026-10-17 15:19:08 +03:00
Add the ability to embed code samples from GitHub into tutorials, so we can have a single source of truth for the source code. Introduces the <$CodeSample /> syntax, which is a special syntax and not a real React component (see the directives/README.md for why on earth I did it this way -- in this specific case, CodeHike adjusts the MDX syntax tree before it gets compiled, and we need to adjust it ourselves before CodeHike sees it, so we need to get down to the level of manipulating the AST in order to make this work with CodeHike). Adjusted one of the example tutorials to use this new feature as a test.
82 lines
2.0 KiB
TypeScript
82 lines
2.0 KiB
TypeScript
import 'server-only'
|
|
|
|
import { createAppAuth } from '@octokit/auth-app'
|
|
import { Octokit } from '@octokit/core'
|
|
import crypto from 'node:crypto'
|
|
|
|
import { fetchRevalidatePerDay } from '~/features/helpers.fetch'
|
|
|
|
let octokitInstance: Octokit
|
|
|
|
function octokit() {
|
|
if (!octokitInstance) {
|
|
const privateKeyPkcs8 = crypto
|
|
.createPrivateKey(process.env.DOCS_GITHUB_APP_PRIVATE_KEY)
|
|
.export({
|
|
type: 'pkcs8',
|
|
format: 'pem',
|
|
})
|
|
|
|
octokitInstance = new Octokit({
|
|
authStrategy: createAppAuth,
|
|
auth: {
|
|
appId: process.env.DOCS_GITHUB_APP_ID,
|
|
installationId: process.env.DOCS_GITHUB_APP_INSTALLATION_ID,
|
|
privateKey: privateKeyPkcs8,
|
|
},
|
|
})
|
|
}
|
|
|
|
return octokitInstance
|
|
}
|
|
|
|
export async function getGitHubFileContents({
|
|
org,
|
|
repo,
|
|
path,
|
|
branch,
|
|
options: { onError },
|
|
}: {
|
|
org: string
|
|
repo: string
|
|
path: string
|
|
branch: string
|
|
options: {
|
|
onError: (err?: unknown) => void
|
|
/**
|
|
*
|
|
* A custom fetch implementation to control Next.js caching.
|
|
* By default, uses a "once-per-day" revalidation strategy.
|
|
* This default may change later as we move to on-demand revalidation.
|
|
*/
|
|
fetch?: (info: RequestInfo, init?: RequestInit) => Promise<Response>
|
|
}
|
|
}) {
|
|
if (path.startsWith('/')) {
|
|
path = path.slice(1)
|
|
}
|
|
|
|
try {
|
|
const response = await octokit().request('GET /repos/{owner}/{repo}/contents/{path}', {
|
|
owner: org,
|
|
repo: repo,
|
|
path: path,
|
|
ref: branch,
|
|
options: {
|
|
fetch: fetchRevalidatePerDay,
|
|
},
|
|
})
|
|
if (response.status !== 200 || !response.data) {
|
|
throw Error(`Could not find contents of ${path} in ${org}/${repo}`)
|
|
}
|
|
if (!('type' in response.data) || response.data.type !== 'file') {
|
|
throw Error(`${path} in ${org}/${repo} is not a file`)
|
|
}
|
|
const content = Buffer.from(response.data.content, 'base64').toString('utf-8')
|
|
return content
|
|
} catch (err) {
|
|
console.error('Error fetching GitHub file: %o', err)
|
|
onError?.(err)
|
|
}
|
|
}
|