fury-adapter-oas3-parser
Advanced tools
Comparing version 0.9.1 to 0.10.0
# Fury OAS3 Parser Changelog | ||
## 0.10.0 (2019-12-06) | ||
### Enhancements | ||
- Added support for `info.license` (License Object). | ||
## 0.9.1 (2019-08-08) | ||
@@ -4,0 +10,0 @@ |
@@ -19,4 +19,16 @@ const State = require('./state.js'); | ||
} | ||
oauthFlow(id, flow) { | ||
return this.state.oauthFlow(id, flow); | ||
} | ||
registerScheme(id) { | ||
return this.state.registerScheme(id); | ||
} | ||
hasScheme(id) { | ||
return this.state.hasScheme(id); | ||
} | ||
} | ||
module.exports = Context; |
@@ -155,13 +155,43 @@ const R = require('ramda'); | ||
(object) => { | ||
const parseResult = new namespace.elements.ParseResult([]); | ||
const array = new namespace.elements.Array([]); | ||
object.forEach((value, key) => { | ||
const keyValue = key.toValue(); | ||
if (value) { | ||
// eslint-disable-next-line no-param-reassign | ||
value.meta.id = key.clone(); | ||
array.push(value); | ||
if (value instanceof namespace.elements.AuthScheme) { | ||
if (!context.registerScheme(keyValue)) { | ||
parseResult.push(createWarning(namespace, | ||
`'${keyValue}' security scheme is already defined`, key)); | ||
} else { | ||
// eslint-disable-next-line no-param-reassign | ||
value.id = key.clone(); | ||
array.push(value); | ||
} | ||
return; | ||
} | ||
// append oauth2 flow names | ||
value.forEach((flow) => { | ||
const flowSchemeName = `${keyValue} ${flow.grantTypeValue}`; | ||
if (!context.oauthFlow(keyValue, flowSchemeName)) { | ||
parseResult.push(createWarning(namespace, | ||
`'${flowSchemeName}' security scheme can't be created from '${keyValue}' security scheme because it is already defined`, key)); | ||
} else { | ||
// eslint-disable-next-line no-param-reassign | ||
flow.id = flowSchemeName; | ||
array.push(flow); | ||
} | ||
}); | ||
} | ||
}); | ||
return array; | ||
if (!array.isEmpty) { | ||
parseResult.push(array); | ||
} | ||
return parseResult; | ||
}); | ||
@@ -168,0 +198,0 @@ |
@@ -8,3 +8,3 @@ const R = require('ramda'); | ||
const { | ||
isObject, hasKey, isExtension, | ||
isObject, hasKey, getValue, isExtension, | ||
} = require('../../predicates'); | ||
@@ -15,6 +15,7 @@ const parseObject = require('../parseObject'); | ||
const pipeParseResult = require('../../pipeParseResult'); | ||
const parseLicenseObject = require('./parseLicenseObject'); | ||
const name = 'Info Object'; | ||
const requiredKeys = ['title', 'version']; | ||
const unsupportedKeys = ['termsOfService', 'contact', 'license']; | ||
const unsupportedKeys = ['termsOfService', 'contact']; | ||
@@ -43,2 +44,3 @@ /** | ||
[hasKey('description'), parseCopy(context, name, false)], | ||
[hasKey('license'), R.compose(parseLicenseObject(context), getValue)], | ||
[isUnsupportedKey, createUnsupportedMemberWarning(namespace, name)], | ||
@@ -66,2 +68,6 @@ | ||
if (info.get('license')) { | ||
api.links.push(info.get('license')); | ||
} | ||
return api; | ||
@@ -68,0 +74,0 @@ }); |
@@ -43,7 +43,21 @@ const R = require('ramda'); | ||
const parseUrl = pipeParseResult(namespace, | ||
parseString(context, name, false), | ||
(url) => { | ||
const transition = new namespace.elements.Transition(); | ||
transition.href = url.value.clone(); | ||
transition.relation = url.key.clone(); | ||
// remove 'Url' from key | ||
transition.relation.content = transition.relation.toValue().slice(0, -3); | ||
return transition; | ||
}); | ||
const parseMember = R.cond([ | ||
[hasKey('scopes'), R.compose(parseScopes, getValue)], | ||
[hasKey('refreshUrl'), parseString(context, name, false)], | ||
[hasKey('authorizationUrl'), parseString(context, name, false)], | ||
[hasKey('tokenUrl'), parseString(context, name, false)], | ||
[hasKey('refreshUrl'), parseUrl], | ||
[hasKey('authorizationUrl'), parseUrl], | ||
[hasKey('tokenUrl'), parseUrl], | ||
@@ -50,0 +64,0 @@ // FIXME Support exposing extensions into parse result |
@@ -75,2 +75,6 @@ const R = require('ramda'); | ||
R.filter(R.is(namespace.elements.Transition), member.value).forEach((item) => { | ||
authScheme.push(item); | ||
}); | ||
return authScheme; | ||
@@ -77,0 +81,0 @@ })); |
@@ -18,6 +18,7 @@ /* eslint-disable no-underscore-dangle */ | ||
const parseComponentsObject = require('./parseComponentsObject'); | ||
const parseSecurityRequirementsArray = require('./parseSecurityRequirementsArray'); | ||
const name = 'OpenAPI Object'; | ||
const requiredKeys = ['openapi', 'info', 'paths']; | ||
const unsupportedKeys = ['servers', 'security', 'tags', 'externalDocs']; | ||
const unsupportedKeys = ['servers', 'tags', 'externalDocs']; | ||
@@ -113,4 +114,5 @@ /** | ||
[hasKey('info'), R.compose(parseInfoObject(context), getValue)], | ||
[hasKey('components'), R.compose(parseComponentsObject(context), getValue)], | ||
[hasKey('paths'), R.compose(asArray, parsePathsObject(context), getValue)], | ||
[hasKey('components'), R.compose(parseComponentsObject(context), getValue)], | ||
[hasKey('security'), R.compose(parseSecurityRequirementsArray(context), getValue)], | ||
@@ -130,3 +132,15 @@ // FIXME Support exposing extensions into parse result | ||
const api = object.get('info'); | ||
const components = object.get('components'); | ||
const security = object.get('security'); | ||
if (components) { | ||
const schemes = R.or(components.get('securitySchemes'), new namespace.elements.Array()); | ||
if (!schemes.isEmpty) { | ||
api.push(new namespace.elements.Category( | ||
schemes.content, { classes: ['authSchemes'] } | ||
)); | ||
} | ||
} | ||
const resources = object.get('paths'); | ||
@@ -137,3 +151,16 @@ if (resources) { | ||
const components = object.get('components'); | ||
api.resources.forEach((resource) => { | ||
resource.transitions.forEach((transition) => { | ||
transition.transactions.forEach((transaction) => { | ||
if (!transaction.authSchemes && security && !security.isEmpty) { | ||
transaction.attributes.set('authSchemes', security.clone()); | ||
} | ||
if (transaction.authSchemes && transaction.authSchemes.isEmpty) { | ||
transaction.attributes.remove('authSchemes'); | ||
} | ||
}); | ||
}); | ||
}); | ||
if (components) { | ||
@@ -140,0 +167,0 @@ const schemas = R.or(components.get('schemas'), new namespace.elements.Array()) |
@@ -17,2 +17,3 @@ const R = require('ramda'); | ||
const parseRequestBodyObject = require('./parseRequestBodyObject'); | ||
const parseSecurityRequirementsArray = require('./parseSecurityRequirementsArray'); | ||
const parseReference = require('../parseReference'); | ||
@@ -25,3 +26,3 @@ | ||
const unsupportedKeys = [ | ||
'tags', 'externalDocs', 'callbacks', 'deprecated', 'security', | ||
'tags', 'externalDocs', 'callbacks', 'deprecated', | ||
]; | ||
@@ -114,2 +115,3 @@ const isUnsupportedKey = R.anyPass(R.map(hasKey, unsupportedKeys)); | ||
[hasKey('parameters'), R.compose(parseParameterObjects(context, name), getValue)], | ||
[hasKey('security'), R.compose(parseSecurityRequirementsArray(context), getValue)], | ||
@@ -167,2 +169,9 @@ [isUnsupportedKey, createUnsupportedMemberWarning(namespace, name)], | ||
const security = operation.get('security'); | ||
if (security) { | ||
transactions.forEach((transaction) => { | ||
transaction.attributes.set('authSchemes', security.clone()); | ||
}); | ||
} | ||
return transition; | ||
@@ -169,0 +178,0 @@ }); |
@@ -43,19 +43,43 @@ const R = require('ramda'); | ||
(securityRequirement) => { | ||
const arr = new namespace.elements.Array([]); | ||
const parseResult = new namespace.elements.ParseResult([]); | ||
const array = new namespace.elements.Array([]); | ||
securityRequirement.forEach((value, key) => { | ||
let e; | ||
const schemeName = key.toValue(); | ||
const scopes = value.map(scope => scope.toValue()); | ||
if (scopes.length) { | ||
e = new namespace.elements.Object({ scopes }); | ||
e = new namespace.elements.AuthScheme({ scopes }); | ||
} else { | ||
e = new namespace.elements.Object({}); | ||
e = new namespace.elements.AuthScheme({}); | ||
} | ||
e.element = key.toValue(); | ||
arr.push(e); | ||
// Expand oauth2 flows | ||
const hasFlows = context.state.oauthFlows[schemeName] || []; | ||
if (hasFlows.length !== 0) { | ||
hasFlows.forEach((flow) => { | ||
const element = e.clone(); | ||
element.element = flow; | ||
array.push(element); | ||
}); | ||
return; | ||
} | ||
if (!context.hasScheme(schemeName)) { | ||
parseResult.push(createWarning(namespace, `'${schemeName}' security scheme not found`, key)); | ||
} else { | ||
e.element = schemeName; | ||
array.push(e); | ||
} | ||
}); | ||
return arr; | ||
if (!array.isEmpty) { | ||
parseResult.push(array); | ||
} | ||
return parseResult; | ||
}); | ||
@@ -62,0 +86,0 @@ |
@@ -13,2 +13,3 @@ const R = require('ramda'); | ||
const parseString = require('../parseString'); | ||
const parseOauthFlowsObject = require('./parseOauthFlowsObject'); | ||
@@ -19,7 +20,8 @@ const name = 'Security Scheme Object'; | ||
const isUnsupportedKey = R.anyPass(R.map(hasKey, unsupportedKeys)); | ||
const passThrough = R.anyPass(R.map(hasKey, ['name', 'in', 'scheme', 'flows'])); | ||
const outerPassThrough = R.anyPass(R.map(hasKey, ['name', 'in', 'scheme', 'flows'])); | ||
const innerPassThrough = R.anyPass(R.map(hasKey, ['type', 'description'])); | ||
const isApiKeyScheme = securityScheme => securityScheme.getValue('type') === 'apiKey'; | ||
const isHttpScheme = securityScheme => securityScheme.getValue('type') === 'http'; | ||
// const isOauth2Scheme = securityScheme => securityScheme.getValue('type') === 'oauth2'; | ||
const isOauth2Scheme = securityScheme => securityScheme.getValue('type') === 'oauth2'; | ||
@@ -29,3 +31,2 @@ const isValidTypeValue = R.anyPass(R.map(hasValue, ['apiKey', 'http', 'oauth2', 'openIdConnect'])); | ||
const isValidInValue = R.anyPass(R.map(hasValue, ['query', 'header', 'cookie'])); | ||
const isSupportedIn = R.anyPass(R.map(hasValue, ['query', 'header'])); | ||
@@ -41,10 +42,5 @@ function validateApiKeyScheme(context, securityScheme) { | ||
const createUnsupportedInWarning = member => createWarning(namespace, | ||
`'${name}' 'in' '${member.value.toValue()}' is unsupported`, member.value); | ||
const ensureSupportedIn = R.unless(isSupportedIn, createUnsupportedInWarning); | ||
const parseIn = pipeParseResult(namespace, | ||
parseString(context, name, false), | ||
validateIn, | ||
ensureSupportedIn); | ||
validateIn); | ||
@@ -55,3 +51,7 @@ const parseMember = R.cond([ | ||
[R.T, e => e], | ||
[innerPassThrough, e => e], | ||
[isUnsupportedKey, e => e], | ||
[isExtension, e => e], | ||
[R.T, createInvalidMemberWarning(namespace, `${name}' 'apiKey`)], | ||
]); | ||
@@ -63,6 +63,12 @@ | ||
function validateHttpScheme(context, securityScheme) { | ||
const { namespace } = context; | ||
const parseMember = R.cond([ | ||
[hasKey('scheme'), parseString(context, name, false)], | ||
[R.T, e => e], | ||
[innerPassThrough, e => e], | ||
[isUnsupportedKey, e => e], | ||
[isExtension, e => e], | ||
[R.T, createInvalidMemberWarning(namespace, `${name}' 'http`)], | ||
]); | ||
@@ -73,2 +79,18 @@ | ||
function validateOauth2Scheme(context, securityScheme) { | ||
const { namespace } = context; | ||
const parseMember = R.cond([ | ||
[hasKey('flows'), R.compose(parseOauthFlowsObject(context), getValue)], | ||
[innerPassThrough, e => e], | ||
[isUnsupportedKey, e => e], | ||
[isExtension, e => e], | ||
[R.T, createInvalidMemberWarning(namespace, `${name}' 'oauth2`)], | ||
]); | ||
return parseObject(context, name, parseMember, ['flows'], [], true)(securityScheme); | ||
} | ||
/** | ||
@@ -105,3 +127,3 @@ * Parse Security Scheme Object | ||
[hasKey('description'), parseString(context, name, false)], | ||
[passThrough, e => e], | ||
[outerPassThrough, e => e], | ||
@@ -121,3 +143,3 @@ [isUnsupportedKey, createUnsupportedMemberWarning(namespace, name)], | ||
R.when(isHttpScheme, R.curry(validateHttpScheme)(context)), | ||
// R.when(isOauth2Scheme, parseSecuritySchemeFlowsObject), | ||
R.when(isOauth2Scheme, R.curry(validateOauth2Scheme)(context)), | ||
(securityScheme) => { | ||
@@ -128,3 +150,17 @@ const authScheme = new namespace.elements.AuthScheme(); | ||
const scheme = securityScheme.getValue('scheme'); | ||
const description = securityScheme.get('description'); | ||
if (type === 'oauth2') { | ||
const flows = securityScheme.get('flows'); | ||
if (description) { | ||
flows.forEach((flow) => { | ||
// eslint-disable-next-line no-param-reassign | ||
flow.description = description.clone(); | ||
}); | ||
} | ||
return flows; | ||
} | ||
if (type === 'apiKey' || (type === 'http' && scheme === 'bearer')) { | ||
@@ -134,5 +170,6 @@ authScheme.element = 'Token Authentication Scheme'; | ||
authScheme.element = 'Basic Authentication Scheme'; | ||
} else { | ||
throw new Error(`Invalid security Scheme '${type}' '${scheme}'`); | ||
} | ||
const description = securityScheme.get('description'); | ||
if (description) { | ||
@@ -150,2 +187,4 @@ authScheme.description = description; | ||
key = 'queryParameterName'; | ||
} else if (inValue === 'cookie') { | ||
key = 'cookieName'; | ||
} | ||
@@ -152,0 +191,0 @@ |
@@ -114,4 +114,6 @@ /* eslint-disable no-use-before-define */ | ||
message = `${problem}, ${error.context}`; | ||
} else if (error.context) { | ||
message = error.context; | ||
} else { | ||
message = error.context; | ||
({ message } = error); | ||
} | ||
@@ -125,8 +127,10 @@ | ||
const marker = error.context_mark || error.problem_mark; | ||
copySourceMap( | ||
marker, | ||
marker, | ||
annotation, | ||
namespace | ||
); | ||
if (marker) { | ||
copySourceMap( | ||
marker, | ||
marker, | ||
annotation, | ||
namespace | ||
); | ||
} | ||
@@ -133,0 +137,0 @@ parseResult.push(annotation); |
class State { | ||
constructor() { | ||
this.registeredIds = new Set(); | ||
this.registeredSchemes = new Set(); | ||
this.oauthFlows = {}; | ||
} | ||
@@ -14,4 +17,24 @@ | ||
} | ||
oauthFlow(id, flow) { | ||
this.oauthFlows[id] = this.oauthFlows[id] || new Set(); | ||
this.oauthFlows[id].add(flow); | ||
return this.registerScheme(flow); | ||
} | ||
registerScheme(id) { | ||
if (this.registeredSchemes.has(id)) { | ||
return false; | ||
} | ||
this.registeredSchemes.add(id); | ||
return true; | ||
} | ||
hasScheme(id) { | ||
return this.registeredSchemes.has(id); | ||
} | ||
} | ||
module.exports = State; |
{ | ||
"name": "fury-adapter-oas3-parser", | ||
"version": "0.9.1", | ||
"version": "0.10.0", | ||
"description": "Open API Specification 3 API Elements Parser", | ||
@@ -32,3 +32,3 @@ "author": "Apiary.io <support@apiary.io>", | ||
"peerDependencies": { | ||
"fury": "3.0.0-beta.12" | ||
"fury": "3.0.0-beta.13" | ||
}, | ||
@@ -38,3 +38,3 @@ "devDependencies": { | ||
"eslint": "^5.16.0", | ||
"fury": "3.0.0-beta.12", | ||
"fury": "3.0.0-beta.13", | ||
"mocha": "^5.2.0" | ||
@@ -45,3 +45,3 @@ }, | ||
}, | ||
"gitHead": "35f97c5d690450c1894a6932dc217e166cb853ec" | ||
"gitHead": "92e12bd81f6f5c873b411fa34e7df59cbe1dcc88" | ||
} |
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
128138
43
2957