mirror of
https://github.com/Redocly/redoc.git
synced 2025-08-07 13:44:54 +03:00
feat: add basic support openApi 3.1
This commit is contained in:
parent
e03c4e86d0
commit
c342f6f0f5
|
@ -6,7 +6,7 @@ describe('Menu', () => {
|
|||
it('should have valid items count', () => {
|
||||
cy.get('.menu-content')
|
||||
.find('li')
|
||||
.should('have.length', 34);
|
||||
.should('have.length', 33);
|
||||
});
|
||||
|
||||
it('should sync active menu items while scroll', () => {
|
||||
|
|
12
package-lock.json
generated
12
package-lock.json
generated
|
@ -1222,9 +1222,9 @@
|
|||
}
|
||||
},
|
||||
"@redocly/openapi-core": {
|
||||
"version": "1.0.0-beta.44",
|
||||
"resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.0.0-beta.44.tgz",
|
||||
"integrity": "sha512-9HNnh1MzvMsLK1liuidFBqWiAsZ2Yg3RY58fcEsy0QruSMdDbn7SoeI1qnXe6O+BkBS+vAP4oVzZDMHCMKGsOQ==",
|
||||
"version": "1.0.0-beta.46",
|
||||
"resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.0.0-beta.46.tgz",
|
||||
"integrity": "sha512-w4VG2KNLFDuZgN7fBmbzbI0GJDiPnJ0SYszj4uuSkMW35SVTvDWyTaeWjW8ggQJ3gluDnTgUvm9tjLdR2tLqUg==",
|
||||
"requires": {
|
||||
"@redocly/ajv": "^6.12.3",
|
||||
"@types/node": "^14.11.8",
|
||||
|
@ -1238,9 +1238,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "14.14.37",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.37.tgz",
|
||||
"integrity": "sha512-XYmBiy+ohOR4Lh5jE379fV2IU+6Jn4g5qASinhitfyO71b/sCo6MKsMLF5tc7Zf2CE8hViVQyYSobJNke8OvUw=="
|
||||
"version": "14.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.0.tgz",
|
||||
"integrity": "sha512-w8VZUN/f7SSbvVReb9SWp6cJFevxb4/nkG65yLAya//98WgocKm5PLDAtSs5CtJJJM+kHmJjO/6mmYW4MHShZA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -134,7 +134,7 @@
|
|||
"styled-components": "^4.1.1 || ^5.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@redocly/openapi-core": "^1.0.0-beta.44",
|
||||
"@redocly/openapi-core": "^1.0.0-beta.45",
|
||||
"@redocly/react-dropdown-aria": "^2.0.11",
|
||||
"@types/node": "^13.11.1",
|
||||
"classnames": "^2.2.6",
|
||||
|
|
|
@ -61,11 +61,6 @@ export const RecursiveLabel = styled(FieldLabel)`
|
|||
font-size: 13px;
|
||||
`;
|
||||
|
||||
export const NullableLabel = styled(FieldLabel)`
|
||||
color: #0e7c86;
|
||||
font-size: 13px;
|
||||
`;
|
||||
|
||||
export const PatternLabel = styled(FieldLabel)`
|
||||
color: #0e7c86;
|
||||
&::before,
|
||||
|
|
|
@ -8,7 +8,7 @@ import { RedocRawOptions } from '../../services/RedocNormalizedOptions';
|
|||
|
||||
export interface EnumValuesProps {
|
||||
values: string[];
|
||||
type: string;
|
||||
type: string | string[];
|
||||
}
|
||||
|
||||
export interface EnumValuesState {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import * as React from 'react';
|
||||
|
||||
import {
|
||||
NullableLabel,
|
||||
PatternLabel,
|
||||
RecursiveLabel,
|
||||
TypeFormat,
|
||||
|
@ -79,7 +78,6 @@ export class FieldDetails extends React.PureComponent<FieldProps, { patternShown
|
|||
)}
|
||||
{schema.title && !hideSchemaTitles && <TypeTitle> ({schema.title}) </TypeTitle>}
|
||||
<ConstraintsView constraints={schema.constraints} />
|
||||
{schema.nullable && <NullableLabel> {l('nullable')} </NullableLabel>}
|
||||
{schema.pattern && !hideSchemaPattern && (
|
||||
<>
|
||||
<PatternLabel>
|
||||
|
|
|
@ -39,7 +39,7 @@ export class Redoc extends React.Component<RedocProps> {
|
|||
const store = this.props.store;
|
||||
return (
|
||||
<ThemeProvider theme={options.theme}>
|
||||
<StoreProvider value={this.props.store}>
|
||||
<StoreProvider value={store}>
|
||||
<OptionsProvider value={options}>
|
||||
<RedocWrap className="redoc-wrap">
|
||||
<StickyResponsiveSidebar menu={menu} className="menu-content">
|
||||
|
|
|
@ -29,7 +29,6 @@ exports[`Components SchemaView discriminator should correctly render discriminat
|
|||
"format": undefined,
|
||||
"isCircular": undefined,
|
||||
"isPrimitive": true,
|
||||
"nullable": false,
|
||||
"options": "<<<filtered>>>",
|
||||
"pattern": undefined,
|
||||
"pointer": "#/components/schemas/Dog/properties/packSize",
|
||||
|
@ -79,7 +78,6 @@ exports[`Components SchemaView discriminator should correctly render discriminat
|
|||
"format": undefined,
|
||||
"isCircular": undefined,
|
||||
"isPrimitive": true,
|
||||
"nullable": false,
|
||||
"options": "<<<filtered>>>",
|
||||
"pattern": undefined,
|
||||
"pointer": "#/components/schemas/Dog/properties/type",
|
||||
|
|
|
@ -6,7 +6,6 @@ export interface LabelsConfig {
|
|||
deprecated: string;
|
||||
example: string;
|
||||
examples: string;
|
||||
nullable: string;
|
||||
recursive: string;
|
||||
arrayOf: string;
|
||||
webhook: string;
|
||||
|
@ -22,7 +21,6 @@ const labels: LabelsConfig = {
|
|||
deprecated: 'Deprecated',
|
||||
example: 'Example',
|
||||
examples: 'Examples',
|
||||
nullable: 'Nullable',
|
||||
recursive: 'Recursive',
|
||||
arrayOf: 'Array of ',
|
||||
webhook: 'Event',
|
||||
|
|
|
@ -220,10 +220,11 @@ export class MenuBuilder {
|
|||
for (const tag of spec.tags || []) {
|
||||
tags[tag.name] = { ...tag, operations: [] };
|
||||
}
|
||||
|
||||
if (spec.paths){
|
||||
getTags(spec.paths);
|
||||
if (spec['x-webhooks']) {
|
||||
getTags(spec['x-webhooks'], true);
|
||||
}
|
||||
if (spec.webhooks) {
|
||||
getTags(spec.webhooks, true);
|
||||
}
|
||||
|
||||
function getTags(paths: OpenAPIPaths, isWebhook?: boolean) {
|
||||
|
|
|
@ -25,7 +25,7 @@ import { l } from '../Labels';
|
|||
export class SchemaModel {
|
||||
pointer: string;
|
||||
|
||||
type: string;
|
||||
type: string | string[];
|
||||
displayType: string;
|
||||
typePrefix: string = '';
|
||||
title: string;
|
||||
|
@ -77,11 +77,6 @@ export class SchemaModel {
|
|||
this.pointer = schemaOrRef.$ref || pointer || '';
|
||||
this.rawSchema = parser.deref(schemaOrRef);
|
||||
|
||||
if (Array.isArray(this.rawSchema.type)) {
|
||||
this.rawSchema.oneOf = this.rawSchema.type.map( type => ({type}));
|
||||
delete this.rawSchema.type;
|
||||
}
|
||||
|
||||
this.schema = parser.mergeAllOf(this.rawSchema, this.pointer, isChild);
|
||||
|
||||
this.init(parser, isChild);
|
||||
|
@ -110,9 +105,8 @@ export class SchemaModel {
|
|||
this.title =
|
||||
schema.title || (isNamedDefinition(this.pointer) && JsonPointer.baseName(this.pointer)) || '';
|
||||
this.description = schema.description || '';
|
||||
this.type = schema.type || detectType(schema);
|
||||
this.type = (Array.isArray(schema.type) && schema.type) || (schema.type || detectType(schema));
|
||||
this.format = schema.format;
|
||||
this.nullable = !!schema.nullable;
|
||||
this.enum = schema.enum || [];
|
||||
this.example = schema.example;
|
||||
this.deprecated = !!schema.deprecated;
|
||||
|
@ -120,13 +114,19 @@ export class SchemaModel {
|
|||
this.externalDocs = schema.externalDocs;
|
||||
|
||||
this.constraints = humanizeConstraints(schema);
|
||||
this.displayType = Array.isArray(this.type) ? this.type.join(' or ') : this.type;
|
||||
this.displayFormat = this.format;
|
||||
this.isPrimitive = isPrimitiveType(schema, this.type);
|
||||
this.default = schema.default;
|
||||
this.readOnly = !!schema.readOnly;
|
||||
this.writeOnly = !!schema.writeOnly;
|
||||
|
||||
if (!!schema.nullable) {
|
||||
if (Array.isArray(this.type)) this.type.push('null');
|
||||
else this.type = [this.type, 'null'];
|
||||
}
|
||||
|
||||
this.displayType = Array.isArray(this.type) ? this.type.join(' or ') : this.type;
|
||||
|
||||
if (this.isCircular) {
|
||||
return;
|
||||
}
|
||||
|
@ -144,8 +144,7 @@ export class SchemaModel {
|
|||
}
|
||||
|
||||
if (schema.oneOf !== undefined) {
|
||||
this.nullable = this.nullable || schema.oneOf.some(s => s.type === 'null');
|
||||
this.initOneOf(schema.oneOf.filter(s => s.type !== 'null'), parser);
|
||||
this.initOneOf(schema.oneOf, parser);
|
||||
this.oneOfType = 'One of';
|
||||
if (schema.anyOf !== undefined) {
|
||||
console.warn(
|
||||
|
@ -156,8 +155,7 @@ export class SchemaModel {
|
|||
}
|
||||
|
||||
if (schema.anyOf !== undefined) {
|
||||
this.nullable = this.nullable || schema.anyOf.some(s => s.type === 'null');
|
||||
this.initOneOf(schema.anyOf.filter(s => s.type !== 'null'), parser);
|
||||
this.initOneOf(schema.anyOf, parser);
|
||||
this.oneOfType = 'Any of';
|
||||
return;
|
||||
}
|
||||
|
|
3
src/types/open-api.d.ts
vendored
3
src/types/open-api.d.ts
vendored
|
@ -10,6 +10,7 @@ export interface OpenAPISpec {
|
|||
tags?: OpenAPITag[];
|
||||
externalDocs?: OpenAPIExternalDocumentation;
|
||||
'x-webhooks'?: OpenAPIPaths;
|
||||
webhooks?: OpenAPIPaths;
|
||||
}
|
||||
|
||||
export interface OpenAPIInfo {
|
||||
|
@ -107,7 +108,7 @@ export interface OpenAPIExample {
|
|||
|
||||
export interface OpenAPISchema {
|
||||
$ref?: string;
|
||||
type?: string;
|
||||
type?: string | string[];
|
||||
properties?: { [name: string]: OpenAPISchema };
|
||||
additionalProperties?: boolean | OpenAPISchema;
|
||||
description?: string;
|
||||
|
|
|
@ -174,6 +174,20 @@ describe('Utils', () => {
|
|||
expect(isPrimitiveType(schema)).toEqual(false);
|
||||
});
|
||||
|
||||
it('Should return false for array of strings', () => {
|
||||
const schema = {
|
||||
type: ['object', 'string'],
|
||||
};
|
||||
expect(isPrimitiveType(schema)).toEqual(false);
|
||||
});
|
||||
|
||||
it('Should return false for array of string which include the null value', () => {
|
||||
const schema = {
|
||||
type: ['object', 'string', 'null'],
|
||||
};
|
||||
expect(isPrimitiveType(schema)).toEqual(false);
|
||||
});
|
||||
|
||||
it('Should return false for array with non-empty objects', () => {
|
||||
const schema = {
|
||||
type: 'array',
|
||||
|
|
|
@ -96,7 +96,7 @@ const schemaKeywordTypes = {
|
|||
};
|
||||
|
||||
export function detectType(schema: OpenAPISchema): string {
|
||||
if (schema.type !== undefined) {
|
||||
if (schema.type !== undefined && !Array.isArray(schema.type)) {
|
||||
return schema.type;
|
||||
}
|
||||
const keywords = Object.keys(schemaKeywordTypes);
|
||||
|
@ -110,7 +110,7 @@ export function detectType(schema: OpenAPISchema): string {
|
|||
return 'any';
|
||||
}
|
||||
|
||||
export function isPrimitiveType(schema: OpenAPISchema, type: string | undefined = schema.type) {
|
||||
export function isPrimitiveType(schema: OpenAPISchema, type: string | string[] | undefined = schema.type) {
|
||||
if (schema.oneOf !== undefined || schema.anyOf !== undefined) {
|
||||
return false;
|
||||
}
|
||||
|
@ -128,6 +128,8 @@ export function isPrimitiveType(schema: OpenAPISchema, type: string | undefined
|
|||
return false;
|
||||
}
|
||||
|
||||
if (Array.isArray(type)) return false
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user