Skip to content

Commit

Permalink
feat: handle AsyncAPI v3 for diff command (#1596)
Browse files Browse the repository at this point in the history
Co-authored-by: Ashish Padhy <[email protected]>
  • Loading branch information
aayushmau5 and Shurtu-gal authored Dec 20, 2024
1 parent 75e17be commit 8ae33c4
Show file tree
Hide file tree
Showing 6 changed files with 284 additions and 37 deletions.
5 changes: 5 additions & 0 deletions .changeset/silent-olives-battle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@asyncapi/cli": patch
---

Handle AsyncAPI v3 in diff command
9 changes: 4 additions & 5 deletions package-lock.json

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

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"@asyncapi/avro-schema-parser": "^3.0.23",
"@asyncapi/bundler": "^0.6.4",
"@asyncapi/converter": "^1.6.2",
"@asyncapi/diff": "^0.4.1",
"@asyncapi/diff": "^0.5.0",
"@asyncapi/generator": "^1.17.25",
"@asyncapi/modelina-cli": "^4.0.0-next.48",
"@asyncapi/openapi-schema-parser": "^3.0.24",
Expand Down Expand Up @@ -172,4 +172,4 @@
"action:test": "cd github-action && make test"
},
"types": "lib/index.d.ts"
}
}
22 changes: 6 additions & 16 deletions src/commands/diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
DiffOverrideJSONError,
} from '../core/errors/diff-error';
import { specWatcher } from '../core/globals';
import { parse, convertToOldAPI } from '../core/parser';
import { parse } from '../core/parser';

