Skip to content
This repository was archived by the owner on Nov 8, 2024. It is now read-only.

Commit ac55c73

Browse files
authored
Merge pull request #197 from apiaryio/kylef/components-order
Handle pre-parsing object members in parseObject
2 parents ad2b20a + f75a2e4 commit ac55c73

File tree

4 files changed

+30
-25
lines changed

4 files changed

+30
-25
lines changed

packages/fury-adapter-oas3-parser/lib/parser/oas/parseComponentsObject.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,19 @@ function parseComponentsObject(context, element) {
109109
* @param parser {function}
110110
* @param member {Member}
111111
*
112-
* @returns ParseResult
112+
* @returns ParseResult<ObjectElement>
113113
* @private
114114
*/
115115
const parseComponentObjectMember = (parser) => {
116116
const parseMember = parseComponentMember(context, parser);
117117

118-
return pipeParseResult(context.namespace,
118+
return member => pipeParseResult(context.namespace,
119119
validateIsObject,
120-
R.compose(parseObject(context, name, parseMember), getValue));
120+
R.compose(parseObject(context, name, parseMember), getValue),
121+
(object) => {
122+
context.state.components.push(new namespace.elements.Member(member.key, object));
123+
return object;
124+
})(member);
121125
};
122126

123127
const setDataStructureId = (dataStructure, key) => {

packages/fury-adapter-oas3-parser/lib/parser/oas/parseOpenAPIObject.js

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -106,22 +106,11 @@ function parseOASObject(context, object) {
106106
return new namespace.elements.ParseResult([array].concat(parseResult.annotations.elements));
107107
};
108108

109-
// Pre-parse 'components', this needs to be done first since other
110-
// structures can reference it.
111-
let components = object.get('components');
112-
if (components) {
113-
components = parseComponentsObject(context, components);
114-
object.set('components', components);
115-
116-
// eslint-disable-next-line no-param-reassign
117-
context.state.components = components.reject(isAnnotation).get(0);
118-
}
119-
120109
const parseMember = R.cond([
121110
[hasKey('openapi'), parseOpenAPI(context)],
122111
[hasKey('info'), R.compose(parseInfoObject(context), getValue)],
123112
[hasKey('paths'), R.compose(asArray, parsePathsObject(context), getValue)],
124-
[hasKey('components'), getValue],
113+
[hasKey('components'), R.compose(parseComponentsObject(context), getValue)],
125114

126115
// FIXME Support exposing extensions into parse result
127116
[isExtension, () => new namespace.elements.ParseResult()],
@@ -133,7 +122,7 @@ function parseOASObject(context, object) {
133122
]);
134123

135124
const parseOASObject = pipeParseResult(namespace,
136-
parseObject(context, name, parseMember, requiredKeys),
125+
parseObject(context, name, parseMember, requiredKeys, ['components']),
137126
(object) => {
138127
const api = object.get('info');
139128

packages/fury-adapter-oas3-parser/lib/parser/oas/parseSecuritySchemeObject.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ function validateApiKeyScheme(context, securityScheme) {
6060
[R.T, e => e],
6161
]);
6262

63-
return parseObject(context, name, parseMember, ['name', 'in'], true)(securityScheme);
63+
return parseObject(context, name, parseMember, ['name', 'in'], [], true)(securityScheme);
6464
}
6565

6666
function validateHttpScheme(context, securityScheme) {
@@ -70,7 +70,7 @@ function validateHttpScheme(context, securityScheme) {
7070
[R.T, e => e],
7171
]);
7272

73-
return parseObject(context, name, parseMember, ['scheme'], true)(securityScheme);
73+
return parseObject(context, name, parseMember, ['scheme'], [], true)(securityScheme);
7474
}
7575

7676
/**
@@ -116,7 +116,7 @@ function parseSecuritySchemeObject(context, object) {
116116
]);
117117

118118
const parseSecurityScheme = pipeParseResult(namespace,
119-
parseObject(context, name, parseMember, requiredKeys, true),
119+
parseObject(context, name, parseMember, requiredKeys, [], true),
120120
R.when(isApiKeyScheme, R.curry(validateApiKeyScheme)(context)),
121121
R.when(isHttpScheme, R.curry(validateHttpScheme)(context)),
122122
(securityScheme) => {

packages/fury-adapter-oas3-parser/lib/parser/parseObject.js

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const R = require('ramda');
22
const {
3-
isAnnotation, isMember, isParseResult, isObject,
3+
isAnnotation, isMember, isParseResult, isObject, getValue,
44
} = require('../predicates');
55
const { createError, createWarning } = require('./annotations');
66
const pipeParseResult = require('../pipeParseResult');
@@ -97,13 +97,13 @@ const validateObjectContainsRequiredKeysNoError = R.curry((namespace, requiredKe
9797
* @param name {string} - The human readable name of the element. Used for annotation messages.
9898
* @param transform {transformMember} - The callback to transform a member
9999
* @param requiredKeys {string[]} - The callback to transform a member
100+
* @param orderedKeys {string[]} - An ordered list of keys which should be parsed first - This is useful when some keys depend on others. All non-ordered keys past last in user-defined order.
100101
* @param sendWarning {boolean}
101102
* @param object {ObjectElement} - The object containing members to transform
102-
*
103103
* @returns {ParseResult<ObjectElement>}
104104
* @private
105105
*/
106-
function parseObject(context, name, parseMember, requiredKeys = [], sendWarning = false) {
106+
function parseObject(context, name, parseMember, requiredKeys = [], orderedKeys = [], sendWarning = false) {
107107
const { namespace } = context;
108108

109109
// Create a member from a key and value
@@ -120,8 +120,9 @@ function parseObject(context, name, parseMember, requiredKeys = [], sendWarning
120120
// values in the parse result that are not annotations or a member
121121
// into a member using the same key as provided
122122
const transformMember = (member) => {
123+
const transformUnlessParseResult = R.ifElse(R.compose(isParseResult, getValue), getValue, transform);
123124
const coerceMember = (R.unless(isAnnotationOrMember, createMember(member.key)));
124-
return R.map(coerceMember, transform(member));
125+
return R.map(coerceMember, transformUnlessParseResult(member));
125126
};
126127

127128
/**
@@ -140,11 +141,22 @@ function parseObject(context, name, parseMember, requiredKeys = [], sendWarning
140141
// Create a parse result from an object using all of the members
141142
const wrapObjectInParseResult = object => new namespace.elements.ParseResult(object.content);
142143

143-
const validateMembers = R.pipe(
144+
const validateMembers = object => R.pipe(
144145
wrapObjectInParseResult,
146+
(value) => {
147+
// pre-parse the ordered keys in order
148+
orderedKeys.forEach((key) => {
149+
const isOrderedKey = R.allPass([isMember, m => m.key.equals(key)]);
150+
const member = R.filter(isOrderedKey, value).get(0);
151+
if (member) {
152+
member.value = parseMember(member);
153+
}
154+
});
155+
return value;
156+
},
145157
chainParseResult(transformMember),
146158
R.unless(parseResultHasErrors, convertParseResultMembersToObject)
147-
);
159+
)(object);
148160

149161
return pipeParseResult(namespace,
150162
R.unless(isObject, createWarning(namespace, `'${name}' is not an object`)),

0 commit comments

Comments
 (0)