mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-25 04:20:02 +00:00
OpenAPI: change Scalar usage
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
---
|
||||
'fumadocs-openapi': major
|
||||
---
|
||||
|
||||
**Change interface for `useScalar`**
|
||||
|
||||
From:
|
||||
|
||||
```tsx
|
||||
import { createOpenAPI } from 'fumadocs-openapi/server';
|
||||
import { APIPlayground } from 'fumadocs-openapi/scalar';
|
||||
|
||||
export const openapi = createOpenAPI({
|
||||
useScalar: true
|
||||
});
|
||||
```
|
||||
|
||||
To:
|
||||
|
||||
```tsx
|
||||
import { createOpenAPI } from 'fumadocs-openapi/server';
|
||||
import { APIPlayground } from 'fumadocs-openapi/scalar';
|
||||
|
||||
export const openapi = createOpenAPI({
|
||||
renderer: {
|
||||
APIPlayground,
|
||||
},
|
||||
});
|
||||
```
|
||||
@@ -115,9 +115,12 @@ You can enable the Scalar API Client using `useScalar` option in `createOpenAPI(
|
||||
|
||||
```ts
|
||||
import { createOpenAPI } from 'fumadocs-openapi/server';
|
||||
import { APIPlayground } from 'fumadocs-openapi/scalar';
|
||||
|
||||
export const openapi = createOpenAPI({
|
||||
useScalar: true,
|
||||
renderer: {
|
||||
APIPlayground,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
"@radix-ui/react-popover": "^1.1.5",
|
||||
"@radix-ui/react-slot": "^1.1.1",
|
||||
"@radix-ui/react-tooltip": "^1.1.7",
|
||||
"@scalar/api-client-react": "^1.1.17",
|
||||
"@shikijs/rehype": "^2.1.0",
|
||||
"@shikijs/twoslash": "^2.1.0",
|
||||
"@theguild/remark-mermaid": "^0.2.0",
|
||||
|
||||
@@ -2,6 +2,7 @@ import { createMDXSource } from 'fumadocs-mdx';
|
||||
import { loader } from 'fumadocs-core/source';
|
||||
import { attachFile, createOpenAPI } from 'fumadocs-openapi/server';
|
||||
import { docs, meta } from '@/.source';
|
||||
import { APIPlayground } from 'fumadocs-openapi/scalar';
|
||||
|
||||
export const source = loader({
|
||||
baseUrl: '/docs',
|
||||
@@ -11,4 +12,8 @@ export const source = loader({
|
||||
},
|
||||
});
|
||||
|
||||
export const openapi = createOpenAPI();
|
||||
export const openapi = createOpenAPI({
|
||||
renderer: {
|
||||
APIPlayground,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
"import": "./dist/ui/index.js",
|
||||
"types": "./dist/ui/index.d.ts"
|
||||
},
|
||||
"./scalar": {
|
||||
"import": "./dist/scalar/index.js",
|
||||
"types": "./dist/scalar/index.d.ts"
|
||||
},
|
||||
"./server": {
|
||||
"import": "./dist/server/index.js",
|
||||
"types": "./dist/server/index.d.ts"
|
||||
|
||||
@@ -14,7 +14,6 @@ import type {
|
||||
import { getPreferredType, NoReference } from '@/utils/schema';
|
||||
import { getTypescriptSchema } from '@/utils/get-typescript-schema';
|
||||
import { getSecurities, getSecurityPrefix } from '@/utils/get-security';
|
||||
import { Playground } from '@/render/playground';
|
||||
import { idToTitle } from '@/utils/id-to-title';
|
||||
import { type ResponseTypeProps } from '@/render/renderer';
|
||||
import { Markdown } from './markdown';
|
||||
@@ -202,7 +201,7 @@ export function Operation({
|
||||
const info = (
|
||||
<ctx.renderer.APIInfo head={headNode} method={method.method} route={path}>
|
||||
{type === 'operation' ? (
|
||||
<Playground path={path} method={method} ctx={ctx} />
|
||||
<ctx.renderer.APIPlayground path={path} method={method} ctx={ctx} />
|
||||
) : null}
|
||||
{security ? (
|
||||
<>
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
type ParsedSchema,
|
||||
} from '@/utils/schema';
|
||||
import { getSecurities } from '@/utils/get-security';
|
||||
import { ScalarPlayground } from '@/ui';
|
||||
import { APIPlayground } from '@/ui';
|
||||
|
||||
interface BaseRequestField {
|
||||
name: string;
|
||||
@@ -104,16 +104,6 @@ export function Playground({
|
||||
method: MethodInformation;
|
||||
ctx: RenderContext;
|
||||
}): ReactNode {
|
||||
if (ctx.useScalar) {
|
||||
return (
|
||||
<ScalarPlayground
|
||||
spec={ctx.schema.downloaded}
|
||||
method={method.method}
|
||||
path={path}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
let currentId = 0;
|
||||
const bodyContent = method.requestBody?.content;
|
||||
const mediaType = bodyContent ? getPreferredType(bodyContent) : undefined;
|
||||
@@ -157,7 +147,7 @@ export function Playground({
|
||||
proxyUrl: ctx.proxyUrl,
|
||||
};
|
||||
|
||||
return <ctx.renderer.APIPlayground {...props} />;
|
||||
return <APIPlayground {...props} />;
|
||||
}
|
||||
|
||||
function getAuthorizationField(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { ComponentType, ReactNode } from 'react';
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
||||
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
|
||||
import type { APIPlaygroundProps } from '@/render/playground';
|
||||
import { CodeBlock } from '@/render/codeblock';
|
||||
import {
|
||||
API,
|
||||
@@ -10,9 +9,9 @@ import {
|
||||
APIExample,
|
||||
Property,
|
||||
ObjectCollapsible,
|
||||
APIPlayground,
|
||||
} from '@/ui';
|
||||
import type { RenderContext, ServerObject } from '@/types';
|
||||
import type { MethodInformation, RenderContext, ServerObject } from '@/types';
|
||||
import { Playground } from '@/render/playground';
|
||||
|
||||
export interface ResponsesProps {
|
||||
items: string[];
|
||||
@@ -81,7 +80,11 @@ export interface Renderer {
|
||||
*/
|
||||
ObjectCollapsible: ComponentType<ObjectCollapsibleProps>;
|
||||
Property: ComponentType<PropertyProps>;
|
||||
APIPlayground: ComponentType<APIPlaygroundProps>;
|
||||
APIPlayground: ComponentType<{
|
||||
path: string;
|
||||
method: MethodInformation;
|
||||
ctx: RenderContext;
|
||||
}>;
|
||||
}
|
||||
|
||||
export type {
|
||||
@@ -93,7 +96,6 @@ export type {
|
||||
|
||||
export function createRenders(
|
||||
shikiOptions: RenderContext['shikiOptions'],
|
||||
_useScalar: boolean,
|
||||
): Renderer {
|
||||
return {
|
||||
Root: (props) => (
|
||||
@@ -139,6 +141,6 @@ export function createRenders(
|
||||
/>
|
||||
</Tab>
|
||||
),
|
||||
APIPlayground,
|
||||
APIPlayground: Playground,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { MethodInformation, RenderContext } from '@/types';
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
const Client = dynamic(() => import('./client'));
|
||||
|
||||
export function APIPlayground({
|
||||
path,
|
||||
method,
|
||||
ctx,
|
||||
}: {
|
||||
path: string;
|
||||
method: MethodInformation;
|
||||
ctx: RenderContext;
|
||||
}) {
|
||||
return (
|
||||
<Client method={method.method} path={path} spec={ctx.schema.downloaded} />
|
||||
);
|
||||
}
|
||||
@@ -18,7 +18,6 @@ type ApiPageContextProps = Pick<
|
||||
| 'generateCodeSamples'
|
||||
| 'proxyUrl'
|
||||
| 'showResponseSchema'
|
||||
| 'useScalar'
|
||||
>;
|
||||
|
||||
export interface ApiPageProps extends ApiPageContextProps {
|
||||
@@ -124,12 +123,11 @@ export async function getContext(
|
||||
const server = servers[0];
|
||||
|
||||
return {
|
||||
useScalar: options.useScalar ?? false,
|
||||
schema,
|
||||
proxyUrl: options.proxyUrl,
|
||||
showResponseSchema: options.showResponseSchema,
|
||||
renderer: {
|
||||
...createRenders(options.shikiOptions, options.useScalar ?? false),
|
||||
...createRenders(options.shikiOptions),
|
||||
...options.renderer,
|
||||
},
|
||||
shikiOptions: options.shikiOptions,
|
||||
|
||||
@@ -34,11 +34,6 @@ type Awaitable<T> = T | Promise<T>;
|
||||
export type DereferenceMap = Map<unknown, string>;
|
||||
|
||||
export interface RenderContext {
|
||||
/**
|
||||
* Use Scalar for API Playground
|
||||
*/
|
||||
useScalar: boolean;
|
||||
|
||||
/**
|
||||
* The url of proxy to avoid CORS issues
|
||||
*/
|
||||
|
||||
@@ -1,23 +1,15 @@
|
||||
'use client';
|
||||
import {
|
||||
type ButtonHTMLAttributes,
|
||||
type HTMLAttributes,
|
||||
type ReactNode,
|
||||
} from 'react';
|
||||
import { Check, Copy } from 'lucide-react';
|
||||
import { cn, useCopyButton, buttonVariants } from 'fumadocs-ui/components/api';
|
||||
import { type HTMLAttributes, type ReactNode } from 'react';
|
||||
import { cn } from 'fumadocs-ui/components/api';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { ApiProvider, useApiContext } from '@/ui/contexts/api';
|
||||
import { ApiProvider } from '@/ui/contexts/api';
|
||||
import { type RootProps } from '@/render/renderer';
|
||||
import type { RenderContext } from '@/types';
|
||||
import { getUrl } from '@/utils/server-url';
|
||||
|
||||
export const APIPlayground = dynamic(() =>
|
||||
import('./playground').then((mod) => mod.APIPlayground),
|
||||
);
|
||||
|
||||
export const ScalarPlayground = dynamic(() => import('./scalar/index'));
|
||||
|
||||
export function Root({
|
||||
children,
|
||||
baseUrl,
|
||||
@@ -47,41 +39,4 @@ export function Root({
|
||||
);
|
||||
}
|
||||
|
||||
export function CopyRouteButton({
|
||||
className,
|
||||
route,
|
||||
...props
|
||||
}: ButtonHTMLAttributes<HTMLButtonElement> & {
|
||||
route: string;
|
||||
}): ReactNode {
|
||||
const { serverRef } = useApiContext();
|
||||
|
||||
const [checked, onCopy] = useCopyButton(() => {
|
||||
void navigator.clipboard.writeText(
|
||||
`${serverRef.current ? getUrl(serverRef.current.url, serverRef.current.variables) : ''}${route}`,
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
buttonVariants({
|
||||
color: 'ghost',
|
||||
className,
|
||||
}),
|
||||
)}
|
||||
onClick={onCopy}
|
||||
aria-label="Copy route path"
|
||||
{...props}
|
||||
>
|
||||
{checked ? (
|
||||
<Check className="size-full" />
|
||||
) : (
|
||||
<Copy className="size-full" />
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
export { useSchemaContext } from './contexts/schema';
|
||||
|
||||
@@ -9,12 +9,7 @@ import {
|
||||
} from 'fumadocs-ui/components/ui/collapsible';
|
||||
import { ChevronDown } from 'lucide-react';
|
||||
|
||||
export {
|
||||
Root,
|
||||
useSchemaContext,
|
||||
APIPlayground,
|
||||
ScalarPlayground,
|
||||
} from './client';
|
||||
export { Root, useSchemaContext, APIPlayground } from './client';
|
||||
|
||||
export function APIInfo({
|
||||
className,
|
||||
|
||||
@@ -39,7 +39,7 @@ export const roundedTable = {
|
||||
borderSpacing: '0',
|
||||
background: 'var(--color-fd-card)',
|
||||
borderRadius: 'var(--radius-lg)',
|
||||
border: '1p solid var(--color-fd-border)',
|
||||
border: '1px solid var(--color-fd-border)',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
th: {
|
||||
|
||||
Generated
-3
@@ -77,9 +77,6 @@ importers:
|
||||
'@radix-ui/react-tooltip':
|
||||
specifier: ^1.1.7
|
||||
version: 1.1.7(@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected]([email protected]))([email protected])
|
||||
'@scalar/api-client-react':
|
||||
specifier: ^1.1.17
|
||||
version: 1.1.17(@hyperjump/[email protected])([email protected])([email protected])([email protected])
|
||||
'@shikijs/rehype':
|
||||
specifier: ^2.1.0
|
||||
version: 2.1.0
|
||||
|
||||
Reference in New Issue
Block a user