OpenAPI: Change playground localStorage key for authorization info

This commit is contained in:
Fuma Nama
2025-03-31 22:17:13 +08:00
parent 5e7656a132
commit 70d7ab0977
4 changed files with 70 additions and 59 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'fumadocs-openapi': patch
---
Change playground `localStorage` key for authorization info
@@ -1,6 +1,4 @@
'use client';
import dynamic from 'next/dynamic';
export const ClientLazy = dynamic(() =>
import('./client').then((mod) => mod.Client),
);
export const ClientLazy = dynamic(() => import('./client'));
+57 -52
View File
@@ -84,7 +84,9 @@ export interface CustomField<TName extends FieldPath<FormValues>, Info> {
export type ClientProps = HTMLAttributes<HTMLFormElement> & {
route: string;
method: string;
authorization?: Security;
authorization?: Security & {
persistentId: string;
};
parameters?: PrimitiveRequestField[];
body?: RequestSchema & {
mediaType: string;
@@ -148,7 +150,7 @@ function toRequestData(
};
}
export function Client({
export default function Client({
route,
method = 'GET',
authorization,
@@ -296,6 +298,56 @@ function FormBody({
return paramTypes.map((param) => parameters.filter((v) => v.in === param));
}, [parameters]);
function renderAuth() {
if (!authorization) return null;
const schema: RequestSchema =
authorization.type === 'http' && authorization.scheme === 'basic'
? {
type: 'object',
isRequired: true,
properties: {
username: {
type: 'string',
isRequired: true,
},
password: {
type: 'string',
isRequired: true,
},
},
}
: {
type: 'string',
isRequired: true,
description: 'The Authorization access token',
};
if (fields?.auth)
return renderCustomField('authorization', schema, fields.auth);
return (
<>
<FieldSet
fieldName="authorization"
name="Authorization"
field={schema}
/>
{authorization?.type === 'oauth2' && (
<OauthDialogTrigger
type="button"
className={cn(
buttonVariants({
color: 'secondary',
}),
)}
>
Open
</OauthDialogTrigger>
)}
</>
);
}
return (
<>
{servers.length > 1 ? (
@@ -316,9 +368,7 @@ function FormBody({
return (
<CollapsiblePanel key={name} title={name}>
{type === 'header' && authorization ? (
<AuthField authorization={authorization} />
) : null}
{type === 'header' ? renderAuth() : null}
{param.map((field) => {
const fieldName = `${type}.${field.name}` as const;
@@ -399,51 +449,6 @@ function AuthProvider({
);
}
function AuthField({ authorization }: { authorization: Security }) {
return (
<>
<FieldSet
fieldName="authorization"
name="Authorization"
field={
authorization?.type === 'http' && authorization.scheme === 'basic'
? {
type: 'object',
isRequired: true,
properties: {
username: {
type: 'string',
isRequired: true,
},
password: {
type: 'string',
isRequired: true,
},
},
}
: {
type: 'string',
isRequired: true,
description: 'The Authorization access token',
}
}
/>
{authorization?.type === 'oauth2' && (
<OauthDialogTrigger
type="button"
className={cn(
buttonVariants({
color: 'secondary',
}),
)}
>
Open
</OauthDialogTrigger>
)}
</>
);
}
function Route({
route,
...props
@@ -502,9 +507,9 @@ function DefaultResultDisplay({ data }: { data: FetchResult }) {
);
}
function usePersistentAuthInfo(authorization?: Security) {
function usePersistentAuthInfo(authorization?: ClientProps['authorization']) {
const key = authorization
? `__fumadocs_auth_${JSON.stringify(authorization)}`
? `__fumadocs_auth_${authorization.persistentId}`
: null;
const [info, setInfo] = useState<FormValues['authorization']>(() => {
if (!authorization || authorization.type === 'apiKey') return '';
+7 -4
View File
@@ -8,8 +8,9 @@ import {
type NoReference,
type ParsedSchema,
} from '@/utils/schema';
import { getSecurities, type Security } from '@/utils/get-security';
import { getSecurities } from '@/utils/get-security';
import { type ClientProps } from './client';
import { ClientLazy } from '@/playground/client.lazy';
interface BaseRequestField {
name: string;
@@ -98,7 +99,6 @@ export async function APIPlayground({
ctx,
client,
}: APIPlaygroundProps) {
const { ClientLazy } = await import('./client.lazy');
let currentId = 0;
const bodyContent = method.requestBody?.content;
const mediaType = bodyContent ? getPreferredType(bodyContent) : undefined;
@@ -141,7 +141,7 @@ export async function APIPlayground({
function getAuthorizationField(
method: MethodInformation,
{ schema: { document } }: RenderContext,
): Security | undefined {
): ClientProps['authorization'] {
const security = method.security ?? document.security ?? [];
if (security.length === 0) return;
@@ -172,7 +172,10 @@ function getAuthorizationField(
);
}
return scheme;
return {
persistentId: Object.keys(item)[0],
...scheme,
};
}
function getIdFromSchema(