-
-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ref's not resolved in v3 documents #151
Comments
Welcome to AsyncAPI. Thanks a lot for reporting your first issue. Please check out our contributors guide and the instructions about a basic recommended setup useful for opening a pull request. |
I am on this issue, but at the same time, the [
{
code: 'asyncapi3-operation-messages-from-referred-channel',
message: 'Operation message does not belong to the specified channel.',
path: [ 'operations', 'UserSignedUp', 'messages', '0' ],
severity: 0,
range: { start: [Object], end: [Object] }
},
{
code: 'asyncapi3-operation-messages-from-referred-channel',
message: 'Operation message does not belong to the specified channel.',
path: [ 'operations', 'TestOpp', 'messages', '0' ],
severity: 0,
range: { start: [Object], end: [Object] }
}
] So, while I'm checking from my side, I would please ask you to simultaneously check the AsyncAPI Document's format from your side. |
Can I please ask you to be a beta-tester of my PR a bit? Do $ mkdir test
$ cd test/
$ git clone https://github.com/aeworxet/asyncapi-bundler.git .
$ git switch feat-add-x-origin-property # <-- essential, because "@apidevtools/json-schema-ref-parser" has another version in this branch
$ npm install
$ tsc
$ cd example/
$ npm install
# add your testing YAMLs
$ node bundle-cjs.cjs and tell if the PR's code outputs to If the resulting (dereferenced) AsyncAPI Document doesn't pass validation, it outputs an error, similar to Validation of the resulting AsyncAPI Document failed.
List of remarks:
[
{
code: 'asyncapi3-operation-messages-from-referred-channel',
message: 'Operation message does not belong to the specified channel.',
path: [ 'operations', 'UserSignedUp', 'messages', '0' ],
severity: 0,
range: { start: [Object], end: [Object] }
},
{
code: 'asyncapi3-operation-messages-from-referred-channel',
message: 'Operation message does not belong to the specified channel.',
path: [ 'operations', 'TestOpp', 'messages', '0' ],
severity: 0,
range: { start: [Object], end: [Object] }
}
] and exits without writing to |
Currently, bundler is only resolving the references in channels and operations, I think that is why |
Thank you @aeworxet - great work on this feature so far. I've been playing with your fork and find it works well for me. I did have a few errors in my original files that caused the validation issues you pointed out. I'm attaching new files that pass validation, and resolve correctly using your beta bundler. main.yaml: asyncapi: 3.0.0
info:
$ref: './info.yaml#/info'
channels:
userSignedup:
address: 'user/signedup'
messages:
userSignedUpMessage:
$ref: './messages.yaml#/messages/UserSignedUp'
test:
address: '/test'
messages:
testMessage:
$ref: '#/components/messages/TestMessage'
operations:
UserSignedUp:
action: send
channel:
$ref: '#/channels/userSignedup'
messages:
- $ref: '#/channels/userSignedup/messages/userSignedUpMessage'
TestOpp:
action: send
channel:
$ref: '#/channels/test'
messages:
- $ref: '#/channels/test/messages/testMessage'
components:
messages:
TestMessage:
payload:
type: string info.yaml: info:
title: Account Service
version: 1.0.0
description: This service is in charge of processing user signups messages.yaml: messages:
UserSignedUp:
payload:
type: object
properties:
displayName:
type: string
description: Name of the user
email:
type: string
format: email
description: Email of the user
UserLoggedIn:
payload:
type: object
properties:
id:
type: string I have only been validating my files after bundling, which is why I didn't notice the validation errors before posting. My view has been the multi-file spec is treated as "source" and the bundler produces the final output. I can see flaws in this logic though, and do agree it is better to have validation at each step. I assume asyncapi is promoting a src -> bundler -> optimizer workflow, with validation each step of the way. I, however, was not able to resolve references to entire channel and operation objects, due to how the bundler resolves objects in-line instead of moving them to the components section for reuse. It would be very convenient to be able to do something like: main.yaml: asyncapi: 3.0.0
info:
$ref: './info.yaml#/info'
channels:
userLoggedIn:
$ref: './channels.yaml#/channels/userLoggedIn'
operations:
UserLoggedIn:
$ref: './operations.yaml#/operations/UserLoggedIn' info.yaml: info:
title: Account Service
version: 1.0.0
description: This service is in charge of processing user signups messages.yaml: messages:
UserLoggedIn:
payload:
type: object
properties:
id:
type: string channels.yaml: channels:
userLoggedIn:
address: 'user/loggedin'
messages:
userLoggedInMessage:
$ref: './messages.yaml#/messages/UserLoggedIn' operations.yaml operations:
UserLoggedIn:
action: send
channel:
$ref: './channels.yaml#/channels/userLoggedIn'
messages:
- $ref: './messages.yaml#/messages/UserLoggedIn' The above gets a validation error:
Failed Document: {
"asyncapi": "3.0.0",
"info": {
"x-origin": "./info.yaml#/info",
"title": "Account Service",
"version": "1.0.0",
"description": "This service is in charge of processing user signups"
},
"channels": {
"userLoggedIn": {
"x-origin": "./channels.yaml#/channels/userLoggedIn",
"address": "user/loggedin",
"messages": {
"userLoggedInMessage": {
"payload": {
"type": "object",
"properties": {
"id": {
"type": "string"
}
}
}
}
}
}
},
"operations": {
"UserLoggedIn": {
"x-origin": "./operations.yaml#/operations/UserLoggedIn",
"action": "send",
"channel": {
"$ref": "./channels.yaml#/channels/userLoggedIn"
},
"messages": [
{
"$ref": "./messages.yaml#/messages/UserLoggedIn"
}
]
}
}
} This error seems to be due to bundler resolving objects in-line instead of moving them to the components section for reuse. You can see how the channel message gets resolved in-line, and the operation fails to resolve entirely. Maybe optimizer takes care of this, but it would be nice to have it happen at bundling time so the source documents can be written more efficiently. Maybe I missed something though? Might be wishful thinking, but it would be even more convenient to bulk reference, like: main.yaml: asyncapi: 3.0.0
info:
$ref: './info.yaml#/info'
channels:
$ref: './channels.yaml#/channels'
operations:
$ref: './operations.yaml#/operations' Overall, the beta bundler clearly seems headed in a great direction. |
After completion of #141, the process Meanwhile, I'm gathering feedback during the development. @SnakeDoc |
@aeworxet Thanks for the follow-up. I've reviewed #141 and can offer a few thoughts:
Two different messages can share the same payload (schema), but have different headers, etc, or even be exactly the same. Duplicating and in-lining the payload definition seems unnecessary, and perhaps incorrectly hints that the two definitions are not the same object. I think the primary audience for bundled & optimized documents is mostly code/documentation generators, and to a much lesser extent, actual people. Therefore, the verbosity and complex references produced using the schema option probably doesn't matter much in my opinion. Further - from a document writer perspective (document source, pre-bundler and pre-optimizer), I want to clearly communicate my intentions, and re-use as much as possible wherever possible (DRY). Modularity of various components also greatly enhances the maintainability of larger documents as the api grows. I would love to do something like: main.yamlasyncapi: 3.0.0
info:
title: Example Service
version: 1.0.0
description: Example Service.
channels:
commentLikedChannel:
$ref: './channels.yaml#/channels/commentLikedChannel' channels.yamlchannels:
commentLikedChannel:
address: comment/liked
messages:
commentLikedMessage:
$ref: './messages.yaml#/messages/commentLikedMessage' messages.yamlmessages:
commentLikedMessage:
description: Message that is being sent when a comment has been liked by someone.
payload:
$ref: './schemas.yaml#/schemas/commentLikedSchema' schemas.yamlschemas:
commentLikedSchema:
type: object
title: commentLikedPayload
properties:
commentId:
$ref: './schemas.yaml#/schemas/idSchema'
idSchema:
type: string
description: an id object and produce this after bundler -> optimizer: asyncapi.yamlasyncapi: 3.0.0
info:
title: Example Service
version: 1.0.0
description: Example Service.
channels:
commentLikedChannel:
$ref: '#/components/channels/commentLikedChannel'
components:
channels:
commentLikedChannel:
address: comment/liked
messages:
commentLikedMessage:
$ref: '#/components/messages/commentLikedMessage'
messages:
commentLikedMessage:
description: Message that is being sent when a comment has been liked by someone.
payload:
$ref: '#/components/schemas/commentLikedSchema'
schemas:
commentLikedSchema:
type: object
title: commentLikedPayload
properties:
commentId:
$ref: '#/components/schemas/idSchema'
idSchema:
type: string
description: an id object |
@SnakeDoc, thank you for the test case!
and your expectations meet everything except @KhudaDad414 |
@SnakeDoc |
and is essential to mindful properties' naming during optimization with
So A switch might be introduced to remove it after the optimization or not to add it at all during bundling if a user doesn't need it, though; this point is completely valid. |
@SnakeDoc, can you please check if it is understandable how to perform this process to achieve this result, using code from PRs #147 and asyncapi/optimizer#216 ? |
@aeworxet excellent work on both #147 and asyncapi/optimizer#216! With latest aeworxet/asyncapi-bundler:feat-add-x-origin-property, I was able to produce the following using the above example: asyncapi.yamlasyncapi: 3.0.0
info:
title: Example Service
version: 1.0.0
description: Example Service.
channels:
commentLikedChannel:
address: comment/liked
messages:
commentLikedMessage:
description: Message that is being sent when a comment has been liked by someone.
payload:
type: object
title: commentLikedPayload
properties:
commentId:
type: string
description: an id object
x-origin: ./schemas.yaml#/schemas/idSchema
x-origin: ./schemas.yaml#/schemas/commentLikedSchema
x-origin: ./messages.yaml#/messages/commentLikedMessage
x-origin: ./channels.yaml#/channels/commentLikedChannel With latest aeworxet/asyncapi-optimizer:feat-add-flag-moveAllToComponents, and the below configuration, the following optimized document was produced: optimizer config{
"output": "YAML",
"rules": {
"reuseComponents": true,
"removeComponents": true,
"moveAllToComponents": true,
"moveDuplicatesToComponents": false
},
"disableOptimizationFor": {
"schema": false
}
} optimized.yamlasyncapi: 3.0.0
info:
title: Example Service
version: 1.0.0
description: Example Service.
channels:
commentLikedChannel:
$ref: '#/components/channels/commentLikedChannel'
components:
schemas:
idSchema:
type: string
description: an id object
x-origin: ./schemas.yaml#/schemas/idSchema
commentLikedSchema:
type: object
title: commentLikedPayload
properties:
commentId:
$ref: '#/components/schemas/idSchema'
x-origin: ./schemas.yaml#/schemas/commentLikedSchema
messages:
commentLikedMessage:
description: Message that is being sent when a comment has been liked by someone.
payload:
$ref: '#/components/schemas/commentLikedSchema'
x-origin: ./messages.yaml#/messages/commentLikedMessage
channels:
commentLikedChannel:
address: comment/liked
messages:
commentLikedMessage:
$ref: '#/components/messages/commentLikedMessage'
x-origin: ./channels.yaml#/channels/commentLikedChannel Which makes me quite happy! 👍 Disabling the schema optimization with schema-false.yamlasyncapi: 3.0.0
info:
title: Example Service
version: 1.0.0
description: Example Service.
channels:
commentLikedChannel:
$ref: '#/components/channels/commentLikedChannel'
components:
messages:
commentLikedMessage:
description: Message that is being sent when a comment has been liked by someone.
payload:
type: object
title: commentLikedPayload
properties:
commentId:
type: string
description: an id object
x-origin: ./schemas.yaml#/schemas/idSchema
x-origin: ./schemas.yaml#/schemas/commentLikedSchema
x-origin: ./messages.yaml#/messages/commentLikedMessage
channels:
commentLikedChannel:
address: comment/liked
messages:
commentLikedMessage:
$ref: '#/components/messages/commentLikedMessage'
x-origin: ./channels.yaml#/channels/commentLikedChannel All of the above validates with @asyncapi/[email protected]. Coupled with the other newly available optimizer configurations, I imagine this covers just about it all. Very good work! |
@SnakeDoc |
There was a |
bundler/src/v3/parser.ts
Line 101 in f4cc6d9
Referencing the linked line - is there a reason the bundler is not being used? As-is, resolving a v3 document only resolves references found within channels and operations. I might be missing something?
ends up outputting
$ref: './info.yaml#/info'
instead of resolving the value of the reference into the final document. The same goes for other parts of the v3 document, including tags, etc.Switching the spec version to 2.6.0 does result in correctly resolved references (ignoring differences between 2.x and 3.x specs).
main.yaml:
messages.yaml:
info.yaml:
expected output:
actual output:
the following test fails when run against the above files:
The text was updated successfully, but these errors were encountered: