Skip to content

Commit

Permalink
fix: clone message payload into x-parser-original-payload (#253)
Browse files Browse the repository at this point in the history
Signed-off-by: Jordan Tucker <[email protected]>

Co-authored-by: Lukasz Gornicki <[email protected]>
  • Loading branch information
Jordan Tucker and derberg authored Mar 29, 2021
1 parent cc570dd commit 5ede87c
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 8 deletions.
6 changes: 5 additions & 1 deletion lib/asyncapiSchemaFormatParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const Ajv = require('ajv');
const ParserError = require('./errors/parser-error');
const asyncapi = require('@asyncapi/specs');
const { improveAjvErrors } = require('./utils');
const cloneDeep = require('lodash.clonedeep');

module.exports = {
parse,
Expand All @@ -11,10 +12,13 @@ module.exports = {
/**
* @private
*/
async function parse({ message, originalAsyncAPIDocument, fileFormat, parsedAsyncAPIDocument, pathToPayload }) {
async function parse({ message, originalAsyncAPIDocument, fileFormat, parsedAsyncAPIDocument, pathToPayload, defaultSchemaFormat }) {
const payload = message.payload;
if (!payload) return;

message['x-parser-original-schema-format'] = message.schemaFormat || defaultSchemaFormat;
message['x-parser-original-payload'] = cloneDeep(message.payload);

const ajv = new Ajv({
jsonPointers: true,
allErrors: true,
Expand Down
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
"ajv": "^6.10.1",
"js-yaml": "^3.13.1",
"json-to-ast": "^2.1.0",
"lodash.clonedeep": "^4.5.0",
"node-fetch": "^2.6.0",
"tiny-merge-patch": "^0.1.2"
},
Expand Down
48 changes: 47 additions & 1 deletion test/asyncapiSchemaFormatParser_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,20 @@ const expect = chai.expect;
describe('asyncapiSchemaFormatParser', function() {
it('should throw an error because of invalid schema', async function() {
const invalidAsyncapi = fs.readFileSync(path.resolve(__dirname, './wrong/invalid-payload-asyncapi-format.json'), 'utf8');

const parsedJSON = JSON.parse(invalidAsyncapi);
parsedJSON.channels.mychannel.publish.message['x-parser-original-payload'] = {
type: 'object',
additionalProperties: [
'invalid_array'
]
};
parsedJSON.channels.mychannel.publish.message['x-parser-original-schema-format'] = 'application/vnd.aai.asyncapi;version=2.0.0';

const expectedErrorObject = {
type: 'https://github.com/asyncapi/parser-js/schema-validation-errors',
title: 'This is not a valid AsyncAPI Schema Object.',
parsedJSON: JSON.parse(invalidAsyncapi),
parsedJSON,
validationErrors: [{
title: '/channels/mychannel/publish/message/payload/additionalProperties should be object,boolean',
location: {
Expand Down Expand Up @@ -78,6 +88,7 @@ describe('asyncapiSchemaFormatParser', function() {
await parser.parse(invalidAsyncapi);
}, expectedErrorObject);
});

it('should not throw error if payload not provided', async function() {
const inputString = `{
"asyncapi": "2.0.0",
Expand All @@ -98,4 +109,39 @@ describe('asyncapiSchemaFormatParser', function() {

expect(async () => await parser.parse(parsedInput)).to.not.throw();
});

it('should deep clone schema into x-parser-original-payload', async function() {
const asyncapi = fs.readFileSync(path.resolve(__dirname, './good/asyncapi-complex-schema.yml'), 'utf8');
const expectedOriginalPayload = {
type: 'object',
properties: {
id: {
description: 'Id of the streetlight.',
minimum: 0,
type: 'integer'
},
lumens: {
description: 'Light intensity measured in lumens.',
minimum: 0,
type: 'integer'
},
sentAt: {
description: 'Date and time when the message was sent.',
format: 'date-time',
type: 'string'
}
}
};
const expectedOriginalSchemaFormat = 'application/vnd.aai.asyncapi;version=2.0.0';

const parsedOutput = await parser.parse(asyncapi);
const parsedMessage = parsedOutput.channel('light/measured').publish().message().json();

expect(parsedMessage.payload).to.have.property('x-parser-schema-id');
expect(parsedMessage).to.have.property('x-parser-original-payload');
expect(parsedMessage).to.have.property('x-parser-original-schema-format');
expect(parsedMessage['x-parser-original-payload']).to.deep.equal(expectedOriginalPayload);
expect(parsedMessage['x-parser-original-payload']).to.not.equal(parsedMessage.payload);
expect(parsedMessage['x-parser-original-schema-format']).to.deep.equal(expectedOriginalSchemaFormat);
});
});
35 changes: 35 additions & 0 deletions test/good/asyncapi-complex-schema.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
asyncapi: '2.0.0'
info:
title: Streetlights API
version: '1.0.0'
description: |
The Smartylighting Streetlights API allows you
to remotely manage the city lights.
license:
name: Apache 2.0
url: 'https://www.apache.org/licenses/LICENSE-2.0'
servers:
mosquitto:
url: mqtt://test.mosquitto.org
protocol: mqtt
channels:
light/measured:
publish:
summary: Inform about environmental lighting conditions for a particular streetlight.
operationId: onLightMeasured
message:
payload:
type: object
properties:
id:
type: integer
minimum: 0
description: Id of the streetlight.
lumens:
type: integer
minimum: 0
description: Light intensity measured in lumens.
sentAt:
type: string
format: date-time
description: Date and time when the message was sent.
Loading

0 comments on commit 5ede87c

Please sign in to comment.