fury-adapter-oas3-parser
Advanced tools
Comparing version 0.6.0 to 0.7.0
# Fury OAS3 Parser Changelog | ||
## 0.6.0 (26-02-19) | ||
## 0.7.0 (2019-03-26) | ||
### Enhancements | ||
- Compatibility with [Fury 3.0.0 Beta 10](https://github.com/apiaryio/api-elements.js/releases/tag/fury@3.0.0-beta.10). | ||
- Added primitive support for 'examples' in 'Media Type Object'. The first | ||
example value is used for JSON media types. | ||
- Added support for generating a JSON message body from a schema for | ||
JSON media types. | ||
- Added support for header parameters. | ||
- Instances of referenced data structures will now be instances of the | ||
referenced type. | ||
For example, given a schema named 'username' contains `type: string`. | ||
When another data structure references the 'username' schema, it's instance | ||
will be a `StringElement`. | ||
### Bug Fixes | ||
- Prevents an exception being raised due to improper handling of invalid | ||
schemas found in the reusable components section of an OpenAPI 3 document. | ||
## 0.6.0 (2019-02-26) | ||
### Enhancements | ||
- Compatibility with [Fury 3.0.0 Beta 9](https://github.com/apiaryio/api-elements.js/releases/tag/fury-3.0.0-beta.9). | ||
@@ -13,3 +39,3 @@ | ||
## 0.5.2 (19-02-19) | ||
## 0.5.2 (2019-02-19) | ||
@@ -35,3 +61,3 @@ ### Enhancements | ||
## 0.5.1 (30-01-19) | ||
## 0.5.1 (2019-01-30) | ||
@@ -42,3 +68,3 @@ ### Bug Fixes | ||
## 0.5.0 (30-01-19) | ||
## 0.5.0 (2019-01-30) | ||
@@ -58,3 +84,3 @@ ### Enhancements | ||
## 0.4.1 (28-01-19) | ||
## 0.4.1 (2019-01-28) | ||
@@ -81,3 +107,3 @@ ### Enhancements | ||
## 0.4.0 (25-01-19) | ||
## 0.4.0 (2019-01-25) | ||
@@ -84,0 +110,0 @@ ### Enhancements |
@@ -12,2 +12,3 @@ const R = require('ramda'); | ||
const pipeParseResult = require('../../pipeParseResult'); | ||
const parseMap = require('../parseMap'); | ||
const parseSchemaObject = require('./parseSchemaObject'); | ||
@@ -17,7 +18,8 @@ const parseParameterObject = require('./parseParameterObject'); | ||
const parseRequestBodyObject = require('./parseRequestBodyObject'); | ||
const parseMap = require('../parseMap'); | ||
const parseHeaderObject = require('./parseHeaderObject'); | ||
const parseExampleObject = require('./parseExampleObject'); | ||
const parseSecuritySchemeObject = require('./parseSecuritySchemeObject'); | ||
const name = 'Components Object'; | ||
const unsupportedKeys = ['examples', 'securitySchemes', 'links', 'callbacks']; | ||
const unsupportedKeys = ['links', 'callbacks']; | ||
const isUnsupportedKey = R.anyPass(R.map(hasKey, unsupportedKeys)); | ||
@@ -32,2 +34,3 @@ | ||
* @returns boolean | ||
* @private | ||
*/ | ||
@@ -53,2 +56,3 @@ const isParseResultEmpty = parseResult => R.reject(isAnnotation, parseResult).isEmpty; | ||
* @returns ParseResult | ||
* @private | ||
*/ | ||
@@ -83,2 +87,3 @@ const parseComponentMember = R.curry((context, parser, member) => { | ||
* @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#componentsObject | ||
* @private | ||
*/ | ||
@@ -112,3 +117,4 @@ function parseComponentsObject(context, element) { | ||
* | ||
* @returns ParseResult | ||
* @returns ParseResult<ObjectElement> | ||
* @private | ||
*/ | ||
@@ -118,9 +124,24 @@ const parseComponentObjectMember = (parser) => { | ||
return pipeParseResult(context.namespace, | ||
return member => pipeParseResult(context.namespace, | ||
validateIsObject, | ||
R.compose(parseObject(context, name, parseMember), getValue)); | ||
R.compose(parseObject(context, name, parseMember), getValue), | ||
(object) => { | ||
const contextMember = context.state.components.getMember(member.key.toValue()); | ||
if (contextMember) { | ||
contextMember.value = object; | ||
} else { | ||
context.state.components.push(new namespace.elements.Member(member.key, object)); | ||
} | ||
return object; | ||
})(member); | ||
}; | ||
// eslint-disable-next-line no-param-reassign | ||
const setDataStructureId = (dataStructure, key) => { dataStructure.content.id = key.clone(); }; | ||
const setDataStructureId = (dataStructure, key) => { | ||
if (dataStructure) { | ||
// eslint-disable-next-line no-param-reassign | ||
dataStructure.content.id = key.clone(); | ||
} | ||
}; | ||
const parseSchemas = pipeParseResult(namespace, | ||
@@ -133,2 +154,16 @@ parseComponentObjectMember(parseSchemaObject), | ||
const parseSecuritySchemes = pipeParseResult(namespace, | ||
parseComponentObjectMember(parseSecuritySchemeObject), | ||
(object) => { | ||
const array = new namespace.elements.Array([]); | ||
object.forEach((value, key) => { | ||
// eslint-disable-next-line no-param-reassign | ||
value.meta.id = key.clone(); | ||
array.push(value); | ||
}); | ||
return array; | ||
}); | ||
const parseMember = R.cond([ | ||
@@ -139,3 +174,6 @@ [hasKey('schemas'), parseSchemas], | ||
[hasKey('requestBodies'), parseComponentObjectMember(parseRequestBodyObject)], | ||
[hasKey('examples'), parseComponentObjectMember(parseExampleObject)], | ||
[hasKey('headers'), parseMap(context, name, 'headers', parseHeaderObject)], | ||
[hasKey('securitySchemes'), parseSecuritySchemes], | ||
[isUnsupportedKey, createUnsupportedMemberWarning(namespace, name)], | ||
@@ -150,3 +188,4 @@ | ||
return parseObject(context, name, parseMember)(element); | ||
const order = ['schemas']; | ||
return parseObject(context, name, parseMember, [], order)(element); | ||
} | ||
@@ -153,0 +192,0 @@ |
@@ -24,2 +24,3 @@ const R = require('ramda'); | ||
* @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#headerObject | ||
* @private | ||
*/ | ||
@@ -26,0 +27,0 @@ function parseHeaderObject(context, object) { |
@@ -24,2 +24,3 @@ const R = require('ramda'); | ||
* @see unsupportedKeys | ||
* @private | ||
*/ | ||
@@ -32,2 +33,3 @@ const isUnsupportedKey = R.anyPass(R.map(hasKey, unsupportedKeys)); | ||
* @returns ParseResult<Category> | ||
* @private | ||
*/ | ||
@@ -34,0 +36,0 @@ function parseInfo(context, info) { |
@@ -12,36 +12,36 @@ const R = require('ramda'); | ||
const parseSchemaObject = require('./parseSchemaObject'); | ||
const parseExampleObject = require('./parseExampleObject'); | ||
const parseReference = require('../parseReference'); | ||
const name = 'Media Type Object'; | ||
const unsupportedKeys = [ | ||
'examples', 'encoding', | ||
]; | ||
const unsupportedKeys = ['encoding']; | ||
const isUnsupportedKey = R.anyPass(R.map(hasKey, unsupportedKeys)); | ||
function parseExample(namespace, mediaType) { | ||
const isJSONMediaType = () => { | ||
const type = mediaTyper.parse(mediaType); | ||
return ( | ||
type.type === 'application' | ||
&& (type.subtype === 'json' || type.suffix === 'json') | ||
); | ||
}; | ||
function isJSONMediaType(mediaType) { | ||
const type = mediaTyper.parse(mediaType); | ||
return ( | ||
type.type === 'application' | ||
&& (type.subtype === 'json' || type.suffix === 'json') | ||
); | ||
} | ||
const parseJSONExample = (example) => { | ||
const body = JSON.stringify(example.value.toValue()); | ||
const asset = new namespace.elements.Asset(body); | ||
asset.classes.push('messageBody'); | ||
asset.contentType = mediaType; | ||
return asset; | ||
}; | ||
const createJSONMessageBodyAsset = R.curry((namespace, mediaType, value) => { | ||
const body = JSON.stringify(value.toValue()); | ||
const asset = new namespace.elements.Asset(body); | ||
asset.classes.push('messageBody'); | ||
asset.contentType = mediaType; | ||
return asset; | ||
}); | ||
function parseExample(namespace, mediaType) { | ||
const createExampleNotJSONWarning = createWarning(namespace, | ||
"'Media Type Object' 'example' is only supported for JSON media types"); | ||
return R.ifElse(isJSONMediaType, | ||
parseJSONExample, | ||
return R.ifElse(() => isJSONMediaType(mediaType), | ||
R.compose(createJSONMessageBodyAsset(namespace, mediaType), getValue), | ||
createExampleNotJSONWarning); | ||
} | ||
const parseSchema = parseReference('schemas', parseSchemaObject); | ||
const parseSchemaObjectOrRef = parseReference('schemas', parseSchemaObject); | ||
const parseExampleObjectOrRef = parseReference('examples', parseExampleObject); | ||
@@ -57,2 +57,3 @@ /** | ||
* @see https://github.com/OAI/OpenAPI-Specification/blob/50c152549263cda0f05608d514ba78546b390d0e/versions/3.0.0.md#media-type-object | ||
* @private | ||
*/ | ||
@@ -63,5 +64,31 @@ function parseMediaTypeObject(context, MessageBodyClass, element) { | ||
const createExamplesNotJSONWarning = createWarning(namespace, | ||
`'${name}' 'examples' is only supported for JSON media types`); | ||
const parseExamples = pipeParseResult(namespace, | ||
R.unless(() => isJSONMediaType(mediaType), createExamplesNotJSONWarning), | ||
parseObject(context, `${name}' 'examples`, R.compose(parseExampleObjectOrRef(context), getValue)), | ||
(examples) => { | ||
const parseResult = new namespace.elements.ParseResult(); | ||
if (!examples.isEmpty) { | ||
const firstExample = examples.first.value; | ||
const value = firstExample.get('value'); | ||
if (value) { | ||
parseResult.push(value); | ||
} | ||
} | ||
if (examples.length > 1) { | ||
parseResult.push(createWarning(namespace, `'${name}' 'examples' only one example is supported, other examples have been ignored`, examples)); | ||
} | ||
return parseResult; | ||
}, | ||
createJSONMessageBodyAsset(namespace, mediaType)); | ||
const parseMember = R.cond([ | ||
[hasKey('example'), parseExample(namespace, mediaType)], | ||
[hasKey('schema'), R.compose(parseSchema(context), getValue)], | ||
[hasKey('examples'), R.compose(parseExamples, getValue)], | ||
[hasKey('schema'), R.compose(parseSchemaObjectOrRef(context), getValue)], | ||
@@ -86,3 +113,3 @@ [isUnsupportedKey, createUnsupportedMemberWarning(namespace, name)], | ||
const messageBody = mediaTypeObject.get('example'); | ||
const messageBody = mediaTypeObject.get('example') || mediaTypeObject.get('examples'); | ||
if (messageBody) { | ||
@@ -93,2 +120,26 @@ message.push(messageBody); | ||
const dataStructure = mediaTypeObject.get('schema'); | ||
if (!messageBody && dataStructure && isJSONMediaType(mediaType)) { | ||
let elements = []; | ||
const { components } = context.state; | ||
if (components) { | ||
const schemas = components.get('schemas'); | ||
if (schemas) { | ||
elements = schemas.content | ||
.filter(e => e.value && e.value.content) | ||
.map(e => e.value.content); | ||
} | ||
} | ||
const value = dataStructure.content.valueOf(undefined, elements); | ||
if (value) { | ||
const body = JSON.stringify(value); | ||
const asset = new namespace.elements.Asset(body); | ||
asset.classes.push('messageBody'); | ||
asset.contentType = mediaType; | ||
message.push(asset); | ||
} | ||
} | ||
if (dataStructure) { | ||
@@ -95,0 +146,0 @@ message.push(dataStructure); |
@@ -28,2 +28,3 @@ /* eslint-disable no-underscore-dangle */ | ||
* @see unsupportedKeys | ||
* @private | ||
*/ | ||
@@ -109,13 +110,2 @@ const isUnsupportedKey = R.anyPass(R.map(hasKey, unsupportedKeys)); | ||
// Pre-parse 'components', this needs to be done first since other | ||
// structures can reference it. | ||
let components = object.get('components'); | ||
if (components) { | ||
components = parseComponentsObject(context, components); | ||
object.set('components', components); | ||
// eslint-disable-next-line no-param-reassign | ||
context.state.components = components.reject(isAnnotation).get(0); | ||
} | ||
const parseMember = R.cond([ | ||
@@ -125,3 +115,3 @@ [hasKey('openapi'), parseOpenAPI(context)], | ||
[hasKey('paths'), R.compose(asArray, parsePathsObject(context), getValue)], | ||
[hasKey('components'), getValue], | ||
[hasKey('components'), R.compose(parseComponentsObject(context), getValue)], | ||
@@ -138,3 +128,3 @@ // FIXME Support exposing extensions into parse result | ||
const parseOASObject = pipeParseResult(namespace, | ||
parseObject(context, name, parseMember, requiredKeys), | ||
parseObject(context, name, parseMember, requiredKeys, ['components']), | ||
(object) => { | ||
@@ -150,7 +140,10 @@ const api = object.get('info'); | ||
if (components) { | ||
const schemas = components.get('schemas'); | ||
if (schemas) { | ||
const schemas = R.or(components.get('schemas'), new namespace.elements.Array()) | ||
.content | ||
.filter(member => member.value) | ||
.map(getValue); | ||
if (schemas.length > 0) { | ||
const dataStructures = new namespace.elements.Category( | ||
schemas.content.map(getValue), | ||
{ classes: ['dataStructures'] } | ||
schemas, { classes: ['dataStructures'] } | ||
); | ||
@@ -164,3 +157,2 @@ api.push(dataStructures); | ||
if (context.options.generateSourceMap) { | ||
@@ -167,0 +159,0 @@ return filterColumnLine(parseOASObject(object)); |
@@ -90,2 +90,3 @@ const R = require('ramda'); | ||
* @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#operationObject | ||
* @private | ||
*/ | ||
@@ -138,2 +139,5 @@ function parseOperationObject(context, path, member) { | ||
const transactions = createTransactions(namespace, member, operation); | ||
transition.content = transition.content.concat(transactions); | ||
const parameters = operation.get('parameters'); | ||
@@ -147,7 +151,17 @@ if (parameters) { | ||
transition.hrefVariables = hrefVariablesFromParameters(namespace, parameters); | ||
const headerParameters = parameters.get('header'); | ||
if (headerParameters) { | ||
transactions.map(transaction => transaction.request).forEach((request) => { | ||
const headers = R.or(request.headers, new namespace.elements.HttpHeaders()); | ||
headers.content = headers.content.concat( | ||
R.reject(member => !headers.include(member.key.toValue()).isEmpty, headerParameters.content) | ||
); | ||
request.headers = headers; | ||
}); | ||
} | ||
} | ||
const transactions = createTransactions(namespace, member, operation); | ||
transition.content = transition.content.concat(transactions); | ||
return transition; | ||
@@ -154,0 +168,0 @@ }); |
@@ -25,7 +25,7 @@ const R = require('ramda'); | ||
const isValidInValue = R.anyPass([ | ||
hasValue('query'), | ||
hasValue('header'), | ||
hasValue('path'), | ||
hasValue('cookie'), | ||
hasValue('query'), hasValue('header'), hasValue('path'), hasValue('cookie'), | ||
]); | ||
const isSupportedIn = R.anyPass([ | ||
hasValue('path'), hasValue('query'), hasValue('header'), | ||
]); | ||
@@ -65,2 +65,3 @@ const unreservedCharacterRegex = /^[A-z0-9\\.\\_\\~\\-]+$/; | ||
* @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#parameterObject | ||
* @private | ||
*/ | ||
@@ -71,3 +72,3 @@ function parseParameterObject(context, object) { | ||
const createInvalidInWarning = R.compose( | ||
createWarning(namespace, `'${name}' 'in' must be either 'query, 'header', 'path' or 'cookie'`), | ||
createWarning(namespace, `'${name}' 'in' must be either 'query', 'header', 'path' or 'cookie'`), | ||
getValue | ||
@@ -77,3 +78,2 @@ ); | ||
const isSupportedIn = R.anyPass([hasValue('path'), hasValue('query')]); | ||
const createUnsupportedInWarning = member => createWarning(namespace, | ||
@@ -80,0 +80,0 @@ `'${name}' 'in' '${member.value.toValue()}' is unsupported`, member.value); |
@@ -23,2 +23,3 @@ const R = require('ramda'); | ||
* be treated as a "named tuple". | ||
* @private | ||
*/ | ||
@@ -25,0 +26,0 @@ function parseParameterObjects(context, name, array) { |
@@ -27,2 +27,3 @@ const R = require('ramda'); | ||
* @return array | ||
* @private | ||
*/ | ||
@@ -49,2 +50,3 @@ function extractPathVariables(path) { | ||
* @retuns ParseResult<HrefVariables> | ||
* @private | ||
*/ | ||
@@ -70,2 +72,3 @@ const validateHrefVariablesInPath = R.curry((namespace, path, hrefVariables) => { | ||
* @param member {MemberElement} parameters member from an object element | ||
* @private | ||
*/ | ||
@@ -78,2 +81,3 @@ function parseParameters(context, path, member) { | ||
[hasKey('query'), member => member], | ||
[hasKey('header'), member => member], | ||
]); | ||
@@ -121,2 +125,3 @@ | ||
* @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#path-item-object | ||
* @private | ||
*/ | ||
@@ -168,2 +173,19 @@ function parsePathItemObject(context, member) { | ||
if (parameters && parameters.get('header')) { | ||
const headerParameters = parameters.get('header'); | ||
const transactions = R.chain(method => method.transactions.elements, methods); | ||
const requests = R.map(transaction => transaction.request, transactions); | ||
requests.forEach((request) => { | ||
const headers = R.or(request.headers, new namespace.elements.HttpHeaders()); | ||
headers.content = headers.content.concat( | ||
R.reject(member => !headers.include(member.key.toValue()).isEmpty, headerParameters.content) | ||
); | ||
request.headers = headers; | ||
}); | ||
} | ||
return resource; | ||
@@ -170,0 +192,0 @@ }); |
@@ -16,2 +16,3 @@ const R = require('ramda'); | ||
* @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#pathsObject | ||
* @private | ||
*/ | ||
@@ -18,0 +19,0 @@ function parsePaths(context, paths) { |
@@ -26,2 +26,3 @@ const R = require('ramda'); | ||
* @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#referenceObject | ||
* @private | ||
*/ | ||
@@ -62,3 +63,12 @@ function parseReferenceObject(context, componentName, element, returnReferenceElement) { | ||
if (returnReferenceElement) { | ||
const element = new context.namespace.elements.Element(); | ||
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; | ||
@@ -65,0 +75,0 @@ return element; |
@@ -32,2 +32,3 @@ const R = require('ramda'); | ||
* @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#requestBodyObject | ||
* @private | ||
*/ | ||
@@ -34,0 +35,0 @@ function parseRequestBodyObject(context, element) { |
@@ -35,2 +35,3 @@ const R = require('ramda'); | ||
* @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#responseObject | ||
* @private | ||
*/ | ||
@@ -37,0 +38,0 @@ function parseResponseObject(context, element) { |
@@ -36,2 +36,3 @@ const R = require('ramda'); | ||
* @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#responsesObject | ||
* @private | ||
*/ | ||
@@ -38,0 +39,0 @@ function parseResponsesObject(context, element) { |
@@ -12,2 +12,3 @@ const R = require('ramda'); | ||
const parseObject = require('../parseObject'); | ||
const parseArray = require('../parseArray'); | ||
const parseString = require('../parseString'); | ||
@@ -144,14 +145,5 @@ const parseBoolean = require('../parseBoolean'); | ||
const arrayElementToParseResult = array => new namespace.elements.ParseResult(array.content); | ||
const parseArray = itemParser => pipeParseResult(namespace, | ||
R.unless(isArray, createWarning(namespace, `'${name}' 'required' is not an array`)), | ||
R.compose( | ||
R.map(itemParser), | ||
arrayElementToParseResult | ||
), | ||
(...required) => new namespace.elements.Array([...required])); | ||
const parseRequiredString = R.unless(isString, | ||
createWarning(namespace, `'${name}' 'required' array value is not a string`)); | ||
const parseRequired = parseArray(parseRequiredString); | ||
const parseRequired = parseArray(context, `${name}' 'required`, parseRequiredString); | ||
@@ -241,2 +233,3 @@ const parseMember = R.cond([ | ||
* @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject | ||
* @private | ||
*/ | ||
@@ -243,0 +236,0 @@ function parseSchemaObject(context, element) { |
@@ -12,2 +12,3 @@ const R = require('ramda'); | ||
* @returns {boolean} | ||
* @private | ||
*/ | ||
@@ -22,2 +23,3 @@ const isValueBoolean = R.compose(isBoolean, getValue); | ||
* @returns {ParseResult<MemberElement<BooleanElement>>} | ||
* @private | ||
*/ | ||
@@ -38,2 +40,3 @@ const parseOptionalBoolean = (context, name, member) => new context.namespace.elements.ParseResult([ | ||
* @returns {ParseResult<MemberElement<BooleanElement>>} | ||
* @private | ||
*/ | ||
@@ -55,2 +58,3 @@ const parseRequiredBoolean = (context, name, member) => new context.namespace.elements.ParseResult([ | ||
* @returns {ParseResult<MemberElement<BooleanElement>>} | ||
* @private | ||
*/ | ||
@@ -57,0 +61,0 @@ function parseBoolean(context, name, required, member) { |
@@ -18,2 +18,3 @@ const R = require('ramda'); | ||
* @returns {ParseResult<MemberElement<Copy>>} | ||
* @private | ||
*/ | ||
@@ -20,0 +21,0 @@ function parseCopy(context, name, required, member) { |
@@ -40,2 +40,3 @@ const R = require('ramda'); | ||
* @returns ParseResult | ||
* @private | ||
*/ | ||
@@ -42,0 +43,0 @@ const parseMap = (context, name, key, valueParser) => pipeParseResult(context.namespace, |
const R = require('ramda'); | ||
const { | ||
isAnnotation, isMember, isParseResult, isObject, | ||
isAnnotation, isMember, isParseResult, isObject, getValue, | ||
} = require('../predicates'); | ||
@@ -8,6 +8,7 @@ const { createError, createWarning } = require('./annotations'); | ||
/* | ||
/** | ||
* Returns true iff the given element is either an annotation or member element | ||
* @param element {Element} | ||
* @returns boolean | ||
* @returns {boolean} | ||
* @private | ||
*/ | ||
@@ -20,2 +21,3 @@ const isAnnotationOrMember = R.anyPass([isAnnotation, isMember]); | ||
* @param parseResult {ParseResult} | ||
* @private | ||
*/ | ||
@@ -41,9 +43,10 @@ const chainParseResult = R.curry((transform, parseResult) => { | ||
const validateObjectContainsRequiredKeys = R.curry((namespace, path, requiredKeys, object) => { | ||
const validateObjectContainsRequiredKeys = R.curry((namespace, path, requiredKeys, sendWarning, object) => { | ||
const missingKeys = R.reject(hasMember(object), requiredKeys); | ||
const errorFromKey = key => createError(namespace, `'${path}' is missing required property '${key}'`, object); | ||
const createAnnotation = sendWarning ? createWarning : createError; | ||
const annotationFromKey = key => createAnnotation(namespace, `'${path}' is missing required property '${key}'`, object); | ||
if (missingKeys.length > 0) { | ||
return new namespace.elements.ParseResult( | ||
R.map(errorFromKey, missingKeys) | ||
R.map(annotationFromKey, missingKeys) | ||
); | ||
@@ -71,2 +74,3 @@ } | ||
* @returns {Element} Either a ParseResult to be unwrapped, or an element | ||
* @private | ||
*/ | ||
@@ -84,3 +88,3 @@ | ||
* If the transform callback returns a parse result without any non-annotation | ||
* elements then the member will be removed from the resultant object return int he parse result. | ||
* elements then the member will be removed from the resultant object return in the parse result. | ||
* | ||
@@ -97,11 +101,13 @@ * Splits up each member from an object, invokes the given parseMember | ||
* | ||
* @param namespace | ||
* @param context | ||
* @param name {string} - The human readable name of the element. Used for annotation messages. | ||
* @param transform {transformMember} - The callback to transform a member | ||
* @param requiredKeys {string[]} - The callback to transform a member | ||
* @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. | ||
* @param sendWarning {boolean} | ||
* @param object {ObjectElement} - The object containing members to transform | ||
* | ||
* @returns ParseResult<ObjectElement> | ||
* @returns {ParseResult<ObjectElement>} | ||
* @private | ||
*/ | ||
function parseObject(context, name, parseMember, requiredKeys) { | ||
function parseObject(context, name, parseMember, requiredKeys = [], orderedKeys = [], sendWarning = false) { | ||
const { namespace } = context; | ||
@@ -123,4 +129,5 @@ | ||
const transformMember = (member) => { | ||
const transformUnlessParseResult = R.ifElse(R.compose(isParseResult, getValue), getValue, transform); | ||
const coerceMember = (R.unless(isAnnotationOrMember, createMember(member.key))); | ||
return R.map(coerceMember, transform(member)); | ||
return R.map(coerceMember, transformUnlessParseResult(member)); | ||
}; | ||
@@ -131,3 +138,4 @@ | ||
* @param parseResult {ParseResult<Member>} | ||
* @returns ParseResult<Object> | ||
* @returns {ParseResult<Object>} | ||
* @private | ||
*/ | ||
@@ -144,13 +152,24 @@ const convertParseResultMembersToObject = (parseResult) => { | ||
const validateMembers = R.pipe( | ||
const validateMembers = object => R.pipe( | ||
wrapObjectInParseResult, | ||
(value) => { | ||
// pre-parse the ordered keys in order | ||
orderedKeys.forEach((key) => { | ||
const isOrderedKey = R.allPass([isMember, m => m.key.equals(key)]); | ||
const member = R.filter(isOrderedKey, value).get(0); | ||
if (member) { | ||
member.value = parseMember(member); | ||
} | ||
}); | ||
return value; | ||
}, | ||
chainParseResult(transformMember), | ||
R.unless(parseResultHasErrors, convertParseResultMembersToObject) | ||
); | ||
)(object); | ||
return pipeParseResult(namespace, | ||
R.unless(isObject, createWarning(namespace, `'${name}' is not an object`)), | ||
validateObjectContainsRequiredKeys(namespace, name, requiredKeys || []), | ||
validateObjectContainsRequiredKeys(namespace, name, requiredKeys, sendWarning), | ||
validateMembers, | ||
validateObjectContainsRequiredKeysNoError(namespace, requiredKeys || [])); | ||
validateObjectContainsRequiredKeysNoError(namespace, requiredKeys)); | ||
} | ||
@@ -157,0 +176,0 @@ |
@@ -12,2 +12,3 @@ const R = require('ramda'); | ||
* @returns {boolean} | ||
* @private | ||
*/ | ||
@@ -22,2 +23,3 @@ const isValueString = R.compose(isString, getValue); | ||
* @returns {ParseResult<MemberElement<StringElement>>} | ||
* @private | ||
*/ | ||
@@ -38,2 +40,3 @@ const parseOptionalString = (namespace, name, member) => new namespace.elements.ParseResult([ | ||
* @returns {ParseResult<MemberElement<StringElement>>} | ||
* @private | ||
*/ | ||
@@ -55,2 +58,3 @@ const parseRequiredString = (namespace, name, member) => new namespace.elements.ParseResult([ | ||
* @returns {ParseResult<MemberElement<StringElement>>} | ||
* @private | ||
*/ | ||
@@ -57,0 +61,0 @@ function parseString(context, name, required, member) { |
@@ -113,8 +113,11 @@ /* eslint-disable no-use-before-define */ | ||
); | ||
const marker = error.context_mark || error.problem_mark; | ||
copySourceMap( | ||
error.context_mark, | ||
error.context_mark, | ||
marker, | ||
marker, | ||
annotation, | ||
namespace | ||
); | ||
parseResult.push(annotation); | ||
@@ -121,0 +124,0 @@ return parseResult; |
@@ -8,2 +8,3 @@ const R = require('ramda'); | ||
* @returns boolean | ||
* @private | ||
*/ | ||
@@ -16,2 +17,3 @@ const hasNoErrors = parseResult => parseResult.errors.isEmpty; | ||
* @returns boolean | ||
* @private | ||
*/ | ||
@@ -32,2 +34,3 @@ const hasValue = parseResult => !R.reject(isAnnotation, parseResult).isEmpty; | ||
* @returns {ParseResult} | ||
* @private | ||
*/ | ||
@@ -53,2 +56,3 @@ function concatParseResult(namespace, lhs, rhs) { | ||
* @see R.pipe | ||
* @private | ||
*/ | ||
@@ -55,0 +59,0 @@ function pipeParseResult(namespace, ...functions) { |
const R = require('ramda'); | ||
/** @module predicates */ | ||
/** | ||
* @module predicates | ||
* @private | ||
*/ | ||
@@ -22,2 +25,3 @@ const isArray = element => element.element === 'array'; | ||
* @returns {boolean} | ||
* @private | ||
*/ | ||
@@ -31,2 +35,3 @@ const hasKey = (key, member) => member.key.toValue() === key; | ||
* @returns {boolean} | ||
* @private | ||
*/ | ||
@@ -39,2 +44,3 @@ const hasValue = (value, member) => member.value.toValue() === value; | ||
* @returns {boolean} | ||
* @private | ||
*/ | ||
@@ -47,2 +53,3 @@ const isExtension = member => member.key && isString(member.key) && member.key.toValue().startsWith('x-'); | ||
* @returns {Element} | ||
* @private | ||
*/ | ||
@@ -55,2 +62,3 @@ const getKey = member => member.key; | ||
* @returns {Element} | ||
* @private | ||
*/ | ||
@@ -57,0 +65,0 @@ const getValue = member => member.value; |
{ | ||
"name": "fury-adapter-oas3-parser", | ||
"version": "0.6.0", | ||
"version": "0.7.0", | ||
"description": "Open API Specification 3 API Elements Parser", | ||
@@ -28,3 +28,3 @@ "author": "Apiary.io <support@apiary.io>", | ||
"peerDependencies": { | ||
"fury": "3.0.0-beta.9" | ||
"fury": "3.0.0-beta.10" | ||
}, | ||
@@ -34,8 +34,9 @@ "devDependencies": { | ||
"eslint": "^5.9.0", | ||
"fury": "3.0.0-beta.9", | ||
"fury": "3.0.0-beta.10", | ||
"mocha": "^5.0.2" | ||
}, | ||
"engines": { | ||
"node": ">=4" | ||
} | ||
"node": ">=6" | ||
}, | ||
"gitHead": "853dfac567e80f4c57b6058eabcc231d282753a5" | ||
} |
@@ -106,3 +106,3 @@ # OpenAPI Support | ||
| query | ✓ | | ||
| header | ✕ | | ||
| header | ✓ | | ||
| cookie | ✕ | | ||
@@ -142,3 +142,3 @@ | ||
| example | ✓ | | ||
| examples | ✕ | | ||
| examples | ~ | | ||
| encoding | ✕ | | ||
@@ -156,6 +156,6 @@ | ||
| parameters | ✓ | | ||
| examples | ✕ | | ||
| examples | ✓ | | ||
| requestBodies | ✓ | | ||
| headers | [~](#header-object) | | ||
| securitySchemes | ✕ | | ||
| securitySchemes | [~](#security-scheme-object) | | ||
| links | ✕ | | ||
@@ -214,1 +214,32 @@ | callbacks | ✕ | | ||
| allowEmptyValue | ✕ | | ||
## Security Scheme Object | ||
| Field Name | Support | | ||
|:--|:--| | ||
| type | [~](#security-scheme-type) | | ||
| description | ✓ | | ||
| name | ✓ | | ||
| in | ~ | | ||
| scheme | ~ | | ||
| bearerFormat | ✕ | | ||
| flows | ✕ | | ||
| openIdConnectUrl | ✕ | | ||
## Security Scheme Type | ||
| Field Name | Support | | ||
|:--|:--| | ||
| apiKey | ✓ | | ||
| http | ✓ | | ||
| oauth2 | ✕ | | ||
| openIdConnect | ✕ | | ||
## Example Object | ||
| Field Name | Support | | ||
|:--|:--| | ||
| summary | ✕ | | ||
| description | ✕ | | ||
| value | ✓ | | ||
| externalValue | ✕ | |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
837485
89
3028