mirror of
https://github.com/Redocly/redoc.git
synced 2024-11-26 10:33:44 +03:00
Fix search inside circular discriminators
This commit is contained in:
parent
6e13acbc64
commit
c52703f1ed
|
@ -64,7 +64,8 @@ export class JsonSchemaLazy implements OnDestroy, OnInit, AfterViewInit {
|
|||
|
||||
// skip caching view with descendant schemas
|
||||
// as it needs attached controller
|
||||
if (!this.disableLazy && (compRef.instance.hasDescendants || compRef.instance._hasSubSchemas)) {
|
||||
let hasDescendants = compRef.instance.descendants && compRef.instance.descendants.length;
|
||||
if (!this.disableLazy && (hasDescendants || compRef.instance._hasSubSchemas)) {
|
||||
this._loadAfterSelf();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ export class JsonSchema extends BaseSearchableComponent implements OnInit {
|
|||
|
||||
schema: any = {};
|
||||
activeDescendant:any = {};
|
||||
hasDescendants: boolean = false;
|
||||
discriminator: string = null;
|
||||
_hasSubSchemas: boolean = false;
|
||||
properties: any;
|
||||
_isArray: boolean;
|
||||
|
@ -75,8 +75,7 @@ export class JsonSchema extends BaseSearchableComponent implements OnInit {
|
|||
initDescendants() {
|
||||
this.descendants = this.specMgr.findDerivedDefinitions(this.normPointer, this.schema);
|
||||
if (!this.descendants.length) return;
|
||||
this.hasDescendants = true;
|
||||
let discriminator = this.schema.discriminator || this.schema['x-extendedDiscriminator'];
|
||||
let discriminator = this.discriminator = this.schema.discriminator || this.schema['x-extendedDiscriminator'];
|
||||
let discrProperty = this.schema.properties &&
|
||||
this.schema.properties[discriminator];
|
||||
if (discrProperty && discrProperty.enum) {
|
||||
|
@ -91,6 +90,7 @@ export class JsonSchema extends BaseSearchableComponent implements OnInit {
|
|||
}).sort((a, b) => {
|
||||
return enumOrder[a.name] > enumOrder[b.name] ? 1 : -1;
|
||||
});
|
||||
this.descendants.forEach((d, idx) => d.idx = idx);
|
||||
}
|
||||
this.selectDescendantByIdx(0);
|
||||
}
|
||||
|
@ -119,11 +119,12 @@ export class JsonSchema extends BaseSearchableComponent implements OnInit {
|
|||
|
||||
if (!this.schema.isTrivial) {
|
||||
SchemaHelper.preprocessProperties(this.schema, this.normPointer, {
|
||||
childFor: this.childFor
|
||||
childFor: this.childFor,
|
||||
discriminator: this.discriminator
|
||||
});
|
||||
}
|
||||
|
||||
this.properties = this.schema._properties;
|
||||
this.properties = this.schema._properties || [];
|
||||
if (this.isRequestSchema) {
|
||||
this.properties = this.properties && this.properties.filter(prop => !prop.readOnly);
|
||||
}
|
||||
|
|
|
@ -6,22 +6,6 @@ import { Subscription } from 'rxjs/Subscription';
|
|||
|
||||
export { SpecManager };
|
||||
|
||||
function snapshot(obj) {
|
||||
if(obj == undefined || typeof(obj) !== 'object') {
|
||||
return obj;
|
||||
}
|
||||
|
||||
var temp = new obj.constructor();
|
||||
|
||||
for(var key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
temp[key] = snapshot(obj[key]);
|
||||
}
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic Component
|
||||
* @class
|
||||
|
|
|
@ -7,6 +7,7 @@ import * as slugify from 'slugify';
|
|||
interface PropertyPreprocessOptions {
|
||||
childFor: string;
|
||||
skipReadOnly?: boolean;
|
||||
discriminator?: string;
|
||||
}
|
||||
|
||||
// global var for this module
|
||||
|
@ -220,8 +221,7 @@ export class SchemaHelper {
|
|||
propertySchema._pointer = null;
|
||||
}
|
||||
propertySchema._required = !!requiredMap[propName];
|
||||
propertySchema.isDiscriminator = (schema.discriminator === propName
|
||||
|| schema['x-extendedDiscriminator'] === propName);
|
||||
propertySchema.isDiscriminator = opts.discriminator === propName;
|
||||
return propertySchema;
|
||||
});
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ export class SchemaNormalizer {
|
|||
let hasPtr = !!schema.$ref;
|
||||
if (opts.resolved && !hasPtr) this._dereferencer.visit(ptr);
|
||||
|
||||
if (opts.childFor) this._dereferencer.visit(opts.childFor);
|
||||
if (schema['x-redoc-normalized']) return schema;
|
||||
let res = SchemaWalker.walk(schema, ptr, (subSchema, ptr) => {
|
||||
let resolved = this._dereferencer.dereference(subSchema, ptr);
|
||||
|
@ -38,6 +39,7 @@ export class SchemaNormalizer {
|
|||
return resolved;
|
||||
});
|
||||
if (opts.resolved && !hasPtr) this._dereferencer.exit(ptr);
|
||||
if (opts.childFor) this._dereferencer.exit(opts.childFor);
|
||||
res['x-redoc-normalized'] = true;
|
||||
return res;
|
||||
}
|
||||
|
@ -113,6 +115,7 @@ export class AllOfMerger {
|
|||
defaults(into, subSchema);
|
||||
subSchema._pointer = tmpPtr;
|
||||
}
|
||||
into.discriminator = null;
|
||||
into.allOf = null;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { AppStateService } from './app-state.service';
|
||||
import { SchemaNormalizer } from './schema-normalizer.service';
|
||||
import { JsonPointer, groupBy, SpecManager, StringMap } from '../utils/';
|
||||
import { JsonPointer, groupBy, SpecManager, StringMap, snapshot } from '../utils/';
|
||||
|
||||
import * as lunr from 'lunr';
|
||||
|
||||
|
@ -13,7 +13,7 @@ interface IndexElement {
|
|||
}
|
||||
|
||||
const index = lunr(function () {
|
||||
this.field('menuId', {boost: 0});
|
||||
//this.field('menuId', {boost: 0});
|
||||
this.field('title', {boost: 1.5});
|
||||
this.field('body');
|
||||
this.ref('pointer');
|
||||
|
@ -33,13 +33,13 @@ export class SearchService {
|
|||
}
|
||||
|
||||
indexAll() {
|
||||
const swagger = this.spec.schema;
|
||||
|
||||
this.indexPaths(swagger);
|
||||
this.indexPaths(this.spec.schema);
|
||||
}
|
||||
|
||||
search(q):StringMap<IndexElement[]> {
|
||||
var items = {};
|
||||
const res:IndexElement[] = index.search(q).map(res => {
|
||||
items[res.menuId] = res;
|
||||
return store[res.ref];
|
||||
});
|
||||
const grouped = groupBy(res, 'menuId');
|
||||
|
@ -79,6 +79,7 @@ export class SearchService {
|
|||
|
||||
indexOperationParameters(operation: any, operationPointer: string) {
|
||||
const parameters = operation.parameters;
|
||||
if (!parameters) return;
|
||||
for (let i=0; i<parameters.length; ++i) {
|
||||
const param = parameters[i];
|
||||
const paramPointer = JsonPointer.join(operationPointer, ['parameters', i]);
|
||||
|
@ -90,6 +91,7 @@ export class SearchService {
|
|||
});
|
||||
|
||||
if (param.in === 'body') {
|
||||
this.normalizer.reset();
|
||||
this.indexSchema(param.schema, '', JsonPointer.join(paramPointer, ['schema']), operationPointer);
|
||||
}
|
||||
}
|
||||
|
@ -109,18 +111,17 @@ export class SearchService {
|
|||
});
|
||||
|
||||
if (resp.schema) {
|
||||
this.normalizer.reset();
|
||||
this.indexSchema(resp.schema, '', JsonPointer.join(respPtr, 'schema'), operationPtr);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
indexSchema(_schema:any, name: string, absolutePointer: string, menuPointer: string) {
|
||||
indexSchema(_schema:any, name: string, absolutePointer: string, menuPointer: string, parent?: string) {
|
||||
if (!_schema) return;
|
||||
let schema = _schema;
|
||||
let title = name;
|
||||
|
||||
this.normalizer.reset();
|
||||
schema = this.normalizer.normalize(schema, schema._pointer || absolutePointer);
|
||||
schema = this.normalizer.normalize(schema, schema._pointer || absolutePointer, { childFor: parent });
|
||||
|
||||
let body = schema.description; // TODO: defaults, examples, etc...
|
||||
|
||||
|
@ -129,11 +130,11 @@ export class SearchService {
|
|||
return;
|
||||
}
|
||||
|
||||
if (schema.discriminator && !schema['x-derived-from']) {
|
||||
if (schema.discriminator) {
|
||||
let derived = this.spec.findDerivedDefinitions(schema._pointer, schema);
|
||||
for (let defInfo of derived ) {
|
||||
let subSpec = this.spec.getDescendant(defInfo, schema);
|
||||
this.indexSchema(subSpec, '', absolutePointer, menuPointer);
|
||||
this.indexSchema(snapshot(subSpec), '', absolutePointer, menuPointer, schema._pointer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -94,3 +94,19 @@ export function throttle(fn, threshhold, scope) {
|
|||
export const isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0
|
||||
|| (function (p) { return p.toString() === '[object SafariRemoteNotification]'; })(!window['safari']
|
||||
|| safari.pushNotification);
|
||||
|
||||
export function snapshot(obj) {
|
||||
if(obj == undefined || typeof(obj) !== 'object') {
|
||||
return obj;
|
||||
}
|
||||
|
||||
var temp = new obj.constructor();
|
||||
|
||||
for(var key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
temp[key] = snapshot(obj[key]);
|
||||
}
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ export class SpecManager {
|
|||
if (!definition.discriminator && !definition['x-extendedDiscriminator']) return [];
|
||||
|
||||
let globalDefs = this._schema.definitions || {};
|
||||
let res = [];
|
||||
let res:DescendantInfo[] = [];
|
||||
let extendedDiscriminatorProp = definition['x-extendedDiscriminator'];
|
||||
for (let defName of Object.keys(globalDefs)) {
|
||||
let def = globalDefs[defName];
|
||||
|
@ -208,7 +208,7 @@ export class SpecManager {
|
|||
}
|
||||
}
|
||||
|
||||
res.push({name: derivedName, $ref: `#/definitions/${defName}`, idx: res.length});
|
||||
res.push({name: derivedName, $ref: `#/definitions/${defName}`, idx: null});
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user