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

Commit 7f8206d

Browse files
committed
feat(oas3): support array of type in Schema Object
The caveat, is that the array can only be a single value.
1 parent 6bb1b2d commit 7f8206d

File tree

2 files changed

+249
-85
lines changed

2 files changed

+249
-85
lines changed

packages/openapi3-parser/lib/parser/oas/parseSchemaObject.js

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const {
66
} = require('../annotations');
77
const pipeParseResult = require('../../pipeParseResult');
88
const {
9-
isString, hasKey, getValue,
9+
isArray, isString, hasKey, getValue,
1010
} = require('../../predicates');
1111
const parseObject = require('../parseObject');
1212
const parseArray = require('../parseArray');
@@ -128,10 +128,14 @@ const typeToElementNameMap = {
128128
* Normalises result into an ArrayElement of StringElement
129129
*/
130130
function parseType(context) {
131+
const { namespace } = context;
132+
131133
let types;
132134
let isValidType;
133135

134-
if (context.isOpenAPIVersionMoreThanOrEqual(3, 1)) {
136+
const isOpenAPI31OrHigher = R.always(context.isOpenAPIVersionMoreThanOrEqual(3, 1));
137+
138+
if (isOpenAPI31OrHigher()) {
135139
types = openapi31Types;
136140
isValidType = isValidOpenAPI31Type;
137141
} else {
@@ -141,13 +145,71 @@ function parseType(context) {
141145

142146
const ensureValidType = R.unless(
143147
element => isValidType(element.toValue()),
144-
createWarning(context.namespace, `'${name}' 'type' must be either ${types.join(', ')}`)
148+
createWarning(namespace, `'${name}' 'type' must be either ${types.join(', ')}`)
145149
);
146150

147-
return pipeParseResult(context.namespace,
148-
R.unless(isString, value => createWarning(context.namespace, `'${name}' 'type' is not a string`, value)),
151+
const parseStringType = pipeParseResult(namespace,
149152
ensureValidType,
150-
type => new context.namespace.elements.Array([type]));
153+
type => new namespace.elements.Array([type]));
154+
155+
const ensureValidTypeInArray = R.unless(
156+
element => isValidType(element.toValue()),
157+
createWarning(namespace, `'${name}' 'type' array must only contain values: ${types.join(', ')}`)
158+
);
159+
160+
const parseArrayTypeItem = pipeParseResult(namespace,
161+
R.unless(isString, createWarning(namespace, `'${name}' 'type' array value is not a string`)),
162+
ensureValidTypeInArray);
163+
164+
const isEmpty = arrayElement => arrayElement.isEmpty;
165+
166+
// ArrayElement -> ParseResult<ArrayElement, Annotation>
167+
const ensureTypesAreUnique = (types) => {
168+
const inspectedTypes = [];
169+
const warnings = [];
170+
const permittedTypes = R.filter((type) => {
171+
if (inspectedTypes.includes(type.toValue())) {
172+
warnings.push(createWarning(namespace, `'${name}' 'type' array must contain unique items, ${type.toValue()} is already present`, type));
173+
return false;
174+
}
175+
176+
inspectedTypes.push(type.toValue());
177+
return true;
178+
}, types);
179+
180+
const parseResult = new namespace.elements.ParseResult();
181+
parseResult.push(permittedTypes.elements);
182+
183+
if (warnings.length > 0) {
184+
parseResult.push(...warnings);
185+
}
186+
return parseResult;
187+
};
188+
189+
const parseArrayType = pipeParseResult(namespace,
190+
R.when(isEmpty, createWarning(namespace, `'${name}' 'type' array must contain at least one type`)),
191+
parseArray(context, `${name}' 'type`, parseArrayTypeItem),
192+
ensureTypesAreUnique,
193+
194+
// FIXME support >1 type
195+
R.when(e => e.length > 1, createWarning(namespace, `'${name}' 'type' more than one type is current unsupported`)));
196+
197+
return R.cond([
198+
[isString, parseStringType],
199+
[
200+
R.both(isArray, isOpenAPI31OrHigher),
201+
parseArrayType,
202+
],
203+
204+
[
205+
isOpenAPI31OrHigher,
206+
value => createWarning(namespace, `'${name}' 'type' is not a string or an array`, value),
207+
],
208+
[
209+
R.T,
210+
value => createWarning(namespace, `'${name}' 'type' is not a string`, value),
211+
],
212+
]);
151213
}
152214

153215
// Returns whether the given element value matches the provided schema type

0 commit comments

Comments
 (0)