OpenAPI: Fix example value generation for parameters

This commit is contained in:
Fuma Nama
2025-12-13 19:58:46 +08:00
parent 157b5854b9
commit 90ada4bd56
3 changed files with 58 additions and 24 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'fumadocs-openapi': patch
---
Fix example value generation for parameters
@@ -1,5 +1,9 @@
import type { MethodInformation, RenderContext } from '@/types';
import { getPreferredType, type NoReference } from '@/utils/schema';
import {
getPreferredType,
type NoReference,
pickExample,
} from '@/utils/schema';
import {
AccordionContent,
AccordionHeader,
@@ -91,28 +95,21 @@ function getRequestData(
};
for (const param of method.parameters ?? []) {
let schema = param.schema;
let value: unknown | undefined;
let value = pickExample(param);
if (!schema && param.content) {
const type = getPreferredType(param.content);
if (value === undefined && param.required) {
if (param.schema) {
value = sample(param.schema as object);
} else if (param.content) {
const type = getPreferredType(param.content);
const content = type ? param.content[type] : undefined;
if (!content || !content.schema)
throw new Error(
`Cannot find "${param.name}" parameter info for media type "${type}" in ${path} ${method.method}`,
);
const content = type ? param.content[type] : undefined;
if (!content || !content.schema)
throw new Error(
`Cannot find parameter schema for ${param.name} in ${path} ${method.method}`,
);
schema = content.schema;
value = content.example ?? param.example;
} else {
value = param.example;
}
if (param.required) {
value ??= sample(schema as object);
} else if (value === undefined) {
continue;
value = sample(content.schema as object);
}
}
switch (param.in) {
+35 -3
View File
@@ -7,6 +7,7 @@ import type {
TagObject,
} from '@/types';
import { idToTitle } from '@/utils/id-to-title';
import { OpenAPIV3_1 } from 'openapi-types';
export const methodKeys = [
'get',
@@ -36,9 +37,9 @@ type NoReferenceJSONSchema<T> = T extends (infer I)[]
export type ParsedSchema = JSONSchema;
export type ResolvedSchema = NoReferenceJSONSchema<ParsedSchema>;
export function getPreferredType<B extends Record<string, unknown>>(
body: B,
): keyof B | undefined {
export function getPreferredType(
body: Record<string, unknown>,
): string | undefined {
if ('application/json' in body) return 'application/json';
return Object.keys(body)[0];
@@ -66,3 +67,34 @@ export function createMethod(
method: method.toUpperCase(),
};
}
interface ExampleLike {
example?: unknown;
examples?: {
[media: string]: OpenAPIV3_1.ExampleObject;
};
content?: {
[media: string]: OpenAPIV3_1.MediaTypeObject;
};
}
export function pickExample(value: ExampleLike): unknown | undefined {
if (value.example !== undefined) {
return value.example;
}
if (value.content) {
const type = getPreferredType(value.content);
const content = type ? value.content[type] : undefined;
if (type && content) {
const out = value.examples?.[type].value ?? pickExample(content);
if (out !== undefined) return out;
}
}
if (value.examples) {
const examples = Object.values(value.examples);
if (examples.length > 0) return examples[0].value;
}
}