mirror of
https://github.com/LukeHagar/redocly-cli.git
synced 2025-12-10 04:21:20 +00:00
fix: visit and bundle discriminator mappings (#90)
This commit is contained in:
@@ -92,6 +92,11 @@ function traverseNode(node, definition, ctx, visited = []) {
|
|||||||
|
|
||||||
const resolvedDefinition = resolveDefinition(definition, ctx, nodeContext.resolvedNode);
|
const resolvedDefinition = resolveDefinition(definition, ctx, nodeContext.resolvedNode);
|
||||||
resolveScalars(nodeContext.resolvedNode, definition, ctx);
|
resolveScalars(nodeContext.resolvedNode, definition, ctx);
|
||||||
|
|
||||||
|
if (definition.customResolveFields) {
|
||||||
|
definition.customResolveFields(nodeContext.resolvedNode, ctx, visited);
|
||||||
|
}
|
||||||
|
|
||||||
if (Array.isArray(nodeContext.resolvedNode)) {
|
if (Array.isArray(nodeContext.resolvedNode)) {
|
||||||
nodeContext.resolvedNode.forEach((nodeChild, i) => {
|
nodeContext.resolvedNode.forEach((nodeChild, i) => {
|
||||||
ctx.path.push(i);
|
ctx.path.push(i);
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/* eslint-disable import/no-cycle */
|
||||||
|
import traverseNode from '../traverse';
|
||||||
|
import OpenAPISchema from './OpenAPISchema';
|
||||||
|
|
||||||
|
export const MAPPING_DATA_KEY = 'x-openapiCli_resolveMappingData';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'OpenAPIDiscriminator',
|
name: 'OpenAPIDiscriminator',
|
||||||
isIdempotent: true,
|
isIdempotent: true,
|
||||||
@@ -5,4 +11,26 @@ export default {
|
|||||||
propertyName: null,
|
propertyName: null,
|
||||||
mapping: null,
|
mapping: null,
|
||||||
},
|
},
|
||||||
|
customResolveFields: (node, ctx, visited) => {
|
||||||
|
if (node && node.mapping && typeof node.mapping === 'object') {
|
||||||
|
ctx.path.push('mapping');
|
||||||
|
for (const key of Object.keys(node.mapping)) {
|
||||||
|
ctx.path.push(key);
|
||||||
|
traverseNode(
|
||||||
|
{
|
||||||
|
$ref: node.mapping[key],
|
||||||
|
[MAPPING_DATA_KEY]: { // FIXME: too hacky
|
||||||
|
mapping: node.mapping,
|
||||||
|
key,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
OpenAPISchema,
|
||||||
|
ctx,
|
||||||
|
visited,
|
||||||
|
);
|
||||||
|
ctx.path.pop();
|
||||||
|
}
|
||||||
|
ctx.path.pop();
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import isEqual from 'lodash.isequal';
|
|||||||
|
|
||||||
import { getMsgLevelFromString, messageLevels } from '../error/default';
|
import { getMsgLevelFromString, messageLevels } from '../error/default';
|
||||||
import OpenAPISchemaObject from '../types/OpenAPISchema';
|
import OpenAPISchemaObject from '../types/OpenAPISchema';
|
||||||
|
import { MAPPING_DATA_KEY } from '../types/OpenAPIDiscriminator';
|
||||||
import { isRef } from '../utils';
|
import { isRef } from '../utils';
|
||||||
|
|
||||||
const getComponentName = (refString, components, componentType, node, ctx) => {
|
const getComponentName = (refString, components, componentType, node, ctx) => {
|
||||||
@@ -90,7 +91,7 @@ class Bundler {
|
|||||||
const $ref = `#/${pointer.join('/')}`;
|
const $ref = `#/${pointer.join('/')}`;
|
||||||
const errors = [];
|
const errors = [];
|
||||||
|
|
||||||
for (const [name, schema] of Object.entries(schemas)) {
|
for (const [name, schema] of Object.entries(schemas || {})) {
|
||||||
if (schema.allOf && schema.allOf.find((s) => s.$ref === $ref)) {
|
if (schema.allOf && schema.allOf.find((s) => s.$ref === $ref)) {
|
||||||
const existingSchema = this.components.schemas && this.components.schemas[name];
|
const existingSchema = this.components.schemas && this.components.schemas[name];
|
||||||
if (existingSchema && !isEqual(existingSchema, schema)) {
|
if (existingSchema && !isEqual(existingSchema, schema)) {
|
||||||
@@ -123,7 +124,7 @@ class Bundler {
|
|||||||
onExit: (node, definition, ctx, unresolvedNode, { traverseNode, visited }) => {
|
onExit: (node, definition, ctx, unresolvedNode, { traverseNode, visited }) => {
|
||||||
let errors = [];
|
let errors = [];
|
||||||
|
|
||||||
if (node.discriminator && !node.oneOf && !node.anyOf) {
|
if (node.discriminator && !node.oneOf && !node.anyOf && !node.mapping) {
|
||||||
errors = this.includeImplicitDiscriminator(
|
errors = this.includeImplicitDiscriminator(
|
||||||
ctx.path,
|
ctx.path,
|
||||||
ctx.document.components && ctx.document.components.schemas,
|
ctx.document.components && ctx.document.components.schemas,
|
||||||
@@ -153,9 +154,15 @@ class Bundler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.components[componentType][name] = node;
|
this.components[componentType][name] = node;
|
||||||
|
|
||||||
|
if (unresolvedNode[MAPPING_DATA_KEY]) { // FIXME: too hack
|
||||||
|
const { mapping, key } = unresolvedNode[MAPPING_DATA_KEY];
|
||||||
|
mapping[key] = newRef;
|
||||||
|
} else {
|
||||||
unresolvedNode.$ref = newRef;
|
unresolvedNode.$ref = newRef;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
errors.forEach((e) => {
|
errors.forEach((e) => {
|
||||||
e.severity = this.nameConflictsSeverity;
|
e.severity = this.nameConflictsSeverity;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
import { MAPPING_DATA_KEY } from '../../../types/OpenAPIDiscriminator';
|
||||||
|
|
||||||
class NoRefSiblings {
|
class NoRefSiblings {
|
||||||
static get rule() {
|
static get rule() {
|
||||||
@@ -29,7 +30,7 @@ class NoRefSiblings {
|
|||||||
ctx.source = fs.readFileSync(prevPathItem.file, 'utf-8');
|
ctx.source = fs.readFileSync(prevPathItem.file, 'utf-8');
|
||||||
|
|
||||||
for (let i = 0; i < nodeKeys.length; i++) {
|
for (let i = 0; i < nodeKeys.length; i++) {
|
||||||
if (nodeKeys[i] !== '$ref') {
|
if (nodeKeys[i] !== '$ref' && nodeKeys[i] !== MAPPING_DATA_KEY) {
|
||||||
ctx.path.push(nodeKeys[i]);
|
ctx.path.push(nodeKeys[i]);
|
||||||
const e = ctx.createError(
|
const e = ctx.createError(
|
||||||
'No siblings are allowed inside object with $ref property.',
|
'No siblings are allowed inside object with $ref property.',
|
||||||
|
|||||||
Reference in New Issue
Block a user