diff --git a/.sonarcloud.properties b/.sonarcloud.properties new file mode 100644 index 00000000..4f1a81cc --- /dev/null +++ b/.sonarcloud.properties @@ -0,0 +1 @@ +sonar.exclusions=test/integration.test.js \ No newline at end of file diff --git a/README.md b/README.md index 7df394b8..cd00072c 100644 --- a/README.md +++ b/README.md @@ -64,12 +64,12 @@ $ npm install -g @asyncapi/cli # Run generation from the root of the template to use tes MQTT example # To use the template -$ asyncapi generate fromTemplate test/mocks/mqtt/asyncapi.yml @asyncapi/nodejs-template -o test/output -p server=production +$ asyncapi generate fromTemplate test/mocks/mqtt/asyncapi-v3.yml @asyncapi/nodejs-template -o test/output -p server=production # OR # To test your local changes provided inside template -$ asyncapi generate fromTemplate test/mocks/mqtt/asyncapi.yml ./ -o test/output -p server=production +$ asyncapi generate fromTemplate test/mocks/mqtt/asyncapi-v3.yml ./ -o test/output -p server=production ## ## Install dependencies of generated library @@ -100,10 +100,6 @@ $ npm run test:example $ npm install mqtt -g #You should see the sent message in the logs of the started example. -#Notice that the server automatically validates incoming messages and logs out validation errors - -#publish an invalid message. -$ mqtt pub -t 'smartylighting/streetlights/1/0/event/123/lighting/measured' -h 'test.mosquitto.org' -m '{"id": 1, "lumens": "3", "sentAt": "2017-06-07T12:34:32.000Z"}' #publish a valid message $ mqtt pub -t 'smartylighting/streetlights/1/0/event/123/lighting/measured' -h 'test.mosquitto.org' -m '{"id": 1, "lumens": 3, "sentAt": "2017-06-07T12:34:32.000Z"}' @@ -123,7 +119,6 @@ To avoid this, user code remains external to the generated code, functioning as Facilitating this separation involves creating handlers and associating them with their respective routes. These handlers can then be seamlessly integrated into the template's workflow by importing the appropriate methods to register the handlers. In doing so, the template's `client.registerMiddleware` method becomes the bridge between the user-written handlers and the generated code. This can be used to register middlewares for specific methods on specific channels. Look closely into [example script](test/example/script.js) that works with library generated using [this MQTT based AsyncAPI document](test/mocks/mqtt/asyncapi.yml). Look at available handlers API for reading incomming messages and processing outgoing messages. Learn how to start generated server with `init()` and also learn how to send messages, if needed. -``` ## Template configuration diff --git a/helpers/channels-topics.js b/helpers/channels-topics.js index 05772ee4..5d8d60ff 100644 --- a/helpers/channels-topics.js +++ b/helpers/channels-topics.js @@ -50,12 +50,8 @@ export function toHermesTopic(str) { return str.replace(/\{([^}]+)\}/g, ':$1'); } -export function channelNamesWithPublish(asyncapi) { - const result = []; - asyncapi.channelNames().forEach((name) => { - if (asyncapi.channel(name).hasPublish()) result.push(name); - }); - return result; +export function channelNamesWithReceive(asyncapi) { + return asyncapi.channels().filterByReceive().map(channel => channel.address()); } export function host(url) { @@ -151,4 +147,4 @@ export function getProtocol(p) { // https://mozilla.github.io/nunjucks/templating.html#dump export function dump(obj) { return JSON.stringify(obj); -} +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 46e8a44e..63ec6870 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,19 +13,19 @@ "@asyncapi/generator-hooks": "^0.1.0", "@asyncapi/generator-react-sdk": "^1.0.18", "eslint-plugin-react": "^7.34.1", - "filenamify": "^4.1.0", + "filenamify": "^4.3.0", "js-beautify": "^1.15.1", - "lodash": "^4.17.15", + "lodash": "^4.17.21", "markdown-toc": "^1.2.0" }, "devDependencies": { "@asyncapi/generator": "^1.17.25", - "eslint": "^8.7.0", + "eslint": "^8.57.0", "eslint-plugin-jest": "^25.7.0", "eslint-plugin-sonarjs": "^0.11.0", - "jest": "^27.3.1", - "node-fetch": "^2.6.1", - "rimraf": "^5.0.1" + "jest": "^27.5.1", + "node-fetch": "^2.7.0", + "rimraf": "^5.0.5" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -320,9 +320,9 @@ } }, "node_modules/@asyncapi/specs": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-6.6.0.tgz", - "integrity": "sha512-pXJa0sCeBpif5al5CSa0f3HvwVBQXzd96/Xgq8Jsh6KM4CYxCe7p6paaC9fDjdBVXyWAioQmZiGRxEVUMINbUw==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-6.7.0.tgz", + "integrity": "sha512-TygnAHctm0e7Y55Zy2PBjE6t/jai/txu4MZiyHkcbom9WQoC6Nl7M1M3TQQMzDrb5iLZtuRDm1GAwvawZPPn5A==", "dependencies": { "@types/json-schema": "^7.0.11" } @@ -340,9 +340,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.1.tgz", - "integrity": "sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", + "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", "engines": { "node": ">=6.9.0" } @@ -444,18 +444,18 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.1.tgz", - "integrity": "sha512-1yJa9dX9g//V6fDebXoEfEsxkZHk3Hcbm+zLhyu6qVgYFLvmTALTeV+jNU9e5RnYtioBrGEOdoI2joMSNQ/+aA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.5.tgz", + "integrity": "sha512-uRc4Cv8UQWnE4NXlYTIIdM7wfFkOqlFztcC/gVXDKohKoVB3OyonfelUBaJzSwpBntZ2KYGF/9S7asCHsXwW6g==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", - "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.24.5", "@babel/helper-optimise-call-expression": "^7.22.5", "@babel/helper-replace-supers": "^7.24.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-split-export-declaration": "^7.24.5", "semver": "^6.3.1" }, "engines": { @@ -498,9 +498,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.1.tgz", - "integrity": "sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", @@ -544,11 +544,11 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.5.tgz", + "integrity": "sha512-4owRteeihKWKamtqg4JmWSsEZU445xpFRXPEwp44HbgbxdWlUV1b4Agg4lkA806Lil5XM/e+FJyS0vj5T6vmcA==", "dependencies": { - "@babel/types": "^7.23.0" + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -595,9 +595,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", - "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz", + "integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==", "engines": { "node": ">=6.9.0" } @@ -657,11 +657,11 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz", + "integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -676,9 +676,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", + "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==", "engines": { "node": ">=6.9.0" } @@ -692,13 +692,13 @@ } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", - "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.5.tgz", + "integrity": "sha512-/xxzuNvgRl4/HLNKvnFwdhdgN3cpLxgLROeLDl83Yx0AJ1SGvq1ak0OszTOjDfiB8Vx03eJbeDWh9r+jCCWttw==", "dependencies": { - "@babel/helper-function-name": "^7.22.5", - "@babel/template": "^7.22.15", - "@babel/types": "^7.22.19" + "@babel/helper-function-name": "^7.23.0", + "@babel/template": "^7.24.0", + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -742,6 +742,21 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.5.tgz", + "integrity": "sha512-LdXRi1wEMTrHVR4Zc9F8OewC3vdm5h4QB6L71zy6StmYeqGi1b3ttIO8UC+BfZKcH9jdr4aI249rBkm+3+YvHw==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.24.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.24.1", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.1.tgz", @@ -1118,11 +1133,11 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.1.tgz", - "integrity": "sha512-h71T2QQvDgM2SmT29UYU6ozjMlAt7s7CSs5Hvy8f8cf/GM/Z4a2zMfN+fjVGaieeCrXR3EdQl6C4gQG+OgmbKw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.5.tgz", + "integrity": "sha512-sMfBc3OxghjC95BkYrYocHL3NaOplrcaunblzwXhGmlPwpmfsxr4vK+mBBt49r+S240vahmv+kUxkeKgs+haCw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -1147,11 +1162,11 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.1.tgz", - "integrity": "sha512-FUHlKCn6J3ERiu8Dv+4eoz7w8+kFLSyeVG4vDAikwADGjUCoHw/JHokyGtr8OR4UjpwPVivyF+h8Q5iv/JmrtA==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.4.tgz", + "integrity": "sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-create-class-features-plugin": "^7.24.4", "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, @@ -1163,17 +1178,17 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.1.tgz", - "integrity": "sha512-ZTIe3W7UejJd3/3R4p7ScyyOoafetUShSf4kCqV0O7F/RiHxVj/wRaRnQlrGwflvcehNA8M42HkAiEDYZu2F1Q==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.5.tgz", + "integrity": "sha512-gWkLP25DFj2dwe9Ck8uwMOpko4YsqyfZJrOmqqcegeDYEbp7rmn4U6UQZNj08UF6MaX39XenSpKRCvpDRBtZ7Q==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-plugin-utils": "^7.24.5", "@babel/helper-replace-supers": "^7.24.1", - "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-split-export-declaration": "^7.24.5", "globals": "^11.1.0" }, "engines": { @@ -1199,11 +1214,11 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz", - "integrity": "sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.5.tgz", + "integrity": "sha512-SZuuLyfxvsm+Ah57I/i1HVjveBENYK9ue8MJ7qkc7ndoNjqquJiElzA7f5yaAXjyW2hKojosOTAQQRX50bPSVg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -1498,14 +1513,14 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.1.tgz", - "integrity": "sha512-XjD5f0YqOtebto4HGISLNfiNMTTs6tbkFf2TOqJlYKYmbo+mN9Dnpl4SRoofiziuOWMIyq3sZEUqLo3hLITFEA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.5.tgz", + "integrity": "sha512-7EauQHszLGM3ay7a161tTQH7fj+3vVM/gThlz5HpFtnygTxjrlvoeq7MPVA1Vy9Q555OB8SnAOsMkLShNkkrHA==", "dependencies": { "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-plugin-utils": "^7.24.5", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.24.1" + "@babel/plugin-transform-parameters": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -1545,11 +1560,11 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.1.tgz", - "integrity": "sha512-n03wmDt+987qXwAgcBlnUUivrZBPZ8z1plL0YvgQalLm+ZE5BMhGm94jhxXtA1wzv1Cu2aaOv1BM9vbVttrzSg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.5.tgz", + "integrity": "sha512-xWCkmwKT+ihmA6l7SSTpk8e4qQl/274iNbSKRRS8mpqFR32ksy36+a+LWY8OXCCEefF8WFlnOHVsaDI2231wBg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-plugin-utils": "^7.24.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, @@ -1561,11 +1576,11 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.1.tgz", - "integrity": "sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.5.tgz", + "integrity": "sha512-9Co00MqZ2aoky+4j2jhofErthm6QVLKbpQrvz20c3CH9KQCLHyNB+t2ya4/UrRpQGR+Wrwjg9foopoeSdnHOkA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -1590,13 +1605,13 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.1.tgz", - "integrity": "sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.5.tgz", + "integrity": "sha512-JM4MHZqnWR04jPMujQDTBVRnqxpLLpx2tkn7iPn+Hmsc0Gnb79yvRWOkvqFOx3Z7P7VxiRIR22c4eGSNj87OBQ==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-create-class-features-plugin": "^7.24.5", + "@babel/helper-plugin-utils": "^7.24.5", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { @@ -1768,11 +1783,11 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.1.tgz", - "integrity": "sha512-CBfU4l/A+KruSUoW+vTQthwcAdwuqbpRNB8HQKlZABwHRhsdHZ9fezp4Sn18PeAlYxTNiLMlx4xUBV3AWfg1BA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.5.tgz", + "integrity": "sha512-UTGnhYVZtTAjdwOTzT+sCyXmTn8AhaxOS/MjG9REclZ6ULHWF9KoCZur0HSGU7hk8PdBFKKbYe6+gqdXWz84Jg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -1841,14 +1856,15 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.3.tgz", - "integrity": "sha512-fSk430k5c2ff8536JcPvPWK4tZDwehWLGlBp0wrsBUjZVdeQV6lePbwKWZaZfK2vnh/1kQX1PzAJWsnBmVgGJA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.5.tgz", + "integrity": "sha512-UGK2ifKtcC8i5AI4cH+sbLLuLc2ktYSFJgBAXorKAsHUZmrQ1q6aQ6i3BvU24wWs2AAKqQB6kq3N9V9Gw1HiMQ==", "dependencies": { - "@babel/compat-data": "^7.24.1", + "@babel/compat-data": "^7.24.4", "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-plugin-utils": "^7.24.5", "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.5", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.1", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.1", "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.1", @@ -1875,12 +1891,12 @@ "@babel/plugin-transform-async-generator-functions": "^7.24.3", "@babel/plugin-transform-async-to-generator": "^7.24.1", "@babel/plugin-transform-block-scoped-functions": "^7.24.1", - "@babel/plugin-transform-block-scoping": "^7.24.1", + "@babel/plugin-transform-block-scoping": "^7.24.5", "@babel/plugin-transform-class-properties": "^7.24.1", - "@babel/plugin-transform-class-static-block": "^7.24.1", - "@babel/plugin-transform-classes": "^7.24.1", + "@babel/plugin-transform-class-static-block": "^7.24.4", + "@babel/plugin-transform-classes": "^7.24.5", "@babel/plugin-transform-computed-properties": "^7.24.1", - "@babel/plugin-transform-destructuring": "^7.24.1", + "@babel/plugin-transform-destructuring": "^7.24.5", "@babel/plugin-transform-dotall-regex": "^7.24.1", "@babel/plugin-transform-duplicate-keys": "^7.24.1", "@babel/plugin-transform-dynamic-import": "^7.24.1", @@ -1900,13 +1916,13 @@ "@babel/plugin-transform-new-target": "^7.24.1", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.1", "@babel/plugin-transform-numeric-separator": "^7.24.1", - "@babel/plugin-transform-object-rest-spread": "^7.24.1", + "@babel/plugin-transform-object-rest-spread": "^7.24.5", "@babel/plugin-transform-object-super": "^7.24.1", "@babel/plugin-transform-optional-catch-binding": "^7.24.1", - "@babel/plugin-transform-optional-chaining": "^7.24.1", - "@babel/plugin-transform-parameters": "^7.24.1", + "@babel/plugin-transform-optional-chaining": "^7.24.5", + "@babel/plugin-transform-parameters": "^7.24.5", "@babel/plugin-transform-private-methods": "^7.24.1", - "@babel/plugin-transform-private-property-in-object": "^7.24.1", + "@babel/plugin-transform-private-property-in-object": "^7.24.5", "@babel/plugin-transform-property-literals": "^7.24.1", "@babel/plugin-transform-regenerator": "^7.24.1", "@babel/plugin-transform-reserved-words": "^7.24.1", @@ -1914,7 +1930,7 @@ "@babel/plugin-transform-spread": "^7.24.1", "@babel/plugin-transform-sticky-regex": "^7.24.1", "@babel/plugin-transform-template-literals": "^7.24.1", - "@babel/plugin-transform-typeof-symbol": "^7.24.1", + "@babel/plugin-transform-typeof-symbol": "^7.24.5", "@babel/plugin-transform-unicode-escapes": "^7.24.1", "@babel/plugin-transform-unicode-property-regex": "^7.24.1", "@babel/plugin-transform-unicode-regex": "^7.24.1", @@ -1979,9 +1995,9 @@ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" }, "node_modules/@babel/runtime": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz", - "integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz", + "integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -2023,12 +2039,12 @@ } }, "node_modules/@babel/types": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", - "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", + "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-string-parser": "^7.24.1", + "@babel/helper-validator-identifier": "^7.24.5", "to-fast-properties": "^2.0.0" }, "engines": { @@ -4888,12 +4904,12 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz", - "integrity": "sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ==", + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", "dependencies": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.1", + "@babel/helper-define-polyfill-provider": "^0.6.2", "semver": "^6.3.1" }, "peerDependencies": { @@ -4921,11 +4937,11 @@ } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.1.tgz", - "integrity": "sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.1" + "@babel/helper-define-polyfill-provider": "^0.6.2" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -5503,9 +5519,9 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, "node_modules/core-js-compat": { - "version": "3.36.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.1.tgz", - "integrity": "sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA==", + "version": "3.37.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.0.tgz", + "integrity": "sha512-vYq4L+T8aS5UuFg4UwDhc7YNRWVeVZwltad9C/jV3R2LgVOpS9BDr7l/WL6BN0dbV3k1XejPTHqqEzJgsa0frA==", "dependencies": { "browserslist": "^4.23.0" }, @@ -14566,9 +14582,9 @@ } }, "@asyncapi/specs": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-6.6.0.tgz", - "integrity": "sha512-pXJa0sCeBpif5al5CSa0f3HvwVBQXzd96/Xgq8Jsh6KM4CYxCe7p6paaC9fDjdBVXyWAioQmZiGRxEVUMINbUw==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-6.7.0.tgz", + "integrity": "sha512-TygnAHctm0e7Y55Zy2PBjE6t/jai/txu4MZiyHkcbom9WQoC6Nl7M1M3TQQMzDrb5iLZtuRDm1GAwvawZPPn5A==", "requires": { "@types/json-schema": "^7.0.11" } @@ -14583,9 +14599,9 @@ } }, "@babel/compat-data": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.1.tgz", - "integrity": "sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA==" + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", + "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==" }, "@babel/core": { "version": "7.24.3", @@ -14663,18 +14679,18 @@ } }, "@babel/helper-create-class-features-plugin": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.1.tgz", - "integrity": "sha512-1yJa9dX9g//V6fDebXoEfEsxkZHk3Hcbm+zLhyu6qVgYFLvmTALTeV+jNU9e5RnYtioBrGEOdoI2joMSNQ/+aA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.5.tgz", + "integrity": "sha512-uRc4Cv8UQWnE4NXlYTIIdM7wfFkOqlFztcC/gVXDKohKoVB3OyonfelUBaJzSwpBntZ2KYGF/9S7asCHsXwW6g==", "requires": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", - "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.24.5", "@babel/helper-optimise-call-expression": "^7.22.5", "@babel/helper-replace-supers": "^7.24.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-split-export-declaration": "^7.24.5", "semver": "^6.3.1" }, "dependencies": { @@ -14703,9 +14719,9 @@ } }, "@babel/helper-define-polyfill-provider": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.1.tgz", - "integrity": "sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", "requires": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", @@ -14737,11 +14753,11 @@ } }, "@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.5.tgz", + "integrity": "sha512-4owRteeihKWKamtqg4JmWSsEZU445xpFRXPEwp44HbgbxdWlUV1b4Agg4lkA806Lil5XM/e+FJyS0vj5T6vmcA==", "requires": { - "@babel/types": "^7.23.0" + "@babel/types": "^7.24.5" } }, "@babel/helper-module-imports": { @@ -14773,9 +14789,9 @@ } }, "@babel/helper-plugin-utils": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", - "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==" + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz", + "integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==" }, "@babel/helper-remap-async-to-generator": { "version": "7.22.20", @@ -14814,11 +14830,11 @@ } }, "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz", + "integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==", "requires": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.5" } }, "@babel/helper-string-parser": { @@ -14827,9 +14843,9 @@ "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==" }, "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", + "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==" }, "@babel/helper-validator-option": { "version": "7.23.5", @@ -14837,13 +14853,13 @@ "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==" }, "@babel/helper-wrap-function": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", - "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.5.tgz", + "integrity": "sha512-/xxzuNvgRl4/HLNKvnFwdhdgN3cpLxgLROeLDl83Yx0AJ1SGvq1ak0OszTOjDfiB8Vx03eJbeDWh9r+jCCWttw==", "requires": { - "@babel/helper-function-name": "^7.22.5", - "@babel/template": "^7.22.15", - "@babel/types": "^7.22.19" + "@babel/helper-function-name": "^7.23.0", + "@babel/template": "^7.24.0", + "@babel/types": "^7.24.5" } }, "@babel/helpers": { @@ -14872,6 +14888,15 @@ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==" }, + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.5.tgz", + "integrity": "sha512-LdXRi1wEMTrHVR4Zc9F8OewC3vdm5h4QB6L71zy6StmYeqGi1b3ttIO8UC+BfZKcH9jdr4aI249rBkm+3+YvHw==", + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.24.5" + } + }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.24.1", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.1.tgz", @@ -15114,11 +15139,11 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.1.tgz", - "integrity": "sha512-h71T2QQvDgM2SmT29UYU6ozjMlAt7s7CSs5Hvy8f8cf/GM/Z4a2zMfN+fjVGaieeCrXR3EdQl6C4gQG+OgmbKw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.5.tgz", + "integrity": "sha512-sMfBc3OxghjC95BkYrYocHL3NaOplrcaunblzwXhGmlPwpmfsxr4vK+mBBt49r+S240vahmv+kUxkeKgs+haCw==", "requires": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.24.5" } }, "@babel/plugin-transform-class-properties": { @@ -15131,27 +15156,27 @@ } }, "@babel/plugin-transform-class-static-block": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.1.tgz", - "integrity": "sha512-FUHlKCn6J3ERiu8Dv+4eoz7w8+kFLSyeVG4vDAikwADGjUCoHw/JHokyGtr8OR4UjpwPVivyF+h8Q5iv/JmrtA==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.4.tgz", + "integrity": "sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-create-class-features-plugin": "^7.24.4", "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-class-static-block": "^7.14.5" } }, "@babel/plugin-transform-classes": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.1.tgz", - "integrity": "sha512-ZTIe3W7UejJd3/3R4p7ScyyOoafetUShSf4kCqV0O7F/RiHxVj/wRaRnQlrGwflvcehNA8M42HkAiEDYZu2F1Q==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.5.tgz", + "integrity": "sha512-gWkLP25DFj2dwe9Ck8uwMOpko4YsqyfZJrOmqqcegeDYEbp7rmn4U6UQZNj08UF6MaX39XenSpKRCvpDRBtZ7Q==", "requires": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-plugin-utils": "^7.24.5", "@babel/helper-replace-supers": "^7.24.1", - "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-split-export-declaration": "^7.24.5", "globals": "^11.1.0" } }, @@ -15165,11 +15190,11 @@ } }, "@babel/plugin-transform-destructuring": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz", - "integrity": "sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.5.tgz", + "integrity": "sha512-SZuuLyfxvsm+Ah57I/i1HVjveBENYK9ue8MJ7qkc7ndoNjqquJiElzA7f5yaAXjyW2hKojosOTAQQRX50bPSVg==", "requires": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.24.5" } }, "@babel/plugin-transform-dotall-regex": { @@ -15344,14 +15369,14 @@ } }, "@babel/plugin-transform-object-rest-spread": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.1.tgz", - "integrity": "sha512-XjD5f0YqOtebto4HGISLNfiNMTTs6tbkFf2TOqJlYKYmbo+mN9Dnpl4SRoofiziuOWMIyq3sZEUqLo3hLITFEA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.5.tgz", + "integrity": "sha512-7EauQHszLGM3ay7a161tTQH7fj+3vVM/gThlz5HpFtnygTxjrlvoeq7MPVA1Vy9Q555OB8SnAOsMkLShNkkrHA==", "requires": { "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-plugin-utils": "^7.24.5", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.24.1" + "@babel/plugin-transform-parameters": "^7.24.5" } }, "@babel/plugin-transform-object-super": { @@ -15373,21 +15398,21 @@ } }, "@babel/plugin-transform-optional-chaining": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.1.tgz", - "integrity": "sha512-n03wmDt+987qXwAgcBlnUUivrZBPZ8z1plL0YvgQalLm+ZE5BMhGm94jhxXtA1wzv1Cu2aaOv1BM9vbVttrzSg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.5.tgz", + "integrity": "sha512-xWCkmwKT+ihmA6l7SSTpk8e4qQl/274iNbSKRRS8mpqFR32ksy36+a+LWY8OXCCEefF8WFlnOHVsaDI2231wBg==", "requires": { - "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-plugin-utils": "^7.24.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", "@babel/plugin-syntax-optional-chaining": "^7.8.3" } }, "@babel/plugin-transform-parameters": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.1.tgz", - "integrity": "sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.5.tgz", + "integrity": "sha512-9Co00MqZ2aoky+4j2jhofErthm6QVLKbpQrvz20c3CH9KQCLHyNB+t2ya4/UrRpQGR+Wrwjg9foopoeSdnHOkA==", "requires": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.24.5" } }, "@babel/plugin-transform-private-methods": { @@ -15400,13 +15425,13 @@ } }, "@babel/plugin-transform-private-property-in-object": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.1.tgz", - "integrity": "sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.5.tgz", + "integrity": "sha512-JM4MHZqnWR04jPMujQDTBVRnqxpLLpx2tkn7iPn+Hmsc0Gnb79yvRWOkvqFOx3Z7P7VxiRIR22c4eGSNj87OBQ==", "requires": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-create-class-features-plugin": "^7.24.5", + "@babel/helper-plugin-utils": "^7.24.5", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" } }, @@ -15506,11 +15531,11 @@ } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.1.tgz", - "integrity": "sha512-CBfU4l/A+KruSUoW+vTQthwcAdwuqbpRNB8HQKlZABwHRhsdHZ9fezp4Sn18PeAlYxTNiLMlx4xUBV3AWfg1BA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.5.tgz", + "integrity": "sha512-UTGnhYVZtTAjdwOTzT+sCyXmTn8AhaxOS/MjG9REclZ6ULHWF9KoCZur0HSGU7hk8PdBFKKbYe6+gqdXWz84Jg==", "requires": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.24.5" } }, "@babel/plugin-transform-unicode-escapes": { @@ -15549,14 +15574,15 @@ } }, "@babel/preset-env": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.3.tgz", - "integrity": "sha512-fSk430k5c2ff8536JcPvPWK4tZDwehWLGlBp0wrsBUjZVdeQV6lePbwKWZaZfK2vnh/1kQX1PzAJWsnBmVgGJA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.5.tgz", + "integrity": "sha512-UGK2ifKtcC8i5AI4cH+sbLLuLc2ktYSFJgBAXorKAsHUZmrQ1q6aQ6i3BvU24wWs2AAKqQB6kq3N9V9Gw1HiMQ==", "requires": { - "@babel/compat-data": "^7.24.1", + "@babel/compat-data": "^7.24.4", "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-plugin-utils": "^7.24.5", "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.5", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.1", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.1", "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.1", @@ -15583,12 +15609,12 @@ "@babel/plugin-transform-async-generator-functions": "^7.24.3", "@babel/plugin-transform-async-to-generator": "^7.24.1", "@babel/plugin-transform-block-scoped-functions": "^7.24.1", - "@babel/plugin-transform-block-scoping": "^7.24.1", + "@babel/plugin-transform-block-scoping": "^7.24.5", "@babel/plugin-transform-class-properties": "^7.24.1", - "@babel/plugin-transform-class-static-block": "^7.24.1", - "@babel/plugin-transform-classes": "^7.24.1", + "@babel/plugin-transform-class-static-block": "^7.24.4", + "@babel/plugin-transform-classes": "^7.24.5", "@babel/plugin-transform-computed-properties": "^7.24.1", - "@babel/plugin-transform-destructuring": "^7.24.1", + "@babel/plugin-transform-destructuring": "^7.24.5", "@babel/plugin-transform-dotall-regex": "^7.24.1", "@babel/plugin-transform-duplicate-keys": "^7.24.1", "@babel/plugin-transform-dynamic-import": "^7.24.1", @@ -15608,13 +15634,13 @@ "@babel/plugin-transform-new-target": "^7.24.1", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.1", "@babel/plugin-transform-numeric-separator": "^7.24.1", - "@babel/plugin-transform-object-rest-spread": "^7.24.1", + "@babel/plugin-transform-object-rest-spread": "^7.24.5", "@babel/plugin-transform-object-super": "^7.24.1", "@babel/plugin-transform-optional-catch-binding": "^7.24.1", - "@babel/plugin-transform-optional-chaining": "^7.24.1", - "@babel/plugin-transform-parameters": "^7.24.1", + "@babel/plugin-transform-optional-chaining": "^7.24.5", + "@babel/plugin-transform-parameters": "^7.24.5", "@babel/plugin-transform-private-methods": "^7.24.1", - "@babel/plugin-transform-private-property-in-object": "^7.24.1", + "@babel/plugin-transform-private-property-in-object": "^7.24.5", "@babel/plugin-transform-property-literals": "^7.24.1", "@babel/plugin-transform-regenerator": "^7.24.1", "@babel/plugin-transform-reserved-words": "^7.24.1", @@ -15622,7 +15648,7 @@ "@babel/plugin-transform-spread": "^7.24.1", "@babel/plugin-transform-sticky-regex": "^7.24.1", "@babel/plugin-transform-template-literals": "^7.24.1", - "@babel/plugin-transform-typeof-symbol": "^7.24.1", + "@babel/plugin-transform-typeof-symbol": "^7.24.5", "@babel/plugin-transform-unicode-escapes": "^7.24.1", "@babel/plugin-transform-unicode-property-regex": "^7.24.1", "@babel/plugin-transform-unicode-regex": "^7.24.1", @@ -15671,9 +15697,9 @@ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" }, "@babel/runtime": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz", - "integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz", + "integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==", "requires": { "regenerator-runtime": "^0.14.0" } @@ -15706,12 +15732,12 @@ } }, "@babel/types": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", - "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", + "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", "requires": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-string-parser": "^7.24.1", + "@babel/helper-validator-identifier": "^7.24.5", "to-fast-properties": "^2.0.0" } }, @@ -17937,12 +17963,12 @@ } }, "babel-plugin-polyfill-corejs2": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz", - "integrity": "sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ==", + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", "requires": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.1", + "@babel/helper-define-polyfill-provider": "^0.6.2", "semver": "^6.3.1" }, "dependencies": { @@ -17963,11 +17989,11 @@ } }, "babel-plugin-polyfill-regenerator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.1.tgz", - "integrity": "sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", "requires": { - "@babel/helper-define-polyfill-provider": "^0.6.1" + "@babel/helper-define-polyfill-provider": "^0.6.2" } }, "babel-plugin-source-map-support": { @@ -18394,9 +18420,9 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, "core-js-compat": { - "version": "3.36.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.1.tgz", - "integrity": "sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA==", + "version": "3.37.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.0.tgz", + "integrity": "sha512-vYq4L+T8aS5UuFg4UwDhc7YNRWVeVZwltad9C/jV3R2LgVOpS9BDr7l/WL6BN0dbV3k1XejPTHqqEzJgsa0frA==", "requires": { "browserslist": "^4.23.0" } diff --git a/package.json b/package.json index 5b6eec31..8a021cdc 100644 --- a/package.json +++ b/package.json @@ -36,21 +36,22 @@ "@asyncapi/generator-hooks": "^0.1.0", "@asyncapi/generator-react-sdk": "^1.0.18", "eslint-plugin-react": "^7.34.1", - "filenamify": "^4.1.0", + "filenamify": "^4.3.0", "js-beautify": "^1.15.1", - "lodash": "^4.17.15", + "lodash": "^4.17.21", "markdown-toc": "^1.2.0" }, "devDependencies": { "@asyncapi/generator": "^1.17.25", - "eslint": "^8.7.0", + "eslint": "^8.57.0", "eslint-plugin-jest": "^25.7.0", "eslint-plugin-sonarjs": "^0.11.0", - "jest": "^27.3.1", - "node-fetch": "^2.6.1", - "rimraf": "^5.0.1" + "jest": "^27.5.1", + "node-fetch": "^2.7.0", + "rimraf": "^5.0.5" }, "generator": { + "apiVersion": "v3", "supportedProtocols": [ "amqp", "mqtt", @@ -94,4 +95,4 @@ "^nimma/(.*)": "/node_modules/nimma/dist/cjs/$1" } } -} +} \ No newline at end of file diff --git a/template/README.md.js b/template/README.md.js index 28149c00..38d6f1e3 100644 --- a/template/README.md.js +++ b/template/README.md.js @@ -1,6 +1,21 @@ import { File } from '@asyncapi/generator-react-sdk'; export default function readmeFile({asyncapi, params}) { + const server = asyncapi.allServers().get(params.server); + const protocol = server.protocol(); + const security = server.security(); + + let hasSecuritySchemeX509 = false; + let securitySchemeType; + if (params.securityScheme && security && security.length > 0) { + const securityReq = security[0].all(); + if (securityReq && securityReq.length > 0) { + securitySchemeType = securityReq[0].scheme().type(); + } + } + + hasSecuritySchemeX509 = (params.securityScheme && (protocol === 'kafka' || protocol === 'kafka-secure') && securitySchemeType === 'X509'); + return {`# ${ asyncapi.info().title() } @@ -12,7 +27,7 @@ ${ asyncapi.info().description() || '' } \`\`\`sh npm i \`\`\` -${(params.securityScheme && (asyncapi.server(params.server).protocol() === 'kafka' || asyncapi.server(params.server).protocol() === 'kafka-secure') && asyncapi.components().securityScheme(params.securityScheme).type() === 'X509') ? '1. (Optional) For X509 security provide files with all data required to establish secure connection using certificates. Place files like `ca.pem`, `service.cert`, `service.key` in the root of the project or the location that you explicitly specified during generation.' : ''} +${ hasSecuritySchemeX509 ? '1. (Optional) For X509 security provide files with all data required to establish secure connection using certificates. Place files like `ca.pem`, `service.cert`, `service.key` in the root of the project or the location that you explicitly specified during generation.' : ''} ## Import and start diff --git a/template/config/common.yml.js b/template/config/common.yml.js index 9bd54fb5..07f1f701 100644 --- a/template/config/common.yml.js +++ b/template/config/common.yml.js @@ -1,11 +1,17 @@ import { File } from '@asyncapi/generator-react-sdk'; -import { camelCase, channelNamesWithPublish, dump, host, port, queueName, stripProtocol, toAmqpTopic, toKafkaTopic, toMqttTopic } from '../../helpers/index'; +import { camelCase, channelNamesWithReceive, dump, host, port, queueName, stripProtocol, toAmqpTopic, toKafkaTopic, toMqttTopic } from '../../helpers/index'; import { replaceServerVariablesWithValues } from '@asyncapi/generator-filters/src/customFilters'; export default function CommonConfigYAMLRender({ asyncapi, params }) { - const serverProtocol = asyncapi.server(params.server).protocol(); - const serverVariables = asyncapi.server(params.server).variables(); - const resolvedBrokerUrlWithReplacedVariables = replaceServerVariablesWithValues(asyncapi.server(params.server).url(), serverVariables); + const server = asyncapi.allServers().get(params.server); + const serverProtocol = server.protocol(); + const serverVariablesArray = server.variables(); + const serverVariables = {}; + serverVariablesArray.forEach(item => { + serverVariables[item.id()] = item; + }); + + const resolvedBrokerUrlWithReplacedVariables = replaceServerVariablesWithValues(server.url(), serverVariables); return ( @@ -47,7 +53,7 @@ function amqpBlock(url, asyncapi) { password: host: ${host(url)} port: - topics: ${dump(toAmqpTopic(channelNamesWithPublish(asyncapi)))} + topics: ${dump(toAmqpTopic(channelNamesWithReceive(asyncapi)))} queue: ${queueName(asyncapi.info().title(), asyncapi.info().version())} queueOptions: exclusive: false @@ -57,9 +63,10 @@ function amqpBlock(url, asyncapi) { } function mqttBlock(url, asyncapi, params) { + const server = asyncapi.allServers().get(params.server); return ` mqtt: - url: ${asyncapi.server(params.server).protocol()}://${stripProtocol(url)} - topics: ${dump(toMqttTopic(channelNamesWithPublish(asyncapi)))} + url: ${server.protocol()}://${stripProtocol(url)} + topics: ${dump(toMqttTopic(channelNamesWithReceive(asyncapi)))} qos: protocol: mqtt retain: @@ -75,7 +82,7 @@ function kafkaBlock(url, asyncapi) { consumerOptions: groupId: ${camelCase(asyncapi.info().title())} topics: - ${channelNamesWithPublish(asyncapi).map(topic => `- ${toKafkaTopic(topic)}`).join('\n')} + ${channelNamesWithReceive(asyncapi).map(topic => `- ${toKafkaTopic(topic)}`).join('\n')} topicSeparator: '__' topicPrefix: `; @@ -87,7 +94,7 @@ function kafkaProductionBlock(params, asyncapi) { ssl: rejectUnauthorized: true `; - if (params.securityScheme && asyncapi.components().securityScheme(params.securityScheme).type() !== 'X509') { + if (params.securityScheme && asyncapi.components().securitySchemes().get(params.securityScheme).type() !== 'X509') { productionBlock += ` sasl: mechanism: 'plain' username: @@ -95,4 +102,4 @@ function kafkaProductionBlock(params, asyncapi) { `; } return productionBlock; -} +} \ No newline at end of file diff --git a/template/package.json.js b/template/package.json.js index d690acf8..a042409e 100644 --- a/template/package.json.js +++ b/template/package.json.js @@ -7,12 +7,17 @@ export default function packageFile({ asyncapi, params }) { dotenv: '8.1.0', hermesjs: '2.x', 'hermesjs-router': '1.x', - 'asyncapi-validator': '3.0.0', 'node-fetch': '2.6.0', 'node-yaml-config': '0.0.4', }; - const serverProtocol = asyncapi.server(params.server).protocol(); + const majorSpecVersion = parseInt(asyncapi.version().split('.')[0], 10); + const isSpecV3 = (majorSpecVersion === 3); + if (!isSpecV3) { + dependencies['asyncapi-validator'] = '3.0.0'; + } + + const serverProtocol = asyncapi.allServers().get(params.server).protocol(); if (serverProtocol === 'mqtt' || serverProtocol === 'mqtts') { dependencies['hermesjs-mqtt'] = '2.x'; } else if (serverProtocol === 'kafka' || serverProtocol === 'kafka-secure') { diff --git a/template/src/api/handlers/handler.js b/template/src/api/handlers/handler.js index 6a2320e6..593ee94f 100644 --- a/template/src/api/handlers/handler.js +++ b/template/src/api/handlers/handler.js @@ -8,43 +8,38 @@ import { File } from '@asyncapi/generator-react-sdk'; const OPTIONS_MESSAGE_HEADERS_STRING = 'options.message.headers'; -function publishHandler(channel) { - if (!channel.hasPublish()) { - return ''; - } - - const lambdaChannel = channel.publish().ext('x-lambda'); - const publishOperationId = channel.publish().id(); - const publishMessage = channel.publish().message(0); +function handler(operation) { + const operationId = operation.id(); + const message = operation.messages().all()[0]; + + const lambdaChannel = operation.isReceive() && operation.extensions().get('x-lambda'); const exportedHandler = ` /** - * Registers a middleware function for the ${publishOperationId} operation to be executed during request processing. + * Registers a middleware function for the ${operationId} operation to be executed during request processing. * * Middleware functions have access to options object that you can use to access the message content and other helper functions * * @param {function} middlewareFn - The middleware function to be registered. * @throws {TypeError} If middlewareFn is not a function. */ - handler.${convertOpertionIdToMiddlewareFn( - channel.publish().id() - )} = (middlewareFn) => { + handler.${convertOpertionIdToMiddlewareFn(operationId)} = (middlewareFn) => { if (typeof middlewareFn !== 'function') { throw new TypeError('middlewareFn must be a function'); } - ${publishOperationId}Middlewares.push(middlewareFn); + ${operationId}Middlewares.push(middlewareFn); } `; const privateHandlerLogic = ` /** - * ${channel.publish().summary() || ''} + * ${operation.hasSummary() ? operation.summary() : ''} * * @param {object} options * @param {object} options.message ${ - publishMessage.headers() - ? Object.entries(publishMessage.headers().properties()) + message.headers() + ? Object.entries(message.headers().properties()) .map(([fieldName, field]) => { return docline(field, fieldName, OPTIONS_MESSAGE_HEADERS_STRING); }) @@ -53,8 +48,8 @@ function publishHandler(channel) { } * ${ - publishMessage.payload() - ? Object.entries(publishMessage.payload().properties()) + message.payload() + ? Object.entries(message.payload().properties()) .map(([fieldName, field]) => { return docline(field, fieldName, OPTIONS_MESSAGE_HEADERS_STRING); }) @@ -62,7 +57,7 @@ function publishHandler(channel) { : '' } */ - handler._${publishOperationId} = async ({message}) => { + handler._${operationId} = async ({message}) => { ${ lambdaChannel ? ` @@ -74,7 +69,7 @@ function publishHandler(channel) { .then(res => res.json()) .then(json => console.log(json)) .catch(err => { throw err; });` - : `for (const middleware of ${publishOperationId}Middlewares) { + : `for (const middleware of ${operationId}Middlewares) { await middleware(message); }` } @@ -82,78 +77,9 @@ function publishHandler(channel) { `; return ` - ${lambdaChannel ? 'const fetch = require("node-fetch");' : ''} + ${ lambdaChannel ? 'const fetch = require("node-fetch");' : ''} - const ${publishOperationId}Middlewares = []; - - ${exportedHandler} - - ${privateHandlerLogic} - `; -} - -function subscribeHandler(channel) { - if (!channel.hasSubscribe()) { - return ''; - } - - const subscribeOperationId = channel.subscribe().id(); - const subscribeMessage = channel.subscribe().message(0); - - const exportedHandler = ` - /** - * Registers a middleware function for the ${subscribeOperationId} operation to be executed during request processing. - * - * Middleware functions have access to options object that you can use to access the message content and other helper functions - * - * @param {function} middlewareFn - The middleware function to be registered. - * @throws {TypeError} If middlewareFn is not a function. - */ - handler.${convertOpertionIdToMiddlewareFn( - channel.subscribe().id() - )} = (middlewareFn) => { - if (typeof middlewareFn !== 'function') { - throw new TypeError('middlewareFn must be a function'); - } - ${subscribeOperationId}Middlewares.push(middlewareFn); - } - `; - - const privateHandlerLogic = ` - /** - * ${channel.subscribe().summary() || ''} - * - * @param {object} options - * @param {object} options.message - ${ - subscribeMessage.headers() - ? Object.entries(subscribeMessage.headers().properties()) - .map(([fieldName, field]) => { - return docline(field, fieldName, OPTIONS_MESSAGE_HEADERS_STRING); - }) - .join('\n') - : '' - } - * - ${ - subscribeMessage.payload() - ? Object.entries(subscribeMessage.payload().properties()) - .map(([fieldName, field]) => { - return docline(field, fieldName, OPTIONS_MESSAGE_HEADERS_STRING); - }) - .join('\n') - : '' - } - */ - handler._${subscribeOperationId} = async ({message}) => { - for (const middleware of ${subscribeOperationId}Middlewares) { - await middleware(message); - } - }; - `; - - return ` - const ${subscribeOperationId}Middlewares = []; + const ${operationId}Middlewares = []; ${exportedHandler} @@ -167,21 +93,17 @@ export default function handlerRender({ const general = ` const handler = module.exports = {}; `; - - const channels = asyncapi.channels(); - return Object.entries(channels).map(([channelName, channel]) => { - const hasPublish = channel.publish(); - const hasSubscribe = channel.hasSubscribe(); - - return ( - - {` - ${general} - ${hasPublish ? publishHandler(channel) : ''} - ${hasSubscribe ? subscribeHandler(channel) : ''} - `} - - ); + return asyncapi.channels().all().map(channel => { + const channelName = channel.id(); + + let routeHandler = ` + ${general} + `; + + for (const operation of channel.operations()) { + routeHandler += handler(operation); + } + return {routeHandler}; }); } diff --git a/template/src/api/index.js b/template/src/api/index.js index 32027199..f186ead5 100644 --- a/template/src/api/index.js +++ b/template/src/api/index.js @@ -2,7 +2,8 @@ import { File } from '@asyncapi/generator-react-sdk'; import { capitalize, getProtocol, getConfig, camelCase, convertToFilename, convertOpertionIdToMiddlewareFn } from '../../../helpers/index'; export default function indexEntrypointFile({asyncapi, params}) { - const protocol = asyncapi.server(params.server).protocol() === 'mqtts' ? 'mqtt' : asyncapi.server(params.server).protocol(); + const server = asyncapi.allServers().get(params.server); + const protocol = server.protocol() === 'mqtts' ? 'mqtt' : server.protocol(); const capitalizedProtocol = capitalize(getProtocol(protocol)); const standardImports = ` @@ -20,11 +21,12 @@ export default function indexEntrypointFile({asyncapi, params}) { const ${capitalizedProtocol}Adapter = require('hermesjs-${protocol}'); `; - const channelHandlerImports = Object.entries(asyncapi.channels()).map(([channelName, channel]) => { + const channelHandlerImports = asyncapi.channels().all().map(channel => { + const channelName = channel.id(); return `const ${camelCase(channelName)} = require('./routes/${convertToFilename(channelName)}.js');`; }).join('\n'); - const isSecurityEnabled = params.securityScheme && (asyncapi.server(params.server).protocol() === 'kafka' || asyncapi.server(params.server).protocol() === 'kafka-secure') && (asyncapi.components().securityScheme(params.securityScheme).type() === 'X509'); + const isSecurityEnabled = params.securityScheme && (server.protocol() === 'kafka' || server.protocol() === 'kafka-secure') && (asyncapi.components().securitySchemes().get(params.securityScheme).type() === 'X509'); let securitySchemeImports = isSecurityEnabled ? ` const fs = require('fs') const certFilesDir = '${params.certFilesDir}'; @@ -43,19 +45,20 @@ export default function indexEntrypointFile({asyncapi, params}) { ${securitySchemeImports} ` - const channelsMiddleware = ` - ${Object.entries(asyncapi.channels()).map(([channelName, channel]) => { + const channelsMiddleware = asyncapi.channels().all().map(channel => { + const channelName = channel.address(); + const channelOperationId = channel.id(); let channelLogic = ''; - if (channel.hasPublish()) { + if (channel.operations().filterByReceive().length > 0) { channelLogic += `console.log(cyan.bold.inverse(' SUB '), gray('Subscribed to'), yellow('${channelName}')); - app.use(${camelCase(channelName)});`; + app.use(${camelCase(channelOperationId)});`; } - if (channel.hasSubscribe()) { + if (channel.operations().filterBySend().length > 0) { channelLogic += `console.log(yellow.bold.inverse(' PUB '), gray('Will eventually publish to'), yellow('${channelName}')); - app.useOutbound(${camelCase(channelName)});`; + app.useOutbound(${camelCase(channelOperationId)});`; } return channelLogic; - }).join('\n')}`; + }).join('\n'); const middlewares = ` app.addAdapter(${capitalizedProtocol}Adapter, serverConfig); @@ -65,6 +68,7 @@ export default function indexEntrypointFile({asyncapi, params}) { app.use(logger); // Channels + ${channelsMiddleware} app.use(errorLogger); @@ -87,16 +91,13 @@ export default function indexEntrypointFile({asyncapi, params}) { } `; - const handlers = Object.entries(asyncapi.channels()).map(([channelName, channel]) => { - let handler = ''; - if (channel.hasPublish()) { - handler += `${convertOpertionIdToMiddlewareFn(channel.publish().id())} : require('./handlers/${convertToFilename(channelName)}').${convertOpertionIdToMiddlewareFn(channel.publish().id())},`; - } - if (channel.hasSubscribe()) { - handler += `${convertOpertionIdToMiddlewareFn(channel.subscribe().id())} : require('./handlers/${convertToFilename(channelName)}').${convertOpertionIdToMiddlewareFn(channel.subscribe().id())},`; - } - return handler; - }).join('\n'); + const handlers = asyncapi.channels().all().map(channel => { + const channelName = channel.id(); + return channel.operations().all().map(operation => { + const operationId = operation.id(); + return `${convertOpertionIdToMiddlewareFn(operationId)} : require('./handlers/${convertToFilename(channelName)}').${convertOpertionIdToMiddlewareFn(operationId)}` + }); + }).join(','); return {` diff --git a/template/src/api/routes/route.js b/template/src/api/routes/route.js index d34f3c31..62d99baa 100644 --- a/template/src/api/routes/route.js +++ b/template/src/api/routes/route.js @@ -2,53 +2,48 @@ import { File } from '@asyncapi/generator-react-sdk'; import { camelCase, convertToFilename, toHermesTopic } from '../../../../helpers/index'; -function publishHandler(channel, channelName) { - if (!channel.hasPublish()) { +function receiveHandler(operation, channelName, channelAddress, isSpecV3) { + if (!operation.isReceive()) { return ''; } - const publishOperationId = channel.publish().id(); - const publishMessage = channel.publish().message(0); + const operationId = operation.id(); + const message = operation.messages().all()[0]; + const messageValidationLogic = (operation.messages().length > 1) ? ` + /* + * TODO: If https://github.com/asyncapi/parser-js/issues/372 is addressed, simplify this + * code to just validate the message against the combined message schema which will + * include the \`oneOf\` in the JSON schema - let the JSON schema validator handle the + * oneOf semantics (rather than each generator having to emit conditional code) + */ + let nValidated = 0; + // For oneOf, only one message schema should match. + // Validate payload against each message and count those which validate + + ${ + operation.messages().all().map(message => `try { + nValidated = await validateMessage(message.payload,'${ channelAddress }','${ message.name() }','publish', nValidated); + } catch { };`).join('\n') + } + + if (nValidated === 1) { + await ${camelCase(channelName)}Handler._${operationId}({message}); + next() + } else { + throw new Error(\`\${nValidated} of ${ operation.messages().length } message schemas matched when exactly 1 should match\`); + }` : `await validateMessage(message.payload,'${ channelAddress }','${ message.name() }','publish');`; return ` - ${channel.publish().summary() ? ` + ${operation.hasSummary() ? ` /** - * ${ channel.publish().summary() } + * ${ operation.summary() } */ `: ''} - router.use('${toHermesTopic(channelName)}', async (message, next) => { + router.use('${toHermesTopic(channelAddress)}', async (message, next) => { try { - ${channel.publish().hasMultipleMessages() - ? ` - /* - * TODO: If https://github.com/asyncapi/parser-js/issues/372 is addressed, simplify this - * code to just validate the message against the combined message schema which will - * include the \`oneOf\` in the JSON schema - let the JSON schema validator handle the - * oneOf semantics (rather than each generator having to emit conditional code) - */ - let nValidated = 0; - // For oneOf, only one message schema should match. - // Validate payload against each message and count those which validate - - ${ - Array.from(Array(channel.publish().messages().length).keys()).map(i => `try { - nValidated = await validateMessage(message.payload,'${ channelName }','${ channel.publish().message(i).name() }','publish', nValidated); - } catch { };`).join('\n') - } - - if (nValidated === 1) { - await ${camelCase(channelName)}Handler._${publishOperationId}({message}); - next() - } else { - throw new Error(\`\${nValidated} of ${ channel.publish().messages().length } message schemas matched when exactly 1 should match\`); - } - ` - : ` - await validateMessage(message.payload,'${ channelName }','${ publishMessage.name() }','publish'); - await ${camelCase(channelName)}Handler._${ publishOperationId }({message}); + ${isSpecV3 ? '' : messageValidationLogic} + await ${camelCase(channelName)}Handler._${ operationId }({message}); next(); - ` - } } catch (e) { next(e); } @@ -56,47 +51,42 @@ function publishHandler(channel, channelName) { `; } -function subscribeHandler(channel, channelName) { - if (!channel.hasSubscribe()) { +function sendHandler(operation, channelName, channelAddress, isSpecV3) { + if (!operation.isSend()) { return ''; } - const subscribeOperationId = channel.subscribe().id(); - const subscribeMessage = channel.subscribe().message(0); + const operationId = operation.id(); + const message = operation.messages().all()[0]; + const messageValidationLogic = (operation.messages().length > 1) ? ` + let nValidated = 0; + // For oneOf, only one message schema should match. + // Validate payload against each message and count those which validate + + ${ + operation.messages().all().map(message => `try { + nValidated = await validateMessage(message.payload,'${ channelAddress }','${ message.name() }','subscribe', nValidated); + } catch { };`).join('\n') + } + + if (nValidated === 1) { + await ${camelCase(channelName)}Handler._${operationId}({message}); + next() + } else { + throw new Error(\`\${nValidated} of ${ operation.messages().length } message schemas matched when exactly 1 should match\`); + }` : `await validateMessage(message.payload,'${ channelAddress }','${ message.name() }','subscribe');`; return ` - ${channel.subscribe().summary() ? ` + ${operation.hasSummary() ? ` /** - * ${ channel.subscribe().summary() } + * ${ operation.summary() } */ `: ''} - router.use('${toHermesTopic(channelName)}', async (message, next) => { + router.useOutbound('${toHermesTopic(channelAddress)}', async (message, next) => { try { - ${channel.subscribe().hasMultipleMessages() - ? ` - let nValidated = 0; - // For oneOf, only one message schema should match. - // Validate payload against each message and count those which validate - - ${ - Array.from(Array(channel.subscribe().messages().length).keys()).map(i => `try { - nValidated = await validateMessage(message.payload,'${ channelName }','${ channel.subscribe().message(i).name() }','subscribe', nValidated); - } catch { };`).join('\n') - } - - if (nValidated === 1) { - await ${camelCase(channelName)}Handler._${subscribeOperationId}({message}); - next() - } else { - throw new Error(\`\${nValidated} of ${ channel.subscribe().messages().length } message schemas matched when exactly 1 should match\`); - } - ` - : ` - await validateMessage(message.payload,'${ channelName }','${ subscribeMessage.name() }','subscribe'); - await ${camelCase(channelName)}Handler._${ subscribeOperationId }({message}); + ${isSpecV3 ? '' : messageValidationLogic} + await ${camelCase(channelName)}Handler._${ operationId }({message}); next(); - ` - } } catch (e) { next(e); } @@ -104,33 +94,36 @@ function subscribeHandler(channel, channelName) { `; } -function routeCode(channel, channelName) { - const hasPublish = channel.publish(); - const hasSubscribe = channel.hasSubscribe(); - +function routeCode(channel, isSpecV3) { + const channelName = channel.id(); const generalImport = ` const Router = require('hermesjs/lib/router'); - const { validateMessage } = require('../../lib/message-validator'); + ${isSpecV3 ? '': 'const { validateMessage } = require(\'../../lib/message-validator\');'} const router = new Router(); const ${ camelCase(channelName) }Handler = require('../handlers/${convertToFilename(channelName)}'); module.exports = router; `; - return ( - - {` - ${generalImport} - ${hasPublish ? publishHandler(channel, channelName): ''} - ${hasSubscribe ? subscribeHandler(channel, channelName): ''} - `} - - ); + let routeHandler = ` + ${generalImport} + `; + + for (const operation of channel.operations()) { + if (operation.isSend()) { + routeHandler += sendHandler(operation, channel.id(), channel.address(), isSpecV3); + } + if (operation.isReceive()) { + routeHandler += receiveHandler(operation, channel.id(), channel.address(), isSpecV3); + } + } + + return {routeHandler}; } export default function routeRender({asyncapi}) { - const channels = asyncapi.channels(); - - return Object.entries(channels).map(([channelName, channel]) => { - return routeCode(channel, channelName); + const majorSpecVersion = parseInt(asyncapi.version().split('.')[0], 10); + const isSpecV3 = (majorSpecVersion === 3); + return asyncapi.channels().all().map(channel => { + return routeCode(channel, isSpecV3); }); } \ No newline at end of file diff --git a/test/__snapshots__/integration.test.js.snap b/test/__snapshots__/integration.test.js.snap index 94a2741b..e8c63cd1 100644 --- a/test/__snapshots__/integration.test.js.snap +++ b/test/__snapshots__/integration.test.js.snap @@ -1,6 +1,746 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`template integration tests for generated files using the generator and mqtt example should generate proper handlers and routes files 1`] = ` +exports[`template integration tests for generated files using the generator and kafka example - v3 spec should generate proper handlers and routes files 1`] = ` +"const handler = module.exports = {}; + +const turnOffMiddlewares = []; + +/** + * Registers a middleware function for the turnOff operation to be executed during request processing. + * + * Middleware functions have access to options object that you can use to access the message content and other helper functions + * + * @param {function} middlewareFn - The middleware function to be registered. + * @throws {TypeError} If middlewareFn is not a function. + */ +handler.registerTurnOffMiddleware = (middlewareFn) => { + if (typeof middlewareFn !== 'function') { + throw new TypeError('middlewareFn must be a function'); + } + turnOffMiddlewares.push(middlewareFn); +} + +/** + * + * + * @param {object} options + * @param {object} options.message + * @param {integer} options.message.headers.my-app-header + * + * @param {string} options.message.headers.command - Whether to turn on or off the light. + * @param {string} options.message.headers.sentAt - Date and time when the message was sent. + */ +handler._turnOff = async ({ + message +}) => { + for (const middleware of turnOffMiddlewares) { + await middleware(message); + } +};" +`; + +exports[`template integration tests for generated files using the generator and kafka example - v3 spec should generate proper handlers and routes files 2`] = ` +"const handler = module.exports = {}; + +const receiveLightMeasurementMiddlewares = []; + +/** + * Registers a middleware function for the receiveLightMeasurement operation to be executed during request processing. + * + * Middleware functions have access to options object that you can use to access the message content and other helper functions + * + * @param {function} middlewareFn - The middleware function to be registered. + * @throws {TypeError} If middlewareFn is not a function. + */ +handler.registerReceiveLightMeasurementMiddleware = (middlewareFn) => { + if (typeof middlewareFn !== 'function') { + throw new TypeError('middlewareFn must be a function'); + } + receiveLightMeasurementMiddlewares.push(middlewareFn); +} + +/** + * Inform about environmental lighting conditions of a particular streetlight. + * + * @param {object} options + * @param {object} options.message + * @param {integer} options.message.headers.my-app-header + * + * @param {integer} options.message.headers.lumens - Light intensity measured in lumens. + * @param {string} options.message.headers.sentAt - Date and time when the message was sent. + */ +handler._receiveLightMeasurement = async ({ + message +}) => { + for (const middleware of receiveLightMeasurementMiddlewares) { + await middleware(message); + } +};" +`; + +exports[`template integration tests for generated files using the generator and kafka example - v3 spec should generate proper handlers and routes files 3`] = ` +"const handler = module.exports = {}; + +const turnOnMiddlewares = []; + +/** + * Registers a middleware function for the turnOn operation to be executed during request processing. + * + * Middleware functions have access to options object that you can use to access the message content and other helper functions + * + * @param {function} middlewareFn - The middleware function to be registered. + * @throws {TypeError} If middlewareFn is not a function. + */ +handler.registerTurnOnMiddleware = (middlewareFn) => { + if (typeof middlewareFn !== 'function') { + throw new TypeError('middlewareFn must be a function'); + } + turnOnMiddlewares.push(middlewareFn); +} + +/** + * + * + * @param {object} options + * @param {object} options.message + * @param {integer} options.message.headers.my-app-header + * + * @param {string} options.message.headers.command - Whether to turn on or off the light. + * @param {string} options.message.headers.sentAt - Date and time when the message was sent. + */ +handler._turnOn = async ({ + message +}) => { + for (const middleware of turnOnMiddlewares) { + await middleware(message); + } +};" +`; + +exports[`template integration tests for generated files using the generator and kafka example - v3 spec should generate proper handlers and routes files 4`] = ` +"const handler = module.exports = {}; + +const dimLightMiddlewares = []; + +/** + * Registers a middleware function for the dimLight operation to be executed during request processing. + * + * Middleware functions have access to options object that you can use to access the message content and other helper functions + * + * @param {function} middlewareFn - The middleware function to be registered. + * @throws {TypeError} If middlewareFn is not a function. + */ +handler.registerDimLightMiddleware = (middlewareFn) => { + if (typeof middlewareFn !== 'function') { + throw new TypeError('middlewareFn must be a function'); + } + dimLightMiddlewares.push(middlewareFn); +} + +/** + * + * + * @param {object} options + * @param {object} options.message + * @param {integer} options.message.headers.my-app-header + * + * @param {integer} options.message.headers.percentage - Percentage to which the light should be dimmed to. + * @param {string} options.message.headers.sentAt - Date and time when the message was sent. + */ +handler._dimLight = async ({ + message +}) => { + for (const middleware of dimLightMiddlewares) { + await middleware(message); + } +};" +`; + +exports[`template integration tests for generated files using the generator and kafka example - v3 spec should generate proper handlers and routes files 5`] = ` +"const Router = require('hermesjs/lib/router'); + +const router = new Router(); +const lightTurnOffHandler = require('../handlers/lightTurnOff'); +module.exports = router; + +router.useOutbound('smartylighting.streetlights.1.0.action.:streetlightId.turn.off', async (message, next) => { + try { + + await lightTurnOffHandler._turnOff({ + message + }); + next(); + } catch (e) { + next(e); + } +});" +`; + +exports[`template integration tests for generated files using the generator and kafka example - v3 spec should generate proper handlers and routes files 6`] = ` +"const Router = require('hermesjs/lib/router'); + +const router = new Router(); +const lightingMeasuredHandler = require('../handlers/lightingMeasured'); +module.exports = router; + +/** + * Inform about environmental lighting conditions of a particular streetlight. + */ + +router.use('smartylighting.streetlights.1.0.event.:streetlightId.lighting.measured', async (message, next) => { + try { + + await lightingMeasuredHandler._receiveLightMeasurement({ + message + }); + next(); + } catch (e) { + next(e); + } +});" +`; + +exports[`template integration tests for generated files using the generator and kafka example - v3 spec should generate proper handlers and routes files 7`] = ` +"const Router = require('hermesjs/lib/router'); + +const router = new Router(); +const lightTurnOnHandler = require('../handlers/lightTurnOn'); +module.exports = router; + +router.useOutbound('smartylighting.streetlights.1.0.action.:streetlightId.turn.on', async (message, next) => { + try { + + await lightTurnOnHandler._turnOn({ + message + }); + next(); + } catch (e) { + next(e); + } +});" +`; + +exports[`template integration tests for generated files using the generator and kafka example - v3 spec should generate proper handlers and routes files 8`] = ` +"const Router = require('hermesjs/lib/router'); + +const router = new Router(); +const lightsDimHandler = require('../handlers/lightsDim'); +module.exports = router; + +router.useOutbound('smartylighting.streetlights.1.0.action.:streetlightId.dim', async (message, next) => { + try { + + await lightsDimHandler._dimLight({ + message + }); + next(); + } catch (e) { + next(e); + } +});" +`; + +exports[`template integration tests for generated files using the generator and kafka example - v3 spec should generate proper handlers and routes files 9`] = ` +"const Hermes = require('hermesjs'); +const app = new Hermes(); +const path = require('path'); +const { + yellow, + gray, + cyan +} = require('chalk'); +const buffer2string = require('./middlewares/buffer2string'); +const string2json = require('./middlewares/string2json'); +const json2string = require('./middlewares/json2string'); +const logger = require('./middlewares/logger'); +const errorLogger = require('./middlewares/error-logger'); +const config = require('../lib/config'); +const serverConfig = config.broker.kafka; +const KafkaAdapter = require('hermesjs-kafka-secure'); + +const lightingMeasured = require('./routes/lightingMeasured.js'); +const lightTurnOn = require('./routes/lightTurnOn.js'); +const lightTurnOff = require('./routes/lightTurnOff.js'); +const lightsDim = require('./routes/lightsDim.js'); + +app.addAdapter(KafkaAdapter, serverConfig); + +app.use(buffer2string); +app.use(string2json); +app.use(logger); + +// Channels + +console.log(cyan.bold.inverse(' SUB '), gray('Subscribed to'), yellow('smartylighting.streetlights.1.0.event.{streetlightId}.lighting.measured')); +app.use(lightingMeasured); +console.log(yellow.bold.inverse(' PUB '), gray('Will eventually publish to'), yellow('smartylighting.streetlights.1.0.action.{streetlightId}.turn.on')); +app.useOutbound(lightTurnOn); +console.log(yellow.bold.inverse(' PUB '), gray('Will eventually publish to'), yellow('smartylighting.streetlights.1.0.action.{streetlightId}.turn.off')); +app.useOutbound(lightTurnOff); +console.log(yellow.bold.inverse(' PUB '), gray('Will eventually publish to'), yellow('smartylighting.streetlights.1.0.action.{streetlightId}.dim')); +app.useOutbound(lightsDim); + +app.use(errorLogger); +app.useOutbound(errorLogger); +app.useOutbound(logger); +app.useOutbound(json2string); + +function init() { + app + .listen() + .then((adapters) => { + console.log(cyan.underline(\`\${config.app.name} \${config.app.version}\`), gray('is ready!'), '\\\\n'); + adapters.forEach(adapter => { + console.log('🔗 ', adapter.name(), gray('is connected!')); + }); + }) + .catch(console.error); +} + +const handlers = { + registerReceiveLightMeasurementMiddleware: require('./handlers/lightingMeasured').registerReceiveLightMeasurementMiddleware, + registerTurnOnMiddleware: require('./handlers/lightTurnOn').registerTurnOnMiddleware, + registerTurnOffMiddleware: require('./handlers/lightTurnOff').registerTurnOffMiddleware, + registerDimLightMiddleware: require('./handlers/lightsDim').registerDimLightMiddleware +} + +const client = { + app, + init, + ...handlers +}; + +module.exports = { + client +};" +`; + +exports[`template integration tests for generated files using the generator and kafka example - v3 spec should generate proper handlers and routes files 10`] = ` +"default: + app: + name: Streetlights Kafka API + version: 1.0.0 + + broker: + + + + kafka: + clientId: streetlightsKafkaApi + brokers: + - test.mykafkacluster.org:18092/ + consumerOptions: + groupId: streetlightsKafkaApi + topics: + - smartylighting.streetlights.1.0.event.{streetlightId}.lighting.measured + topicSeparator: '__' + topicPrefix: + +development: + +test: + +staging: + +production: + broker: + kafka: + ssl: + rejectUnauthorized: true + +" +`; + +exports[`template integration tests for generated files using the generator and kafka example - v3 spec should generate proper handlers and routes files 11`] = ` +"{ + \\"name\\": \\"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 📈\\", + \\"main\\": \\"./src/api\\", + \\"dependencies\\": { + \\"chalk\\": \\"4.1.2\\", + \\"dotenv\\": \\"8.1.0\\", + \\"hermesjs\\": \\"2.x\\", + \\"hermesjs-router\\": \\"1.x\\", + \\"node-fetch\\": \\"2.6.0\\", + \\"node-yaml-config\\": \\"0.0.4\\", + \\"hermesjs-kafka\\": \\"2.x\\" + } +}" +`; + +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should generate proper handlers and routes files 1`] = ` +"const handler = module.exports = {}; + +const dimLightMiddlewares = []; + +/** + * Registers a middleware function for the dimLight operation to be executed during request processing. + * + * Middleware functions have access to options object that you can use to access the message content and other helper functions + * + * @param {function} middlewareFn - The middleware function to be registered. + * @throws {TypeError} If middlewareFn is not a function. + */ +handler.registerDimLightMiddleware = (middlewareFn) => { + if (typeof middlewareFn !== 'function') { + throw new TypeError('middlewareFn must be a function'); + } + dimLightMiddlewares.push(middlewareFn); +} + +/** + * + * + * @param {object} options + * @param {object} options.message + * @param {integer} options.message.headers.my-app-header + * + * @param {integer} options.message.headers.percentage - Percentage to which the light should be dimmed to. + * @param {string} options.message.headers.sentAt - Date and time when the message was sent. + */ +handler._dimLight = async ({ + message +}) => { + for (const middleware of dimLightMiddlewares) { + await middleware(message); + } +};" +`; + +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should generate proper handlers and routes files 2`] = ` +"const handler = module.exports = {}; + +const turnOffMiddlewares = []; + +/** + * Registers a middleware function for the turnOff operation to be executed during request processing. + * + * Middleware functions have access to options object that you can use to access the message content and other helper functions + * + * @param {function} middlewareFn - The middleware function to be registered. + * @throws {TypeError} If middlewareFn is not a function. + */ +handler.registerTurnOffMiddleware = (middlewareFn) => { + if (typeof middlewareFn !== 'function') { + throw new TypeError('middlewareFn must be a function'); + } + turnOffMiddlewares.push(middlewareFn); +} + +/** + * + * + * @param {object} options + * @param {object} options.message + * @param {integer} options.message.headers.my-app-header + * + * @param {string} options.message.headers.command - Whether to turn on or off the light. + * @param {string} options.message.headers.sentAt - Date and time when the message was sent. + */ +handler._turnOff = async ({ + message +}) => { + for (const middleware of turnOffMiddlewares) { + await middleware(message); + } +};" +`; + +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should generate proper handlers and routes files 3`] = ` +"const handler = module.exports = {}; + +const turnOnMiddlewares = []; + +/** + * Registers a middleware function for the turnOn operation to be executed during request processing. + * + * Middleware functions have access to options object that you can use to access the message content and other helper functions + * + * @param {function} middlewareFn - The middleware function to be registered. + * @throws {TypeError} If middlewareFn is not a function. + */ +handler.registerTurnOnMiddleware = (middlewareFn) => { + if (typeof middlewareFn !== 'function') { + throw new TypeError('middlewareFn must be a function'); + } + turnOnMiddlewares.push(middlewareFn); +} + +/** + * + * + * @param {object} options + * @param {object} options.message + * @param {integer} options.message.headers.my-app-header + * + * @param {string} options.message.headers.command - Whether to turn on or off the light. + * @param {string} options.message.headers.sentAt - Date and time when the message was sent. + */ +handler._turnOn = async ({ + message +}) => { + for (const middleware of turnOnMiddlewares) { + await middleware(message); + } +};" +`; + +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should generate proper handlers and routes files 4`] = ` +"const handler = module.exports = {}; + +const receiveLightMeasurementMiddlewares = []; + +/** + * Registers a middleware function for the receiveLightMeasurement operation to be executed during request processing. + * + * Middleware functions have access to options object that you can use to access the message content and other helper functions + * + * @param {function} middlewareFn - The middleware function to be registered. + * @throws {TypeError} If middlewareFn is not a function. + */ +handler.registerReceiveLightMeasurementMiddleware = (middlewareFn) => { + if (typeof middlewareFn !== 'function') { + throw new TypeError('middlewareFn must be a function'); + } + receiveLightMeasurementMiddlewares.push(middlewareFn); +} + +/** + * Inform about environmental lighting conditions of a particular streetlight. + * + * @param {object} options + * @param {object} options.message + * @param {integer} options.message.headers.my-app-header + * + * @param {integer} options.message.headers.lumens - Light intensity measured in lumens. + * @param {string} options.message.headers.sentAt - Date and time when the message was sent. + */ +handler._receiveLightMeasurement = async ({ + message +}) => { + for (const middleware of receiveLightMeasurementMiddlewares) { + await middleware(message); + } +};" +`; + +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should generate proper handlers and routes files 5`] = ` +"const Router = require('hermesjs/lib/router'); +const { + validateMessage +} = require('../../lib/message-validator'); +const router = new Router(); +const smartylightingStreetlights10ActionStreetlightIdDimHandler = require('../handlers/smartylighting-streetlights-1-0-action-{streetlightId}-dim'); +module.exports = router; + +router.useOutbound('smartylighting/streetlights/1/0/action/:streetlightId/dim', async (message, next) => { + try { + await validateMessage(message.payload, 'smartylighting/streetlights/1/0/action/{streetlightId}/dim', 'dimLight', 'subscribe'); + await smartylightingStreetlights10ActionStreetlightIdDimHandler._dimLight({ + message + }); + next(); + } catch (e) { + next(e); + } +});" +`; + +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should generate proper handlers and routes files 6`] = ` +"const Router = require('hermesjs/lib/router'); +const { + validateMessage +} = require('../../lib/message-validator'); +const router = new Router(); +const smartylightingStreetlights10ActionStreetlightIdTurnOffHandler = require('../handlers/smartylighting-streetlights-1-0-action-{streetlightId}-turn-off'); +module.exports = router; + +router.useOutbound('smartylighting/streetlights/1/0/action/:streetlightId/turn/off', async (message, next) => { + try { + await validateMessage(message.payload, 'smartylighting/streetlights/1/0/action/{streetlightId}/turn/off', 'turnOnOff', 'subscribe'); + await smartylightingStreetlights10ActionStreetlightIdTurnOffHandler._turnOff({ + message + }); + next(); + } catch (e) { + next(e); + } +});" +`; + +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should generate proper handlers and routes files 7`] = ` +"const Router = require('hermesjs/lib/router'); +const { + validateMessage +} = require('../../lib/message-validator'); +const router = new Router(); +const smartylightingStreetlights10ActionStreetlightIdTurnOnHandler = require('../handlers/smartylighting-streetlights-1-0-action-{streetlightId}-turn-on'); +module.exports = router; + +router.useOutbound('smartylighting/streetlights/1/0/action/:streetlightId/turn/on', async (message, next) => { + try { + await validateMessage(message.payload, 'smartylighting/streetlights/1/0/action/{streetlightId}/turn/on', 'turnOnOff', 'subscribe'); + await smartylightingStreetlights10ActionStreetlightIdTurnOnHandler._turnOn({ + message + }); + next(); + } catch (e) { + next(e); + } +});" +`; + +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should generate proper handlers and routes files 8`] = ` +"const Router = require('hermesjs/lib/router'); +const { + validateMessage +} = require('../../lib/message-validator'); +const router = new Router(); +const smartylightingStreetlights10EventStreetlightIdLightingMeasuredHandler = require('../handlers/smartylighting-streetlights-1-0-event-{streetlightId}-lighting-measured'); +module.exports = router; + +/** + * Inform about environmental lighting conditions of a particular streetlight. + */ + +router.use('smartylighting/streetlights/1/0/event/:streetlightId/lighting/measured', async (message, next) => { + try { + await validateMessage(message.payload, 'smartylighting/streetlights/1/0/event/{streetlightId}/lighting/measured', 'lightMeasured', 'publish'); + await smartylightingStreetlights10EventStreetlightIdLightingMeasuredHandler._receiveLightMeasurement({ + message + }); + next(); + } catch (e) { + next(e); + } +});" +`; + +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should generate proper handlers and routes files 9`] = ` +"const Hermes = require('hermesjs'); +const app = new Hermes(); +const path = require('path'); +const { + yellow, + gray, + cyan +} = require('chalk'); +const buffer2string = require('./middlewares/buffer2string'); +const string2json = require('./middlewares/string2json'); +const json2string = require('./middlewares/json2string'); +const logger = require('./middlewares/logger'); +const errorLogger = require('./middlewares/error-logger'); +const config = require('../lib/config'); +const serverConfig = config.broker.mqtt; +const MqttAdapter = require('hermesjs-mqtt'); + +const smartylightingStreetlights10EventStreetlightIdLightingMeasured = require('./routes/smartylighting-streetlights-1-0-event-{streetlightId}-lighting-measured.js'); +const smartylightingStreetlights10ActionStreetlightIdTurnOn = require('./routes/smartylighting-streetlights-1-0-action-{streetlightId}-turn-on.js'); +const smartylightingStreetlights10ActionStreetlightIdTurnOff = require('./routes/smartylighting-streetlights-1-0-action-{streetlightId}-turn-off.js'); +const smartylightingStreetlights10ActionStreetlightIdDim = require('./routes/smartylighting-streetlights-1-0-action-{streetlightId}-dim.js'); + +app.addAdapter(MqttAdapter, serverConfig); + +app.use(buffer2string); +app.use(string2json); +app.use(logger); + +// Channels + +console.log(cyan.bold.inverse(' SUB '), gray('Subscribed to'), yellow('smartylighting/streetlights/1/0/event/{streetlightId}/lighting/measured')); +app.use(smartylightingStreetlights10EventStreetlightIdLightingMeasured); +console.log(yellow.bold.inverse(' PUB '), gray('Will eventually publish to'), yellow('smartylighting/streetlights/1/0/action/{streetlightId}/turn/on')); +app.useOutbound(smartylightingStreetlights10ActionStreetlightIdTurnOn); +console.log(yellow.bold.inverse(' PUB '), gray('Will eventually publish to'), yellow('smartylighting/streetlights/1/0/action/{streetlightId}/turn/off')); +app.useOutbound(smartylightingStreetlights10ActionStreetlightIdTurnOff); +console.log(yellow.bold.inverse(' PUB '), gray('Will eventually publish to'), yellow('smartylighting/streetlights/1/0/action/{streetlightId}/dim')); +app.useOutbound(smartylightingStreetlights10ActionStreetlightIdDim); + +app.use(errorLogger); +app.useOutbound(errorLogger); +app.useOutbound(logger); +app.useOutbound(json2string); + +function init() { + app + .listen() + .then((adapters) => { + console.log(cyan.underline(\`\${config.app.name} \${config.app.version}\`), gray('is ready!'), '\\\\n'); + adapters.forEach(adapter => { + console.log('🔗 ', adapter.name(), gray('is connected!')); + }); + }) + .catch(console.error); +} + +const handlers = { + registerReceiveLightMeasurementMiddleware: require('./handlers/smartylighting-streetlights-1-0-event-{streetlightId}-lighting-measured').registerReceiveLightMeasurementMiddleware, + registerTurnOnMiddleware: require('./handlers/smartylighting-streetlights-1-0-action-{streetlightId}-turn-on').registerTurnOnMiddleware, + registerTurnOffMiddleware: require('./handlers/smartylighting-streetlights-1-0-action-{streetlightId}-turn-off').registerTurnOffMiddleware, + registerDimLightMiddleware: require('./handlers/smartylighting-streetlights-1-0-action-{streetlightId}-dim').registerDimLightMiddleware +} + +const client = { + app, + init, + ...handlers +}; + +module.exports = { + client +};" +`; + +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should generate proper handlers and routes files 10`] = ` +"default: + app: + name: Streetlights MQTT API + version: 1.0.0 + + broker: + + + mqtt: + url: mqtt://test.mosquitto.org:1883 + topics: [\\"smartylighting/streetlights/1/0/event/+/lighting/measured\\"] + qos: + protocol: mqtt + retain: + subscribe: true + + +development: + +test: + +staging: + +production: + +" +`; + +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should generate proper handlers and routes files 11`] = ` +"{ + \\"name\\": \\"streetlights-mqtt-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 📈\\", + \\"main\\": \\"./src/api\\", + \\"dependencies\\": { + \\"chalk\\": \\"4.1.2\\", + \\"dotenv\\": \\"8.1.0\\", + \\"hermesjs\\": \\"2.x\\", + \\"hermesjs-router\\": \\"1.x\\", + \\"node-fetch\\": \\"2.6.0\\", + \\"node-yaml-config\\": \\"0.0.4\\", + \\"asyncapi-validator\\": \\"3.0.0\\", + \\"hermesjs-mqtt\\": \\"2.x\\" + } +}" +`; + +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should use mqtt logic for mqtts protocol 1`] = ` "const handler = module.exports = {}; const dimLightMiddlewares = []; @@ -39,7 +779,7 @@ handler._dimLight = async ({ };" `; -exports[`template integration tests for generated files using the generator and mqtt example should generate proper handlers and routes files 2`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should use mqtt logic for mqtts protocol 2`] = ` "const handler = module.exports = {}; const turnOffMiddlewares = []; @@ -78,7 +818,7 @@ handler._turnOff = async ({ };" `; -exports[`template integration tests for generated files using the generator and mqtt example should generate proper handlers and routes files 3`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should use mqtt logic for mqtts protocol 3`] = ` "const handler = module.exports = {}; const turnOnMiddlewares = []; @@ -117,7 +857,7 @@ handler._turnOn = async ({ };" `; -exports[`template integration tests for generated files using the generator and mqtt example should generate proper handlers and routes files 4`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should use mqtt logic for mqtts protocol 4`] = ` "const handler = module.exports = {}; const receiveLightMeasurementMiddlewares = []; @@ -156,7 +896,7 @@ handler._receiveLightMeasurement = async ({ };" `; -exports[`template integration tests for generated files using the generator and mqtt example should generate proper handlers and routes files 5`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should use mqtt logic for mqtts protocol 5`] = ` "const Router = require('hermesjs/lib/router'); const { validateMessage @@ -165,22 +905,20 @@ const router = new Router(); const smartylightingStreetlights10ActionStreetlightIdDimHandler = require('../handlers/smartylighting-streetlights-1-0-action-{streetlightId}-dim'); module.exports = router; -router.use('smartylighting/streetlights/1/0/action/:streetlightId/dim', async (message, next) => { +router.useOutbound('smartylighting/streetlights/1/0/action/:streetlightId/dim', async (message, next) => { try { - await validateMessage(message.payload, 'smartylighting/streetlights/1/0/action/{streetlightId}/dim', 'dimLight', 'subscribe'); await smartylightingStreetlights10ActionStreetlightIdDimHandler._dimLight({ message }); next(); - } catch (e) { next(e); } });" `; -exports[`template integration tests for generated files using the generator and mqtt example should generate proper handlers and routes files 6`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should use mqtt logic for mqtts protocol 6`] = ` "const Router = require('hermesjs/lib/router'); const { validateMessage @@ -189,22 +927,20 @@ const router = new Router(); const smartylightingStreetlights10ActionStreetlightIdTurnOffHandler = require('../handlers/smartylighting-streetlights-1-0-action-{streetlightId}-turn-off'); module.exports = router; -router.use('smartylighting/streetlights/1/0/action/:streetlightId/turn/off', async (message, next) => { +router.useOutbound('smartylighting/streetlights/1/0/action/:streetlightId/turn/off', async (message, next) => { try { - await validateMessage(message.payload, 'smartylighting/streetlights/1/0/action/{streetlightId}/turn/off', 'turnOnOff', 'subscribe'); await smartylightingStreetlights10ActionStreetlightIdTurnOffHandler._turnOff({ message }); next(); - } catch (e) { next(e); } });" `; -exports[`template integration tests for generated files using the generator and mqtt example should generate proper handlers and routes files 7`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should use mqtt logic for mqtts protocol 7`] = ` "const Router = require('hermesjs/lib/router'); const { validateMessage @@ -213,22 +949,20 @@ const router = new Router(); const smartylightingStreetlights10ActionStreetlightIdTurnOnHandler = require('../handlers/smartylighting-streetlights-1-0-action-{streetlightId}-turn-on'); module.exports = router; -router.use('smartylighting/streetlights/1/0/action/:streetlightId/turn/on', async (message, next) => { +router.useOutbound('smartylighting/streetlights/1/0/action/:streetlightId/turn/on', async (message, next) => { try { - await validateMessage(message.payload, 'smartylighting/streetlights/1/0/action/{streetlightId}/turn/on', 'turnOnOff', 'subscribe'); await smartylightingStreetlights10ActionStreetlightIdTurnOnHandler._turnOn({ message }); next(); - } catch (e) { next(e); } });" `; -exports[`template integration tests for generated files using the generator and mqtt example should generate proper handlers and routes files 8`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should use mqtt logic for mqtts protocol 8`] = ` "const Router = require('hermesjs/lib/router'); const { validateMessage @@ -243,20 +977,18 @@ module.exports = router; router.use('smartylighting/streetlights/1/0/event/:streetlightId/lighting/measured', async (message, next) => { try { - await validateMessage(message.payload, 'smartylighting/streetlights/1/0/event/{streetlightId}/lighting/measured', 'lightMeasured', 'publish'); await smartylightingStreetlights10EventStreetlightIdLightingMeasuredHandler._receiveLightMeasurement({ message }); next(); - } catch (e) { next(e); } });" `; -exports[`template integration tests for generated files using the generator and mqtt example should generate proper handlers and routes files 9`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should use mqtt logic for mqtts protocol 9`] = ` "const Hermes = require('hermesjs'); const app = new Hermes(); const path = require('path'); @@ -317,7 +1049,7 @@ const handlers = { registerReceiveLightMeasurementMiddleware: require('./handlers/smartylighting-streetlights-1-0-event-{streetlightId}-lighting-measured').registerReceiveLightMeasurementMiddleware, registerTurnOnMiddleware: require('./handlers/smartylighting-streetlights-1-0-action-{streetlightId}-turn-on').registerTurnOnMiddleware, registerTurnOffMiddleware: require('./handlers/smartylighting-streetlights-1-0-action-{streetlightId}-turn-off').registerTurnOffMiddleware, - registerDimLightMiddleware: require('./handlers/smartylighting-streetlights-1-0-action-{streetlightId}-dim').registerDimLightMiddleware, + registerDimLightMiddleware: require('./handlers/smartylighting-streetlights-1-0-action-{streetlightId}-dim').registerDimLightMiddleware } const client = { @@ -331,7 +1063,7 @@ module.exports = { };" `; -exports[`template integration tests for generated files using the generator and mqtt example should generate proper handlers and routes files 10`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should use mqtt logic for mqtts protocol 10`] = ` "default: app: name: Streetlights MQTT API @@ -341,7 +1073,7 @@ exports[`template integration tests for generated files using the generator and mqtt: - url: mqtt://test.mosquitto.org:1883 + url: mqtts://test.mosquitto.org:8886 topics: [\\"smartylighting/streetlights/1/0/event/+/lighting/measured\\"] qos: protocol: mqtt @@ -360,7 +1092,7 @@ production: " `; -exports[`template integration tests for generated files using the generator and mqtt example should generate proper handlers and routes files 11`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v2 spec should use mqtt logic for mqtts protocol 11`] = ` "{ \\"name\\": \\"streetlights-mqtt-api\\", \\"version\\": \\"1.0.0\\", @@ -371,32 +1103,32 @@ exports[`template integration tests for generated files using the generator and \\"dotenv\\": \\"8.1.0\\", \\"hermesjs\\": \\"2.x\\", \\"hermesjs-router\\": \\"1.x\\", - \\"asyncapi-validator\\": \\"3.0.0\\", \\"node-fetch\\": \\"2.6.0\\", \\"node-yaml-config\\": \\"0.0.4\\", + \\"asyncapi-validator\\": \\"3.0.0\\", \\"hermesjs-mqtt\\": \\"2.x\\" } }" `; -exports[`template integration tests for generated files using the generator and mqtt example should use mqtt logic for mqtts protocol 1`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v3 spec should generate proper handlers and routes files 1`] = ` "const handler = module.exports = {}; -const dimLightMiddlewares = []; +const turnOffMiddlewares = []; /** - * Registers a middleware function for the dimLight operation to be executed during request processing. + * Registers a middleware function for the turnOff operation to be executed during request processing. * * Middleware functions have access to options object that you can use to access the message content and other helper functions * * @param {function} middlewareFn - The middleware function to be registered. * @throws {TypeError} If middlewareFn is not a function. */ -handler.registerDimLightMiddleware = (middlewareFn) => { +handler.registerTurnOffMiddleware = (middlewareFn) => { if (typeof middlewareFn !== 'function') { throw new TypeError('middlewareFn must be a function'); } - dimLightMiddlewares.push(middlewareFn); + turnOffMiddlewares.push(middlewareFn); } /** @@ -406,58 +1138,58 @@ handler.registerDimLightMiddleware = (middlewareFn) => { * @param {object} options.message * @param {integer} options.message.headers.my-app-header * - * @param {integer} options.message.headers.percentage - Percentage to which the light should be dimmed to. + * @param {string} options.message.headers.command - Whether to turn on or off the light. * @param {string} options.message.headers.sentAt - Date and time when the message was sent. */ -handler._dimLight = async ({ +handler._turnOff = async ({ message }) => { - for (const middleware of dimLightMiddlewares) { + for (const middleware of turnOffMiddlewares) { await middleware(message); } };" `; -exports[`template integration tests for generated files using the generator and mqtt example should use mqtt logic for mqtts protocol 2`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v3 spec should generate proper handlers and routes files 2`] = ` "const handler = module.exports = {}; -const turnOffMiddlewares = []; +const receiveLightMeasurementMiddlewares = []; /** - * Registers a middleware function for the turnOff operation to be executed during request processing. + * Registers a middleware function for the receiveLightMeasurement operation to be executed during request processing. * * Middleware functions have access to options object that you can use to access the message content and other helper functions * * @param {function} middlewareFn - The middleware function to be registered. * @throws {TypeError} If middlewareFn is not a function. */ -handler.registerTurnOffMiddleware = (middlewareFn) => { +handler.registerReceiveLightMeasurementMiddleware = (middlewareFn) => { if (typeof middlewareFn !== 'function') { throw new TypeError('middlewareFn must be a function'); } - turnOffMiddlewares.push(middlewareFn); + receiveLightMeasurementMiddlewares.push(middlewareFn); } /** - * + * Inform about environmental lighting conditions of a particular streetlight. * * @param {object} options * @param {object} options.message * @param {integer} options.message.headers.my-app-header * - * @param {string} options.message.headers.command - Whether to turn on or off the light. + * @param {integer} options.message.headers.lumens - Light intensity measured in lumens. * @param {string} options.message.headers.sentAt - Date and time when the message was sent. */ -handler._turnOff = async ({ +handler._receiveLightMeasurement = async ({ message }) => { - for (const middleware of turnOffMiddlewares) { + for (const middleware of receiveLightMeasurementMiddlewares) { await middleware(message); } };" `; -exports[`template integration tests for generated files using the generator and mqtt example should use mqtt logic for mqtts protocol 3`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v3 spec should generate proper handlers and routes files 3`] = ` "const handler = module.exports = {}; const turnOnMiddlewares = []; @@ -496,146 +1228,130 @@ handler._turnOn = async ({ };" `; -exports[`template integration tests for generated files using the generator and mqtt example should use mqtt logic for mqtts protocol 4`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v3 spec should generate proper handlers and routes files 4`] = ` "const handler = module.exports = {}; -const receiveLightMeasurementMiddlewares = []; +const dimLightMiddlewares = []; /** - * Registers a middleware function for the receiveLightMeasurement operation to be executed during request processing. + * Registers a middleware function for the dimLight operation to be executed during request processing. * * Middleware functions have access to options object that you can use to access the message content and other helper functions * * @param {function} middlewareFn - The middleware function to be registered. * @throws {TypeError} If middlewareFn is not a function. */ -handler.registerReceiveLightMeasurementMiddleware = (middlewareFn) => { +handler.registerDimLightMiddleware = (middlewareFn) => { if (typeof middlewareFn !== 'function') { throw new TypeError('middlewareFn must be a function'); } - receiveLightMeasurementMiddlewares.push(middlewareFn); + dimLightMiddlewares.push(middlewareFn); } /** - * Inform about environmental lighting conditions of a particular streetlight. + * * * @param {object} options * @param {object} options.message * @param {integer} options.message.headers.my-app-header * - * @param {integer} options.message.headers.lumens - Light intensity measured in lumens. + * @param {integer} options.message.headers.percentage - Percentage to which the light should be dimmed to. * @param {string} options.message.headers.sentAt - Date and time when the message was sent. */ -handler._receiveLightMeasurement = async ({ +handler._dimLight = async ({ message }) => { - for (const middleware of receiveLightMeasurementMiddlewares) { + for (const middleware of dimLightMiddlewares) { await middleware(message); } };" `; -exports[`template integration tests for generated files using the generator and mqtt example should use mqtt logic for mqtts protocol 5`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v3 spec should generate proper handlers and routes files 5`] = ` "const Router = require('hermesjs/lib/router'); -const { - validateMessage -} = require('../../lib/message-validator'); + const router = new Router(); -const smartylightingStreetlights10ActionStreetlightIdDimHandler = require('../handlers/smartylighting-streetlights-1-0-action-{streetlightId}-dim'); +const lightTurnOffHandler = require('../handlers/lightTurnOff'); module.exports = router; -router.use('smartylighting/streetlights/1/0/action/:streetlightId/dim', async (message, next) => { +router.useOutbound('smartylighting/streetlights/1/0/action/:streetlightId/turn/off', async (message, next) => { try { - await validateMessage(message.payload, 'smartylighting/streetlights/1/0/action/{streetlightId}/dim', 'dimLight', 'subscribe'); - await smartylightingStreetlights10ActionStreetlightIdDimHandler._dimLight({ + await lightTurnOffHandler._turnOff({ message }); next(); - } catch (e) { next(e); } });" `; -exports[`template integration tests for generated files using the generator and mqtt example should use mqtt logic for mqtts protocol 6`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v3 spec should generate proper handlers and routes files 6`] = ` "const Router = require('hermesjs/lib/router'); -const { - validateMessage -} = require('../../lib/message-validator'); + const router = new Router(); -const smartylightingStreetlights10ActionStreetlightIdTurnOffHandler = require('../handlers/smartylighting-streetlights-1-0-action-{streetlightId}-turn-off'); +const lightingMeasuredHandler = require('../handlers/lightingMeasured'); module.exports = router; -router.use('smartylighting/streetlights/1/0/action/:streetlightId/turn/off', async (message, next) => { +/** + * Inform about environmental lighting conditions of a particular streetlight. + */ + +router.use('smartylighting/streetlights/1/0/event/:streetlightId/lighting/measured', async (message, next) => { try { - await validateMessage(message.payload, 'smartylighting/streetlights/1/0/action/{streetlightId}/turn/off', 'turnOnOff', 'subscribe'); - await smartylightingStreetlights10ActionStreetlightIdTurnOffHandler._turnOff({ + await lightingMeasuredHandler._receiveLightMeasurement({ message }); next(); - } catch (e) { next(e); } });" `; -exports[`template integration tests for generated files using the generator and mqtt example should use mqtt logic for mqtts protocol 7`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v3 spec should generate proper handlers and routes files 7`] = ` "const Router = require('hermesjs/lib/router'); -const { - validateMessage -} = require('../../lib/message-validator'); + const router = new Router(); -const smartylightingStreetlights10ActionStreetlightIdTurnOnHandler = require('../handlers/smartylighting-streetlights-1-0-action-{streetlightId}-turn-on'); +const lightTurnOnHandler = require('../handlers/lightTurnOn'); module.exports = router; -router.use('smartylighting/streetlights/1/0/action/:streetlightId/turn/on', async (message, next) => { +router.useOutbound('smartylighting/streetlights/1/0/action/:streetlightId/turn/on', async (message, next) => { try { - await validateMessage(message.payload, 'smartylighting/streetlights/1/0/action/{streetlightId}/turn/on', 'turnOnOff', 'subscribe'); - await smartylightingStreetlights10ActionStreetlightIdTurnOnHandler._turnOn({ + await lightTurnOnHandler._turnOn({ message }); next(); - } catch (e) { next(e); } });" `; -exports[`template integration tests for generated files using the generator and mqtt example should use mqtt logic for mqtts protocol 8`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v3 spec should generate proper handlers and routes files 8`] = ` "const Router = require('hermesjs/lib/router'); -const { - validateMessage -} = require('../../lib/message-validator'); + const router = new Router(); -const smartylightingStreetlights10EventStreetlightIdLightingMeasuredHandler = require('../handlers/smartylighting-streetlights-1-0-event-{streetlightId}-lighting-measured'); +const lightsDimHandler = require('../handlers/lightsDim'); module.exports = router; -/** - * Inform about environmental lighting conditions of a particular streetlight. - */ - -router.use('smartylighting/streetlights/1/0/event/:streetlightId/lighting/measured', async (message, next) => { +router.useOutbound('smartylighting/streetlights/1/0/action/:streetlightId/dim', async (message, next) => { try { - await validateMessage(message.payload, 'smartylighting/streetlights/1/0/event/{streetlightId}/lighting/measured', 'lightMeasured', 'publish'); - await smartylightingStreetlights10EventStreetlightIdLightingMeasuredHandler._receiveLightMeasurement({ + await lightsDimHandler._dimLight({ message }); next(); - } catch (e) { next(e); } });" `; -exports[`template integration tests for generated files using the generator and mqtt example should use mqtt logic for mqtts protocol 9`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v3 spec should generate proper handlers and routes files 9`] = ` "const Hermes = require('hermesjs'); const app = new Hermes(); const path = require('path'); @@ -653,10 +1369,10 @@ const config = require('../lib/config'); const serverConfig = config.broker.mqtt; const MqttAdapter = require('hermesjs-mqtt'); -const smartylightingStreetlights10EventStreetlightIdLightingMeasured = require('./routes/smartylighting-streetlights-1-0-event-{streetlightId}-lighting-measured.js'); -const smartylightingStreetlights10ActionStreetlightIdTurnOn = require('./routes/smartylighting-streetlights-1-0-action-{streetlightId}-turn-on.js'); -const smartylightingStreetlights10ActionStreetlightIdTurnOff = require('./routes/smartylighting-streetlights-1-0-action-{streetlightId}-turn-off.js'); -const smartylightingStreetlights10ActionStreetlightIdDim = require('./routes/smartylighting-streetlights-1-0-action-{streetlightId}-dim.js'); +const lightingMeasured = require('./routes/lightingMeasured.js'); +const lightTurnOn = require('./routes/lightTurnOn.js'); +const lightTurnOff = require('./routes/lightTurnOff.js'); +const lightsDim = require('./routes/lightsDim.js'); app.addAdapter(MqttAdapter, serverConfig); @@ -667,13 +1383,13 @@ app.use(logger); // Channels console.log(cyan.bold.inverse(' SUB '), gray('Subscribed to'), yellow('smartylighting/streetlights/1/0/event/{streetlightId}/lighting/measured')); -app.use(smartylightingStreetlights10EventStreetlightIdLightingMeasured); +app.use(lightingMeasured); console.log(yellow.bold.inverse(' PUB '), gray('Will eventually publish to'), yellow('smartylighting/streetlights/1/0/action/{streetlightId}/turn/on')); -app.useOutbound(smartylightingStreetlights10ActionStreetlightIdTurnOn); +app.useOutbound(lightTurnOn); console.log(yellow.bold.inverse(' PUB '), gray('Will eventually publish to'), yellow('smartylighting/streetlights/1/0/action/{streetlightId}/turn/off')); -app.useOutbound(smartylightingStreetlights10ActionStreetlightIdTurnOff); +app.useOutbound(lightTurnOff); console.log(yellow.bold.inverse(' PUB '), gray('Will eventually publish to'), yellow('smartylighting/streetlights/1/0/action/{streetlightId}/dim')); -app.useOutbound(smartylightingStreetlights10ActionStreetlightIdDim); +app.useOutbound(lightsDim); app.use(errorLogger); app.useOutbound(errorLogger); @@ -693,10 +1409,10 @@ function init() { } const handlers = { - registerReceiveLightMeasurementMiddleware: require('./handlers/smartylighting-streetlights-1-0-event-{streetlightId}-lighting-measured').registerReceiveLightMeasurementMiddleware, - registerTurnOnMiddleware: require('./handlers/smartylighting-streetlights-1-0-action-{streetlightId}-turn-on').registerTurnOnMiddleware, - registerTurnOffMiddleware: require('./handlers/smartylighting-streetlights-1-0-action-{streetlightId}-turn-off').registerTurnOffMiddleware, - registerDimLightMiddleware: require('./handlers/smartylighting-streetlights-1-0-action-{streetlightId}-dim').registerDimLightMiddleware, + registerReceiveLightMeasurementMiddleware: require('./handlers/lightingMeasured').registerReceiveLightMeasurementMiddleware, + registerTurnOnMiddleware: require('./handlers/lightTurnOn').registerTurnOnMiddleware, + registerTurnOffMiddleware: require('./handlers/lightTurnOff').registerTurnOffMiddleware, + registerDimLightMiddleware: require('./handlers/lightsDim').registerDimLightMiddleware } const client = { @@ -710,7 +1426,7 @@ module.exports = { };" `; -exports[`template integration tests for generated files using the generator and mqtt example should use mqtt logic for mqtts protocol 10`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v3 spec should generate proper handlers and routes files 10`] = ` "default: app: name: Streetlights MQTT API @@ -720,7 +1436,7 @@ exports[`template integration tests for generated files using the generator and mqtt: - url: mqtts://test.mosquitto.org:8886 + url: mqtt://test.mosquitto.org:1883/ topics: [\\"smartylighting/streetlights/1/0/event/+/lighting/measured\\"] qos: protocol: mqtt @@ -739,7 +1455,7 @@ production: " `; -exports[`template integration tests for generated files using the generator and mqtt example should use mqtt logic for mqtts protocol 11`] = ` +exports[`template integration tests for generated files using the generator and mqtt example - v3 spec should generate proper handlers and routes files 11`] = ` "{ \\"name\\": \\"streetlights-mqtt-api\\", \\"version\\": \\"1.0.0\\", @@ -750,7 +1466,6 @@ exports[`template integration tests for generated files using the generator and \\"dotenv\\": \\"8.1.0\\", \\"hermesjs\\": \\"2.x\\", \\"hermesjs-router\\": \\"1.x\\", - \\"asyncapi-validator\\": \\"3.0.0\\", \\"node-fetch\\": \\"2.6.0\\", \\"node-yaml-config\\": \\"0.0.4\\", \\"hermesjs-mqtt\\": \\"2.x\\" diff --git a/test/integration.test.js b/test/integration.test.js index 84e3e671..7bbb99d4 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -1,3 +1,4 @@ +/* eslint-disable sonarjs/no-duplicate-string */ const path = require('path'); const Generator = require('@asyncapi/generator'); const { readFile } = require('fs').promises; @@ -9,7 +10,7 @@ const generateFolderName = () => { return path.resolve(MAIN_TEST_RESULT_PATH, Date.now().toString()); }; -describe('template integration tests for generated files using the generator and mqtt example', () => { +describe('template integration tests for generated files using the generator and mqtt example - v2 spec', () => { jest.setTimeout(30000); it.each` @@ -49,7 +50,7 @@ describe('template integration tests for generated files using the generator and ); }); -describe('template integration tests for generated files using the generator and kafka example', () => { +describe('template integration tests for generated files using the generator and kafka example - v2 spec', () => { jest.setTimeout(30000); const outputDir = generateFolderName(); @@ -78,6 +79,117 @@ describe('template integration tests for generated files using the generator and const generator = new Generator(path.normalize('./'), outputDir, { forceWrite: true, templateParams: params }); await generator.generateFromFile(path.resolve('test', kafkaExamplePath)); + const file = await readFile(path.join(outputDir, expectedFile), 'utf8'); + expect(file.includes(expectedVariable)).toBeTruthy(); + }); +}); + +describe('template integration tests for generated files using the generator and mqtt example - v3 spec', () => { + jest.setTimeout(30000); + + it.each` + server | description + ${'production'} | ${'should generate proper handlers and routes files'} + `( + '$description', + async ({ server}) => { + const outputDir = generateFolderName(); + const params = { + server + }; + const mqttExamplePath = './mocks/mqtt/asyncapi-v3.yml'; + + const generator = new Generator(path.normalize('./'), outputDir, { forceWrite: true, templateParams: params }); + await generator.generateFromFile(path.resolve('test', mqttExamplePath)); + + const expectedFiles = [ + '/src/api/handlers/lightTurnOff.js', + '/src/api/handlers/lightingMeasured.js', + '/src/api/handlers/lightTurnOn.js', + '/src/api/handlers/lightsDim.js', + '/src/api/routes/lightTurnOff.js', + '/src/api/routes/lightingMeasured.js', + '/src/api/routes/lightTurnOn.js', + '/src/api/routes/lightsDim.js', + '/src/api/index.js', + '/config/common.yml', + '/package.json' + ]; + for (const index in expectedFiles) { + const file = await readFile(path.join(outputDir, expectedFiles[index]), 'utf8'); + expect(file).toMatchSnapshot(); + } + } + ); +}); + +describe('template integration tests for generated files using the generator and kafka example - v3 spec', () => { + jest.setTimeout(30000); + + const outputDir = generateFolderName(); + const kafkaExamplePath = './mocks/kafka/asyncapi-v3.yml'; + + it.each` + server | description + ${'scram-connections'} | ${'should generate proper handlers and routes files'} + `( + '$description', + async ({ server}) => { + const params = { + server + }; + + const generator = new Generator(path.normalize('./'), outputDir, { forceWrite: true, templateParams: params }); + await generator.generateFromFile(path.resolve('test', kafkaExamplePath)); + + const expectedFiles = [ + '/src/api/handlers/lightTurnOff.js', + '/src/api/handlers/lightingMeasured.js', + '/src/api/handlers/lightTurnOn.js', + '/src/api/handlers/lightsDim.js', + '/src/api/routes/lightTurnOff.js', + '/src/api/routes/lightingMeasured.js', + '/src/api/routes/lightTurnOn.js', + '/src/api/routes/lightsDim.js', + '/src/api/index.js', + '/config/common.yml', + '/package.json' + ]; + for (const index in expectedFiles) { + const file = await readFile(path.join(outputDir, expectedFiles[index]), 'utf8'); + expect(file).toMatchSnapshot(); + } + } + ); + + it('should generate proper config for X509 security', async() => { + const params = { + server: 'scram-connections', + securityScheme: 'certs', + certFilesDir: './mocks/kafka/dummyCerts' + }; + const expectedSecuritySetting = 'rejectUnauthorized: true'; + const expectedConfigFile = '/config/common.yml'; + + const generator = new Generator(path.normalize('./'), outputDir, { forceWrite: true, templateParams: params }); + await generator.generateFromFile(path.resolve('test', kafkaExamplePath)); + + const file = await readFile(path.join(outputDir, expectedConfigFile), 'utf8'); + expect(file.includes(expectedSecuritySetting)).toBeTruthy(); + }); + + it('should generate proper variable that points to custom cert files location', async() => { + const params = { + server: 'scram-connections', + securityScheme: 'certs', + certFilesDir: './mocks/kafka/dummyCerts' + }; + const expectedVariable = 'const certFilesDir = \'./mocks/kafka/dummyCerts\';'; + const expectedFile = '/src/api/index.js'; + + const generator = new Generator(path.normalize('./'), outputDir, { forceWrite: true, templateParams: params }); + await generator.generateFromFile(path.resolve('test', kafkaExamplePath)); + const file = await readFile(path.join(outputDir, expectedFile), 'utf8'); expect(file.includes(expectedVariable)).toBeTruthy(); }); diff --git a/test/mocks/kafka/asyncapi-v3.yml b/test/mocks/kafka/asyncapi-v3.yml new file mode 100644 index 00000000..9df24bae --- /dev/null +++ b/test/mocks/kafka/asyncapi-v3.yml @@ -0,0 +1,199 @@ +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.\n\n### Check out its awesome features:\n\n* Turn a specific streetlight on/off \U0001F303\n* Dim a specific streetlight \U0001F60E\n* Receive real-time information about environmental lighting conditions \U0001F4C8\n" + 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' + parameters: + streetlightId: + $ref: '#/components/parameters/streetlightId' + lightTurnOff: + address: 'smartylighting.streetlights.1.0.action.{streetlightId}.turn.off' + messages: + turnOff: + $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/lightTurnOn' + traits: + - $ref: '#/components/operationTraits/kafka' + messages: + - $ref: '#/channels/lightTurnOn/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 + 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 \ No newline at end of file diff --git a/test/mocks/mqtt/asyncapi-v3.yml b/test/mocks/mqtt/asyncapi-v3.yml new file mode 100644 index 00000000..c94091c6 --- /dev/null +++ b/test/mocks/mqtt/asyncapi-v3.yml @@ -0,0 +1,253 @@ +asyncapi: 3.0.0 +info: + title: Streetlights MQTT API + version: 1.0.0 + description: "The Smartylighting Streetlights API allows you to remotely manage the city lights.\n\n### Check out its awesome features:\n\n* Turn a specific streetlight on/off \U0001F303\n* Dim a specific streetlight \U0001F60E\n* Receive real-time information about environmental lighting conditions \U0001F4C8\n" + license: + name: Apache 2.0 + url: 'https://www.apache.org/licenses/LICENSE-2.0' +defaultContentType: application/json +servers: + production: + host: 'test.mosquitto.org:{port}' + 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' + - type: oauth2 + description: Flows to support OAuth 2.0 + flows: + implicit: + authorizationUrl: 'https://authserver.example/auth' + availableScopes: + 'streetlights:on': Ability to switch lights on + 'streetlights:off': Ability to switch lights off + 'streetlights:dim': Ability to dim the lights + password: + tokenUrl: 'https://authserver.example/token' + availableScopes: + 'streetlights:on': Ability to switch lights on + 'streetlights:off': Ability to switch lights off + 'streetlights:dim': Ability to dim the lights + clientCredentials: + tokenUrl: 'https://authserver.example/token' + availableScopes: + 'streetlights:on': Ability to switch lights on + 'streetlights:off': Ability to switch lights off + 'streetlights:dim': Ability to dim the lights + authorizationCode: + authorizationUrl: 'https://authserver.example/auth' + tokenUrl: 'https://authserver.example/token' + refreshUrl: 'https://authserver.example/refresh' + availableScopes: + 'streetlights:on': Ability to switch lights on + 'streetlights:off': Ability to switch lights off + 'streetlights:dim': Ability to dim the lights + scopes: + - 'streetlights:on' + - 'streetlights:off' + - 'streetlights:dim' + - $ref: '#/components/securitySchemes/openIdConnectWellKnown' + tags: + - name: 'env:production' + description: This environment is meant for production use case + - name: 'kind:remote' + description: This server is a remote server. Not exposed by the application + - name: 'visibility:public' + description: This resource is public and available to everyone +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' + parameters: + streetlightId: + $ref: '#/components/parameters/streetlightId' + lightTurnOff: + address: 'smartylighting/streetlights/1/0/action/{streetlightId}/turn/off' + messages: + turnOff: + $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/mqtt' + messages: + - $ref: '#/channels/lightingMeasured/messages/lightMeasured' + turnOn: + action: send + channel: + $ref: '#/channels/lightTurnOn' + traits: + - $ref: '#/components/operationTraits/mqtt' + messages: + - $ref: '#/channels/lightTurnOn/messages/turnOn' + turnOff: + action: send + channel: + $ref: '#/channels/lightTurnOff' + traits: + - $ref: '#/components/operationTraits/mqtt' + messages: + - $ref: '#/channels/lightTurnOff/messages/turnOff' + dimLight: + action: send + channel: + $ref: '#/channels/lightsDim' + traits: + - $ref: '#/components/operationTraits/mqtt' + 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 + 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. + supportedOauthFlows: + type: oauth2 + description: Flows to support OAuth 2.0 + flows: + implicit: + authorizationUrl: 'https://authserver.example/auth' + availableScopes: + 'streetlights:on': Ability to switch lights on + 'streetlights:off': Ability to switch lights off + 'streetlights:dim': Ability to dim the lights + password: + tokenUrl: 'https://authserver.example/token' + availableScopes: + 'streetlights:on': Ability to switch lights on + 'streetlights:off': Ability to switch lights off + 'streetlights:dim': Ability to dim the lights + clientCredentials: + tokenUrl: 'https://authserver.example/token' + availableScopes: + 'streetlights:on': Ability to switch lights on + 'streetlights:off': Ability to switch lights off + 'streetlights:dim': Ability to dim the lights + authorizationCode: + authorizationUrl: 'https://authserver.example/auth' + tokenUrl: 'https://authserver.example/token' + refreshUrl: 'https://authserver.example/refresh' + availableScopes: + 'streetlights:on': Ability to switch lights on + 'streetlights:off': Ability to switch lights off + 'streetlights:dim': Ability to dim the lights + openIdConnectWellKnown: + type: openIdConnect + openIdConnectUrl: 'https://authserver.example/.well-known' + parameters: + streetlightId: + description: The ID of the streetlight. + messageTraits: + commonHeaders: + headers: + type: object + properties: + my-app-header: + type: integer + minimum: 0 + maximum: 100 + operationTraits: + mqtt: + bindings: + mqtt: + qos: 1 \ No newline at end of file