-
Notifications
You must be signed in to change notification settings - Fork 18
Fix support for using $ref
in a component definition
#503
Conversation
This is related to apiaryio/dredd#1762, the underlying document on this issue makes use of this feature of OpenAPI 3.0. |
I think there’s a case where this logic will get into an infinite loop, should be simple to resolve so adding this step
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. One nit to consider.
packages/openapi3-parser/lib/parser/oas/parseComponentsObject.js
Outdated
Show resolved
Hide resolved
(object) => { | ||
const contextMember = context.state.components.getMember(member.key.toValue()); | ||
|
||
if (contextMember) { | ||
contextMember.value = object; | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For review, this branch becomes dead code due to the first commit we only ever have the first case. This was evident in code coverage going down due to this line no longer being called/tested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚀
I think it might be a bit hard for a reviewer to get their head around some of these changes as the referencing logic is some of the most complicated code in the project, so I'll try do my best at explaining these changes.
The following OpenAPI 3 document was not being parsed correctly:
Support for using
$ref
directly in a reusable component against another reusable component wasn't supported. If users did that, they'd get incorrect behaviour and possibly incorrect errors (in the case for parameters which have required properties which a$ref
object wouldn't contain).To fix this I've made 3 changes which are broken into separate commits:
context.state.components.set('schemas', ...)
where there is a collection of member elements with all the nessecery schema names. That way we can validate schemas exist. This particular code was specific to schemas only, in the first commit I have made this generic to apply to all reusable components. This internal state is needed to support references in other components.parseReferenceObject
(which has dereferencing capabilities) to support multi-level referencing. This function supports returning "dereferenced" elements, this is used in areas such asparseParametersObject
where parameter validation against ahref
uses the dereferenced parameter to get hold of the 'name'. Without this change, the function would return an element such as{"element": "LimitAlias"}
instead the dereferenced limit parameter such as{"element": "member", ...}
.parseReference
function. I've had to add the argumentreturnReferenceElement
ofparseReferenceObject
toparseReference
so it can be used here. Since we do actually want a referenced element back instead of a dereference element in this case (which isn't common with the rest of the uses ofparseReference
).The last commit also contains integration tests to ensure this works end-to-end (for example JSON message body is created from the reference, etc). I want to ensure it works at all levels.