diff --git a/packages/fury-adapter-oas3-parser/lib/parser/oas/parseMediaTypeObject.js b/packages/fury-adapter-oas3-parser/lib/parser/oas/parseMediaTypeObject.js index 2d3cdfa19..be2f352ad 100644 --- a/packages/fury-adapter-oas3-parser/lib/parser/oas/parseMediaTypeObject.js +++ b/packages/fury-adapter-oas3-parser/lib/parser/oas/parseMediaTypeObject.js @@ -1,5 +1,6 @@ const R = require('ramda'); -const contentType = require('content-type'); +const contentTyper = require('content-type'); +const mediaTyper = require('media-typer'); const pipeParseResult = require('../../pipeParseResult'); const { isExtension, hasKey, getKey, getValue, @@ -19,9 +20,52 @@ const unsupportedKeys = ['encoding']; const isUnsupportedKey = R.anyPass(R.map(hasKey, unsupportedKeys)); function isJSONMediaType(mediaType) { - const type = contentType.parse(mediaType); - const jsonMediaType = /^application\/\S*json$/i; - return jsonMediaType.test(type.type); + const contentType = contentTyper.parse(mediaType); + const { type, suffix, subtype } = mediaTyper.parse(contentType.type); + return type === 'application' && (suffix === 'json' || subtype === 'json'); +} + +function isTextMediaType(mediaType) { + const contentType = contentTyper.parse(mediaType); + const { type } = mediaTyper.parse(contentType.type); + return type === 'text'; +} + +const canGenerateMessageBodyForMediaType = R.anyPass([isJSONMediaType, isTextMediaType]); + +function generateMessageBody(context, mediaType, dataStructure) { + const elements = {}; + const { components } = context.state; + if (components) { + const schemas = components.get('schemas'); + if (schemas) { + schemas.content + .filter(e => e.value && e.value.content) + .forEach((e) => { + const element = e.value.content; + elements[element.id.toValue()] = element; + }); + } + } + + const value = dataStructure.content.valueOf(undefined, elements); + if (!value) { + return undefined; + } + + let body; + if (isJSONMediaType(mediaType)) { + body = JSON.stringify(value); + } else if (isTextMediaType(mediaType) && typeof value === 'string') { + body = value; + } else { + return undefined; + } + + const asset = new context.namespace.elements.Asset(body); + asset.classes.push('messageBody'); + asset.contentType = mediaType; + return asset; } const createJSONMessageBodyAsset = R.curry((namespace, mediaType, value) => { @@ -46,7 +90,7 @@ const parseExampleObjectOrRef = parseReference('examples', parseExampleObject); const isValidMediaType = (mediaType) => { try { - contentType.parse(mediaType.toValue()); + contentTyper.parse(mediaType.toValue()); } catch (error) { return false; } @@ -133,28 +177,9 @@ function parseMediaTypeObject(context, MessageBodyClass, element) { const dataStructure = mediaTypeObject.get('schema'); - if (!messageBody && dataStructure && isJSONMediaType(mediaType)) { - const elements = {}; - const { components } = context.state; - if (components) { - const schemas = components.get('schemas'); - if (schemas) { - schemas.content - .filter(e => e.value && e.value.content) - .forEach((e) => { - const element = e.value.content; - elements[element.id.toValue()] = element; - }); - } - } - - 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; + if (!messageBody && dataStructure && canGenerateMessageBodyForMediaType(mediaType)) { + const asset = generateMessageBody(context, mediaType, dataStructure); + if (asset) { message.push(asset); } } diff --git a/packages/fury-adapter-oas3-parser/package.json b/packages/fury-adapter-oas3-parser/package.json index de981326f..5bce1df07 100644 --- a/packages/fury-adapter-oas3-parser/package.json +++ b/packages/fury-adapter-oas3-parser/package.json @@ -24,6 +24,7 @@ }, "dependencies": { "content-type": "^1.0.4", + "media-typer": "^1.0.1", "ramda": "0.26.1", "yaml-js": "^0.2.3" }, diff --git a/packages/fury-adapter-oas3-parser/test/unit/parser/oas/parseMediaTypeObject-test.js b/packages/fury-adapter-oas3-parser/test/unit/parser/oas/parseMediaTypeObject-test.js index 08670a7c2..def7a3747 100644 --- a/packages/fury-adapter-oas3-parser/test/unit/parser/oas/parseMediaTypeObject-test.js +++ b/packages/fury-adapter-oas3-parser/test/unit/parser/oas/parseMediaTypeObject-test.js @@ -348,5 +348,36 @@ describe('Media Type Object', () => { expect(message.messageBody.toValue()).to.equal('{"parents":[]}'); expect(message.messageBody.contentType.toValue()).to.equal('application/json'); }); + + it('generates an messageBody asset for text type with string schema', () => { + const mediaType = new namespace.elements.Member('text/plain', { + schema: { + type: 'string', + example: 'hello world', + }, + }); + + const parseResult = parse(context, messageBodyClass, mediaType); + + const message = parseResult.get(0); + expect(message).to.be.instanceof(messageBodyClass); + expect(message.messageBody.toValue()).to.equal('hello world'); + expect(message.messageBody.contentType.toValue()).to.equal('text/plain'); + }); + + it('does not generates an messageBody asset for text type with non string type', () => { + const mediaType = new namespace.elements.Member('text/plain', { + schema: { + type: 'number', + example: 5, + }, + }); + + const parseResult = parse(context, messageBodyClass, mediaType); + + const message = parseResult.get(0); + expect(message).to.be.instanceof(messageBodyClass); + expect(message.messageBody).to.be.undefined; + }); }); });