OpenAPI: Add authorization properties to examples

This commit is contained in:
fuma-nama
2024-08-09 14:17:23 +08:00
parent 5ccedc7d39
commit 22549cdac2
8 changed files with 54 additions and 26 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'fumadocs-openapi': patch
---
Add authorization properties to examples
+1 -1
View File
@@ -344,7 +344,7 @@ function Hero(): React.ReactElement {
</h1>
<p className="mb-6 h-fit p-2 text-fd-muted-foreground md:max-w-[80%] md:text-xl">
Fumadocs is the framework for building documentation with{' '}
<b className="text-foreground font-medium">
<b className="font-medium text-fd-foreground">
excellent UI and user experience
</b>
. Using the power of Next.js App Router and React Component.
@@ -0,0 +1,3 @@
{
"title": "APIs"
}
+11 -17
View File
@@ -7,7 +7,7 @@ import * as Go from '@/requests/go';
import { type MethodInformation, type RenderContext } from '@/types';
import { noRef, getPreferredType } from '@/utils/schema';
import { getTypescriptSchema } from '@/utils/get-typescript-schema';
import { getScheme } from '@/utils/get-security';
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';
@@ -95,7 +95,7 @@ export function Operation({
}
const parameterGroups = new Map<string, ReactNode[]>();
const endpoint = generateSample(path, method, ctx.baseUrl);
const endpoint = generateSample(path, method, ctx);
for (const param of method.parameters) {
const pInfo = endpoint.parameters.find(
@@ -232,20 +232,15 @@ function AuthSection({
const info: ReactNode[] = [];
for (const requirement of requirements) {
if (info.length > 0) info.push(`---`);
for (const schema of getSecurities(requirement, document)) {
const prefix = getSecurityPrefix(schema);
for (const schema of getScheme(requirement, document)) {
if (schema.type === 'http') {
info.push(
<renderer.Property
key={id++}
name="Authorization"
type={
{
basic: 'Basic <token>',
bearer: 'Bearer <token>',
}[schema.scheme] ?? '<token>'
}
type={prefix ? `${prefix} <token>` : '<token>'}
required
>
{schema.description ? <Markdown text={schema.description} /> : null}
@@ -261,19 +256,18 @@ function AuthSection({
<renderer.Property
key={id++}
name="Authorization"
type="Bearer <token>"
type={prefix ? `${prefix} <token>` : '<token>'}
required
>
{schema.description ? <Markdown text={schema.description} /> : null}
<p>
In: <code>header</code>
</p>
<p>
Scope:{' '}
<code>
{schema.scopes.length > 0 ? schema.scopes.join(', ') : 'none'}
</code>
</p>
{schema.scopes.length > 0 ? (
<p>
Scope: <code>{schema.scopes.join(', ')}</code>
</p>
) : null}
</renderer.Property>,
);
}
+2 -2
View File
@@ -2,7 +2,7 @@ import type { OpenAPIV3 as OpenAPI } from 'openapi-types';
import type { ReactNode } from 'react';
import type { MethodInformation, RenderContext } from '@/types';
import { getPreferredType, noRef } from '@/utils/schema';
import { getScheme } from '@/utils/get-security';
import { getSecurities } from '@/utils/get-security';
interface BaseRequestField {
name: string;
@@ -141,7 +141,7 @@ function getAuthorizationField(
);
if (!singular) return;
const scheme = getScheme(singular, ctx.document)[0];
const scheme = getSecurities(singular, ctx.document)[0];
return {
type: 'string',
+1 -1
View File
@@ -72,7 +72,7 @@ ${Array.from(variables.entries())
req, _ := http.NewRequest("${endpoint.method}", url, ${variables.has('payload') ? 'payload' : 'nil'})
${Array.from(headers.entries())
.map(([key, value]) => `req.Header.Add("${key}", ${value})`)
.join('\n')}
.join('\n ')}
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
+19 -3
View File
@@ -1,7 +1,8 @@
import type { OpenAPIV3 as OpenAPI } from 'openapi-types';
import { sample } from 'openapi-sampler';
import type { MethodInformation } from '@/types';
import type { MethodInformation, RenderContext } from '@/types';
import { toSampleInput, noRef, getPreferredType } from '@/utils/schema';
import { getSecurities, getSecurityPrefix } from '@/utils/get-security';
/**
* Sample info of endpoint
@@ -37,7 +38,7 @@ interface ParameterSample {
export function generateSample(
path: string,
method: MethodInformation,
baseUrl: string,
{ baseUrl, document }: RenderContext,
): EndpointSample {
const params: ParameterSample[] = [];
const responses: EndpointSample['responses'] = {};
@@ -69,8 +70,23 @@ export function generateSample(
}
}
let bodyOutput: EndpointSample['body'];
const requirements = method.security ?? document.security;
if (requirements && requirements.length > 0) {
for (const security of getSecurities(requirements[0], document)) {
const prefix = getSecurityPrefix(security);
params.push({
name: 'Authorization',
schema: {
type: 'string',
},
sample: prefix ? `${prefix} <token>` : '<token>',
in: 'header',
});
}
}
let bodyOutput: EndpointSample['body'];
if (method.requestBody) {
const body = noRef(method.requestBody).content;
const type = getPreferredType(body);
+12 -2
View File
@@ -1,11 +1,11 @@
import { type OpenAPIV3 as OpenAPI } from 'openapi-types';
import { noRef } from '@/utils/schema';
type Security = OpenAPI.SecuritySchemeObject & {
export type Security = OpenAPI.SecuritySchemeObject & {
scopes: string[];
};
export function getScheme(
export function getSecurities(
requirement: OpenAPI.SecurityRequirementObject,
document: OpenAPI.Document,
): Security[] {
@@ -24,3 +24,13 @@ export function getScheme(
return results;
}
export function getSecurityPrefix(security: Security): string | undefined {
if (security.type === 'http')
return {
basic: 'Basic',
bearer: 'Bearer',
}[security.scheme];
if (security.type === 'oauth2') return 'Bearer';
}