mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-25 04:20:02 +00:00
OpenAPI: Display complex types & self-referencing types
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'fumadocs-openapi': minor
|
||||
---
|
||||
|
||||
Support complex types & self-referencing types
|
||||
@@ -22,9 +22,11 @@ interface Context {
|
||||
|
||||
required: boolean;
|
||||
|
||||
/** Parse object */
|
||||
/** Render the full object */
|
||||
parseObject: boolean;
|
||||
|
||||
stack: OpenAPI.SchemaObject[];
|
||||
|
||||
render: RenderContext;
|
||||
}
|
||||
|
||||
@@ -33,6 +35,17 @@ function isObject(schema: OpenAPI.SchemaObject): boolean {
|
||||
}
|
||||
|
||||
export function schemaElement(
|
||||
name: string,
|
||||
schema: OpenAPI.SchemaObject,
|
||||
ctx: Omit<Context, 'stack'>,
|
||||
): string {
|
||||
return render(name, schema, {
|
||||
...ctx,
|
||||
stack: [],
|
||||
});
|
||||
}
|
||||
|
||||
function render(
|
||||
name: string,
|
||||
schema: OpenAPI.SchemaObject,
|
||||
ctx: Context,
|
||||
@@ -63,7 +76,7 @@ export function schemaElement(
|
||||
);
|
||||
} else if (additionalProperties) {
|
||||
child.push(
|
||||
schemaElement('[key: string]', noRef(additionalProperties), {
|
||||
render('[key: string]', noRef(additionalProperties), {
|
||||
...ctx,
|
||||
required: false,
|
||||
parseObject: false,
|
||||
@@ -73,7 +86,7 @@ export function schemaElement(
|
||||
|
||||
Object.entries(properties ?? {}).forEach(([key, value]) => {
|
||||
child.push(
|
||||
schemaElement(key, noRef(value), {
|
||||
render(key, noRef(value), {
|
||||
...ctx,
|
||||
required: schema.required?.includes(key) ?? false,
|
||||
parseObject: false,
|
||||
@@ -99,38 +112,41 @@ export function schemaElement(
|
||||
);
|
||||
}
|
||||
|
||||
const mentionedObjectTypes = [
|
||||
...(schema.anyOf ?? schema.oneOf ?? schema.allOf ?? []),
|
||||
...(schema.type === 'array' ? [schema.items] : []),
|
||||
]
|
||||
.map(noRef)
|
||||
.filter((s) => isObject(s));
|
||||
|
||||
child.push(
|
||||
...mentionedObjectTypes.map((s, idx) =>
|
||||
renderer.ObjectCollapsible(
|
||||
{ name: s.title ?? `Object ${(idx + 1).toString()}` },
|
||||
[
|
||||
schemaElement('element', noRef(s), {
|
||||
...ctx,
|
||||
parseObject: true,
|
||||
required: false,
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if (isObject(schema) && !ctx.parseObject) {
|
||||
child.push(
|
||||
renderer.ObjectCollapsible({ name }, [
|
||||
schemaElement(name, schema, {
|
||||
render(name, schema, {
|
||||
...ctx,
|
||||
parseObject: true,
|
||||
required: false,
|
||||
}),
|
||||
]),
|
||||
);
|
||||
} else {
|
||||
const mentionedObjectTypes = [
|
||||
...(schema.anyOf ?? schema.oneOf ?? schema.allOf ?? []),
|
||||
...(schema.not ? [schema.not] : []),
|
||||
...(schema.type === 'array' ? [schema.items] : []),
|
||||
]
|
||||
.map(noRef)
|
||||
.filter((s) => isComplexType(s) && !ctx.stack.includes(s));
|
||||
|
||||
ctx.stack.push(schema);
|
||||
child.push(
|
||||
...mentionedObjectTypes.map((s, idx) =>
|
||||
renderer.ObjectCollapsible(
|
||||
{ name: s.title ?? `Object ${(idx + 1).toString()}` },
|
||||
[
|
||||
render('element', noRef(s), {
|
||||
...ctx,
|
||||
parseObject: true,
|
||||
required: false,
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
ctx.stack.pop();
|
||||
}
|
||||
|
||||
return renderer.Property(
|
||||
@@ -144,9 +160,16 @@ export function schemaElement(
|
||||
);
|
||||
}
|
||||
|
||||
function getSchemaType(schema: OpenAPI.SchemaObject): string {
|
||||
if (schema.title) return schema.title;
|
||||
/**
|
||||
* Check if the schema needs another collapsible to explain
|
||||
*/
|
||||
function isComplexType(schema: OpenAPI.SchemaObject): boolean {
|
||||
if (schema.anyOf ?? schema.oneOf ?? schema.allOf) return true;
|
||||
|
||||
return isObject(schema) || schema.type === 'array';
|
||||
}
|
||||
|
||||
function getSchemaType(schema: OpenAPI.SchemaObject): string {
|
||||
if (schema.nullable) {
|
||||
const type = getSchemaType({ ...schema, nullable: false });
|
||||
|
||||
@@ -154,8 +177,10 @@ function getSchemaType(schema: OpenAPI.SchemaObject): string {
|
||||
return type === 'unknown' ? 'null' : `${type} | null`;
|
||||
}
|
||||
|
||||
if (schema.title) return schema.title;
|
||||
|
||||
if (schema.type === 'array')
|
||||
return `array of ${getSchemaType(noRef(schema.items))}`;
|
||||
return `array<${getSchemaType(noRef(schema.items))}>`;
|
||||
|
||||
if (schema.oneOf)
|
||||
return schema.oneOf.map((one) => getSchemaType(noRef(one))).join(' | ');
|
||||
|
||||
@@ -215,7 +215,7 @@ Description of the special event
|
||||
|
||||
</Property>
|
||||
|
||||
<Property name={"dates"} type={"array of string"} required={true} deprecated={undefined}>
|
||||
<Property name={"dates"} type={"array<string>"} required={true} deprecated={undefined}>
|
||||
|
||||
List of planned dates for the special event
|
||||
|
||||
@@ -516,7 +516,7 @@ Description of the special event
|
||||
|
||||
</Property>
|
||||
|
||||
<Property name={"dates"} type={"array of string"} required={false} deprecated={undefined}>
|
||||
<Property name={"dates"} type={"array<string>"} required={false} deprecated={undefined}>
|
||||
|
||||
List of planned dates for the special event
|
||||
|
||||
|
||||
@@ -1138,7 +1138,7 @@ This is a place for dynamic meta data, anything that feels useful for you should
|
||||
|
||||
</Property>
|
||||
|
||||
<Property name={"roles"} type={"array of string"} required={false} deprecated={undefined}>
|
||||
<Property name={"roles"} type={"array<string>"} required={false} deprecated={undefined}>
|
||||
|
||||
A list of roles that this key should have. If the role does not exist, an error is thrown
|
||||
|
||||
@@ -1146,7 +1146,7 @@ A list of roles that this key should have. If the role does not exist, an error
|
||||
|
||||
</Property>
|
||||
|
||||
<Property name={"permissions"} type={"array of string"} required={false} deprecated={undefined}>
|
||||
<Property name={"permissions"} type={"array<string>"} required={false} deprecated={undefined}>
|
||||
|
||||
A list of permissions that this key should have. If the permission does not exist, an error is thrown
|
||||
|
||||
@@ -1790,7 +1790,7 @@ A query for which permissions you require
|
||||
|
||||
<ObjectCollapsible name={"And"}>
|
||||
|
||||
<Property name={"and"} type={"array of LiteralClause | And | Or | null"} required={true} deprecated={undefined}>
|
||||
<Property name={"and"} type={"array<LiteralClause | And | Or | null>"} required={true} deprecated={undefined}>
|
||||
|
||||
</Property>
|
||||
|
||||
@@ -1798,7 +1798,7 @@ A query for which permissions you require
|
||||
|
||||
<ObjectCollapsible name={"Or"}>
|
||||
|
||||
<Property name={"or"} type={"array of LiteralClause | And | Or | null"} required={true} deprecated={undefined}>
|
||||
<Property name={"or"} type={"array<LiteralClause | And | Or | null>"} required={true} deprecated={undefined}>
|
||||
|
||||
</Property>
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ In: `header`
|
||||
|
||||
### Request Body
|
||||
|
||||
<Property name={"body"} type={"array of object"} required={true} deprecated={undefined}>
|
||||
<Property name={"body"} type={"array<object>"} required={true} deprecated={undefined}>
|
||||
|
||||
<ObjectCollapsible name={"Object 1"}>
|
||||
|
||||
@@ -119,7 +119,7 @@ This is a place for dynamic meta data, anything that feels useful for you should
|
||||
|
||||
</Property>
|
||||
|
||||
<Property name={"roles"} type={"array of string"} required={false} deprecated={undefined}>
|
||||
<Property name={"roles"} type={"array<string>"} required={false} deprecated={undefined}>
|
||||
|
||||
A list of roles that this key should have. If the role does not exist, an error is thrown
|
||||
|
||||
@@ -127,7 +127,7 @@ A list of roles that this key should have. If the role does not exist, an error
|
||||
|
||||
</Property>
|
||||
|
||||
<Property name={"permissions"} type={"array of string"} required={false} deprecated={undefined}>
|
||||
<Property name={"permissions"} type={"array<string>"} required={false} deprecated={undefined}>
|
||||
|
||||
A list of permissions that this key should have. If the permission does not exist, an error is thrown
|
||||
|
||||
@@ -762,7 +762,7 @@ The id of the api, you want to migrate keys to
|
||||
|
||||
</Property>
|
||||
|
||||
<Property name={"keys"} type={"array of object"} required={true} deprecated={undefined}>
|
||||
<Property name={"keys"} type={"array<object>"} required={true} deprecated={undefined}>
|
||||
|
||||
<ObjectCollapsible name={"Object 1"}>
|
||||
|
||||
@@ -850,7 +850,7 @@ This is a place for dynamic meta data, anything that feels useful for you should
|
||||
|
||||
</Property>
|
||||
|
||||
<Property name={"roles"} type={"array of string"} required={false} deprecated={undefined}>
|
||||
<Property name={"roles"} type={"array<string>"} required={false} deprecated={undefined}>
|
||||
|
||||
A list of roles that this key should have. If the role does not exist, an error is thrown
|
||||
|
||||
@@ -858,7 +858,7 @@ A list of roles that this key should have. If the role does not exist, an error
|
||||
|
||||
</Property>
|
||||
|
||||
<Property name={"permissions"} type={"array of string"} required={false} deprecated={undefined}>
|
||||
<Property name={"permissions"} type={"array<string>"} required={false} deprecated={undefined}>
|
||||
|
||||
A list of permissions that this key should have. If the permission does not exist, an error is thrown
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ Attach any metadata to this request
|
||||
|
||||
</Property>
|
||||
|
||||
<Property name={"resources"} type={"array of object"} required={false} deprecated={undefined}>
|
||||
<Property name={"resources"} type={"array<object>"} required={false} deprecated={undefined}>
|
||||
|
||||
Resources that are about to be accessed by the user
|
||||
|
||||
|
||||
Reference in New Issue
Block a user