import type { SpecWatcherParams } from '../core/globals';
import { diffFlags } from '../core/flags/diff.flags';
Expand Down Expand Up @@ -57,10 +57,6 @@ export default class Diff extends Command {
try {
firstDocument = await load(firstDocumentPath);

if (firstDocument.isAsyncAPI3()) {
this.error('Diff command does not support AsyncAPI v3 yet which was your first document, please checkout https://github.com/asyncapi/diff/issues/154');
}

enableWatch(watchMode, {
spec: firstDocument,
handler: this,
Expand All @@ -83,10 +79,6 @@ export default class Diff extends Command {
try {
secondDocument = await load(secondDocumentPath);

if (secondDocument.isAsyncAPI3()) {
this.error('Diff command does not support AsyncAPI v3 yet which was your second document, please checkout https://github.com/asyncapi/diff/issues/154');
}

enableWatch(watchMode, {
spec: secondDocument,
handler: this,
Expand Down Expand Up @@ -146,9 +138,9 @@ export default class Diff extends Command {
throwOnBreakingChange(diffOutput, outputFormat);
}
} catch (error) {
if (error instanceof DiffBreakingChangeError) {
if (error instanceof DiffBreakingChangeError || error instanceof TypeError) {
this.error(error);
}
}
throw new ValidationError({
type: 'parser-error',
err: error,
Expand Down Expand Up @@ -196,15 +188,13 @@ function genericOutput(diffOutput: AsyncAPIDiff, outputType: string) {
}

async function parseDocuments(command: Command, firstDocument: Specification, secondDocument: Specification, flags: Record<string, any>) {
const { document: newFirstDocumentParsed, status: firstDocumentStatus } = await parse(command, firstDocument, flags);
const { document: newSecondDocumentParsed, status: secondDocumentStatus } = await parse(command, secondDocument, flags);
const { document: firstDocumentParsed, status: firstDocumentStatus } = await parse(command, firstDocument, flags);
const { document: secondDocumentParsed, status: secondDocumentStatus } = await parse(command, secondDocument, flags);

if (!newFirstDocumentParsed || !newSecondDocumentParsed || firstDocumentStatus === 'invalid' || secondDocumentStatus === 'invalid') {
if (!firstDocumentParsed || !secondDocumentParsed || firstDocumentStatus === 'invalid' || secondDocumentStatus === 'invalid') {
return;
}

const firstDocumentParsed = convertToOldAPI(newFirstDocumentParsed);
const secondDocumentParsed = convertToOldAPI(newSecondDocumentParsed);
return { firstDocumentParsed, secondDocumentParsed };
}

Expand Down
249 changes: 249 additions & 0 deletions test/fixtures/specification-v3-diff.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
asyncapi: 3.0.0
id: 'urn:example:com:smartylighting:streetlights:server'
info:
title: AsyncAPI App
version: 1.0.1
description: This is a sample app.
termsOfService: 'https://asyncapi.com/terms/'
contact:
name: API Support
url: 'https://www.asyncapi.com/support'
email: [email protected]
license:
name: Apache 2.0
url: 'https://www.apache.org/licenses/LICENSE-2.0.html'
tags:
- name: e-commerce
- name: another-tag
description: Description...
externalDocs:
description: Find more info here
url: 'https://www.asyncapi.com'
defaultContentType: application/json
servers:
default:
host: 'api.streetlights.smartylighting.com:{port}'
protocol: mqtt
description: Test broker
variables:
port:
description: Secure connection (TLS) is available through port 8883.
default: '8883'
enum:
- '1883'
- '8883'
security:
- $ref: '#/components/securitySchemes/apiKey'
- type: oauth2
flows:
implicit:
authorizationUrl: 'https://example.com/api/oauth/dialog'
availableScopes:
'write:pets': modify pets in your account
'read:pets': read your pets
scopes:
- 'write:pets'
- type: openIdConnect
openIdConnectUrl: https://example.com/api
scopes:
- 'some:scope:1'
- 'some:scope:2'
production:
host: 'api.streetlights.smartylighting.com:{port}'
pathname: /some/path-name
protocol: mqtt
description: Test broker
variables:
port:
description: Secure connection (TLS) is available through port 8883.
default: '1883'
enum:
- '1883'
- '8883'
security:
- $ref: '#/components/securitySchemes/apiKey'
withProtocol:
host: 'api.streetlights.smartylighting.com:{port}'
pathname: /some/path
protocol: mqtt
description: Test broker
variables:
port:
description: Secure connection (TLS) is available through port 8883.
default: '1883'
enum:
- '1883'
- '8883'
security:
- $ref: '#/components/securitySchemes/apiKey'
channels:
'lightingMeasured':
address: 'smartylighting/streetlights/1/0/event/{streetlightId}/lighting/measured'
messages:
lightMeasured:
payload:
type: object
servers:
- $ref: '#/servers/production'
parameters:
streetlightId:
$ref: '#/components/parameters/streetlightId'
'turnOn':
address: 'smartylighting/streetlights/1/0/action/{streetlightId}/turn/on'
messages:
lightMeasured:
$ref: '#/components/messages/lightMeasured'
subscribe.message.0:
$ref: '#/components/messages/turnOnOff'
customMessageId:
payload:
type: object
subscribe.message.2:
payload:
type: object
servers:
- $ref: '#/servers/default'
- $ref: '#/servers/production'
parameters:
streetlightId:
$ref: '#/components/parameters/streetlightId'
customChannelId:
address: 'smartylighting/streetlights/1/0/action/{streetlightId}/turn/off'
messages:
turnOnOff:
$ref: '#/components/messages/turnOnOff'
parameters:
streetlightId:
$ref: '#/components/parameters/streetlightId'
x-channelId: customChannelId
'dim':
address: 'smartylighting/streetlights/1/0/action/{streetlightId}/dim'
messages:
dimLight:
$ref: '#/components/messages/dimLight'
parameters:
streetlightId:
$ref: '#/components/parameters/streetlightId'
operations:
receiveLightMeasured:
action: receive
channel:
$ref: '#/channels/lightingMeasured'
messages:
- $ref: '#/channels/lightingMeasured/messages/lightMeasured'
'receiveTurnOn':
action: receive
channel:
$ref: '#/channels/turnOn'
messages:
- $ref: '#/channels/turnOn/messages/lightMeasured'
'smartylighting/streetlights/1/0/action/{streetlightId}/turn/on.subscribe':
action: send
channel:
$ref: '#/channels/turnOn'
messages:
- $ref: '#/channels/turnOn/messages/customMessageId'
- $ref: '#/channels/turnOn/messages/subscribe.message.2'
turnOnOff:
action: send
channel:
$ref: '#/channels/customChannelId'
messages:
- $ref: '#/channels/customChannelId/messages/turnOnOff'
dimLight:
action: send
channel:
$ref: '#/channels/dim'
security:
- type: oauth2
flows:
implicit:
authorizationUrl: 'https://example.com/api/oauth/dialog'
availableScopes:
'write:pets': modify pets in your account
'read:pets': read your pets
scopes:
- 'write:pets'
messages:
- $ref: '#/channels/dim/messages/dimLight'
components:
messages:
lightMeasured:
summary: >-
Inform about environmental lighting conditions for a particular
streetlight.
payload:
$ref: '#/components/schemas/lightMeasuredPayload'
turnOnOff:
summary: Command a particular streetlight to turn the lights on or off.
payload:
$ref: '#/components/schemas/turnOnOffPayload'
dimLight:
summary: Command a particular streetlight to dim the lights.
payload:
$ref: '#/components/schemas/dimLightPayload'
schemas:
lightMeasuredPayload:
type: object
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:
apiKey:
type: apiKey
in: user
description: Provide your API key as the user and leave the password empty.
flows:
type: oauth2
flows:
implicit:
authorizationUrl: 'https://example.com/api/oauth/dialog'
availableScopes:
'write:pets': modify pets in your account
'read:pets': read your pets
openIdConnect:
type: openIdConnect
openIdConnectUrl: https://example.com/api
scopes:
- 'some:scope:1'
- 'some:scope:2'
unusedFlows:
type: oauth2
flows:
implicit:
authorizationUrl: 'https://example.com/api/oauth/dialog'
availableScopes:
'write:pets': modify pets in your account
'read:pets': read your pets
parameters:
streetlightId:
description: The ID of the streetlight.
Loading

0 comments on commit 8ae33c4

Please sign in to comment.