Skip to content

Commit

Permalink
fix issue when multiple operations use same channel (#67)
Browse files Browse the repository at this point in the history
  • Loading branch information
WaleedAshraf authored Aug 22, 2024
1 parent e797260 commit ce1fb58
Show file tree
Hide file tree
Showing 8 changed files with 251 additions and 9 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
Change Log
==========

Version 5.0.1 *(2024-08-22)*
----------------------------
* Fix issue when multiple operations use same channel.

Version 5.0.0 *(2024-07-21)*
----------------------------
### Breaking:
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "asyncapi-validator",
"version": "5.0.0",
"version": "5.0.1",
"description": "message validator through asyncapi schema",
"main": "index.js",
"types": "index.d.ts",
Expand Down
8 changes: 4 additions & 4 deletions src/ValidatorFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ function ValidatorFactory() {
*/
const constructsChannels = (schema, msgIdentifier = '') => {
const channels = {}
const messagesWithOperations = {}
const channelsWithOperations = {}
let messagesWithId = {}

if (schema.operations) {
Object.keys(schema.operations).forEach(operation => {
const channel = schema.operations[operation].channel['x-parser-unique-object-id']
messagesWithOperations[channel] = messagesWithOperations[channel] ? messagesWithOperations[channel].push(operation) : [operation]
channelsWithOperations[channel] = channelsWithOperations[channel] ? channelsWithOperations[channel].concat(operation) : [operation]
})
}

Expand All @@ -52,8 +52,8 @@ const constructsChannels = (schema, msgIdentifier = '') => {
})

// For AsyncAPI 3.x.x
if (messagesWithOperations[c] && messagesWithOperations[c].length) {
messagesWithOperations[c].forEach(operation => {
if (channelsWithOperations[c] && channelsWithOperations[c].length) {
channelsWithOperations[c].forEach(operation => {
const {action, messages} = getMessagesByOperations(schema.operations, operation, msgIdentifier)
channels[c] = {
...channels[c],
Expand Down
2 changes: 1 addition & 1 deletion test/schemas/v3.0.0/streetLights.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ info:
lights.
### Check out its awesome features:
* Turn a specific streetlight on/off 🌃
* Turn a specific streetlight on/off 🌃
* Dim a specific streetlight 😎
* Receive real-time information about environmental lighting conditions 📈
license:
Expand Down
212 changes: 212 additions & 0 deletions test/schemas/v3.0.0/streetLightsMultiMsg.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
asyncapi: 3.0.0
info:
title: Streetlights Kafka API
version: 1.0.0
description: |-
The Smartylighting Streetlights API allows you to remotely manage the city
lights.
### Check out its awesome features:
* Turn a specific streetlight on/off 🌃
* Dim a specific streetlight 😎
* Receive real-time information about environmental lighting conditions 📈
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0
defaultContentType: application/json
servers:
scram-connections:
host: test.mykafkacluster.org:18092
protocol: kafka-secure
description: Test broker secured with scramSha256
security:
- $ref: '#/components/securitySchemes/saslScram'
tags:
- name: env:test-scram
description: >-
This environment is meant for running internal tests through
scramSha256
- name: kind:remote
description: This server is a remote server. Not exposed by the application
- name: visibility:private
description: This resource is private and only available to certain users
mtls-connections:
host: test.mykafkacluster.org:28092
protocol: kafka-secure
description: Test broker secured with X509
security:
- $ref: '#/components/securitySchemes/certs'
tags:
- name: env:test-mtls
description: This environment is meant for running internal tests through mtls
- name: kind:remote
description: This server is a remote server. Not exposed by the application
- name: visibility:private
description: This resource is private and only available to certain users
channels:
lightingMeasured:
address: smartylighting.streetlights.1.0.event.{streetlightId}.lighting.measured
messages:
lightMeasured:
$ref: '#/components/messages/lightMeasured'
description: The topic on which measured values may be produced and consumed.
parameters:
streetlightId:
$ref: '#/components/parameters/streetlightId'
lightTurnOn:
address: smartylighting.streetlights.1.0.action.{streetlightId}.turn.on
messages:
turnOn:
$ref: '#/components/messages/turnOnOff'
turnOff:
$ref: '#/components/messages/turnOnOff'
parameters:
streetlightId:
$ref: '#/components/parameters/streetlightId'
lightTurnOff:
address: smartylighting.streetlights.1.0.action.{streetlightId}.turn.off
messages:
turnOff:
$ref: '#/components/messages/turnOnOff'
turnOn:
$ref: '#/components/messages/turnOnOff'
parameters:
streetlightId:
$ref: '#/components/parameters/streetlightId'
lightsDim:
address: smartylighting.streetlights.1.0.action.{streetlightId}.dim
messages:
dimLight:
$ref: '#/components/messages/dimLight'
parameters:
streetlightId:
$ref: '#/components/parameters/streetlightId'
operations:
receiveLightMeasurement:
action: receive
channel:
$ref: '#/channels/lightingMeasured'
summary: >-
Inform about environmental lighting conditions of a particular
streetlight.
traits:
- $ref: '#/components/operationTraits/kafka'
messages:
- $ref: '#/channels/lightingMeasured/messages/lightMeasured'
turnOn:
action: send
channel:
$ref: '#/channels/lightTurnOff'
traits:
- $ref: '#/components/operationTraits/kafka'
messages:
- $ref: '#/channels/lightTurnOff/messages/turnOn'
turnOff:
action: send
channel:
$ref: '#/channels/lightTurnOff'
traits:
- $ref: '#/components/operationTraits/kafka'
messages:
- $ref: '#/channels/lightTurnOff/messages/turnOff'
dimLight:
action: send
channel:
$ref: '#/channels/lightsDim'
traits:
- $ref: '#/components/operationTraits/kafka'
messages:
- $ref: '#/channels/lightsDim/messages/dimLight'
components:
messages:
lightMeasured:
name: lightMeasured
title: Light measured
summary: >-
Inform about environmental lighting conditions of a particular
streetlight.
contentType: application/json
traits:
- $ref: '#/components/messageTraits/commonHeaders'
payload:
$ref: '#/components/schemas/lightMeasuredPayload'
turnOnOff:
name: turnOnOff
title: Turn on/off
summary: Command a particular streetlight to turn the lights on or off.
traits:
- $ref: '#/components/messageTraits/commonHeaders'
payload:
$ref: '#/components/schemas/turnOnOffPayload'
dimLight:
name: dimLight
title: Dim light
summary: Command a particular streetlight to dim the lights.
traits:
- $ref: '#/components/messageTraits/commonHeaders'
payload:
$ref: '#/components/schemas/dimLightPayload'
schemas:
lightMeasuredPayload:
type: object
required:
- lumens
properties:
lumens:
type: integer
minimum: 0
description: Light intensity measured in lumens.
sentAt:
$ref: '#/components/schemas/sentAt'
turnOnOffPayload:
type: object
properties:
command:
type: string
enum:
- 'on'
- 'off'
description: Whether to turn on or off the light.
sentAt:
$ref: '#/components/schemas/sentAt'
dimLightPayload:
type: object
properties:
percentage:
type: integer
description: Percentage to which the light should be dimmed to.
minimum: 0
maximum: 100
sentAt:
$ref: '#/components/schemas/sentAt'
sentAt:
type: string
format: date-time
description: Date and time when the message was sent.
securitySchemes:
saslScram:
type: scramSha256
description: Provide your username and password for SASL/SCRAM authentication
certs:
type: X509
description: Download the certificate files from service provider
parameters:
streetlightId:
description: The ID of the streetlight.
messageTraits:
commonHeaders:
headers:
type: object
properties:
my-app-header:
type: integer
minimum: 0
maximum: 100
operationTraits:
kafka:
bindings:
kafka:
clientId:
type: string
enum:
- my-app-id
2 changes: 1 addition & 1 deletion test/v3.0.0/streetLights.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe('deviceMessages', () => {
expect(validate).toThrowError(new Error('data must have required property \'lumens\''))
})

it('should not throw error with validate()', () => {
it('should validate lightMeasured', () => {
const validate = validator.validate('lightMeasured', {
lumens: 0,
sentAt: '2019-08-24T14:15:22Z'
Expand Down
26 changes: 26 additions & 0 deletions test/v3.0.0/streetLightsMultiMsg.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const AsyncApiValidator = require('../../index')

describe('deviceMessages', () => {
let validator
beforeEach(async () => {
validator = await AsyncApiValidator.fromSource('./test/schemas/v3.0.0/streetLightsMultiMsg.yml', {
msgIdentifier: 'name'
})
})

it('should validate lightMeasured with channel lightTurnOff', () => {
const validate = validator.validate('turnOnOff', {
command: 'on',
sentAt: '2019-08-24T14:15:22Z'
}, 'lightTurnOff', 'send')
expect(validate).toStrictEqual(true)
})

it('should throw error for channel which is not used in any operation', () => {
const validate = () => validator.validate('turnOnOff', {
command: 'on',
sentAt: '2019-08-24T14:15:22Z'
}, 'lightTurnOn', 'send')
expect(validate).toThrowError(new Error('channel "lightTurnOn" not found'))
})
})

0 comments on commit ce1fb58

Please sign in to comment.