diff --git a/packages/gitbook/e2e/util.ts b/packages/gitbook/e2e/util.ts index 39483d252..832b43e33 100644 --- a/packages/gitbook/e2e/util.ts +++ b/packages/gitbook/e2e/util.ts @@ -154,6 +154,12 @@ export function runTestCases(testCases: TestsCase[]) { })) ); } + + // Disable the Vercel toolbar + await page.setExtraHTTPHeaders({ + 'x-vercel-skip-toolbar': '1', + }); + await page.goto(url); if (testEntry.run) { await testEntry.run(page); diff --git a/packages/gitbook/src/lib/openapi/fetch.ts b/packages/gitbook/src/lib/openapi/fetch.ts index b26ce5613..ab78653af 100644 --- a/packages/gitbook/src/lib/openapi/fetch.ts +++ b/packages/gitbook/src/lib/openapi/fetch.ts @@ -6,6 +6,7 @@ import type { GitBookAnyContext } from '@v2/lib/context'; import { type CacheFunctionOptions, cache, noCacheFetchOptions } from '@/lib/cache'; import { resolveContentRef } from '../references'; +import { isV2 } from '../v2'; import { enrichFilesystem } from './enrich'; const weakmap = new WeakMap(); @@ -65,32 +66,18 @@ async function baseResolveOpenAPIBlock(args: ResolveOpenAPIBlockArgs): ResolveOp } } -const fetchFilesystem = cache({ +function fetchFilesystem(url: string) { + if (isV2()) { + return fetchFilesystemV2(url); + } + + return fetchFilesystemV1(url); +} + +const fetchFilesystemV1 = cache({ name: 'openapi.fetch.v6', get: async (url: string, options: CacheFunctionOptions) => { - // Wrap the raw string to prevent invalid URLs from being passed to fetch. - // This can happen if the URL has whitespace, which is currently handled differently by Cloudflare's implementation of fetch: - // https://github.com/cloudflare/workerd/issues/1957 - const response = await fetch(new URL(url), { - ...noCacheFetchOptions, - signal: options.signal, - }); - - if (!response.ok) { - throw new Error( - `Failed to fetch OpenAPI file: ${response.status} ${response.statusText}` - ); - } - - const text = await response.text(); - const filesystem = await parseOpenAPI({ - value: text, - rootURL: url, - // If we fetch the OpenAPI specification - // it's the legacy system, it means the spec can be trusted here. - trust: true, - }); - const richFilesystem = await enrichFilesystem(filesystem); + const richFilesystem = await fetchFilesystemUncached(url, options); return { // Cache for 4 hours ttl: 24 * 60 * 60, @@ -100,3 +87,44 @@ const fetchFilesystem = cache({ }; }, }); + +async function fetchFilesystemV2(url: string) { + 'use cache'; + + // TODO: add cache lifetime once we can use next.js 15 code here + + const response = await fetchFilesystemUncached(url); + + return response; +} + +async function fetchFilesystemUncached( + url: string, + options?: { + signal?: AbortSignal; + } +) { + // Wrap the raw string to prevent invalid URLs from being passed to fetch. + // This can happen if the URL has whitespace, which is currently handled differently by Cloudflare's implementation of fetch: + // https://github.com/cloudflare/workerd/issues/1957 + const response = await fetch(new URL(url), { + ...noCacheFetchOptions, + signal: options?.signal, + }); + + if (!response.ok) { + throw new Error(`Failed to fetch OpenAPI file: ${response.status} ${response.statusText}`); + } + + const text = await response.text(); + const filesystem = await parseOpenAPI({ + value: text, + rootURL: url, + // If we fetch the OpenAPI specification + // it's the legacy system, it means the spec can be trusted here. + trust: true, + }); + const richFilesystem = await enrichFilesystem(filesystem); + + return richFilesystem; +} diff --git a/packages/gitbook/src/lib/v2.ts b/packages/gitbook/src/lib/v2.ts index 158c5d1c5..0d4c9db6d 100644 --- a/packages/gitbook/src/lib/v2.ts +++ b/packages/gitbook/src/lib/v2.ts @@ -1,8 +1,15 @@ +/** + * Check if the code is running in v2. + */ +export function isV2() { + return process.env.GITBOOK_V2 === 'true'; +} + /** * Assert that the code is not running in v2. */ export function assertIsNotV2() { - if (process.env.GITBOOK_V2 === 'true') { + if (isV2()) { throw new Error('This code is not available in V2'); } } diff --git a/packages/react-openapi/src/OpenAPICodeSample.tsx b/packages/react-openapi/src/OpenAPICodeSample.tsx index fd37fb3a7..8cfba1716 100644 --- a/packages/react-openapi/src/OpenAPICodeSample.tsx +++ b/packages/react-openapi/src/OpenAPICodeSample.tsx @@ -5,8 +5,7 @@ import { generateMediaTypeExample, generateSchemaExample } from './generateSchem import { stringifyOpenAPI } from './stringifyOpenAPI'; import type { OpenAPIContextProps, OpenAPIOperationData } from './types'; import { getDefaultServerURL } from './util/server'; -import { createStateKey } from './utils'; -import { checkIsReference } from './utils'; +import { checkIsReference, createStateKey } from './utils'; /** * Display code samples to execute the operation. @@ -95,8 +94,8 @@ export function OpenAPICodeSample(props: { typeof sample.lang === 'string' ); }) - .map((sample) => ({ - key: `redocly-${sample.lang}`, + .map((sample, index) => ({ + key: `redocly-${sample.lang}-${index}`, label: sample.label, body: context.renderCodeBlock({ code: sample.source,