Closed smoya closed 11 months ago
However, if we use the parser under next-major-spec branch so we parse v3 docs, it does not happen:
That example is technically an invalid v3 document as the channel does not contain the messages being references in the operation. If you add the messages to the v3 doc, does that re-create the problem as in v2?
However, if we use the parser under next-major-spec branch so we parse v3 docs, it does not happen:
That example is technically an invalid v3 document as the channel does not contain the messages being references in the operation. If you add the messages to the v3 doc, does that re-create the problem as in v2?
Yes, I was about to write it right now. Same issue happens with v3 as well. And it's about the pointer.
asyncapi: '3.0.0'
info:
title: Account Service
version: 1.0.0
description: This service is in charge of processing user signups
channels:
UserSignedUp:
messages:
UserSignedUp:
$ref: '#/components/messages/UserSignedUp'
operations:
user/signedup:
action: send
channel:
$ref: '#/channels/UserSignedUp'
messages:
- $ref: '#/components/messages/UserSignedUp'
components:
messages:
UserSignedUp:
payload:
type: object
properties:
displayName:
type: string
description: Name of the user
email:
type: string
format: email
description: Email of the user
Updated description according to previous comment
but your v3 example is not valid either, right?
valid is:
asyncapi: '3.0.0'
info:
title: Account Service
version: 1.0.0
description: This service is in charge of processing user signups
channels:
UserSignedUp:
messages:
UserSignedUp:
$ref: '#/components/messages/UserSignedUp'
operations:
user/signedup:
action: send
channel:
$ref: '#/channels/UserSignedUp'
messages:
- $ref: '#/channels/UserSignedUp/messages/UserSignedUp'
components:
messages:
UserSignedUp:
payload:
type: object
properties:
displayName:
type: string
description: Name of the user
email:
type: string
format: email
description: Email of the user
so you should reference message from a channel, not components. How else will you validate if message referenced from the operation it the same as in the channel? especially that you need to validate the messageId as well, right?
let's take
asyncapi: '2.6.0'
info:
title: Account Service
version: 1.0.0
description: This service is in charge of processing user signups
channels:
user/signedup:
subscribe:
message:
$ref: '#/components/messages/UserSignedUp'
components:
messages:
UserSignedUp:
payload:
type: object
properties:
displayName:
type: string
description: Name of the user
email:
type: string
format: email
description: Email of the user
and converter creates
asyncapi: 3.0.0
info:
title: Account Service
version: 1.0.0
description: This service is in charge of processing user signups
channels:
user/signedup:
address: user/signedup
messages:
subscribe.message:
$ref: '#/components/messages/UserSignedUp'
operations:
user/signedup.subscribe:
action: send
channel:
$ref: '#/channels/user~1signedup'
messages:
- $ref: '#/components/messages/UserSignedUp'
components:
messages:
UserSignedUp:
payload:
type: object
properties:
displayName:
type: string
description: Name of the user
email:
type: string
format: email
description: Email of the user
it is invalid document
messages:
- $ref: '#/components/messages/UserSignedUp'
is not the same as
messages:
subscribe.message:
$ref: '#/components/messages/UserSignedUp'
the id do not match
Whatever you use, it doesn't really matter. The issue keeps happening because the ID of those objects are not used for comparing but the .json()
object of those.
BTW, I just found the bug. This is the callback we use for comparing:
const schemas: Set<SchemaInterface> = new Set();
function callback(schema: SchemaInterface) {
if (!schemas.has(schema.json())) {
schemas.add(schema);
}
}
Source: https://github.com/asyncapi/parser-js/blob/next-major-spec/src/models/v3/asyncapi.ts#L149-L154 (same for v2 model as well)
Note that we check if the schema.json()
is already present in the set, however we never store the output of .json()
on it but the Schema. Meaning if (!schemas.has(schema.json())) {
is always true.
Here is the fix https://github.com/asyncapi/parser-js/pull/897
cc @derberg @jonaslagoni
Describe the bug
document.allSchemas()
method returns duplicated schemas when a schema is referenced from a component. In order to compare if two schemas are equal, we compare against their JSON representation (object.json()
).I compared the JSON string between duplicated and the only thing that changes is the pointer: one refers to the component section, the other to the place where the reference is.
How to Reproduce
Given the following doc:
Parse the document and print all schemas:
This prints the following 6 schemas:
Open
```js {"_json":{"type":"object","properties":{"displayName":{"type":"string","description":"Name of the user","x-parser-schema-id":"The issue seems to be the
pointer
field, which differs from/components/messages/UserSignedUp/...
and /channels/user~1signedup/subscribe/message/...`Shall we skip pointer field when comparing perhaps?
Expected behavior
Schemas should not be duplicated, as in v3. As per the example, only 3 schemas should be returned.