chore: Bump nextjs for the docs app (#35333)

* Bump all versions of postcss to 8.5.3.

* Run next/codemod on the docs app.

* Move two experimental flags into stable. Add next-mdx-remote as a transpiled package.

* Add extra folders to the clean command in docs.

* Fix type errors in docs test.

* Run prettier on the new files.

* remove turbopack, fix fetch revalidation, fix metadata awaits

Couple of minor fixes:
- Turbopack doesn't work in dev because of known MDX loader limitations
(cannot load functions in MDX plugin config)
- Fetches not cached by default anymore in Next 15 so need to manually
cache the ones we need
- Missing a few awaits for metadata generation with page params

* Bump the graphiql version because headlessui/react is not building with Next 15.

---------

Co-authored-by: Charis Lam <26616127+charislam@users.noreply.github.com>
This commit is contained in:
Ivan VasilovandCharis Lam authored and GitHub committed 2025-05-08 09:27:22 +00:00
1 parent c1f10a79d1
commit 0cb08341f6
41 files changed
+1091 -190

No files matched your search

+1 -1
View File
@@ -54,7 +54,7 @@
"autoprefixer": "^10.0.1",
"config": "workspace:^",
"mdast-util-toc": "^6.1.1",
"postcss": "^8",
"postcss": "^8.5.3",
"rimraf": "^4.1.3",
"shiki": "^1.1.7",
"tailwindcss": "^3.3.0",
+8 -8
View File
@@ -4,7 +4,7 @@ import { createClient } from '@supabase/supabase-js'
import { revalidateTag } from 'next/cache'
import { headers } from 'next/headers'
import { NextRequest } from 'next/server'
import { describe, it, expect, vi, beforeEach, afterEach, type Mock } from 'vitest'
import { afterEach, beforeEach, describe, expect, it, vi, type Mock } from 'vitest'
import { _handleRevalidateRequest } from './route'
@@ -68,7 +68,7 @@ describe('_handleRevalidateRequest', () => {
method: 'POST',
})
vi.mocked(headers).mockReturnValue(new Headers(request.headers))
vi.mocked(headers).mockReturnValue(Promise.resolve(new Headers(request.headers)))
const response = await _handleRevalidateRequest(request)
expect(response.status).toBe(401)
@@ -83,7 +83,7 @@ describe('_handleRevalidateRequest', () => {
},
})
vi.mocked(headers).mockReturnValue(new Headers(request.headers))
vi.mocked(headers).mockReturnValue(Promise.resolve(new Headers(request.headers)))
const response = await _handleRevalidateRequest(request)
expect(response.status).toBe(401)
@@ -99,7 +99,7 @@ describe('_handleRevalidateRequest', () => {
body: JSON.stringify({ invalid: 'body' }),
})
vi.mocked(headers).mockReturnValue(new Headers(request.headers))
vi.mocked(headers).mockReturnValue(Promise.resolve(new Headers(request.headers)))
const response = await _handleRevalidateRequest(request)
expect(response.status).toBe(400)
@@ -115,7 +115,7 @@ describe('_handleRevalidateRequest', () => {
body: JSON.stringify({ tags: ['graphql', 'wrappers'] }),
})
vi.mocked(headers).mockReturnValue(new Headers(request.headers))
vi.mocked(headers).mockReturnValue(Promise.resolve(new Headers(request.headers)))
mockSupabaseClient.rpc.mockResolvedValue({ data: [] })
@@ -135,7 +135,7 @@ describe('_handleRevalidateRequest', () => {
body: JSON.stringify({ tags: ['graphql'] }),
})
vi.mocked(headers).mockReturnValue(new Headers(request.headers))
vi.mocked(headers).mockReturnValue(Promise.resolve(new Headers(request.headers)))
const fiveHoursAgo = new Date(mockDate.getTime() - 5 * 60 * 60 * 1000)
mockSupabaseClient.rpc.mockResolvedValue({
@@ -156,7 +156,7 @@ describe('_handleRevalidateRequest', () => {
body: JSON.stringify({ tags: ['graphql'] }),
})
vi.mocked(headers).mockReturnValue(new Headers(request.headers))
vi.mocked(headers).mockReturnValue(Promise.resolve(new Headers(request.headers)))
const sevenHoursAgo = new Date(mockDate.getTime() - 7 * 60 * 60 * 1000)
mockSupabaseClient.rpc.mockResolvedValue({
@@ -177,7 +177,7 @@ describe('_handleRevalidateRequest', () => {
body: JSON.stringify({ tags: ['graphql'] }),
})
vi.mocked(headers).mockReturnValue(new Headers(request.headers))
vi.mocked(headers).mockReturnValue(Promise.resolve(new Headers(request.headers)))
const oneHourAgo = new Date(mockDate.getTime() - 1 * 60 * 60 * 1000)
mockSupabaseClient.rpc.mockResolvedValue({
+1 -1
View File
@@ -19,7 +19,7 @@ const requestBodySchema = z.object({
export const POST = handleError(_handleRevalidateRequest)
export async function _handleRevalidateRequest(request: NextRequest) {
const requestHeaders = headers()
const requestHeaders = await headers()
const authorization = requestHeaders.get('Authorization')
if (!authorization) {
return new Response('Missing Authorization header', { status: 401 })
+1 -1
View File
@@ -9,7 +9,7 @@ const LazyGraphiQL = dynamic(
async () => {
const { GraphiQL: GraphiQLPrimitive } = await import('graphiql')
const { createGraphiQLFetcher } = await import('@graphiql/toolkit')
await import('graphiql/graphiql.css')
await import('graphiql/style.css')
return function GraphiQL(props: Omit<ComponentProps<typeof GraphiQLPrimitive>, 'fetcher'>) {
const fetcher = createGraphiQLFetcher({
+2 -1
View File
@@ -9,7 +9,8 @@ export const dynamicParams = false
type Params = { slug?: string[] }
const AiGuidePage = async ({ params }: { params: Params }) => {
const AiGuidePage = async (props: { params: Promise<Params> }) => {
const params = await props.params
const slug = ['ai', ...(params.slug ?? [])]
const data = await getGuidesMarkdown(slug)
@@ -55,7 +55,8 @@ interface Params {
slug: string
}
const PythonClientDocs = async ({ params }: { params: Params }) => {
const PythonClientDocs = async (props: { params: Promise<Params> }) => {
const params = await props.params
const { meta, ...data } = await getContent(params)
const options = {
@@ -9,7 +9,8 @@ export const dynamicParams = false
type Params = { slug?: string[] }
const ApiGuidePage = async ({ params }: { params: Params }) => {
const ApiGuidePage = async (props: { params: Promise<Params> }) => {
const params = await props.params
const slug = ['api', ...(params.slug ?? [])]
const data = await getGuidesMarkdown(slug)
@@ -9,7 +9,8 @@ export const dynamicParams = false
type Params = { slug?: string[] }
const AuthGuidePage = async ({ params }: { params: Params }) => {
const AuthGuidePage = async (props: { params: Promise<Params> }) => {
const params = await props.params
const slug = ['auth', ...(params.slug ?? [])]
const data = await getGuidesMarkdown(slug)
@@ -9,7 +9,8 @@ export const dynamicParams = false
type Params = { slug?: string[] }
const CronGuidePage = async ({ params }: { params: Params }) => {
const CronGuidePage = async (props: { params: Promise<Params> }) => {
const params = await props.params
const slug = ['cron', ...(params.slug ?? [])]
const data = await getGuidesMarkdown(slug)
@@ -9,7 +9,8 @@ export const dynamicParams = false
type Params = { slug?: string[] }
const DatabaseGuidePage = async ({ params }: { params: Params }) => {
const DatabaseGuidePage = async (props: { params: Promise<Params> }) => {
const params = await props.params
const slug = ['database', ...(params.slug ?? [])]
const data = await getGuidesMarkdown(slug)
@@ -208,7 +208,8 @@ interface Params {
slug?: string[]
}
const WrappersDocs = async ({ params }: { params: Params }) => {
const WrappersDocs = async (props: { params: Promise<Params> }) => {
const params = await props.params
const { isExternal, meta, ...data } = await getContent(params)
const options = isExternal
@@ -271,6 +272,7 @@ const getContent = async (params: Params) => {
editLink = `${org}/${repo}/blob/${tag}/${docsDir}/${remoteFile}`
const response = await fetch(`https://raw.githubusercontent.com/${repoPath}`, {
cache: 'force-cache',
next: { tags: [REVALIDATION_TAGS.WRAPPERS] },
})
const rawContent = await response.text()
@@ -9,7 +9,8 @@ export const dynamicParams = false
type Params = { slug?: string[] }
const DeploymentGuidePage = async ({ params }: { params: Params }) => {
const DeploymentGuidePage = async (props: { params: Promise<Params> }) => {
const params = await props.params
const slug = ['deployment', ...(params.slug ?? [])]
const data = await getGuidesMarkdown(slug)
@@ -54,7 +54,8 @@ const pageMap = [
type Params = { slug: string }
const ActionDocs = async ({ params }: { params: Params }) => {
const ActionDocs = async (props: { params: Promise<Params> }) => {
const params = await props.params
const { meta, ...data } = await getContent(params)
const options = {
@@ -42,7 +42,8 @@ interface Params {
slug?: string[]
}
const TerraformDocs = async ({ params }: { params: Params }) => {
const TerraformDocs = async (props: { params: Promise<Params> }) => {
const params = await props.params
const { meta, ...data } = await getContent(params)
const options = {
@@ -9,7 +9,8 @@ export const dynamicParams = false
type Params = { slug?: string[] }
const FunctionsGuidePage = async ({ params }: { params: Params }) => {
const FunctionsGuidePage = async (props: { params: Promise<Params> }) => {
const params = await props.params
const slug = ['functions', ...(params.slug ?? [])]
const data = await getGuidesMarkdown(slug)
@@ -9,7 +9,8 @@ export const dynamicParams = false
type Params = { slug?: string[] }
const GettingStartedGuidePage = async ({ params }: { params: Params }) => {
const GettingStartedGuidePage = async (props: { params: Promise<Params> }) => {
const params = await props.params
const slug = ['getting-started', ...(params.slug ?? [])]
const data = await getGuidesMarkdown(slug)
@@ -79,7 +79,8 @@ async function getAiPromptImpl(prompt: string) {
}
export const getAiPrompt = cache(getAiPromptImpl)
export async function generateAiPromptMetadata({ params: { slug } }: { params: { slug: string } }) {
export async function generateAiPromptMetadata(props: { params: Promise<{ slug: string }> }) {
const { slug } = await props.params
const prompt = await getAiPrompt(slug)
return {
@@ -7,7 +7,11 @@ import {
export const dynamicParams = false
export default async function AiPromptsPage({ params: { slug } }: { params: { slug: string } }) {
export default async function AiPromptsPage(props: { params: Promise<{ slug: string }> }) {
const params = await props.params
const { slug } = params
let { heading, content } = await getAiPrompt(slug)
content = `
## How to use
@@ -108,7 +108,8 @@ interface Params {
slug?: string[]
}
const PGGraphQLDocs = async ({ params }: { params: Params }) => {
const PGGraphQLDocs = async (props: { params: Promise<Params> }) => {
const params = await props.params
const { meta, ...data } = await getContent(params)
const options = {
@@ -137,7 +138,7 @@ const getContent = async ({ slug }: Params) => {
const response = await fetch(
`https://raw.githubusercontent.com/${org}/${repo}/${branch}/${docsDir}/${remoteFile}`,
{ next: { tags: [REVALIDATION_TAGS.GRAPHQL] } }
{ cache: 'force-cache', next: { tags: [REVALIDATION_TAGS.GRAPHQL] } }
)
const content = await response.text()
@@ -9,7 +9,8 @@ export const dynamicParams = false
type Params = { slug?: string[] }
const IntegrationsGuidePage = async ({ params }: { params: Params }) => {
const IntegrationsGuidePage = async (props: { params: Promise<Params> }) => {
const params = await props.params
const slug = ['integrations', ...(params.slug ?? [])]
const data = await getGuidesMarkdown(slug)
@@ -9,7 +9,8 @@ export const dynamicParams = false
type Params = { slug?: string[] }
const LocalDevelopmentGuidePage = async ({ params }: { params: Params }) => {
const LocalDevelopmentGuidePage = async (props: { params: Promise<Params> }) => {
const params = await props.params
const slug = ['local-development', ...(params.slug ?? [])]
const data = await getGuidesMarkdown(slug)
@@ -9,7 +9,8 @@ export const dynamicParams = false
type Params = { slug?: string[] }
const PlatformGuidePage = async ({ params }: { params: Params }) => {
const PlatformGuidePage = async (props: { params: Promise<Params> }) => {
const params = await props.params
const slug = ['platform', ...(params.slug ?? [])]
const data = await getGuidesMarkdown(slug)
@@ -9,7 +9,8 @@ export const dynamicParams = false
type Params = { slug?: string[] }
const QueuesGuidePage = async ({ params }: { params: Params }) => {
const QueuesGuidePage = async (props: { params: Promise<Params> }) => {
const params = await props.params
const slug = ['queues', ...(params.slug ?? [])]
const data = await getGuidesMarkdown(slug)
@@ -9,7 +9,8 @@ import { getEmptyArray } from '~/features/helpers.fn'
type Params = { slug?: string[] }
const RealtimeGuidePage = async ({ params }: { params: Params }) => {
const RealtimeGuidePage = async (props: { params: Promise<Params> }) => {
const params = await props.params
const slug = ['realtime', ...(params.slug ?? [])]
const data = await getGuidesMarkdown(slug)
@@ -9,7 +9,8 @@ export const dynamicParams = false
type Params = { slug?: string[] }
const ResourcesGuidePage = async ({ params }: { params: Params }) => {
const ResourcesGuidePage = async (props: { params: Promise<Params> }) => {
const params = await props.params
const slug = ['resources', ...(params.slug ?? [])]
const data = await getGuidesMarkdown(slug)
@@ -9,7 +9,8 @@ export const dynamicParams = false
type Params = { slug?: string[] }
const SecurityGuidePage = async ({ params }: { params: Params }) => {
const SecurityGuidePage = async (props: { params: Promise<Params> }) => {
const params = await props.params
const slug = ['security', ...(params.slug ?? [])]
const data = await getGuidesMarkdown(slug)
@@ -9,7 +9,8 @@ export const dynamicParams = false
type Params = { slug?: string[] }
const SelfHostingGuidePage = async ({ params }: { params: Params }) => {
const SelfHostingGuidePage = async (props: { params: Promise<Params> }) => {
const params = await props.params
const slug = ['self-hosting', ...(params.slug ?? [])]
const data = await getGuidesMarkdown(slug)
@@ -9,7 +9,8 @@ import { getEmptyArray } from '~/features/helpers.fn'
type Params = { slug?: string[] }
const StorageGuidePage = async ({ params }: { params: Params }) => {
const StorageGuidePage = async (props: { params: Promise<Params> }) => {
const params = await props.params
const slug = ['storage', ...(params.slug ?? [])]
const data = await getGuidesMarkdown(slug)
@@ -9,7 +9,8 @@ export const dynamicParams = false
type Params = { slug?: string[] }
const MonitoringTroubleshootingGuidePage = async ({ params }: { params: Params }) => {
const MonitoringTroubleshootingGuidePage = async (props: { params: Promise<Params> }) => {
const params = await props.params
const slug = ['telemetry', ...(params.slug ?? [])]
const data = await getGuidesMarkdown(slug)
@@ -8,11 +8,13 @@ import { PROD_URL } from '~/lib/constants'
// export const revalidate = 86_400
export const dynamicParams = false
export default async function TroubleshootingEntryPage({
params: { slug },
}: {
params: { slug: string }
export default async function TroubleshootingEntryPage(props: {
params: Promise<{ slug: string }>
}) {
const params = await props.params
const { slug } = params
const allTroubleshootingEntries = await getAllTroubleshootingEntries()
const entry = allTroubleshootingEntries.find((entry) => getArticleSlug(entry) === slug)
@@ -23,7 +25,11 @@ export default async function TroubleshootingEntryPage({
return <TroubleshootingPage entry={entry} />
}
export const generateMetadata = async ({ params: { slug } }: { params: { slug: string } }) => {
export const generateMetadata = async (props: { params: Promise<{ slug: string }> }) => {
const params = await props.params
const { slug } = params
const allTroubleshootingEntries = await getAllTroubleshootingEntries()
const entry = allTroubleshootingEntries.find((entry) => getArticleSlug(entry) === slug)
+5 -5
View File
@@ -14,11 +14,11 @@ import {
export const dynamicParams = false
export default async function ReferencePage({
params: { slug },
}: {
params: { slug: Array<string> }
}) {
export default async function ReferencePage(props: { params: Promise<{ slug: Array<string> }> }) {
const params = await props.params
const { slug } = params
if (!Object.keys(REFERENCES).includes(slug[0].replaceAll('-', '_'))) {
notFound()
}
+2 -1
View File
@@ -120,7 +120,8 @@ const genGuideMeta =
<Params,>(
generate: (params: Params) => OrPromise<{ meta: GuideFrontmatter; pathname: `/${string}` }>
) =>
async ({ params }: { params: Params }, parent: ResolvingMetadata): Promise<Metadata> => {
async (props: { params: Promise<Params> }, parent: ResolvingMetadata): Promise<Metadata> => {
const params = await props.params
const [parentAlternates, parentOg, { meta, pathname }] = await Promise.all([
pluckPromise(parent, 'alternates'),
pluckPromise(parent, 'openGraph'),
+2 -1
View File
@@ -119,9 +119,10 @@ export async function generateReferenceStaticParams() {
}
export async function generateReferenceMetadata(
{ params: { slug } }: { params: { slug: Array<string> } },
props: { params: Promise<{ slug: Array<string> }> },
resolvingParent: ResolvingMetadata
): Promise<Metadata> {
const { slug } = await props.params
const { alternates: parentAlternates, openGraph: parentOg } = await resolvingParent
const parsedPath = parseReferencePath(slug)
+2 -5
View File
@@ -29,11 +29,8 @@ function fetchWithNextOptions({
return (info: RequestInfo) => fetch(info, { next, cache })
}
const fetchRevalidatePerDay_TEMP_TESTING = fetchWithNextOptions({
const fetchRevalidatePerDay = fetchWithNextOptions({
next: { revalidate: ONE_DAY_IN_SECONDS },
})
// [Charis 2024-12-28]
// Temporarily disabling revalidation as a hotfix for Vercel NFT problem
const fetchRevalidatePerDay = fetch
export { fetchWithNextOptions, fetchRevalidatePerDay, fetchRevalidatePerDay_TEMP_TESTING }
export { fetchWithNextOptions, fetchRevalidatePerDay }
+1 -1
View File
@@ -2,4 +2,4 @@
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
+15 -12
View File
@@ -49,19 +49,22 @@ const nextConfig = {
})
return config
},
transpilePackages: ['ui', 'ui-patterns', 'common', 'dayjs', 'shared-data', 'api-types', 'icons'],
experimental: {
outputFileTracingIncludes: {
'/api/crawlers': ['./features/docs/generated/**/*', './docs/ref/**/*'],
'/guides/**/*': [
'./content/guides/**/*',
'./content/troubleshooting/**/*',
'./examples/**/*',
],
'/reference/**/*': ['./features/docs/generated/**/*', './docs/ref/**/*'],
},
serverComponentsExternalPackages: ['libpg-query', 'twoslash'],
transpilePackages: [
'ui',
'ui-patterns',
'common',
'dayjs',
'shared-data',
'api-types',
'icons',
'next-mdx-remote',
],
outputFileTracingIncludes: {
'/api/crawlers': ['./features/docs/generated/**/*', './docs/ref/**/*'],
'/guides/**/*': ['./content/guides/**/*', './content/troubleshooting/**/*', './examples/**/*'],
'/reference/**/*': ['./features/docs/generated/**/*', './docs/ref/**/*'],
},
serverExternalPackages: ['libpg-query', 'twoslash'],
async headers() {
return [
{
+6 -5
View File
@@ -31,14 +31,14 @@
"codemod:frontmatter": "node ./scripts/codemod/mdx-meta.mjs && prettier --write \"content/**/*.mdx\"",
"codegen:graphql": "tsx --conditions=react-server ./scripts/graphqlSchema.ts && graphql-codegen --config codegen.ts",
"codegen:references": "tsx features/docs/Reference.generated.script.ts",
"clean": "rimraf node_modules features/docs/generated examples __generated__"
"clean": "rimraf .next .turbo node_modules features/docs/generated examples __generated__"
},
"dependencies": {
"@har-sdk/openapi-sampler": "^2.2.0",
"@mdx-js/loader": "^2.1.5",
"@mdx-js/react": "^2.3.0",
"@next/bundle-analyzer": "^14.2.3",
"@next/mdx": "^14.2.3",
"@next/bundle-analyzer": "15.3.1",
"@next/mdx": "15.3.1",
"@octokit/auth-app": "^7.0.0",
"@octokit/core": "^6.0.0",
"@octokit/graphql": "^8.0.0",
@@ -80,7 +80,7 @@
"mdast-util-to-string": "^3.1.1",
"micromark-extension-gfm": "^2.0.3",
"micromark-extension-mdxjs": "^1.0.0",
"next": "catalog:",
"next": "15.3.1",
"next-mdx-remote": "^4.4.1",
"next-plugin-yaml": "^1.0.1",
"next-themes": "^0.3.0",
@@ -138,8 +138,9 @@
"dotenv": "^16.0.3",
"ejs": "^3.1.10",
"globby": "^13.2.2",
"graphiql": "^3.8.3",
"graphiql": "^4.0.2",
"openapi-types": "^12.1.3",
"postcss": "^8.5.3",
"shiki": "^3.2.1",
"simple-git": "^3.24.0",
"slugify": "^1.6.6",
+2 -2
View File
@@ -37,7 +37,7 @@
"@heroicons/react": "^2.1.3",
"@hookform/resolvers": "^3.1.1",
"@monaco-editor/react": "^4.6.0",
"@next/bundle-analyzer": "15.3.0",
"@next/bundle-analyzer": "15.3.1",
"@number-flow/react": "^0.3.2",
"@sentry/nextjs": "^8.52.1",
"@std/path": "npm:@jsr/std__path@^1.0.8",
@@ -172,7 +172,7 @@
"import-in-the-middle": "^1.13.1",
"msw": "^2.3.0",
"next-router-mock": "^0.9.13",
"postcss": "^8.4.31",
"postcss": "^8.5.3",
"prettier": "3.2.4",
"raw-loader": "^4.0.2",
"require-in-the-middle": "^7.5.2",
+1 -1
View File
@@ -68,7 +68,7 @@
"config": "workspace:^",
"lodash": "^4.17.21",
"mdast-util-toc": "^6.1.1",
"postcss": "^8",
"postcss": "^8.5.3",
"react-dropzone": "^14.3.8",
"react-router": "^7.5.2",
"rimraf": "^4.1.3",
+1 -1
View File
@@ -98,7 +98,7 @@
"@types/uuid": "^9.0.8",
"api-types": "workspace:*",
"autoprefixer": "^10.4.14",
"postcss": "^8.4.31",
"postcss": "^8.5.3",
"react-hook-form": "^7.45.0",
"tsconfig": "workspace:*",
"uuid": "^9.0.1",
+977 -114
View File
File diff suppressed because it is too large. Load diff