This repository was archived by the owner on Nov 8, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathparseReferenceObject.js
97 lines (81 loc) · 3.11 KB
/
parseReferenceObject.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
const R = require('ramda');
const {
createError,
createWarning,
createInvalidMemberWarning,
} = require('../annotations');
const { isExtension, hasKey } = require('../../predicates');
const pipeParseResult = require('../../pipeParseResult');
const parseObject = require('../parseObject');
const parseString = require('../parseString');
const name = 'Reference Object';
const requiredKeys = ['$ref'];
/**
* Parse Reference Object
*
* @param namespace {Namespace}
* @param componentName {string}
* @param element {Element}
* @returns ParseResult - A parse result containing error if the referenced
* object was not found, the referenced element, or if the referenced
* element was not successfully parsed, an empty parse result.
*
* @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#referenceObject
* @private
*/
function parseReferenceObject(context, componentName, element, returnReferenceElement) {
const { namespace } = context;
const { components } = context.state;
const parseRef = (ref) => {
if (!ref.toValue().startsWith('#/components/')) {
return createError(namespace, "Only local references to '#/components' within the same file are supported", ref);
}
const referenceParts = ref.toValue().split('/');
if (referenceParts[2] !== componentName) {
return createError(namespace, `Only references to '${componentName}' are permitted from this location`, ref);
}
if (referenceParts.length !== 4) {
return createError(namespace,
`Only references to a reusable component inside '#/components/${componentName}' are supported`, ref);
}
if (!components) {
return createError(namespace, "'#/components' is not defined", ref);
}
const component = components.get(referenceParts[2]);
if (!component) {
return createError(namespace, `'#/components/${componentName}' is not defined`, ref);
}
const componentId = referenceParts[3];
if (!component.hasKey(componentId)) {
return createError(namespace, `'${ref.toValue()}' is not defined`, ref);
}
if (returnReferenceElement) {
let Element;
const referenced = component.get(componentId);
if (referenced instanceof context.namespace.elements.DataStructure) {
Element = referenced.content.constructor;
} else {
({ Element } = context.namespace.elements);
}
const element = new Element();
element.element = componentId;
return element;
}
return new namespace.elements.ParseResult(
component
.filter((value, key) => key.toValue() === componentId && value)
.map(value => value)
);
};
const parseMember = R.cond([
[hasKey('$ref'), parseString(context, name, true)],
[isExtension, createWarning(namespace, `Extensions are not permitted in '${name}'`)],
[R.T, createInvalidMemberWarning(namespace, name)],
]);
const parseReference = pipeParseResult(namespace,
parseObject(context, name, parseMember, requiredKeys),
object => object.get('$ref'),
parseRef);
return parseReference(element);
}
module.exports = R.curryN(3, parseReferenceObject);