Skip to content
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

feat: support AsyncAPI spec v3 #193

Merged
merged 14 commits into from
Dec 19, 2023
2 changes: 1 addition & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
}
],
"no-console": "error",
"wrap-regex": 2,
"wrap-regex": 0,
//"linebreak-style": ["error", "unix"],
"linebreak-style": 0,
"arrow-spacing": [
Expand Down
89 changes: 7 additions & 82 deletions examples/index.js
Original file line number Diff line number Diff line change
@@ -1,94 +1,19 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { Optimizer } = require('../lib/Optimizer')

const yaml = `
asyncapi: 2.0.0
info:
title: Streetlights API
version: '1.0.0'
channels:
smartylighting/event/{streetlightId}/lighting/measured:
parameters:
#this parameter is duplicated. it can be moved to components and ref-ed from here.
streetlightId:
schema:
type: string
subscribe:
operationId: receiveLightMeasurement
traits:
- bindings:
kafka:
clientId: my-app-id
message:
name: lightMeasured
title: Light measured
contentType: application/json
traits:
- headers:
type: object
properties:
my-app-header:
type: integer
minimum: 0
maximum: 100
payload:
type: object
properties:
lumens:
type: integer
minimum: 0
#full form is used, we can ref it to: #/components/schemas/sentAt
sentAt:
type: string
format: date-time
smartylighting/action/{streetlightId}/turn/on:
parameters:
streetlightId:
schema:
type: string
publish:
operationId: turnOn
traits:
- bindings:
kafka:
clientId: my-app-id
message:
name: turnOnOff
title: Turn on/off
traits:
- headers:
type: object
properties:
my-app-header:
type: integer
minimum: 0
maximum: 100
payload:
type: object
properties:
sentAt:
$ref: "#/components/schemas/sentAt"
components:
messages:
#libarary should be able to find and delete this message, because it is not used anywhere.
unusedMessage:
name: unusedMessage
title: This message is not used in any channel.

schemas:
#this schema is ref-ed in one channel and used full form in another. library should be able to identify and ref the second channel as well.
sentAt:
type: string
format: date-time`
const optimizer = new Optimizer(yaml)
// read input.yaml file synconously and store it as an string
const input = require('fs').readFileSync('./examples/input.yaml', 'utf8')
const optimizer = new Optimizer(input)
optimizer.getReport().then((report) => {
//console.log(JSON.stringify(report))
console.log(JSON.stringify(report))
const optimizedDocument = optimizer.getOptimizedDocument({
output: 'JSON',
rules: {
reuseComponents: true,
removeComponents: true,
moveToComponents: true,
},
})
console.log(optimizedDocument)
//store optimizedDocument as to output.yaml
require('fs').writeFileSync('./examples/output.yaml', optimizedDocument)
})
93 changes: 93 additions & 0 deletions examples/input.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
{
'asyncapi': '3.0.0',
'info':
{
'title': 'Untidy AsyncAPI file',
'version': '1.0.0',
'description': 'This file contains duplicate and unused messages across the file and is used to test the optimizer.',
},
'channels':
{
'withDuplicatedMessage1':
{
'address': 'user/signedup',
'messages':
{ 'duped1': { 'payload': { 'type': 'object', 'description': 'I am duplicated' } } },
},
'withDuplicatedMessage2':
{
'address': 'user/signedup',
'messages':
{ 'duped2': { 'payload': { 'type': 'object', 'description': 'I am duplicated' } } },
},
'withFullFormMessage':
{
'address': 'user/signedup',
'messages':
{
'canBeReused': { 'payload': { 'type': 'object', 'description': 'I can be reused.' } },
},
},
'UserSignedUp1':
{
'address': 'user/signedup',
'messages': { 'myMessage': { '$ref': '#/components/messages/UserSignedUp' } },
},
'UserSignedUp2':
{
'address': 'user/signedup',
'messages': { 'myMessage': { '$ref': '#/components/messages/UserSignedUp' } },
},
'deleteAccount':
{
'address': 'user/deleteAccount',
'messages': { 'deleteUser': { '$ref': '#/components/messages/DeleteUser' } },
},
},
'operations':
{
'user/deleteAccount.subscribe':
{
'action': 'send',
'channel': { '$ref': '#/channels/deleteAccount' },
'messages': [{ '$ref': '#/components/messages/DeleteUser' }],
},
},
'components':
{
'channels':
{
'unUsedChannel':
{
'address': 'user/unused',
'messages': { 'myMessage': { '$ref': '#/components/messages/UserSignedUp' } },
},
},
'schemas': { 'canBeReused': { 'type': 'object', 'description': 'I can be reused.' } },
'messages':
{
'unUsedMessage': { 'payload': { 'type': 'boolean' } },
'DeleteUser':
{
'payload':
{
'type': 'string',
'description': 'userId of the user that is going to be deleted',
},
},
'UserSignedUp':
{
'payload':
{
'type': 'object',
'properties':
{
'displayName': { 'type': 'string', 'description': 'Name of the user' },
'email':
{ 'type': 'string', 'format': 'email', 'description': 'Email of the user' },
},
},
},
},
},
}
1 change: 1 addition & 0 deletions examples/output.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"asyncapi":"3.0.0","info":{"title":"Untidy AsyncAPI file","version":"1.0.0","description":"This file contains duplicate and unused messages across the file and is used to test the optimizer."},"channels":{"withDuplicatedMessage1":{"address":"user/signedup","messages":{"duped1":{"$ref":"#/components/messages/message-1"}}},"withDuplicatedMessage2":{"address":"user/signedup","messages":{"duped2":{"$ref":"#/components/messages/message-1"}}},"withFullFormMessage":{"address":"user/signedup","messages":{"canBeReused":{"payload":{"$ref":"#/components/schemas/canBeReused"}}}},"UserSignedUp1":{"$ref":"#/components/channels/channel-1"},"UserSignedUp2":{"$ref":"#/components/channels/channel-1"},"deleteAccount":{"address":"user/deleteAccount","messages":{"deleteUser":{"$ref":"#/components/messages/DeleteUser"}}}},"operations":{"user/deleteAccount.subscribe":{"action":"send","channel":{"$ref":"#/channels/deleteAccount"},"messages":[{"$ref":"#/components/messages/DeleteUser"}]}},"components":{"schemas":{"canBeReused":{"type":"object","description":"I can be reused."},"schema-1":{"type":"object","description":"I am duplicated"}},"messages":{"DeleteUser":{"payload":{"type":"string","description":"userId of the user that is going to be deleted"}},"UserSignedUp":{"payload":{"type":"object","properties":{"displayName":{"type":"string","description":"Name of the user"},"email":{"type":"string","format":"email","description":"Email of the user"}}}},"message-1":{"payload":{"$ref":"#/components/schemas/schema-1"}}},"channels":{"channel-1":{"address":"user/signedup","messages":{"myMessage":{"$ref":"#/components/messages/UserSignedUp"}}}}}}
50 changes: 38 additions & 12 deletions package-lock.json

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

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"test": "jest --coverage",
"test:watch": "jest --watch",
"build": "tsc",
"dev": "tsc --watch",
"docs": "jsdoc2md lib/Optimizer.js -f lib/**/*.js > API.md",
"example": "tsc && node examples/index.js",
"lint": "eslint --max-warnings 0 --config .eslintrc .",
Expand Down Expand Up @@ -56,10 +57,12 @@
},
"dependencies": {
"@asyncapi/parser": "^3.0.2",
"@types/debug": "^4.1.8",
"debug": "^4.3.4",
"js-yaml": "^4.1.0",
"jsonpath-plus": "^6.0.1",
"lodash": "^4.17.21",
"merge-deep": "^3.0.3",
"yaml": "^2.3.1"
}
}
}