limit to only mapping when asked to and fix non-uniq mappings

This commit is contained in:
Mohamed Zenadi 2019-01-08 12:21:05 +01:00 committed by zeapo
parent e82e98ebbb
commit 05ea976c26
2 changed files with 44 additions and 20 deletions

View File

@ -1,12 +1,8 @@
import { action, observable } from 'mobx'; import { action, observable } from 'mobx';
import { OpenAPIExternalDocumentation, OpenAPISchema, Referenced } from '../../types';
import { OpenAPIParser } from '../OpenAPIParser';
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
import { FieldModel } from './Field';
import { MergedOpenAPISchema } from '../'; import { MergedOpenAPISchema } from '../';
import { OpenAPIExternalDocumentation, OpenAPISchema, Referenced } from '../../types';
import { import {
detectType, detectType,
extractExtensions, extractExtensions,
@ -21,6 +17,10 @@ import {
import { l } from '../Labels'; import { l } from '../Labels';
import { OpenAPIParser } from '../OpenAPIParser';
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
import { FieldModel } from './Field';
// TODO: refactor this model, maybe use getters instead of copying all the values // TODO: refactor this model, maybe use getters instead of copying all the values
export class SchemaModel { export class SchemaModel {
pointer: string; pointer: string;
@ -216,29 +216,52 @@ export class SchemaModel {
) { ) {
const discriminator = getDiscriminator(schema)!; const discriminator = getDiscriminator(schema)!;
this.discriminatorProp = discriminator.propertyName; this.discriminatorProp = discriminator.propertyName;
const derived = parser.findDerived([...(schema.parentRefs || []), this.pointer]); let derived: Dict<string> = {};
const mapping = discriminator.mapping || {};
// Defines if the mapping is exhaustive. This avoids having references
// that overlap with the mapping entries
let isLimitedToMapping = discriminator['x-limitToMapping'] || false;
// if there are no mappings, assume non-exhaustive
if (Object.keys(mapping).length === 0) {
isLimitedToMapping = false;
}
// when non-exhaustive, search for implicit references
if (!isLimitedToMapping) {
derived = parser.findDerived([...(schema.parentRefs || []), this.pointer]);
if (schema.oneOf) { if (schema.oneOf) {
for (const variant of schema.oneOf) { for (const variant of schema.oneOf) {
if (variant.$ref === undefined) { if (variant.$ref === undefined) {
continue; continue;
} }
const name = JsonPointer.baseName(variant.$ref); derived[variant.$ref] = JsonPointer.baseName(variant.$ref);
derived[variant.$ref] = name; }
} }
} }
const mapping = discriminator.mapping || {}; // concatenate the implict refs with the mapping ones
for (const name in mapping) { const mappingOneOf = Object.keys(mapping).map(name => {
derived[mapping[name]] = name; const ref = mapping[name];
// do not include implicit refs in the list when we have a mapped one
if (ref in derived) {
delete derived[ref];
} }
const refs = Object.keys(derived); const innerSchema = new SchemaModel(parser, parser.byRef(ref)!, ref, this.options, true);
this.oneOf = refs.map(ref => { innerSchema.title = name;
return innerSchema;
});
this.oneOf = mappingOneOf.concat(
Object.keys(derived).map(ref => {
const innerSchema = new SchemaModel(parser, parser.byRef(ref)!, ref, this.options, true); const innerSchema = new SchemaModel(parser, parser.byRef(ref)!, ref, this.options, true);
innerSchema.title = derived[ref]; innerSchema.title = derived[ref];
return innerSchema; return innerSchema;
}); }),
);
} }
} }

View File

@ -144,6 +144,7 @@ export interface OpenAPISchema {
export interface OpenAPIDiscriminator { export interface OpenAPIDiscriminator {
propertyName: string; propertyName: string;
mapping?: { [name: string]: string }; mapping?: { [name: string]: string };
'x-limitToMapping'?: boolean;
} }
export interface OpenAPIMediaType { export interface OpenAPIMediaType {