diff --git a/apps/docs/app/api/revalidate/route.test.ts b/apps/docs/app/api/revalidate/route.test.ts index befeabd43e7..66a30304d41 100644 --- a/apps/docs/app/api/revalidate/route.test.ts +++ b/apps/docs/app/api/revalidate/route.test.ts @@ -40,6 +40,9 @@ describe('_handleRevalidateRequest', () => { process.env.NEXT_PUBLIC_SUPABASE_URL = 'http://localhost:3000' process.env.SUPABASE_SECRET_KEY = 'secret_key' + // Silence intentional console errors for cleaner test output + vi.spyOn(console, 'error').mockImplementation(() => {}) + // Mock current date mockDate = new Date('2023-01-01T12:00:00Z') vi.setSystemTime(mockDate) @@ -109,7 +112,7 @@ describe('_handleRevalidateRequest', () => { headers: { Authorization: 'Bearer basic_key', }, - body: JSON.stringify({ tags: ['tag1', 'tag2'] }), + body: JSON.stringify({ tags: ['graphql', 'wrappers'] }), }) vi.mocked(headers).mockReturnValue(new Headers(request.headers)) @@ -119,8 +122,8 @@ describe('_handleRevalidateRequest', () => { const response = await _handleRevalidateRequest(request) expect(response.status).toBe(204) expect(revalidateTag).toHaveBeenCalledTimes(2) - expect(revalidateTag).toHaveBeenCalledWith('tag1') - expect(revalidateTag).toHaveBeenCalledWith('tag2') + expect(revalidateTag).toHaveBeenCalledWith('graphql') + expect(revalidateTag).toHaveBeenCalledWith('wrappers') }) it('should return 429 if last revalidation was less than 6 hours ago with basic permissions', async () => { @@ -129,7 +132,7 @@ describe('_handleRevalidateRequest', () => { headers: { Authorization: 'Bearer basic_key', }, - body: JSON.stringify({ tags: ['tag1'] }), + body: JSON.stringify({ tags: ['graphql'] }), }) vi.mocked(headers).mockReturnValue(new Headers(request.headers)) @@ -150,7 +153,7 @@ describe('_handleRevalidateRequest', () => { headers: { Authorization: 'Bearer basic_key', }, - body: JSON.stringify({ tags: ['tag1'] }), + body: JSON.stringify({ tags: ['graphql'] }), }) vi.mocked(headers).mockReturnValue(new Headers(request.headers)) @@ -162,7 +165,7 @@ describe('_handleRevalidateRequest', () => { const response = await _handleRevalidateRequest(request) expect(response.status).toBe(204) - expect(revalidateTag).toHaveBeenCalledWith('tag1') + expect(revalidateTag).toHaveBeenCalledWith('graphql') }) it('should revalidate regardless of last revalidation time with override permissions', async () => { @@ -171,7 +174,7 @@ describe('_handleRevalidateRequest', () => { headers: { Authorization: 'Bearer override_key', }, - body: JSON.stringify({ tags: ['tag1'] }), + body: JSON.stringify({ tags: ['graphql'] }), }) vi.mocked(headers).mockReturnValue(new Headers(request.headers)) @@ -183,6 +186,6 @@ describe('_handleRevalidateRequest', () => { const response = await _handleRevalidateRequest(request) expect(response.status).toBe(204) - expect(revalidateTag).toHaveBeenCalledWith('tag1') + expect(revalidateTag).toHaveBeenCalledWith('graphql') }) }) diff --git a/apps/docs/app/api/revalidate/route.ts b/apps/docs/app/api/revalidate/route.ts index 1c751fb6512..86b033e4767 100644 --- a/apps/docs/app/api/revalidate/route.ts +++ b/apps/docs/app/api/revalidate/route.ts @@ -1,10 +1,10 @@ import { createClient } from '@supabase/supabase-js' +import { type Database } from 'common' import { revalidateTag } from 'next/cache' import { headers } from 'next/headers' import { type NextRequest } from 'next/server' import { z } from 'zod' - -import { type Database } from 'common' +import { VALID_REVALIDATION_TAGS } from '~/features/helpers.fetch' enum AuthorizationLevel { Unauthorized, @@ -13,7 +13,7 @@ enum AuthorizationLevel { } const requestBodySchema = z.object({ - tags: z.array(z.string()), + tags: z.array(z.enum(VALID_REVALIDATION_TAGS)), }) export const POST = handleError(_handleRevalidateRequest) @@ -35,14 +35,12 @@ export async function _handleRevalidateRequest(request: NextRequest) { } let authorizationLevel = AuthorizationLevel.Unauthorized - - const token = authorization.replace(/^Bearer\s+/, '') + const token = authorization.replace(/^Bearer /, '') if (overrideKeys.includes(token)) { authorizationLevel = AuthorizationLevel.Override } else if (basicKeys.includes(token)) { authorizationLevel = AuthorizationLevel.Basic } - if (authorizationLevel === AuthorizationLevel.Unauthorized) { return new Response('Invalid Authorization header', { status: 401 }) } diff --git a/apps/docs/app/guides/database/extensions/wrappers/[[...slug]]/page.tsx b/apps/docs/app/guides/database/extensions/wrappers/[[...slug]]/page.tsx index 76c8c71bf48..0bbbee54595 100644 --- a/apps/docs/app/guides/database/extensions/wrappers/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/database/extensions/wrappers/[[...slug]]/page.tsx @@ -11,12 +11,12 @@ import { removeRedundantH1, } from '~/features/docs/GuidesMdx.utils' import { GuideTemplate, newEditLink } from '~/features/docs/GuidesMdx.template' -import { fetchRevalidatePerDay } from '~/features/helpers.fetch' import { GUIDES_DIRECTORY, isValidGuideFrontmatter } from '~/lib/docs' 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 { REVALIDATION_TAGS } from '~/features/helpers.fetch' export const dynamicParams = false @@ -196,7 +196,9 @@ const getContent = async (params: Params) => { const repoPath = `${org}/${repo}/${branch}/${docsDir}/${remoteFile}` editLink = `${org}/${repo}/blob/${branch}/${docsDir}/${remoteFile}` - const response = await fetchRevalidatePerDay(`https://raw.githubusercontent.com/${repoPath}`) + const response = await fetch(`https://raw.githubusercontent.com/${repoPath}`, { + next: { tags: [REVALIDATION_TAGS.WRAPPERS] }, + }) const rawContent = await response.text() const { content: contentWithoutFrontmatter } = matter(rawContent) diff --git a/apps/docs/app/guides/graphql/[[...slug]]/page.tsx b/apps/docs/app/guides/graphql/[[...slug]]/page.tsx index fbf0d930735..69ba3cf793b 100644 --- a/apps/docs/app/guides/graphql/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/graphql/[[...slug]]/page.tsx @@ -5,11 +5,11 @@ import rehypeSlug from 'rehype-slug' import { genGuideMeta } from '~/features/docs/GuidesMdx.utils' import { GuideTemplate, newEditLink } from '~/features/docs/GuidesMdx.template' -import { fetchRevalidatePerDay_TEMP_TESTING } from '~/features/helpers.fetch' 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 { REVALIDATION_TAGS } from '~/features/helpers.fetch' export const dynamicParams = false @@ -135,8 +135,9 @@ const getContent = async ({ slug }: Params) => { const editLink = newEditLink(`${org}/${repo}/blob/${branch}/${docsDir}/${remoteFile}`) - const response = await fetchRevalidatePerDay_TEMP_TESTING( - `https://raw.githubusercontent.com/${org}/${repo}/${branch}/${docsDir}/${remoteFile}` + const response = await fetch( + `https://raw.githubusercontent.com/${org}/${repo}/${branch}/${docsDir}/${remoteFile}`, + { next: { tags: [REVALIDATION_TAGS.GRAPHQL] } } ) const content = await response.text() diff --git a/apps/docs/features/helpers.fetch.ts b/apps/docs/features/helpers.fetch.ts index 494e0444fe4..1275a4817c1 100644 --- a/apps/docs/features/helpers.fetch.ts +++ b/apps/docs/features/helpers.fetch.ts @@ -8,6 +8,17 @@ import { ONE_DAY_IN_SECONDS } from './helpers.time' +export const REVALIDATION_TAGS = { + GRAPHQL: 'graphql', + WRAPPERS: 'wrappers', +} as const +// Casting to avoid problems with using this as a Zod enum, TypeScript does +// not recognize the casted type as a supertype of the original type +export const VALID_REVALIDATION_TAGS = Object.values(REVALIDATION_TAGS) as unknown as readonly [ + string, + ...string[], +] + function fetchWithNextOptions({ next, cache,