Skip to content

Commit

Permalink
fix(resolver): fix referenced elements not being traversed after upda…
Browse files Browse the repository at this point in the history
…ting them in OpenAPI 3.1

Refs #3520
  • Loading branch information
glowcloud committed May 17, 2024
1 parent fa77bfd commit 6a3a4e7
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ class OpenAPI3_1SwaggerClientDereferenceStrategy extends OpenAPI3_1DereferenceSt
options,
allowMetaPatches: this.allowMetaPatches,
ancestors: this.ancestors,
parameterMacro: this.parameterMacro,
modelPropertyMacro: this.modelPropertyMacro,
mode: this.mode,
});
visitors.push(dereferenceVisitor);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
toValue,
cloneShallow,
cloneDeep,
mergeAllVisitors,
} from '@swagger-api/apidom-core';
import { ApiDOMError } from '@swagger-api/apidom-error';
import {
Expand Down Expand Up @@ -50,6 +51,9 @@ import toPath from '../utils/to-path.js';
import getRootCause from '../utils/get-root-cause.js';
import specMapMod from '../../../../../../specmap/lib/refs.js';
import SchemaRefError from '../errors/SchemaRefError.js';
import ParameterMacroVisitor from './parameters.js';
import ModelPropertyMacroVisitor from './properties.js';
import AllOfVisitor from './all-of.js';

const { wrapError } = specMapMod;

Expand All @@ -65,17 +69,29 @@ class OpenAPI3_1SwaggerClientDereferenceVisitor extends OpenAPI3_1DereferenceVis

basePath;

parameterMacro;

modelPropertyMacro;

mode;

constructor({
allowMetaPatches = true,
useCircularStructures = false,
basePath = null,
parameterMacro = null,
modelPropertyMacro = null,
mode = '',
...rest
}) {
super(rest);

this.allowMetaPatches = allowMetaPatches;
this.useCircularStructures = useCircularStructures;
this.basePath = basePath;
this.parameterMacro = parameterMacro;
this.modelPropertyMacro = modelPropertyMacro;
this.mode = mode;
}

async ReferenceElement(referencingElement, key, parent, path, ancestors) {
Expand Down Expand Up @@ -770,6 +786,44 @@ class OpenAPI3_1SwaggerClientDereferenceVisitor extends OpenAPI3_1DereferenceVis
referencedElement = mergedElement;
}

/**
* Traverse the referencedElement with other visitors
*/
const visitors = [];
const options = { ...this.options };

// create parameter macro visitor (if necessary)
if (typeof this.parameterMacro === 'function') {
const parameterMacroVisitor = new ParameterMacroVisitor({
parameterMacro: this.parameterMacro,
options,
});
visitors.push(parameterMacroVisitor);
}

// create model property macro visitor (if necessary)
if (typeof this.modelPropertyMacro === 'function') {
const modelPropertyMacroVisitor = new ModelPropertyMacroVisitor({
modelPropertyMacro: this.modelPropertyMacro,
options,
});
visitors.push(modelPropertyMacroVisitor);
}

// create allOf visitor (if necessary)
if (this.mode !== 'strict') {
const allOfVisitor = new AllOfVisitor({ options });
visitors.push(allOfVisitor);
}

// establish root visitor by visitor merging
const rootVisitor = mergeAllVisitors(visitors, { nodeTypeGetter: getNodeType });

referencedElement = visit(referencedElement, rootVisitor, {
keyMap,
nodeTypeGetter: getNodeType,
});

/**
* Transclude referencing element with merged referenced element.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"openapi": "3.1.0",
"info": {
"title": "Example generation test",
"version": "1.0.0"
},
"paths": {
"/foo": {
"get": {
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Foo"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Foo": {
"type": "object",
"properties": {
"bar": {
"allOf": [
{
"type": "object",
"properties": {
"a": {
"type": "integer"
}
}
}
]
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3101,6 +3101,79 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec
}
`;

exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec option and referenced schema contains allOf keyword should contain schema with merged properties from allOf 1`] = `
{
"errors": [],
"spec": {
"$$normalized": true,
"components": {
"schemas": {
"Foo": {
"properties": {
"bar": {
"properties": {
"a": {
"type": "integer",
},
},
"type": "object",
},
},
"type": "object",
},
},
},
"info": {
"title": "Example generation test",
"version": "1.0.0",
},
"openapi": "3.1.0",
"paths": {
"/foo": {
"get": {
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"properties": {
"bar": {
"properties": {
"a": {
"type": "integer",
},
},
"type": "object",
},
},
"type": "object",
},
},
},
},
},
"servers": [
{
"url": "/",
},
],
},
"servers": [
{
"url": "/",
},
],
},
},
"servers": [
{
"url": "/",
},
],
},
}
`;

exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec option and skipNormalization=false should resolve and normalize 1`] = `
{
"errors": [],
Expand Down
11 changes: 11 additions & 0 deletions test/resolver/strategies/openapi-3-1-apidom/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,17 @@ describe('resolve', () => {
});
});
});

describe('and referenced schema contains allOf keyword', () => {
test('should contain schema with merged properties from allOf', async () => {
const spec = globalThis.loadJsonFile(path.join(fixturePath, 'ref-all-of.json'));
const resolvedSpec = await SwaggerClient.resolve({
spec,
});

expect(resolvedSpec).toMatchSnapshot();
});
});
});
});
});

0 comments on commit 6a3a4e7

Please sign in to comment.