mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-12 05:48:57 +00:00
Merge simple alternatives (#3165)
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@gitbook/react-openapi": patch
|
||||
---
|
||||
|
||||
Merge simple alternatives
|
||||
@@ -35,6 +35,86 @@ describe('getSchemaAlternatives', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('merges string enum', () => {
|
||||
expect(
|
||||
getSchemaAlternatives({
|
||||
oneOf: [
|
||||
{
|
||||
oneOf: [
|
||||
{
|
||||
type: 'string',
|
||||
enum: ['a', 'b'],
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
enum: ['c', 'd'],
|
||||
nullable: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
).toEqual([
|
||||
{
|
||||
type: 'string',
|
||||
enum: ['a', 'b', 'c', 'd'],
|
||||
nullable: true,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('merges objects with allOf', () => {
|
||||
expect(
|
||||
getSchemaAlternatives({
|
||||
allOf: [
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
},
|
||||
map: {
|
||||
type: 'string',
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
required: ['name'],
|
||||
},
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
externalId: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
required: ['map', 'externalId'],
|
||||
},
|
||||
],
|
||||
})
|
||||
).toEqual([
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
},
|
||||
map: {
|
||||
type: 'string',
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
},
|
||||
externalId: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
required: ['name', 'map', 'externalId'],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not flatten oneOf and allOf', () => {
|
||||
expect(
|
||||
getSchemaAlternatives({
|
||||
|
||||
@@ -450,7 +450,91 @@ export function getSchemaAlternatives(
|
||||
}
|
||||
|
||||
const [type, schemas] = alternatives;
|
||||
return flattenAlternatives(type, schemas, new Set(ancestors).add(schema));
|
||||
return mergeAlternatives(
|
||||
type,
|
||||
flattenAlternatives(type, schemas, new Set(ancestors).add(schema))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge alternatives of the same type into a single schema.
|
||||
* - Merge string enums
|
||||
*/
|
||||
function mergeAlternatives(
|
||||
alternativeType: AlternativeType,
|
||||
schemasOrRefs: OpenAPIV3.SchemaObject[]
|
||||
): OpenAPIV3.SchemaObject[] | null {
|
||||
switch (alternativeType) {
|
||||
case 'oneOf': {
|
||||
return schemasOrRefs.reduce<OpenAPIV3.SchemaObject[]>((acc, schemaOrRef) => {
|
||||
const latest = acc.at(-1);
|
||||
|
||||
if (
|
||||
latest &&
|
||||
latest.type === 'string' &&
|
||||
latest.enum &&
|
||||
schemaOrRef.type === 'string' &&
|
||||
schemaOrRef.enum
|
||||
) {
|
||||
latest.enum = Array.from(new Set([...latest.enum, ...schemaOrRef.enum]));
|
||||
latest.nullable = latest.nullable || schemaOrRef.nullable;
|
||||
return acc;
|
||||
}
|
||||
|
||||
acc.push(schemaOrRef);
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
case 'allOf': {
|
||||
return schemasOrRefs.reduce<OpenAPIV3.SchemaObject[]>((acc, schemaOrRef) => {
|
||||
const latest = acc.at(-1);
|
||||
|
||||
if (
|
||||
latest &&
|
||||
latest.type === 'string' &&
|
||||
latest.enum &&
|
||||
schemaOrRef.type === 'string' &&
|
||||
schemaOrRef.enum
|
||||
) {
|
||||
const keys = Object.keys(schemaOrRef);
|
||||
if (keys.every((key) => ['type', 'enum', 'nullable'].includes(key))) {
|
||||
latest.enum = Array.from(new Set([...latest.enum, ...schemaOrRef.enum]));
|
||||
latest.nullable = latest.nullable || schemaOrRef.nullable;
|
||||
return acc;
|
||||
}
|
||||
}
|
||||
|
||||
if (latest && latest.type === 'object' && schemaOrRef.type === 'object') {
|
||||
const keys = Object.keys(schemaOrRef);
|
||||
if (
|
||||
keys.every((key) =>
|
||||
['type', 'properties', 'required', 'nullable'].includes(key)
|
||||
)
|
||||
) {
|
||||
latest.properties = {
|
||||
...latest.properties,
|
||||
...schemaOrRef.properties,
|
||||
};
|
||||
latest.required = Array.from(
|
||||
new Set([
|
||||
...(Array.isArray(latest.required) ? latest.required : []),
|
||||
...(Array.isArray(schemaOrRef.required)
|
||||
? schemaOrRef.required
|
||||
: []),
|
||||
])
|
||||
);
|
||||
latest.nullable = latest.nullable || schemaOrRef.nullable;
|
||||
return acc;
|
||||
}
|
||||
}
|
||||
|
||||
acc.push(schemaOrRef);
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
default:
|
||||
return schemasOrRefs;
|
||||
}
|
||||
}
|
||||
|
||||
function flattenAlternatives(
|
||||
|
||||
Reference in New Issue
Block a user