From 6b157053f73c30d25f14cd07a379a2ffc38e1c7c Mon Sep 17 00:00:00 2001 From: Prince Rajpoot Date: Thu, 23 Apr 2026 00:30:12 +0530 Subject: [PATCH 1/6] Update branch and resolve merge conflicts --- .github/workflows/regenerate-tools.yml | 5 + .../scripts/mailchimp/package-lock.json | 189 +- .gitignore | 1 + CODEOWNERS | 8 +- assets/docs/fragments/cli-installation.md | 4 +- components/Accordion/AccordionItem.tsx | 33 +- components/AlgoliaSearch.tsx | 13 +- components/Calendar.tsx | 13 +- components/CaseTOC.tsx | 11 +- .../FinancialSummary/BarChartComponent.tsx | 110 +- components/FinancialSummary/ContactUs.tsx | 6 +- components/Modal.tsx | 2 +- components/NewsletterSubscribe.tsx | 29 +- components/buttons/ScrollButton.tsx | 17 +- .../campaigns/AnnouncementRemainingDays.tsx | 6 +- components/community/Header.tsx | 2 +- components/dashboard/Header.tsx | 2 +- components/data/ExpenseBreakdownData.ts | 2 +- components/docs/Visualizer.tsx | 49 +- components/editor/CodeBlock.tsx | 13 +- components/helpers/applyFilter.ts | 44 +- components/layout/BlogLayout.tsx | 4 +- components/layout/CommunityLayout.tsx | 2 +- components/layout/DocsLayout.tsx | 4 +- components/navigation/BlogPostItem.tsx | 4 +- components/navigation/EventFilter.tsx | 8 +- components/navigation/EventPostItem.tsx | 16 +- components/navigation/Filter.tsx | 24 +- components/navigation/MobileNavMenu.tsx | 25 +- components/navigation/NavBar.tsx | 3 + components/navigation/NavItem.tsx | 55 +- components/newsroom/FeaturedBlogPost.tsx | 4 +- components/roadmap/RoadmapColumn.tsx | 3 +- components/roadmap/RoadmapItem.tsx | 10 +- components/roadmap/RoadmapList.tsx | 10 +- components/roadmap/RoadmapPill.tsx | 2 +- components/roadmap/types.ts | 13 + components/tools/ToolsDashboard.tsx | 15 +- config/3.1.0.json | 8373 ++++ config/AMBASSADORS_MEMBERS.json | 239 +- config/MAINTAINERS.json | 120 +- config/TSC_BOARD_MEMBERS.json | 212 +- config/all-tags.json | 26 +- config/edit-page-config.json | 4 + config/meetings.json | 161 +- config/newsroom_videos.json | 40 +- config/tools-automated.json | 642 +- config/tools-ignore.json | 31 + config/tools-manual.json | 4 +- config/tools.json | 496 +- cypress/ambassadors.cy.js | 51 + cypress/dashboard.cy.js | 25 + cypress/docspage.cy.js | 6 +- cypress/events.cy.js | 53 + cypress/fixtures/docsSections.json | 4 +- cypress/fixtures/footerPageData.json | 2 +- cypress/fixtures/toolsPages.json | 37 + cypress/header.cy.js | 6 +- cypress/pages/BaseFooterPage.js | 2 +- cypress/pages/BaseHeaderPage.js | 9 +- cypress/pages/BasePage.js | 54 + cypress/pages/BasePageTools.js | 19 +- cypress/pages/BlogPage.js | 7 +- cypress/pages/CaseStudiesPage.js | 7 +- cypress/pages/CommunityPage.js | 8 +- cypress/pages/Footer.js | 6 +- cypress/pages/RoadmapPage.js | 7 +- cypress/pages/ToolsPage.js | 20 +- cypress/pages/ambassadors.js | 32 + cypress/pages/basepagedocs.js | 10 +- cypress/pages/dashboard.js | 40 + cypress/pages/events.js | 109 + cypress/pages/homepage.js | 49 +- cypress/pages/slack.js | 85 + cypress/pages/toolsGenerator.js | 11 + cypress/pages/toolsModelina.js | 14 + cypress/pages/tscpage.js | 36 + cypress/slackworkspace.cy.js | 34 + cypress/tools_cli.cy.js | 27 + cypress/tools_generator.cy.js | 26 + cypress/tools_github_actions.cy.js | 19 + cypress/tools_modelina.cy.js | 26 + cypress/tools_parsers.cy.js | 23 + cypress/toolspage.cy.js | 6 +- cypress/tscpage.cy.js | 80 + docs/tools-ignore-design.md | 391 + markdown/about/index.md | 2 +- markdown/blog/2022Q1-summary.md | 2 +- markdown/blog/2023-mentorship-summary.md | 6 +- markdown/blog/2023-summary.md | 2 +- markdown/blog/2024-Q1-docs-report.md | 2 +- markdown/blog/2024-annual-summary.md | 2 +- markdown/blog/2024-april-summary.md | 2 +- markdown/blog/2024-february-summary.md | 4 +- markdown/blog/2024-july-summary.md | 2 +- markdown/blog/2025-Q1-marketing-report.md | 2 +- markdown/blog/2025-annual-summary.md | 176 + markdown/blog/2025-conference-summary.md | 153 + markdown/blog/2025-december-summary.md | 1 - markdown/blog/2025-february-summary.md | 2 +- markdown/blog/2025-gsoc-phase-1.md | 2 +- markdown/blog/2025-gsoc-summary.md | 174 + markdown/blog/2026-february-summary.md | 98 + markdown/blog/2026-march-summary.md | 66 + markdown/blog/april-2021-at-asyncapi.md | 2 +- markdown/blog/asyncapi-ambassador-program.md | 2 +- markdown/blog/asyncapi-and-websocket.md | 557 + markdown/blog/asyncapi-bounty-program-2024.md | 2 +- markdown/blog/beyond-boundaries.md | 2 +- markdown/blog/board-nomination.md | 63 + markdown/blog/community-spotlight-hugo.md | 104 + markdown/blog/community-spotlight-maya.md | 124 + markdown/blog/first-governance-elections.md | 2 +- markdown/blog/google-season-of-docs-2022.md | 2 +- markdown/blog/gravitee-sponsorship-2025.md | 63 + markdown/blog/july-2023.md | 2 +- .../blog/july-december-2021-at-asyncapi.md | 2 +- markdown/blog/march-2021-at-asyncapi.md | 2 +- markdown/blog/new-governance-board.md | 2 +- markdown/blog/release-notes-3.1.0.md | 57 + markdown/blog/vsasyncapi-preview-extension.md | 59 + .../docs/community/000-onboarding/index.md | 2 +- .../020-governance-and-policies/GOVERNANCE.md | 2 +- .../TSC_MEMBERSHIP.md | 2 +- .../TSC_VOTING_OVERVIEW.md | 120 +- .../040-guides/holopin-badge-workflow.md | 116 + markdown/docs/community/040-guides/index.md | 3 +- .../summer-of-code-2026-project-ideas.md | 84 + ...merofcode-2025-asyncapi-gsoc-ideas-page.md | 2 +- .../asyncapi-document/adding-messages.md | 6 +- .../asyncapi-document/adding-operations.md | 2 +- .../dynamic-channel-address.md | 4 +- .../extending-specification.md | 2 +- .../docs/concepts/asyncapi-document/index.md | 2 +- .../concepts/asyncapi-document/reply-info.md | 6 +- .../reusability-with-traits.md | 2 +- .../asyncapi-document/reusable-parts.md | 2 +- .../asyncapi-document/securing-operations.md | 2 +- .../asyncapi-document/server-security.md | 2 +- .../docs/concepts/asyncapi-document/tags.md | 8 +- .../asyncapi-document/variable-url.md | 4 +- markdown/docs/guides/message-validation.md | 2 +- markdown/docs/reference/bindings/2.x.x.md | 307 + markdown/docs/reference/bindings/3.0.0.md | 332 + markdown/docs/reference/bindings/_section.md | 4 +- markdown/docs/reference/bindings/amqp.md | 159 + markdown/docs/reference/bindings/amqp1.md | 42 + .../docs/reference/bindings/anypointmq.md | 244 + .../docs/reference/bindings/googlepubsub.md | 179 + markdown/docs/reference/bindings/http.md | 103 + markdown/docs/reference/bindings/ibmmq.md | 328 + markdown/docs/reference/bindings/jms.md | 163 + markdown/docs/reference/bindings/kafka.md | 207 + markdown/docs/reference/bindings/mercure.md | 48 + markdown/docs/reference/bindings/mqtt.md | 189 + markdown/docs/reference/bindings/mqtt5.md | 79 + markdown/docs/reference/bindings/nats.md | 38 + markdown/docs/reference/bindings/pulsar.md | 91 + markdown/docs/reference/bindings/redis.md | 45 + markdown/docs/reference/bindings/ros2.md | 335 + markdown/docs/reference/bindings/scripts.md | 6 + markdown/docs/reference/bindings/solace.md | 207 + markdown/docs/reference/bindings/sqs.md | 249 + markdown/docs/reference/bindings/stomp.md | 45 + .../docs/reference/bindings/websockets.md | 58 + .../specification/v3.0.0-explorer.md | 8 +- .../specification/v3.1.0-explorer.md | 2 + .../docs/reference/specification/v3.1.0.md | 2710 ++ markdown/docs/tools/cli/architecture.md | 191 +- markdown/docs/tools/cli/contributing-prs.md | 114 + markdown/docs/tools/cli/debugging-testing.md | 635 + markdown/docs/tools/cli/usage.md | 242 +- markdown/docs/tools/generator/api.md | 2 +- .../docs/tools/generator/api_components.md | 1258 + .../tools/generator/configuration-file.md | 2 +- .../tools/generator/generator-template.md | 140 +- .../docs/tools/generator/model-generation.md | 2 +- markdown/docs/tools/generator/template.md | 2 +- markdown/docs/tools/generator/usage.md | 18 +- markdown/docs/tools/generator/versioning.md | 3 +- .../tutorials/create-asyncapi-document.md | 6 +- .../getting-started/asyncapi-documents.md | 2 +- .../tutorials/getting-started/hello-world.md | 12 +- .../getting-started/request-reply.md | 4 +- .../tutorials/getting-started/security.md | 4 +- .../docs/tutorials/getting-started/servers.md | 2 +- .../tutorials/kafka/bindings-with-kafka.md | 4 +- .../tutorials/kafka/configure-kafka-avro.md | 4 +- markdown/docs/tutorials/kafka/index.md | 6 +- .../managing-schemas-using-schema-registry.md | 4 +- .../tutorials/studio-document-validation.md | 2 +- markdown/docs/tutorials/websocket/index.md | 4 +- .../websocket/websocket-request-reply.md | 2 +- next-i18next.config.cjs | 5 +- package-lock.json | 35042 ++++++++-------- package.json | 24 +- pages/[lang]/index.tsx | 4 +- pages/blog/index.tsx | 1 + pages/community/ambassadors/index.tsx | 2 + pages/community/board.tsx | 4 +- pages/roadmap.tsx | 9 +- pages/tools/generator.tsx | 16 +- public/_redirects | 5 +- public/img/avatars/ruchip16.webp | Bin 0 -> 127228 bytes public/img/diagrams/asyncapi-openapi.webp | Bin 0 -> 91828 bytes public/img/diagrams/ecosystem.webp | Bin 0 -> 128798 bytes public/img/diagrams/spec-first.webp | Bin 0 -> 70404 bytes public/img/docs/SNS-HTTP.png | Bin 0 -> 50765 bytes public/img/docs/SNS-SQS-Pub-Sub.png | Bin 0 -> 47278 bytes public/img/docs/SQS-Point-To-Point.png | Bin 0 -> 37204 bytes .../2025-blog-banner/Active contributors.webp | Bin 0 -> 36968 bytes .../Audience and Engagement.webp | Bin 0 -> 6662 bytes .../2025-blog-banner/Average and Median.webp | Bin 0 -> 8140 bytes .../2025-blog-banner/Followers vs. Year.webp | Bin 0 -> 6150 bytes .../2025-blog-banner/Issues resolution.webp | Bin 0 -> 56620 bytes .../2025-blog-banner/Joiners vs. Year.webp | Bin 0 -> 6108 bytes public/img/posts/2025-blog-banner/NPM.webp | Bin 0 -> 22918 bytes .../posts/2025-blog-banner/Pull requests.webp | Bin 0 -> 61622 bytes .../2025-blog-banner/Search Console.webp | Bin 0 -> 16250 bytes public/img/posts/2025-blog-banner/Visits.webp | Bin 0 -> 14566 bytes .../posts/2025-blog-banner/YouTube stats.webp | Bin 0 -> 9356 bytes public/img/posts/2025-blog-banner/apiconf.png | Bin 0 -> 11502 bytes .../posts/2025-blog-banner/banner-annual.webp | Bin 0 -> 29432 bytes .../posts/2025-blog-banner/banner-conf.webp | Bin 0 -> 173550 bytes .../2025-blog-banner/open vs clicks.webp | Bin 0 -> 23640 bytes .../2025-blog-banner/outside work hours.webp | Bin 0 -> 56206 bytes .../2025-blog-banner/referred-LinkedIn.webp | Bin 0 -> 11026 bytes .../2025-blog-banner/referred-Newsletter.webp | Bin 0 -> 11944 bytes .../posts/2026-blog-banner/booth-day1.webp | Bin 0 -> 842716 bytes .../posts/2026-blog-banner/feb-banner.webp | Bin 0 -> 751764 bytes .../posts/2026-blog-banner/march-banner.webp | Bin 0 -> 206214 bytes .../posts/2026-blog-banner/nominations.webp | Bin 0 -> 21002 bytes public/img/posts/asyncapi-bangalore.webp | Bin 0 -> 99084 bytes public/img/posts/asyncapi-websocket.webp | Bin 0 -> 10370 bytes .../marketing-images/gravitee-community.webp | Bin 0 -> 19996 bytes .../marketing-images/hugo-spotlight.webp | Bin 0 -> 21230 bytes .../posts/marketing-images/maya-story.webp | Bin 0 -> 29056 bytes .../img/posts/release-notes-3.1.0/cover.webp | Bin 0 -> 131448 bytes public/img/posts/simple-chat-api.webp | Bin 0 -> 116786 bytes .../img/posts/vs-asyncapi-preview/image.webp | Bin 0 -> 794618 bytes public/locales/zh_cn/common.json | 28 + public/locales/zh_cn/landing-page.json | 74 + public/locales/zh_cn/tools.json | 25 + scripts/build-rss.ts | 2 +- scripts/build-tools.ts | 33 +- scripts/compose.ts | 4 +- scripts/dashboard/build-dashboard.ts | 22 +- scripts/index.ts | 13 +- scripts/tools/combine-tools.ts | 136 +- scripts/tools/extract-tools-github.ts | 78 +- tests/build-docs/addDocButtons.test.ts | 2 +- tests/build-post-list.test.ts | 18 +- tests/dashboard/build-dashboard.test.ts | 11 +- tests/fixtures/combineToolsData.ts | 129 +- tests/markdown/check-markdown.test.ts | 8 +- tests/tools/combine-tools.test.ts | 357 +- tests/tools/tools-object.test.ts | 8 +- types/scripts/tools.ts | 21 + utils/getUniqueCategories.ts | 7 + utils/i18n.ts | 7 +- utils/staticHelpers.ts | 10 +- 261 files changed, 40225 insertions(+), 19293 deletions(-) create mode 100644 components/roadmap/types.ts create mode 100644 config/3.1.0.json create mode 100644 config/tools-ignore.json create mode 100644 cypress/ambassadors.cy.js create mode 100644 cypress/dashboard.cy.js create mode 100644 cypress/events.cy.js create mode 100644 cypress/fixtures/toolsPages.json create mode 100644 cypress/pages/BasePage.js create mode 100644 cypress/pages/ambassadors.js create mode 100644 cypress/pages/dashboard.js create mode 100644 cypress/pages/events.js create mode 100644 cypress/pages/slack.js create mode 100644 cypress/pages/toolsGenerator.js create mode 100644 cypress/pages/toolsModelina.js create mode 100644 cypress/pages/tscpage.js create mode 100644 cypress/slackworkspace.cy.js create mode 100644 cypress/tools_cli.cy.js create mode 100644 cypress/tools_generator.cy.js create mode 100644 cypress/tools_github_actions.cy.js create mode 100644 cypress/tools_modelina.cy.js create mode 100644 cypress/tools_parsers.cy.js create mode 100644 cypress/tscpage.cy.js create mode 100644 docs/tools-ignore-design.md create mode 100644 markdown/blog/2025-annual-summary.md create mode 100644 markdown/blog/2025-conference-summary.md create mode 100644 markdown/blog/2025-gsoc-summary.md create mode 100644 markdown/blog/2026-february-summary.md create mode 100644 markdown/blog/2026-march-summary.md create mode 100644 markdown/blog/asyncapi-and-websocket.md create mode 100644 markdown/blog/board-nomination.md create mode 100644 markdown/blog/community-spotlight-hugo.md create mode 100644 markdown/blog/community-spotlight-maya.md create mode 100644 markdown/blog/gravitee-sponsorship-2025.md create mode 100644 markdown/blog/release-notes-3.1.0.md create mode 100644 markdown/blog/vsasyncapi-preview-extension.md create mode 100644 markdown/docs/community/040-guides/holopin-badge-workflow.md create mode 100644 markdown/docs/community/050-mentorship-program/summer-of-code-2026-project-ideas.md create mode 100644 markdown/docs/reference/bindings/2.x.x.md create mode 100644 markdown/docs/reference/bindings/3.0.0.md create mode 100644 markdown/docs/reference/bindings/amqp.md create mode 100644 markdown/docs/reference/bindings/amqp1.md create mode 100644 markdown/docs/reference/bindings/anypointmq.md create mode 100644 markdown/docs/reference/bindings/googlepubsub.md create mode 100644 markdown/docs/reference/bindings/http.md create mode 100644 markdown/docs/reference/bindings/ibmmq.md create mode 100644 markdown/docs/reference/bindings/jms.md create mode 100644 markdown/docs/reference/bindings/kafka.md create mode 100644 markdown/docs/reference/bindings/mercure.md create mode 100644 markdown/docs/reference/bindings/mqtt.md create mode 100644 markdown/docs/reference/bindings/mqtt5.md create mode 100644 markdown/docs/reference/bindings/nats.md create mode 100644 markdown/docs/reference/bindings/pulsar.md create mode 100644 markdown/docs/reference/bindings/redis.md create mode 100644 markdown/docs/reference/bindings/ros2.md create mode 100644 markdown/docs/reference/bindings/scripts.md create mode 100644 markdown/docs/reference/bindings/solace.md create mode 100644 markdown/docs/reference/bindings/sqs.md create mode 100644 markdown/docs/reference/bindings/stomp.md create mode 100644 markdown/docs/reference/bindings/websockets.md create mode 100644 markdown/docs/reference/specification/v3.1.0-explorer.md create mode 100644 markdown/docs/reference/specification/v3.1.0.md create mode 100644 markdown/docs/tools/cli/contributing-prs.md create mode 100644 markdown/docs/tools/cli/debugging-testing.md create mode 100644 markdown/docs/tools/generator/api_components.md create mode 100644 public/img/avatars/ruchip16.webp create mode 100644 public/img/diagrams/asyncapi-openapi.webp create mode 100644 public/img/diagrams/ecosystem.webp create mode 100644 public/img/diagrams/spec-first.webp create mode 100644 public/img/docs/SNS-HTTP.png create mode 100644 public/img/docs/SNS-SQS-Pub-Sub.png create mode 100644 public/img/docs/SQS-Point-To-Point.png create mode 100644 public/img/posts/2025-blog-banner/Active contributors.webp create mode 100644 public/img/posts/2025-blog-banner/Audience and Engagement.webp create mode 100644 public/img/posts/2025-blog-banner/Average and Median.webp create mode 100644 public/img/posts/2025-blog-banner/Followers vs. Year.webp create mode 100644 public/img/posts/2025-blog-banner/Issues resolution.webp create mode 100644 public/img/posts/2025-blog-banner/Joiners vs. Year.webp create mode 100644 public/img/posts/2025-blog-banner/NPM.webp create mode 100644 public/img/posts/2025-blog-banner/Pull requests.webp create mode 100644 public/img/posts/2025-blog-banner/Search Console.webp create mode 100644 public/img/posts/2025-blog-banner/Visits.webp create mode 100644 public/img/posts/2025-blog-banner/YouTube stats.webp create mode 100644 public/img/posts/2025-blog-banner/apiconf.png create mode 100644 public/img/posts/2025-blog-banner/banner-annual.webp create mode 100644 public/img/posts/2025-blog-banner/banner-conf.webp create mode 100644 public/img/posts/2025-blog-banner/open vs clicks.webp create mode 100644 public/img/posts/2025-blog-banner/outside work hours.webp create mode 100644 public/img/posts/2025-blog-banner/referred-LinkedIn.webp create mode 100644 public/img/posts/2025-blog-banner/referred-Newsletter.webp create mode 100644 public/img/posts/2026-blog-banner/booth-day1.webp create mode 100644 public/img/posts/2026-blog-banner/feb-banner.webp create mode 100644 public/img/posts/2026-blog-banner/march-banner.webp create mode 100644 public/img/posts/2026-blog-banner/nominations.webp create mode 100644 public/img/posts/asyncapi-bangalore.webp create mode 100644 public/img/posts/asyncapi-websocket.webp create mode 100644 public/img/posts/marketing-images/gravitee-community.webp create mode 100644 public/img/posts/marketing-images/hugo-spotlight.webp create mode 100644 public/img/posts/marketing-images/maya-story.webp create mode 100644 public/img/posts/release-notes-3.1.0/cover.webp create mode 100644 public/img/posts/simple-chat-api.webp create mode 100644 public/img/posts/vs-asyncapi-preview/image.webp create mode 100644 public/locales/zh_cn/common.json create mode 100644 public/locales/zh_cn/landing-page.json create mode 100644 public/locales/zh_cn/tools.json diff --git a/.github/workflows/regenerate-tools.yml b/.github/workflows/regenerate-tools.yml index 705a29508068..93f383faf2d9 100644 --- a/.github/workflows/regenerate-tools.yml +++ b/.github/workflows/regenerate-tools.yml @@ -42,6 +42,11 @@ jobs: committer: asyncapi-bot author: asyncapi-bot title: 'chore: update tools.json' + body: | + Hey, @asyncapi/website-maintainers, please review this updated tools list. + + Check the workflow run logs for any ignored tools summary and verify new entries before merging. + labels: do-not-merge branch: update-tools/${{ github.job }} - if: failure() # Only, on failure, send a message on the 94_bot-failing-ci slack channel diff --git a/.github/workflows/scripts/mailchimp/package-lock.json b/.github/workflows/scripts/mailchimp/package-lock.json index 565e0fd13fec..7c7b1f35d1e9 100644 --- a/.github/workflows/scripts/mailchimp/package-lock.json +++ b/.github/workflows/scripts/mailchimp/package-lock.json @@ -44,18 +44,6 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -68,6 +56,21 @@ "node": ">= 0.4" } }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -346,9 +349,12 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -359,11 +365,11 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "node_modules/qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -411,13 +417,68 @@ ] }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -510,15 +571,6 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, "call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -528,6 +580,15 @@ "function-bind": "^1.1.2" } }, + "call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + } + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -724,9 +785,9 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==" }, "process-nextick-args": { "version": "2.0.1", @@ -734,11 +795,11 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", "requires": { - "side-channel": "^1.0.4" + "side-channel": "^1.1.0" } }, "readable-stream": { @@ -768,13 +829,47 @@ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + } + }, + "side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "requires": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + } + }, + "side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + } + }, + "side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" } }, "string_decoder": { diff --git a/.gitignore b/.gitignore index 876ea0549dab..dd949d926f52 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ cypress/videos *storybook.log /storybook-static/ coverage +config/tools-ignored.json deno.lock cypress/videos cypress/screenshots diff --git a/CODEOWNERS b/CODEOWNERS index 37090733a25d..301c55c96b60 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -8,11 +8,11 @@ * @derberg @akshatnema @anshgoyalevil @sambhavgupta0705 @princerajpoot20 @mayaleeeee @asyncapi-bot-eve # All .md files -*.md @thulieblack @TRohit20 @asyncapi-bot-eve +*.md @thulieblack @TRohit20 @asyncapi-bot-eve @anshgoyalevil -markdown/blog/*.md @thulieblack @TRohit20 -markdown/community/*.md @thulieblack @bandantonio @TRohit20 +markdown/blog/*.md @thulieblack @TRohit20 @anshgoyalevil +markdown/community/*.md @thulieblack @bandantonio @TRohit20 @anshgoyalevil -README.md @thulieblack @derberg @akshatnema @mayaleeeee @TRohit20 @asyncapi-bot-eve +README.md @thulieblack @derberg @akshatnema @mayaleeeee @TRohit20 @asyncapi-bot-eve @anshgoyalevil #docTriagers: bandantonio CBID2 #codeTriagers: devilkiller-ag vishvamsinh28 diff --git a/assets/docs/fragments/cli-installation.md b/assets/docs/fragments/cli-installation.md index ea6f57b9ccaf..201ac34ef1c8 100644 --- a/assets/docs/fragments/cli-installation.md +++ b/assets/docs/fragments/cli-installation.md @@ -48,7 +48,7 @@ Download [asyncapi.x64.exe](https://github.com/asyncapi/cli/releases/latest/down #### Using NPM and Node.js -Alternitavely, you can install the [AsyncAPI CLI](https://github.com/asyncapi/cli#installation) with Node.js `>=v10` and [NPM](https://nodejs.org/en/download/package-manager/). +Alternatively, you can install the [AsyncAPI CLI](https://github.com/asyncapi/cli#installation) with Node.js `>=v10` and [NPM](https://nodejs.org/en/download/package-manager/).
Install CLI globally @@ -63,7 +63,7 @@ npm install -g @asyncapi/cli
Install specific CLI version -To install a specific version of the AsyncAPI CLI, pass the `verion` during installation: +To install a specific version of the AsyncAPI CLI, pass the `version` during installation: ``` npm install -g @asyncapi/cli@{version} diff --git a/components/Accordion/AccordionItem.tsx b/components/Accordion/AccordionItem.tsx index b7c1f61d8296..715244d6ffd4 100644 --- a/components/Accordion/AccordionItem.tsx +++ b/components/Accordion/AccordionItem.tsx @@ -23,12 +23,21 @@ export interface AccordionItemProps { * This is the AccordionItem component. It displays a single item that can be expanded or collapsed. */ export default function AccordionItem({ itemIndex, title, content, isActive, setActiveIndex }: AccordionItemProps) { + const contentRef = React.useRef(null); + const [contentHeight, setContentHeight] = React.useState(0); + const handleClick = () => { const nextIndex = isActive ? null : itemIndex; setActiveIndex(nextIndex); }; + React.useEffect(() => { + if (contentRef.current) { + setContentHeight(isActive ? contentRef.current.scrollHeight : 0); + } + }, [isActive]); + return (
- {isActive && ( -
+
+
{content}
- )} +
); } diff --git a/components/AlgoliaSearch.tsx b/components/AlgoliaSearch.tsx index 6117396c7398..d0d8ca5754c2 100644 --- a/components/AlgoliaSearch.tsx +++ b/components/AlgoliaSearch.tsx @@ -1,6 +1,6 @@ /* eslint-disable no-underscore-dangle */ +import type { DocSearchHit, InternalDocSearchHit, StoredDocSearchHit } from '@docsearch/react'; import { DocSearchModal } from '@docsearch/react'; -import type { DocSearchHit, InternalDocSearchHit, StoredDocSearchHit } from '@docsearch/react/dist/esm/types'; import clsx from 'clsx'; import Head from 'next/head'; import Link from 'next/link'; @@ -283,7 +283,6 @@ export default function AlgoliaSearch({ children }: { children: React.ReactNode */ export function SearchButton({ children, indexName = INDEX_NAME, ...props }: ISearchButtonProps) { const { onOpen, onInput } = useContext(SearchContext); - const [Children, setChildren] = useState(''); const searchButtonRef = useRef(null); const actionKey = getActionKey(); @@ -309,13 +308,7 @@ export function SearchButton({ children, indexName = INDEX_NAME, ...props }: ISe }; }, [onInput, searchButtonRef]); - useEffect(() => { - if (typeof children === 'function') { - setChildren(children({ actionKey })); - } else { - setChildren(children); - } - }, [actionKey, children]); + const childContent = typeof children === 'function' ? children({ actionKey }) : children; return ( ); } diff --git a/components/Calendar.tsx b/components/Calendar.tsx index 49323d6584ad..12ab385b21a2 100644 --- a/components/Calendar.tsx +++ b/components/Calendar.tsx @@ -1,4 +1,5 @@ -import moment from 'moment'; +import dayjs from 'dayjs'; +import localizedFormat from 'dayjs/plugin/localizedFormat'; import React from 'react'; import { twMerge } from 'tailwind-merge'; @@ -11,6 +12,8 @@ import { getEvents } from '../utils/staticHelpers'; import GoogleCalendarButton from './buttons/GoogleCalendarButton'; import Heading from './typography/Heading'; +dayjs.extend(localizedFormat); + interface ICalendarProps { className?: string; size: number; @@ -29,7 +32,7 @@ export default function Calendar({ className = '', size }: ICalendarProps) { const CALENDAR_URL = 'https://calendar.google.com/calendar/embed?src=c_q9tseiglomdsj6njuhvbpts11c%40group.calendar.google.com&ctz=UTC'; const currentDate = new Date(); - const eventsExist = eventsData?.filter((event: IEvent) => moment(event.date).isAfter(currentDate)).length > 0; + const eventsExist = eventsData?.filter((event: IEvent) => dayjs(event.date).isAfter(currentDate)).length > 0; return (
- {moment(event.date).format('D')} + {dayjs(event.date).format('D')}

{event.title}

- {moment(event.date).local().format('LLLL')} UTC - {moment(event.date).local().format('Z')} + {dayjs(event.date).format('LLLL')} UTC + {dayjs(event.date).format('Z')}

diff --git a/components/CaseTOC.tsx b/components/CaseTOC.tsx index 271a6e1cb41d..fc165d249689 100644 --- a/components/CaseTOC.tsx +++ b/components/CaseTOC.tsx @@ -11,6 +11,11 @@ interface TocItem { children?: TocItem[]; } +interface TocSection { + title: string; + children?: TocSection[]; +} + interface TOCItemProps { item: TocItem; index: number; @@ -21,7 +26,7 @@ interface TOCItemProps { interface CaseTOCProps { className: string; cssBreakingPoint?: 'xl' | 'lg'; - toc: any[]; + toc: TocSection[]; } /** @@ -38,11 +43,11 @@ const checkIfActive = (item: TocItem, currSelected: string): boolean => { /** * @description Converts content to TOC items. * - * @param {any[]} content - The content to convert to TOC items. + * @param {TocSection[]} content - The content to convert to TOC items. * @param {number} level - The level of the TOC item. * @returns {TocItem[]} - The array of TOC items. */ -const convertContentToTocItems = (content: any[], level: number = 1): TocItem[] => { +const convertContentToTocItems = (content: TocSection[], level: number = 1): TocItem[] => { const tocItems = []; for (const section of content) { diff --git a/components/FinancialSummary/BarChartComponent.tsx b/components/FinancialSummary/BarChartComponent.tsx index 019927672cb0..3c6ed0dbb0ad 100644 --- a/components/FinancialSummary/BarChartComponent.tsx +++ b/components/FinancialSummary/BarChartComponent.tsx @@ -18,7 +18,77 @@ export default function BarChartComponent() { const [selectedMonth, setSelectedMonth] = useState('All Months'); const [windowWidth, setWindowWidth] = useState(0); - // Extracting unique categories and months from the data + /* + TODO: Uncomment the block below to enable previous-years data (2023) and "All Years" selection. + Uncomment this code to implement data of previous years in finance chart. + When enabled, this replaces direct usage of `ExpensesData`/`ExpensesLinkData` with `currentExpensesData` + and `currentExpensesLinkData` so the chart can show 2023, 2024, or All Years combined. + */ + + // // import Expenses2023Data from '../../config/finance/json-data/Expenses2023.json'; + // // import ExpensesLink2023Data from '../../config/finance/json-data/ExpensesLink2023.json'; + // // + // // // Selected year state + // // const [selectedYear, setSelectedYear] = useState('2024'); + // // + // // // Available years for the dropdown + // // const availableYears = ['2024', '2023', 'All Years']; + // // + // // // Function to get the appropriate data based on selected year + // // const getExpensesData = () => { + // // switch (selectedYear) { + // // case '2023': + // // return Expenses2023Data; + // // case 'All Years': { + // // // Combine all years data with year-prefixed keys + // // const combined: Record = {}; + // // + // // Object.entries(Expenses2023Data).forEach(([month, data]) => { + // // combined[`${month} 2023`] = data as ExpenseItem[]; + // // }); + // // + // // Object.entries(ExpensesData).forEach(([month, data]) => { + // // combined[`${month} 2024`] = data as ExpenseItem[]; + // // }); + // // + // // return combined; + // // } + // // case '2024': + // // default: + // // return ExpensesData; + // // } + // // }; + // // + // // // Function to get the appropriate link data based on selected year + // // const getExpensesLinkData = () => { + // // switch (selectedYear) { + // // case '2023': + // // return ExpensesLink2023Data; + // // case 'All Years': { + // // // Merge links from both years, with 2023 taking precedence for duplicates + // // const allLinks = [...ExpensesLink2023Data]; + // // + // // ExpensesLinkData.forEach((link) => { + // // if (!allLinks.find((l) => l.category === link.category)) { + // // allLinks.push(link); + // // } + // // }); + // // + // // return allLinks; + // // } + // // case '2024': + // // default: + // // return ExpensesLinkData; + // // } + // // }; + // // + // // // Get current data based on selected year + // // const currentExpensesData = getExpensesData(); + // // const currentExpensesLinkData = getExpensesLinkData(); + + // (If you enable the block above, replace categories and months with following block of code: + // const categories: string[] = getUniqueCategories(currentExpensesData as Record>); + // const months: string[] = Object.keys(currentExpensesData);) const categories: string[] = getUniqueCategories(); const months: string[] = Object.keys(ExpensesData); @@ -38,13 +108,22 @@ export default function BarChartComponent() { }; }, []); - // Filtering data based on selected month and category + // Filtering data based on selected month and category (code 2 - active) const filteredData: ExpenseItem[] = Object.entries(ExpensesData).flatMap(([month, entries]) => selectedMonth === 'All Months' || selectedMonth === month ? entries.filter((entry) => selectedCategory === 'All Categories' || entry.Category === selectedCategory) : [] ); + // // --- if previous-years support is enabled: Uncomment code block given below + // // const filteredData: ExpenseItem[] = Object.entries(currentExpensesData).flatMap(([month, entries]) => + // // selectedMonth === 'All Months' || selectedMonth === month + // // ? (entries as ExpenseItem[]).filter( + // // (entry) => selectedCategory === 'All Categories' || entry.Category === selectedCategory + // // ) + // // : [] + // // ); + // Calculating total amount of filtered data const totalAmount: number = filteredData.reduce((total, entry) => total + parseFloat(entry.Amount), 0); @@ -95,6 +174,7 @@ export default function BarChartComponent() { ))} + + + {/* + If you enable the previous-years block above, add the year selector here: + + */}
@@ -122,6 +217,8 @@ export default function BarChartComponent() { fill='#7B5DD3FF' onClick={(data) => { const category = data.payload.Category; + + // Active behavior: use the static 2024 ExpensesLinkData (code 2) const matchedLinkObject: ExpensesLinkItem | undefined = ExpensesLinkData.find( (obj) => obj.category === category ); @@ -129,6 +226,15 @@ export default function BarChartComponent() { if (matchedLinkObject) { window.open(matchedLinkObject.link, '_blank'); } + + // // --- if previous-years support is enabled: Uncomment code given below + // // const matchedLinkObject: ExpensesLinkItem | undefined = currentExpensesLinkData.find( + // // (obj: ExpensesLinkItem) => obj.category === category + // // ); + // // + // // if (matchedLinkObject) { + // // window.open(matchedLinkObject.link, '_blank'); + // // } }} /> diff --git a/components/FinancialSummary/ContactUs.tsx b/components/FinancialSummary/ContactUs.tsx index 1e0dd9560d3e..6636970b5bf0 100644 --- a/components/FinancialSummary/ContactUs.tsx +++ b/components/FinancialSummary/ContactUs.tsx @@ -26,10 +26,10 @@ export default function ContactUs() { - info@asyncapi.io + info@asyncapi.com @@ -37,7 +37,7 @@ export default function ContactUs() {
-
); diff --git a/components/Modal.tsx b/components/Modal.tsx index fb128d6cc49a..77db02d4720e 100644 --- a/components/Modal.tsx +++ b/components/Modal.tsx @@ -57,7 +57,7 @@ export default function Modal({ title, children, onModalClose = () => {} }: IMod

{title}

- diff --git a/components/campaigns/AnnouncementRemainingDays.tsx b/components/campaigns/AnnouncementRemainingDays.tsx index a462d98dc69d..e1488cac8686 100644 --- a/components/campaigns/AnnouncementRemainingDays.tsx +++ b/components/campaigns/AnnouncementRemainingDays.tsx @@ -1,4 +1,4 @@ -import moment from 'moment'; +import dayjs from 'dayjs'; import React from 'react'; interface AnnouncementRemainingDaysProps { @@ -12,8 +12,8 @@ interface AnnouncementRemainingDaysProps { * @param {string} props.eventName - The name of the event */ export default function AnnouncementRemainingDays({ dateTime, eventName }: AnnouncementRemainingDaysProps) { - const date = moment(dateTime); - const now = moment(); + const date = dayjs(dateTime); + const now = dayjs(); const days = date.diff(now, 'days'); const hours = date.diff(now, 'hours'); const minutes = date.diff(now, 'minutes'); diff --git a/components/community/Header.tsx b/components/community/Header.tsx index 2aeb159da97d..99008c602be3 100644 --- a/components/community/Header.tsx +++ b/components/community/Header.tsx @@ -18,7 +18,7 @@ interface HeaderProps { export default function Header({ className = '' }: HeaderProps) { return (
diff --git a/components/dashboard/Header.tsx b/components/dashboard/Header.tsx index 0d49c1491604..c50fd9b31533 100644 --- a/components/dashboard/Header.tsx +++ b/components/dashboard/Header.tsx @@ -26,7 +26,7 @@ export default function Header() {
diff --git a/components/helpers/applyFilter.ts b/components/helpers/applyFilter.ts index a7f3f217d5eb..b63008326f18 100644 --- a/components/helpers/applyFilter.ts +++ b/components/helpers/applyFilter.ts @@ -1,13 +1,13 @@ -interface DataObject { - name: string; - [key: string]: any; +export interface DataObject { + name?: string; + [key: string]: unknown; } interface FilterCriteria { name: string; } -interface Filter { +export interface Filter { [key: string]: string; } @@ -36,12 +36,12 @@ export function sortFilter(arr: { value: string }[]): { value: string }[] { /** * @description Apply filters to data and update the filters. * @param {FilterCriteria[]} checks - Array of filter criteria objects. - * @param {DataObject[]} data - Array of data objects to filter. + * @param {T[]} data - Array of data objects to filter. * @param {(lists: { [key: string]: FilterOption[] }) => void} setFilters - Function to update the filters. */ -export const applyFilterList = ( +export const applyFilterList = ( checks: FilterCriteria[], - data: DataObject[], + data: T[], setFilters: (lists: { [key: string]: FilterOption[] }) => void ): void => { if (Object.keys(checks).length) { @@ -60,7 +60,7 @@ export const applyFilterList = ( if (lists[key].length) { if (Array.isArray(result)) { result.forEach((a) => { - if (a.name) { + if (typeof a === 'object' && a !== null && 'name' in a) { if (!lists[key].some((e) => e.value === a.name)) { const newData = { value: a.name, @@ -70,7 +70,7 @@ export const applyFilterList = ( lists[key].push(newData); sortFilter(lists[key]); } - } else if (!lists[key].some((e) => e.value === a)) { + } else if (typeof a === 'string' && !lists[key].some((e) => e.value === a)) { const newData = { value: a, text: a @@ -80,7 +80,7 @@ export const applyFilterList = ( sortFilter(lists[key]); } }); - } else if (!lists[key].some((e) => e.value === result)) { + } else if (typeof result === 'string' && !lists[key].some((e) => e.value === result)) { const newData = { value: result, text: result @@ -91,14 +91,14 @@ export const applyFilterList = ( } } else if (Array.isArray(result)) { result.forEach((e) => { - if (e.name) { + if (typeof e === 'object' && e !== null && 'name' in e) { const newData = { value: e.name, text: e.name }; lists[key].push(newData); - } else { + } else if (typeof e === 'string') { const newData = { value: e, text: e @@ -107,7 +107,7 @@ export const applyFilterList = ( lists[key].push(newData); } }); - } else { + } else if (typeof result === 'string') { const newData = { value: result, text: result @@ -124,13 +124,13 @@ export const applyFilterList = ( /** * @description Apply filters to data and trigger the filter action. - * @param {DataObject[]} inputData - Array of data objects to filter. - * @param {(result: DataObject[], query: Filter) => void} onFilter - Function to apply the filter action. + * @param {T[]} inputData - Array of data objects to filter. + * @param {(result: T[], query: Filter) => void} onFilter - Function to apply the filter action. * @param {Filter} query - Filter criteria. */ -export const onFilterApply = ( - inputData: DataObject[], - onFilter: (result: DataObject[], query: Filter) => void, +export const onFilterApply = ( + inputData: T[], + onFilter: (result: T[], query: Filter) => void, query: Filter ): void => { let result = inputData; @@ -142,9 +142,13 @@ export const onFilterApply = ( return e[property]; } if (Array.isArray(e[property])) { + const propertyValue = e[property]; + return ( - e[property].some((data: any) => data.name === query[property]) || - e[property].includes(query[property]) || + propertyValue.some((data) => + typeof data === 'object' && data !== null && 'name' in data ? data.name === query[property] : false + ) || + propertyValue.includes(query[property]) || false ); } diff --git a/components/layout/BlogLayout.tsx b/components/layout/BlogLayout.tsx index 5266f413b7d3..7158e0fb7e63 100644 --- a/components/layout/BlogLayout.tsx +++ b/components/layout/BlogLayout.tsx @@ -1,4 +1,4 @@ -import moment from 'moment'; +import dayjs from 'dayjs'; import ErrorPage from 'next/error'; import HtmlHead from 'next/head'; import { useRouter } from 'next/router'; @@ -76,7 +76,7 @@ export default function BlogLayout({ post, children }: IBlogLayoutProps) {

- + · {post.readingTime} min read
diff --git a/components/layout/CommunityLayout.tsx b/components/layout/CommunityLayout.tsx index 2889f4f5e54b..82c9c60a9739 100644 --- a/components/layout/CommunityLayout.tsx +++ b/components/layout/CommunityLayout.tsx @@ -267,7 +267,7 @@ function QuestionCard() {
Want to become a member? Follow this diff --git a/components/layout/DocsLayout.tsx b/components/layout/DocsLayout.tsx index 11470c995a68..44b4ca34efc8 100644 --- a/components/layout/DocsLayout.tsx +++ b/components/layout/DocsLayout.tsx @@ -93,12 +93,12 @@ export default function DocsLayout({ post, navItems = {}, children }: IDocsLayou const sidebar = ; - if (router.pathname.includes('v3.0.0-explorer')) { + if (router.pathname.includes('-explorer')) { return (
diff --git a/components/navigation/EventFilter.tsx b/components/navigation/EventFilter.tsx index 6dfca2494ffb..2bf3d5b56952 100644 --- a/components/navigation/EventFilter.tsx +++ b/components/navigation/EventFilter.tsx @@ -1,4 +1,4 @@ -import moment from 'moment'; +import dayjs from 'dayjs'; import React, { useEffect, useState } from 'react'; import type { IEvent } from '@/types/event'; @@ -23,7 +23,7 @@ interface EventFilterProps { * @param {React.Dispatch>} props.setData - The function to update the filtered events. */ export default function EventFilter({ data, setData }: EventFilterProps) { - const localTime = moment().format('YYYY-MM-DD'); + const localTime = dayjs().format('YYYY-MM-DD'); const currentDate = `${localTime}T00:00:00.000Z`; const filterList: string[] = ['All', 'Upcoming', 'Recorded']; const [active, setActive] = useState('All'); @@ -36,14 +36,14 @@ export default function EventFilter({ data, setData }: EventFilterProps) { case ActiveState.Upcoming: setData( getEvents(data).filter((event: IEvent) => { - return moment(event.date).format() > currentDate; + return dayjs(event.date).format() > currentDate; }) ); break; case ActiveState.Recorded: setData( getEvents(data).filter((event: IEvent) => { - return moment(event.date).format() < currentDate; + return dayjs(event.date).format() < currentDate; }) ); break; diff --git a/components/navigation/EventPostItem.tsx b/components/navigation/EventPostItem.tsx index 2437904ba31d..bd4470560b2e 100644 --- a/components/navigation/EventPostItem.tsx +++ b/components/navigation/EventPostItem.tsx @@ -1,4 +1,4 @@ -import moment from 'moment'; +import dayjs from 'dayjs'; import React from 'react'; import type { IEvent } from '@/types/event'; @@ -20,7 +20,7 @@ interface EventPostItemProps { * */ function EventPostItem({ post, className = '', id }: EventPostItemProps): React.JSX.Element { - const localTime = moment().format('YYYY-MM-DD'); // store localTime + const localTime = dayjs().format('YYYY-MM-DD'); // store localTime const currentDate = `${localTime}T00:00:00.000Z`; const title = post.title || ''; let type = ''; @@ -34,7 +34,7 @@ function EventPostItem({ post, className = '', id }: EventPostItemProps): React. } let active = true; - const postDate = moment(post.date); // Convert post.date to a moment object if necessary + const postDate = dayjs(post.date); // Convert post.date to a dayjs object if necessary if (!postDate.isValid()) { // Handle invalid date if necessary @@ -45,7 +45,7 @@ function EventPostItem({ post, className = '', id }: EventPostItemProps): React. return (
  • -
    +
    @@ -59,15 +59,15 @@ function EventPostItem({ post, className = '', id }: EventPostItemProps): React.
    - + {post.title} -
    +
    - {active ? moment(postDate).format('MMMM D, YYYY') : 'View Recording'} + {active ? dayjs(postDate).format('MMMM D, YYYY') : 'View Recording'}
    -
    {postDate.isValid() && moment(postDate).format('h:mm A [UTC]')}
    +
    {postDate.isValid() && dayjs(postDate).format('h:mm A [UTC]')}
    void; +interface FilterProps { + data: T[]; + onFilter: (data: T[], query: FilterQuery) => void; checks: Check[]; className?: string; } @@ -20,17 +19,22 @@ interface FilterProps { * @description Component representing a filter for data. * @param {Object} props - The props for the Filter component. * @param {Object[]} props.data - The data to be filtered. - * @param {(data: Object[]) => void} props.onFilter - The callback function to handle filtering. + * @param {(data: Object[], query: FilterQuery) => void} props.onFilter - The callback function to handle filtering. * @param {Object[]} props.checks - The list of filter options. * @param {string} [props.className] - Additional CSS classes for styling. */ -export default function Filter({ data, onFilter, checks, className }: FilterProps) { +export default function Filter({ + data, + onFilter, + checks, + className +}: FilterProps) { const route = useRouter(); - const [filters, setFilters] = useState>({}); - const [routeQuery, setQuery] = useState>({}); + const [filters, setFilters] = useState>({}); + const [routeQuery, setQuery] = useState>({}); useEffect(() => { - setQuery(route.query); + setQuery(route.query as Record); applyFilterList(checks, data, setFilters); }, [route, checks, data]); diff --git a/components/navigation/MobileNavMenu.tsx b/components/navigation/MobileNavMenu.tsx index 16102e568e9d..621d756b4c4f 100644 --- a/components/navigation/MobileNavMenu.tsx +++ b/components/navigation/MobileNavMenu.tsx @@ -82,6 +82,7 @@ export default function MobileNavMenu({ onClick={onClickClose} type='button' className='inline-flex items-center justify-center rounded-lg p-2.5 text-gray-700 dark:text-gray-200 transition-all duration-200 ease-in-out hover:bg-gray-100/80 dark:hover:bg-gray-700/50 hover:rotate-90 active:scale-95' + aria-label='Close menu' > @@ -98,7 +99,13 @@ export default function MobileNavMenu({ > Docs - + + + {open === 'learning' && (
    @@ -114,7 +121,13 @@ export default function MobileNavMenu({ > Tools - + + + {open === 'tooling' && (
    @@ -130,7 +143,13 @@ export default function MobileNavMenu({ > Community - + + + {open === 'community' && (
    diff --git a/components/navigation/NavBar.tsx b/components/navigation/NavBar.tsx index 10adc687ad3f..c007d653e8c3 100644 --- a/components/navigation/NavBar.tsx +++ b/components/navigation/NavBar.tsx @@ -216,6 +216,7 @@ export default function NavBar({ className = '', hideLogo = false }: NavBarProps onClick={() => showOnClickMenu('learning')} onMouseEnter={() => showMenu('learning')} hasDropdown + isOpen={open === 'learning'} /> {open === 'learning' && }
    @@ -227,6 +228,7 @@ export default function NavBar({ className = '', hideLogo = false }: NavBarProps onClick={() => showOnClickMenu('tooling')} onMouseEnter={() => showMenu('tooling')} hasDropdown + isOpen={open === 'tooling'} /> {open === 'tooling' && }
    @@ -238,6 +240,7 @@ export default function NavBar({ className = '', hideLogo = false }: NavBarProps onClick={() => showOnClickMenu('community')} onMouseEnter={() => showMenu('community')} hasDropdown + isOpen={open === 'community'} /> {open === 'community' && }
    diff --git a/components/navigation/NavItem.tsx b/components/navigation/NavItem.tsx index c5e12cbf0954..a3d8d61e5df4 100644 --- a/components/navigation/NavItem.tsx +++ b/components/navigation/NavItem.tsx @@ -12,6 +12,7 @@ interface NavItemProps { onMouseEnter?: () => void; hasDropdown?: boolean; className?: string; + isOpen?: boolean; } /** @@ -31,24 +32,25 @@ export default function NavItem({ onClick = () => {}, onMouseEnter = () => {}, hasDropdown = false, - className = '' + className = '', + isOpen = false }: NavItemProps) { const router = useRouter(); if (href && !hasDropdown) { return ( - - {text} - + + {text} + ); } @@ -65,22 +67,39 @@ export default function NavItem({ - + {text} - {hasDropdown && } + {hasDropdown && ( + + + + )} ); } return ( - ); } diff --git a/components/newsroom/FeaturedBlogPost.tsx b/components/newsroom/FeaturedBlogPost.tsx index 49b4c8ef4ab4..af3cb07a2aec 100644 --- a/components/newsroom/FeaturedBlogPost.tsx +++ b/components/newsroom/FeaturedBlogPost.tsx @@ -1,4 +1,4 @@ -import moment from 'moment'; +import dayjs from 'dayjs'; import Link from 'next/link'; import React from 'react'; import TextTruncate from 'react-text-truncate'; @@ -100,7 +100,7 @@ export default function FeaturedBlogPost({ post, className = '' }: FeaturedBlogP
    · {post.readingTime} min read diff --git a/components/roadmap/RoadmapColumn.tsx b/components/roadmap/RoadmapColumn.tsx index 741ae6ebec06..a9b9d3a70d3a 100644 --- a/components/roadmap/RoadmapColumn.tsx +++ b/components/roadmap/RoadmapColumn.tsx @@ -6,12 +6,13 @@ import { ParagraphTypeStyle } from '@/types/typography/Paragraph'; import Heading from '../typography/Heading'; import Paragraph from '../typography/Paragraph'; import RoadmapList from './RoadmapList'; +import type { RoadmapItem } from './types'; interface IRoadmapColumnProps { title: string; description: string; colorClass: string; - items?: any[]; + items?: RoadmapItem[]; childrenCollapsed?: boolean; className?: string; } diff --git a/components/roadmap/RoadmapItem.tsx b/components/roadmap/RoadmapItem.tsx index 07d9293097b7..9a5b83261772 100644 --- a/components/roadmap/RoadmapItem.tsx +++ b/components/roadmap/RoadmapItem.tsx @@ -4,16 +4,10 @@ import React, { useState } from 'react'; /* eslint-disable import/no-cycle*/ import RoadmapList from './RoadmapList'; import Pill from './RoadmapPill'; +import type { RoadmapItem as RoadmapItemType } from './types'; export interface IRoadmapItemProps { - item: { - solutions?: any[]; - implementations?: any[]; - done?: boolean; - url?: string; - description?: string; - title: string; - }; + item: RoadmapItemType; colorClass: string; showConnector?: boolean; collapsed?: boolean; diff --git a/components/roadmap/RoadmapList.tsx b/components/roadmap/RoadmapList.tsx index 57d500978bf4..75a1c7225ee7 100644 --- a/components/roadmap/RoadmapList.tsx +++ b/components/roadmap/RoadmapList.tsx @@ -3,18 +3,12 @@ import React from 'react'; import RoadmapItem from './RoadmapItem'; +import type { RoadmapItem as RoadmapItemType } from './types'; interface IRoadmapListProps { colorClass: string; className?: string; - items?: { - solutions?: any[]; - implementations?: any[]; - done?: boolean; - url?: string; - description?: string; - title: string; - }[]; + items?: RoadmapItemType[]; showConnector?: boolean; collapsed?: boolean; childrenCollapsed?: boolean; diff --git a/components/roadmap/RoadmapPill.tsx b/components/roadmap/RoadmapPill.tsx index d00e1f03cf7a..f7baa591abd4 100644 --- a/components/roadmap/RoadmapPill.tsx +++ b/components/roadmap/RoadmapPill.tsx @@ -29,7 +29,7 @@ interface IPillProps { item: { done?: boolean; url?: string; - description?: string; + description?: string | React.ReactNode; title: string; }; colorClass?: string; diff --git a/components/roadmap/types.ts b/components/roadmap/types.ts new file mode 100644 index 000000000000..f7c06886a495 --- /dev/null +++ b/components/roadmap/types.ts @@ -0,0 +1,13 @@ +import type React from 'react'; + +/** + * Represents a roadmap item that can contain nested roadmap items in solutions or implementations. + */ +export interface RoadmapItem { + title: string; + done?: boolean; + description?: string | React.ReactNode; + url?: string; + solutions?: RoadmapItem[]; + implementations?: RoadmapItem[]; +} diff --git a/components/tools/ToolsDashboard.tsx b/components/tools/ToolsDashboard.tsx index 209d01aa9b42..327be01f39ab 100644 --- a/components/tools/ToolsDashboard.tsx +++ b/components/tools/ToolsDashboard.tsx @@ -28,8 +28,6 @@ export default function ToolsDashboard() { // filter parameters extracted from the context const { isPaid, isAsyncAPIOwner, languages, technologies, categories } = useContext(ToolFilterContext); const [searchName, setSearchName] = useState(''); // state variable used to get the search name - // state variable used to check whether any tool is available according to the needs of the user. - const [checkToolsList, setCheckToolsList] = useState(true); // useEffect function to enable the close Modal feature when clicked outside of the modal useEffect(() => { @@ -81,9 +79,6 @@ export default function ToolsDashboard() { tempToolsList = JSON.parse(JSON.stringify(ToolsData)); } - // checkToolsList is initially made false to check whether any tools are present according to the filters. - setCheckToolsList(false); - // Each tool selected is then traversed to check against each filter variable (only if the filter is applied), // whether they match with the filter applied or not. Object.keys(tempToolsList).forEach((category) => { @@ -134,10 +129,6 @@ export default function ToolsDashboard() { return isLanguageTool && isTechnologyTool && isSearchTool && isAsyncAPITool && isPaidTool; }); - - if (tempToolsList[category].toolsList.length) { - setCheckToolsList(true); - } }); Object.keys(tempToolsList).map((category) => { @@ -149,6 +140,11 @@ export default function ToolsDashboard() { return tempToolsList; }, [isPaid, isAsyncAPIOwner, languages, technologies, categories, searchName]); + // Derive checkToolsList from toolsList - no state updates in useMemo + const checkToolsList = useMemo(() => { + return Object.keys(toolsList).some((category) => toolsList[category].toolsList.length > 0); + }, [toolsList]); + // useEffect to scroll to the opened category when url has category as element id useEffect(() => { const { hash } = window.location; @@ -227,6 +223,7 @@ export default function ToolsDashboard() { diff --git a/config/3.1.0.json b/config/3.1.0.json new file mode 100644 index 000000000000..9eac597f9458 --- /dev/null +++ b/config/3.1.0.json @@ -0,0 +1,8373 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "AsyncAPI 3.1.0 schema.", + "type": "object", + "required": ["asyncapi", "info"], + "properties": { + "id": { + "description": "A unique id representing the application.", + "type": "string", + "format": "uri" + }, + "asyncapi": { + "description": "The AsyncAPI specification version of this document.", + "type": "string", + "const": "3.1.0" + }, + "channels": { + "$ref": "#/definitions/channels" + }, + "components": { + "$ref": "#/definitions/components" + }, + "defaultContentType": { + "description": "Default content type to use when encoding/decoding a message's payload.", + "type": "string" + }, + "info": { + "$ref": "#/definitions/info" + }, + "operations": { + "$ref": "#/definitions/operations" + }, + "servers": { + "$ref": "#/definitions/servers" + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "definitions": { + "channels": { + "description": "An object containing all the Channel Object definitions the Application MUST use during runtime.", + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/channel" + } + ] + }, + "examples": [ + { + "userSignedUp": { + "address": "user.signedup", + "messages": { + "userSignedUp": { + "$ref": "#/components/messages/userSignedUp" + } + } + } + } + ] + }, + "Reference": { + "type": "object", + "description": "A simple object to allow referencing other components in the specification, internally and externally.", + "required": ["$ref"], + "properties": { + "$ref": { + "description": "The reference string.", + "$ref": "#/definitions/ReferenceObject" + } + }, + "examples": [ + { + "$ref": "#/components/schemas/Pet" + } + ] + }, + "ReferenceObject": { + "type": "string", + "format": "uri-reference" + }, + "channel": { + "description": "Describes a shared communication channel.", + "type": "object", + "properties": { + "title": { + "description": "A human-friendly title for the channel.", + "type": "string" + }, + "description": { + "description": "A longer description of the channel. CommonMark is allowed.", + "type": "string" + }, + "address": { + "description": "An optional string representation of this channel's address. The address is typically the \"topic name\", \"routing key\", \"event type\", or \"path\". When `null` or absent, it MUST be interpreted as unknown. This is useful when the address is generated dynamically at runtime or can't be known upfront. It MAY contain Channel Address Expressions.", + "type": ["string", "null"] + }, + "bindings": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/channelBindingsObject" + } + ] + }, + "externalDocs": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/externalDocs" + } + ] + }, + "messages": { + "$ref": "#/definitions/channelMessages" + }, + "parameters": { + "$ref": "#/definitions/parameters" + }, + "servers": { + "description": "The references of the servers on which this channel is available. If absent or empty then this channel must be available on all servers.", + "type": "array", + "uniqueItems": true, + "items": { + "$ref": "#/definitions/Reference" + } + }, + "summary": { + "description": "A brief summary of the channel.", + "type": "string" + }, + "tags": { + "description": "A list of tags for logical grouping of channels.", + "type": "array", + "uniqueItems": true, + "items": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/tag" + } + ] + } + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "address": "users.{userId}", + "title": "Users channel", + "description": "This channel is used to exchange messages about user events.", + "messages": { + "userSignedUp": { + "$ref": "#/components/messages/userSignedUp" + }, + "userCompletedOrder": { + "$ref": "#/components/messages/userCompletedOrder" + } + }, + "parameters": { + "userId": { + "$ref": "#/components/parameters/userId" + } + }, + "servers": [ + { + "$ref": "#/servers/rabbitmqInProd" + }, + { + "$ref": "#/servers/rabbitmqInStaging" + } + ], + "bindings": { + "amqp": { + "is": "queue", + "queue": { + "exclusive": true + } + } + }, + "tags": [ + { + "name": "user", + "description": "User-related messages" + } + ], + "externalDocs": { + "description": "Find more info here", + "url": "https://example.com" + } + } + ] + }, + "channelBindingsObject": { + "description": "Map describing protocol-specific definitions for a channel.", + "type": "object", + "properties": { + "amqp": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-amqp-0.3.0-channel" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.3.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-amqp-0.3.0-channel" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.3.0"] + } + } + }, + "amqp1": {}, + "anypointmq": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-anypointmq-0.0.1-channel" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.0.1" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-anypointmq-0.0.1-channel" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.0.1"] + } + } + }, + "googlepubsub": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-googlepubsub-0.2.0-channel" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.2.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-googlepubsub-0.2.0-channel" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.2.0"] + } + } + }, + "http": {}, + "ibmmq": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-ibmmq-0.1.0-channel" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.1.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-ibmmq-0.1.0-channel" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.1.0"] + } + } + }, + "jms": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-jms-0.0.1-channel" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.0.1" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-jms-0.0.1-channel" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.0.1"] + } + } + }, + "kafka": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-kafka-0.5.0-channel" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.5.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-kafka-0.5.0-channel" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.4.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-kafka-0.4.0-channel" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.3.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-kafka-0.3.0-channel" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.5.0", "0.4.0", "0.3.0"] + } + } + }, + "mqtt": {}, + "nats": {}, + "pulsar": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-pulsar-0.1.0-channel" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.1.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-pulsar-0.1.0-channel" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.1.0"] + } + } + }, + "redis": {}, + "sns": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-sns-0.1.0-channel" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.1.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-sns-0.1.0-channel" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.1.0"] + } + } + }, + "solace": {}, + "sqs": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-sqs-0.2.0-channel" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.2.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-sqs-0.2.0-channel" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.2.0"] + } + } + }, + "stomp": {}, + "ws": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-websockets-0.1.0-channel" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.1.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-websockets-0.1.0-channel" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.1.0"] + } + } + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false + }, + "bindings-amqp-0.3.0-channel": { + "title": "AMQP channel bindings object", + "description": "This object contains information about the channel representation in AMQP.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "is": { + "type": "string", + "enum": ["queue", "routingKey"], + "description": "Defines what type of channel is it. Can be either 'queue' or 'routingKey' (default)." + }, + "exchange": { + "type": "object", + "properties": { + "name": { + "type": "string", + "maxLength": 255, + "description": "The name of the exchange. It MUST NOT exceed 255 characters long." + }, + "type": { + "type": "string", + "enum": ["topic", "direct", "fanout", "default", "headers"], + "description": "The type of the exchange. Can be either 'topic', 'direct', 'fanout', 'default' or 'headers'." + }, + "durable": { + "type": "boolean", + "description": "Whether the exchange should survive broker restarts or not." + }, + "autoDelete": { + "type": "boolean", + "description": "Whether the exchange should be deleted when the last queue is unbound from it." + }, + "vhost": { + "type": "string", + "default": "/", + "description": "The virtual host of the exchange. Defaults to '/'." + } + }, + "description": "When is=routingKey, this object defines the exchange properties." + }, + "queue": { + "type": "object", + "properties": { + "name": { + "type": "string", + "maxLength": 255, + "description": "The name of the queue. It MUST NOT exceed 255 characters long." + }, + "durable": { + "type": "boolean", + "description": "Whether the queue should survive broker restarts or not." + }, + "exclusive": { + "type": "boolean", + "description": "Whether the queue should be used only by one connection or not." + }, + "autoDelete": { + "type": "boolean", + "description": "Whether the queue should be deleted when the last consumer unsubscribes." + }, + "vhost": { + "type": "string", + "default": "/", + "description": "The virtual host of the queue. Defaults to '/'." + } + }, + "description": "When is=queue, this object defines the queue properties." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.3.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "oneOf": [ + { + "properties": { + "is": { + "const": "routingKey" + } + }, + "required": ["exchange"], + "not": { + "required": ["queue"] + } + }, + { + "properties": { + "is": { + "const": "queue" + } + }, + "required": ["queue"], + "not": { + "required": ["exchange"] + } + } + ], + "examples": [ + { + "is": "routingKey", + "exchange": { + "name": "myExchange", + "type": "topic", + "durable": true, + "autoDelete": false, + "vhost": "/" + }, + "bindingVersion": "0.3.0" + }, + { + "is": "queue", + "queue": { + "name": "my-queue-name", + "durable": true, + "exclusive": true, + "autoDelete": false, + "vhost": "/" + }, + "bindingVersion": "0.3.0" + } + ] + }, + "specificationExtension": { + "description": "Any property starting with x- is valid.", + "additionalItems": true, + "additionalProperties": true + }, + "bindings-anypointmq-0.0.1-channel": { + "title": "Anypoint MQ channel bindings object", + "description": "This object contains configuration for describing an Anypoint MQ exchange, queue, or FIFO queue as an AsyncAPI channel. This objects only contains configuration that can not be provided in the AsyncAPI standard channel object.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "destination": { + "type": "string", + "description": "The destination (queue or exchange) name for this channel. SHOULD only be specified if the channel name differs from the actual destination name, such as when the channel name is not a valid destination name in Anypoint MQ. Defaults to the channel name." + }, + "destinationType": { + "type": "string", + "enum": ["exchange", "queue", "fifo-queue"], + "default": "queue", + "description": "The type of destination. SHOULD be specified to document the messaging model (publish/subscribe, point-to-point, strict message ordering) supported by this channel." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.0.1"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "destination": "user-signup-exchg", + "destinationType": "exchange", + "bindingVersion": "0.0.1" + } + ] + }, + "bindings-googlepubsub-0.2.0-channel": { + "title": "Cloud Pub/Sub Channel Schema", + "description": "This object contains information about the channel representation for Google Cloud Pub/Sub.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "bindingVersion": { + "type": "string", + "enum": ["0.2.0"], + "description": "The version of this binding." + }, + "labels": { + "type": "object" + }, + "messageRetentionDuration": { + "type": "string" + }, + "messageStoragePolicy": { + "type": "object", + "additionalProperties": false, + "properties": { + "allowedPersistenceRegions": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "schemaSettings": { + "type": "object", + "additionalItems": false, + "properties": { + "encoding": { + "type": "string" + }, + "firstRevisionId": { + "type": "string" + }, + "lastRevisionId": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": ["encoding", "name"] + } + }, + "required": ["schemaSettings"], + "examples": [ + { + "labels": { + "label1": "value1", + "label2": "value2" + }, + "messageRetentionDuration": "86400s", + "messageStoragePolicy": { + "allowedPersistenceRegions": ["us-central1", "us-east1"] + }, + "schemaSettings": { + "encoding": "json", + "name": "projects/your-project-id/schemas/your-schema" + } + } + ] + }, + "bindings-ibmmq-0.1.0-channel": { + "title": "IBM MQ channel bindings object", + "description": "This object contains information about the channel representation in IBM MQ. Each channel corresponds to a Queue or Topic within IBM MQ.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "destinationType": { + "type": "string", + "enum": ["topic", "queue"], + "default": "topic", + "description": "Defines the type of AsyncAPI channel." + }, + "queue": { + "type": "object", + "description": "Defines the properties of a queue.", + "properties": { + "objectName": { + "type": "string", + "maxLength": 48, + "description": "Defines the name of the IBM MQ queue associated with the channel." + }, + "isPartitioned": { + "type": "boolean", + "default": false, + "description": "Defines if the queue is a cluster queue and therefore partitioned. If 'true', a binding option MAY be specified when accessing the queue. More information on binding options can be found on this page in the IBM MQ Knowledge Center." + }, + "exclusive": { + "type": "boolean", + "default": false, + "description": "Specifies if it is recommended to open the queue exclusively." + } + }, + "required": ["objectName"] + }, + "topic": { + "type": "object", + "description": "Defines the properties of a topic.", + "properties": { + "string": { + "type": "string", + "maxLength": 10240, + "description": "The value of the IBM MQ topic string to be used." + }, + "objectName": { + "type": "string", + "maxLength": 48, + "description": "The name of the IBM MQ topic object." + }, + "durablePermitted": { + "type": "boolean", + "default": true, + "description": "Defines if the subscription may be durable." + }, + "lastMsgRetained": { + "type": "boolean", + "default": false, + "description": "Defines if the last message published will be made available to new subscriptions." + } + } + }, + "maxMsgLength": { + "type": "integer", + "minimum": 0, + "maximum": 104857600, + "description": "The maximum length of the physical message (in bytes) accepted by the Topic or Queue. Messages produced that are greater in size than this value may fail to be delivered. More information on the maximum message length can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q097520_.html) in the IBM MQ Knowledge Center." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.1.0"], + "description": "The version of this binding." + } + }, + "oneOf": [ + { + "properties": { + "destinationType": { + "const": "topic" + } + }, + "not": { + "required": ["queue"] + } + }, + { + "properties": { + "destinationType": { + "const": "queue" + } + }, + "required": ["queue"], + "not": { + "required": ["topic"] + } + } + ], + "examples": [ + { + "destinationType": "topic", + "topic": { + "objectName": "myTopicName" + }, + "bindingVersion": "0.1.0" + }, + { + "destinationType": "queue", + "queue": { + "objectName": "myQueueName", + "exclusive": true + }, + "bindingVersion": "0.1.0" + } + ] + }, + "bindings-jms-0.0.1-channel": { + "title": "Channel Schema", + "description": "This object contains configuration for describing a JMS queue, or FIFO queue as an AsyncAPI channel. This objects only contains configuration that can not be provided in the AsyncAPI standard channel object.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "destination": { + "type": "string", + "description": "The destination (queue) name for this channel. SHOULD only be specified if the channel name differs from the actual destination name, such as when the channel name is not a valid destination name according to the JMS Provider. Defaults to the channel name." + }, + "destinationType": { + "type": "string", + "enum": ["queue", "fifo-queue"], + "default": "queue", + "description": "The type of destination. SHOULD be specified to document the messaging model (point-to-point, or strict message ordering) supported by this channel." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.0.1"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "destination": "user-signed-up", + "destinationType": "fifo-queue", + "bindingVersion": "0.0.1" + } + ] + }, + "bindings-kafka-0.5.0-channel": { + "title": "Channel Schema", + "description": "This object contains information about the channel representation in Kafka.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "topic": { + "type": "string", + "description": "Kafka topic name if different from channel name." + }, + "partitions": { + "type": "integer", + "minimum": 1, + "description": "Number of partitions configured on this topic." + }, + "replicas": { + "type": "integer", + "minimum": 1, + "description": "Number of replicas configured on this topic." + }, + "topicConfiguration": { + "description": "Topic configuration properties that are relevant for the API.", + "type": "object", + "additionalProperties": true, + "properties": { + "cleanup.policy": { + "description": "The [`cleanup.policy`](https://kafka.apache.org/documentation/#topicconfigs_cleanup.policy) configuration option.", + "type": "array", + "items": { + "type": "string", + "enum": ["compact", "delete"] + } + }, + "retention.ms": { + "description": "The [`retention.ms`](https://kafka.apache.org/documentation/#topicconfigs_retention.ms) configuration option.", + "type": "integer", + "minimum": -1 + }, + "retention.bytes": { + "description": "The [`retention.bytes`](https://kafka.apache.org/documentation/#topicconfigs_retention.bytes) configuration option.", + "type": "integer", + "minimum": -1 + }, + "delete.retention.ms": { + "description": "The [`delete.retention.ms`](https://kafka.apache.org/documentation/#topicconfigs_delete.retention.ms) configuration option.", + "type": "integer", + "minimum": 0 + }, + "max.message.bytes": { + "description": "The [`max.message.bytes`](https://kafka.apache.org/documentation/#topicconfigs_max.message.bytes) configuration option.", + "type": "integer", + "minimum": 0 + }, + "confluent.key.schema.validation": { + "description": "It shows whether the schema validation for the message key is enabled. Vendor specific config. For more details: (https://docs.confluent.io/platform/current/installation/configuration/topic-configs.html#confluent-key-schema-validation)", + "type": "boolean" + }, + "confluent.key.subject.name.strategy": { + "description": "The name of the schema lookup strategy for the message key. Vendor specific config. For more details: (https://docs.confluent.io/platform/current/installation/configuration/topic-configs.html#confluent-key-subject-name-strategy)", + "type": "string" + }, + "confluent.value.schema.validation": { + "description": "It shows whether the schema validation for the message value is enabled. Vendor specific config. For more details: (https://docs.confluent.io/platform/current/installation/configuration/topic-configs.html#confluent-value-schema-validation)", + "type": "boolean" + }, + "confluent.value.subject.name.strategy": { + "description": "The name of the schema lookup strategy for the message value. Vendor specific config. For more details: (https://docs.confluent.io/platform/current/installation/configuration/topic-configs.html#confluent-value-subject-name-strategy)", + "type": "string" + } + } + }, + "bindingVersion": { + "type": "string", + "enum": ["0.5.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "topic": "my-specific-topic", + "partitions": 20, + "replicas": 3, + "bindingVersion": "0.5.0" + } + ] + }, + "bindings-kafka-0.4.0-channel": { + "title": "Channel Schema", + "description": "This object contains information about the channel representation in Kafka.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "topic": { + "type": "string", + "description": "Kafka topic name if different from channel name." + }, + "partitions": { + "type": "integer", + "minimum": 1, + "description": "Number of partitions configured on this topic." + }, + "replicas": { + "type": "integer", + "minimum": 1, + "description": "Number of replicas configured on this topic." + }, + "topicConfiguration": { + "description": "Topic configuration properties that are relevant for the API.", + "type": "object", + "additionalProperties": false, + "properties": { + "cleanup.policy": { + "description": "The [`cleanup.policy`](https://kafka.apache.org/documentation/#topicconfigs_cleanup.policy) configuration option.", + "type": "array", + "items": { + "type": "string", + "enum": ["compact", "delete"] + } + }, + "retention.ms": { + "description": "The [`retention.ms`](https://kafka.apache.org/documentation/#topicconfigs_retention.ms) configuration option.", + "type": "integer", + "minimum": -1 + }, + "retention.bytes": { + "description": "The [`retention.bytes`](https://kafka.apache.org/documentation/#topicconfigs_retention.bytes) configuration option.", + "type": "integer", + "minimum": -1 + }, + "delete.retention.ms": { + "description": "The [`delete.retention.ms`](https://kafka.apache.org/documentation/#topicconfigs_delete.retention.ms) configuration option.", + "type": "integer", + "minimum": 0 + }, + "max.message.bytes": { + "description": "The [`max.message.bytes`](https://kafka.apache.org/documentation/#topicconfigs_max.message.bytes) configuration option.", + "type": "integer", + "minimum": 0 + } + } + }, + "bindingVersion": { + "type": "string", + "enum": ["0.4.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "topic": "my-specific-topic", + "partitions": 20, + "replicas": 3, + "bindingVersion": "0.4.0" + } + ] + }, + "bindings-kafka-0.3.0-channel": { + "title": "Channel Schema", + "description": "This object contains information about the channel representation in Kafka.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "topic": { + "type": "string", + "description": "Kafka topic name if different from channel name." + }, + "partitions": { + "type": "integer", + "minimum": 1, + "description": "Number of partitions configured on this topic." + }, + "replicas": { + "type": "integer", + "minimum": 1, + "description": "Number of replicas configured on this topic." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.3.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "topic": "my-specific-topic", + "partitions": 20, + "replicas": 3, + "bindingVersion": "0.3.0" + } + ] + }, + "bindings-pulsar-0.1.0-channel": { + "title": "Channel Schema", + "description": "This object contains information about the channel representation in Pulsar, which covers namespace and topic level admin configuration. This object contains additional information not possible to represent within the core AsyncAPI specification.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "required": ["namespace", "persistence"], + "properties": { + "namespace": { + "type": "string", + "description": "The namespace, the channel is associated with." + }, + "persistence": { + "type": "string", + "enum": ["persistent", "non-persistent"], + "description": "persistence of the topic in Pulsar." + }, + "compaction": { + "type": "integer", + "minimum": 0, + "description": "Topic compaction threshold given in MB" + }, + "geo-replication": { + "type": "array", + "description": "A list of clusters the topic is replicated to.", + "items": { + "type": "string" + } + }, + "retention": { + "type": "object", + "additionalProperties": false, + "properties": { + "time": { + "type": "integer", + "minimum": 0, + "description": "Time given in Minutes. `0` = Disable message retention." + }, + "size": { + "type": "integer", + "minimum": 0, + "description": "Size given in MegaBytes. `0` = Disable message retention." + } + } + }, + "ttl": { + "type": "integer", + "description": "TTL in seconds for the specified topic" + }, + "deduplication": { + "type": "boolean", + "description": "Whether deduplication of events is enabled or not." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.1.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "namespace": "ns1", + "persistence": "persistent", + "compaction": 1000, + "retention": { + "time": 15, + "size": 1000 + }, + "ttl": 360, + "geo-replication": ["us-west", "us-east"], + "deduplication": true, + "bindingVersion": "0.1.0" + } + ] + }, + "bindings-sns-0.1.0-channel": { + "title": "Channel Schema", + "description": "This object contains information about the channel representation in SNS.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "name": { + "type": "string", + "description": "The name of the topic. Can be different from the channel name to allow flexibility around AWS resource naming limitations." + }, + "ordering": { + "$ref": "#/definitions/bindings-sns-0.1.0-channel/definitions/ordering" + }, + "policy": { + "$ref": "#/definitions/bindings-sns-0.1.0-channel/definitions/policy" + }, + "tags": { + "type": "object", + "description": "Key-value pairs that represent AWS tags on the topic." + }, + "bindingVersion": { + "type": "string", + "description": "The version of this binding.", + "default": "latest" + } + }, + "required": ["name"], + "definitions": { + "ordering": { + "type": "object", + "description": "By default, we assume an unordered SNS topic. This field allows configuration of a FIFO SNS Topic.", + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "type": { + "type": "string", + "description": "Defines the type of SNS Topic.", + "enum": ["standard", "FIFO"] + }, + "contentBasedDeduplication": { + "type": "boolean", + "description": "True to turn on de-duplication of messages for a channel." + } + }, + "required": ["type"] + }, + "policy": { + "type": "object", + "description": "The security policy for the SNS Topic.", + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "statements": { + "type": "array", + "description": "An array of statement objects, each of which controls a permission for this topic", + "items": { + "$ref": "#/definitions/bindings-sns-0.1.0-channel/definitions/statement" + } + } + }, + "required": ["statements"] + }, + "statement": { + "type": "object", + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "effect": { + "type": "string", + "enum": ["Allow", "Deny"] + }, + "principal": { + "description": "The AWS account or resource ARN that this statement applies to.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "action": { + "description": "The SNS permission being allowed or denied e.g. sns:Publish", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + }, + "required": ["effect", "principal", "action"] + } + }, + "examples": [ + { + "name": "my-sns-topic", + "policy": { + "statements": [ + { + "effect": "Allow", + "principal": "*", + "action": "SNS:Publish" + } + ] + } + } + ] + }, + "bindings-sqs-0.2.0-channel": { + "title": "Channel Schema", + "description": "This object contains information about the channel representation in SQS.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "queue": { + "description": "A definition of the queue that will be used as the channel.", + "$ref": "#/definitions/bindings-sqs-0.2.0-channel/definitions/queue" + }, + "deadLetterQueue": { + "description": "A definition of the queue that will be used for un-processable messages.", + "$ref": "#/definitions/bindings-sqs-0.2.0-channel/definitions/queue" + }, + "bindingVersion": { + "type": "string", + "enum": ["0.1.0", "0.2.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed.", + "default": "latest" + } + }, + "required": ["queue"], + "definitions": { + "queue": { + "type": "object", + "description": "A definition of a queue.", + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "name": { + "type": "string", + "description": "The name of the queue. When an SNS Operation Binding Object references an SQS queue by name, the identifier should be the one in this field." + }, + "fifoQueue": { + "type": "boolean", + "description": "Is this a FIFO queue?", + "default": false + }, + "deduplicationScope": { + "type": "string", + "enum": ["queue", "messageGroup"], + "description": "Specifies whether message deduplication occurs at the message group or queue level. Valid values are messageGroup and queue (default).", + "default": "queue" + }, + "fifoThroughputLimit": { + "type": "string", + "enum": ["perQueue", "perMessageGroupId"], + "description": "Specifies whether the FIFO queue throughput quota applies to the entire queue or per message group. Valid values are perQueue (default) and perMessageGroupId.", + "default": "perQueue" + }, + "deliveryDelay": { + "type": "integer", + "description": "The number of seconds to delay before a message sent to the queue can be received. used to create a delay queue.", + "minimum": 0, + "maximum": 900, + "default": 0 + }, + "visibilityTimeout": { + "type": "integer", + "description": "The length of time, in seconds, that a consumer locks a message - hiding it from reads - before it is unlocked and can be read again.", + "minimum": 0, + "maximum": 43200, + "default": 30 + }, + "receiveMessageWaitTime": { + "type": "integer", + "description": "Determines if the queue uses short polling or long polling. Set to zero the queue reads available messages and returns immediately. Set to a non-zero integer, long polling waits the specified number of seconds for messages to arrive before returning.", + "default": 0 + }, + "messageRetentionPeriod": { + "type": "integer", + "description": "How long to retain a message on the queue in seconds, unless deleted.", + "minimum": 60, + "maximum": 1209600, + "default": 345600 + }, + "redrivePolicy": { + "$ref": "#/definitions/bindings-sqs-0.2.0-channel/definitions/redrivePolicy" + }, + "policy": { + "$ref": "#/definitions/bindings-sqs-0.2.0-channel/definitions/policy" + }, + "tags": { + "type": "object", + "description": "Key-value pairs that represent AWS tags on the queue." + } + }, + "required": ["name", "fifoQueue"] + }, + "redrivePolicy": { + "type": "object", + "description": "Prevent poison pill messages by moving un-processable messages to an SQS dead letter queue.", + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "deadLetterQueue": { + "$ref": "#/definitions/bindings-sqs-0.2.0-channel/definitions/identifier" + }, + "maxReceiveCount": { + "type": "integer", + "description": "The number of times a message is delivered to the source queue before being moved to the dead-letter queue.", + "default": 10 + } + }, + "required": ["deadLetterQueue"] + }, + "identifier": { + "type": "object", + "description": "The SQS queue to use as a dead letter queue (DLQ).", + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "arn": { + "type": "string", + "description": "The target is an ARN. For example, for SQS, the identifier may be an ARN, which will be of the form: arn:aws:sqs:{region}:{account-id}:{queueName}" + }, + "name": { + "type": "string", + "description": "The endpoint is identified by a name, which corresponds to an identifying field called 'name' of a binding for that protocol on this publish Operation Object. For example, if the protocol is 'sqs' then the name refers to the name field sqs binding." + } + } + }, + "policy": { + "type": "object", + "description": "The security policy for the SQS Queue", + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "statements": { + "type": "array", + "description": "An array of statement objects, each of which controls a permission for this queue.", + "items": { + "$ref": "#/definitions/bindings-sqs-0.2.0-channel/definitions/statement" + } + } + }, + "required": ["statements"] + }, + "statement": { + "type": "object", + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "effect": { + "type": "string", + "enum": ["Allow", "Deny"] + }, + "principal": { + "description": "The AWS account or resource ARN that this statement applies to.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "action": { + "description": "The SQS permission being allowed or denied e.g. sqs:ReceiveMessage", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + }, + "required": ["effect", "principal", "action"] + } + }, + "examples": [ + { + "queue": { + "name": "myQueue", + "fifoQueue": true, + "deduplicationScope": "messageGroup", + "fifoThroughputLimit": "perMessageGroupId", + "deliveryDelay": 15, + "visibilityTimeout": 60, + "receiveMessageWaitTime": 0, + "messageRetentionPeriod": 86400, + "redrivePolicy": { + "deadLetterQueue": { + "arn": "arn:aws:SQS:eu-west-1:0000000:123456789" + }, + "maxReceiveCount": 15 + }, + "policy": { + "statements": [ + { + "effect": "Deny", + "principal": "arn:aws:iam::123456789012:user/dec.kolakowski", + "action": ["sqs:SendMessage", "sqs:ReceiveMessage"] + } + ] + }, + "tags": { + "owner": "AsyncAPI.NET", + "platform": "AsyncAPIOrg" + } + }, + "deadLetterQueue": { + "name": "myQueue_error", + "deliveryDelay": 0, + "visibilityTimeout": 0, + "receiveMessageWaitTime": 0, + "messageRetentionPeriod": 604800 + } + } + ] + }, + "bindings-websockets-0.1.0-channel": { + "title": "WebSockets channel bindings object", + "description": "When using WebSockets, the channel represents the connection. Unlike other protocols that support multiple virtual channels (topics, routing keys, etc.) per connection, WebSockets doesn't support virtual channels or, put it another way, there's only one channel and its characteristics are strongly related to the protocol used for the handshake, i.e., HTTP.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "method": { + "type": "string", + "enum": ["GET", "POST"], + "description": "The HTTP method to use when establishing the connection. Its value MUST be either 'GET' or 'POST'." + }, + "query": { + "oneOf": [ + { + "$ref": "#/definitions/schema" + }, + { + "$ref": "#/definitions/Reference" + } + ], + "description": "A Schema object containing the definitions for each query parameter. This schema MUST be of type 'object' and have a 'properties' key." + }, + "headers": { + "oneOf": [ + { + "$ref": "#/definitions/schema" + }, + { + "$ref": "#/definitions/Reference" + } + ], + "description": "A Schema object containing the definitions of the HTTP headers to use when establishing the connection. This schema MUST be of type 'object' and have a 'properties' key." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.1.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "method": "POST", + "bindingVersion": "0.1.0" + } + ] + }, + "schema": { + "description": "The Schema Object allows the definition of input and output data types. These types can be objects, but also primitives and arrays. This object is a superset of the JSON Schema Specification Draft 07. The empty schema (which allows any instance to validate) MAY be represented by the boolean value true and a schema which allows no instance to validate MAY be represented by the boolean value false.", + "allOf": [ + { + "$ref": "#/definitions/json-schema-draft-07-schema" + }, + { + "properties": { + "deprecated": { + "description": "Specifies that a schema is deprecated and SHOULD be transitioned out of usage. Default value is false.", + "default": false, + "type": "boolean" + }, + "allOf": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/schema" + } + }, + "anyOf": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/schema" + } + }, + "oneOf": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/schema" + } + }, + "not": { + "$ref": "#/definitions/schema" + }, + "contains": { + "$ref": "#/definitions/schema" + }, + "items": { + "default": {}, + "anyOf": [ + { + "$ref": "#/definitions/schema" + }, + { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/schema" + } + } + ] + }, + "propertyNames": { + "$ref": "#/definitions/schema" + }, + "properties": { + "default": {}, + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/schema" + } + }, + "patternProperties": { + "default": {}, + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/schema" + } + }, + "additionalProperties": { + "default": {}, + "anyOf": [ + { + "$ref": "#/definitions/schema" + }, + { + "type": "boolean" + } + ] + }, + "discriminator": { + "description": "Adds support for polymorphism. The discriminator is the schema property name that is used to differentiate between other schema that inherit this schema. The property name used MUST be defined at this schema and it MUST be in the required property list. When used, the value MUST be the name of this schema or any schema that inherits it. See Composition and Inheritance for more details.", + "type": "string" + }, + "externalDocs": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/externalDocs" + } + ] + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + } + } + ] + }, + "json-schema-draft-07-schema": { + "title": "Core schema meta-schema", + "definitions": { + "schemaArray": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/json-schema-draft-07-schema" + } + }, + "nonNegativeInteger": { + "type": "integer", + "minimum": 0 + }, + "nonNegativeIntegerDefault0": { + "allOf": [ + { + "$ref": "#/definitions/json-schema-draft-07-schema/definitions/nonNegativeInteger" + }, + { + "default": 0 + } + ] + }, + "simpleTypes": { + "enum": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ] + }, + "stringArray": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true, + "default": [] + } + }, + "type": ["object", "boolean"], + "properties": { + "$id": { + "type": "string", + "format": "uri-reference" + }, + "$schema": { + "type": "string", + "format": "uri" + }, + "$ref": { + "type": "string", + "format": "uri-reference" + }, + "$comment": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "default": true, + "readOnly": { + "type": "boolean", + "default": false + }, + "writeOnly": { + "type": "boolean", + "default": false + }, + "examples": { + "type": "array", + "items": true + }, + "multipleOf": { + "type": "number", + "exclusiveMinimum": 0 + }, + "maximum": { + "type": "number" + }, + "exclusiveMaximum": { + "type": "number" + }, + "minimum": { + "type": "number" + }, + "exclusiveMinimum": { + "type": "number" + }, + "maxLength": { + "$ref": "#/definitions/json-schema-draft-07-schema/definitions/nonNegativeInteger" + }, + "minLength": { + "$ref": "#/definitions/json-schema-draft-07-schema/definitions/nonNegativeIntegerDefault0" + }, + "pattern": { + "type": "string", + "format": "regex" + }, + "additionalItems": { + "$ref": "#/definitions/json-schema-draft-07-schema" + }, + "items": { + "anyOf": [ + { + "$ref": "#/definitions/json-schema-draft-07-schema" + }, + { + "$ref": "#/definitions/json-schema-draft-07-schema/definitions/schemaArray" + } + ], + "default": true + }, + "maxItems": { + "$ref": "#/definitions/json-schema-draft-07-schema/definitions/nonNegativeInteger" + }, + "minItems": { + "$ref": "#/definitions/json-schema-draft-07-schema/definitions/nonNegativeIntegerDefault0" + }, + "uniqueItems": { + "type": "boolean", + "default": false + }, + "contains": { + "$ref": "#/definitions/json-schema-draft-07-schema" + }, + "maxProperties": { + "$ref": "#/definitions/json-schema-draft-07-schema/definitions/nonNegativeInteger" + }, + "minProperties": { + "$ref": "#/definitions/json-schema-draft-07-schema/definitions/nonNegativeIntegerDefault0" + }, + "required": { + "$ref": "#/definitions/json-schema-draft-07-schema/definitions/stringArray" + }, + "additionalProperties": { + "$ref": "#/definitions/json-schema-draft-07-schema" + }, + "definitions": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/json-schema-draft-07-schema" + }, + "default": {} + }, + "properties": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/json-schema-draft-07-schema" + }, + "default": {} + }, + "patternProperties": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/json-schema-draft-07-schema" + }, + "propertyNames": { + "format": "regex" + }, + "default": {} + }, + "dependencies": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "$ref": "#/definitions/json-schema-draft-07-schema" + }, + { + "$ref": "#/definitions/json-schema-draft-07-schema/definitions/stringArray" + } + ] + } + }, + "propertyNames": { + "$ref": "#/definitions/json-schema-draft-07-schema" + }, + "const": true, + "enum": { + "type": "array", + "items": true, + "minItems": 1, + "uniqueItems": true + }, + "type": { + "anyOf": [ + { + "$ref": "#/definitions/json-schema-draft-07-schema/definitions/simpleTypes" + }, + { + "type": "array", + "items": { + "$ref": "#/definitions/json-schema-draft-07-schema/definitions/simpleTypes" + }, + "minItems": 1, + "uniqueItems": true + } + ] + }, + "format": { + "type": "string" + }, + "contentMediaType": { + "type": "string" + }, + "contentEncoding": { + "type": "string" + }, + "if": { + "$ref": "#/definitions/json-schema-draft-07-schema" + }, + "then": { + "$ref": "#/definitions/json-schema-draft-07-schema" + }, + "else": { + "$ref": "#/definitions/json-schema-draft-07-schema" + }, + "allOf": { + "$ref": "#/definitions/json-schema-draft-07-schema/definitions/schemaArray" + }, + "anyOf": { + "$ref": "#/definitions/json-schema-draft-07-schema/definitions/schemaArray" + }, + "oneOf": { + "$ref": "#/definitions/json-schema-draft-07-schema/definitions/schemaArray" + }, + "not": { + "$ref": "#/definitions/json-schema-draft-07-schema" + } + }, + "default": true + }, + "externalDocs": { + "description": "Allows referencing an external resource for extended documentation.", + "type": "object", + "required": ["url"], + "properties": { + "description": { + "description": "A short description of the target documentation. CommonMark syntax can be used for rich text representation.", + "type": "string" + }, + "url": { + "description": "The URL for the target documentation. This MUST be in the form of an absolute URL.", + "type": "string", + "format": "uri" + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "description": "Find more info here", + "url": "https://example.com" + } + ] + }, + "channelMessages": { + "description": "A map of the messages that will be sent to this channel by any application at any time. **Every message sent to this channel MUST be valid against one, and only one, of the message objects defined in this map.**", + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/messageObject" + } + ] + } + }, + "messageObject": { + "description": "Describes a message received on a given channel and operation.", + "type": "object", + "properties": { + "title": { + "description": "A human-friendly title for the message.", + "type": "string" + }, + "description": { + "description": "A longer description of the message. CommonMark is allowed.", + "type": "string" + }, + "examples": { + "description": "List of examples.", + "type": "array", + "items": { + "$ref": "#/definitions/messageExampleObject" + } + }, + "deprecated": { + "default": false, + "type": "boolean" + }, + "bindings": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/messageBindingsObject" + } + ] + }, + "contentType": { + "description": "The content type to use when encoding/decoding a message's payload. The value MUST be a specific media type (e.g. application/json). When omitted, the value MUST be the one specified on the defaultContentType field.", + "type": "string" + }, + "correlationId": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/correlationId" + } + ] + }, + "externalDocs": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/externalDocs" + } + ] + }, + "headers": { + "$ref": "#/definitions/anySchema" + }, + "name": { + "description": "Name of the message.", + "type": "string" + }, + "payload": { + "$ref": "#/definitions/anySchema" + }, + "summary": { + "description": "A brief summary of the message.", + "type": "string" + }, + "tags": { + "type": "array", + "uniqueItems": true, + "items": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/tag" + } + ] + } + }, + "traits": { + "description": "A list of traits to apply to the message object. Traits MUST be merged using traits merge mechanism. The resulting object MUST be a valid Message Object.", + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/messageTrait" + }, + { + "type": "array", + "items": [ + { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/messageTrait" + } + ] + }, + { + "type": "object", + "additionalItems": true + } + ] + } + ] + } + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "messageId": "userSignup", + "name": "UserSignup", + "title": "User signup", + "summary": "Action to sign a user up.", + "description": "A longer description", + "contentType": "application/json", + "tags": [ + { + "name": "user" + }, + { + "name": "signup" + }, + { + "name": "register" + } + ], + "headers": { + "type": "object", + "properties": { + "correlationId": { + "description": "Correlation ID set by application", + "type": "string" + }, + "applicationInstanceId": { + "description": "Unique identifier for a given instance of the publishing application", + "type": "string" + } + } + }, + "payload": { + "type": "object", + "properties": { + "user": { + "$ref": "#/components/schemas/userCreate" + }, + "signup": { + "$ref": "#/components/schemas/signup" + } + } + }, + "correlationId": { + "description": "Default Correlation ID", + "location": "$message.header#/correlationId" + }, + "traits": [ + { + "$ref": "#/components/messageTraits/commonHeaders" + } + ], + "examples": [ + { + "name": "SimpleSignup", + "summary": "A simple UserSignup example message", + "headers": { + "correlationId": "my-correlation-id", + "applicationInstanceId": "myInstanceId" + }, + "payload": { + "user": { + "someUserKey": "someUserValue" + }, + "signup": { + "someSignupKey": "someSignupValue" + } + } + } + ] + } + ] + }, + "messageExampleObject": { + "type": "object", + "anyOf": [ + { + "required": ["payload"] + }, + { + "required": ["headers"] + } + ], + "properties": { + "headers": { + "description": "Example of the application headers. It can be of any type.", + "type": "object" + }, + "name": { + "description": "Machine readable name of the message example.", + "type": "string" + }, + "payload": { + "description": "Example of the message payload. It can be of any type." + }, + "summary": { + "description": "A brief summary of the message example.", + "type": "string" + } + }, + "additionalProperties": false + }, + "messageBindingsObject": { + "description": "Map describing protocol-specific definitions for a message.", + "type": "object", + "properties": { + "amqp": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-amqp-0.3.0-message" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.3.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-amqp-0.3.0-message" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.3.0"] + } + } + }, + "amqp1": {}, + "anypointmq": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-anypointmq-0.0.1-message" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.0.1" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-anypointmq-0.0.1-message" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.0.1"] + } + } + }, + "googlepubsub": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-googlepubsub-0.2.0-message" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.2.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-googlepubsub-0.2.0-message" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.2.0"] + } + } + }, + "http": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-http-0.3.0-message" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.2.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-http-0.2.0-message" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.3.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-http-0.3.0-message" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.2.0", "0.3.0"] + } + } + }, + "ibmmq": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-ibmmq-0.1.0-message" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.1.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-ibmmq-0.1.0-message" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.1.0"] + } + } + }, + "jms": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-jms-0.0.1-message" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.0.1" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-jms-0.0.1-message" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.0.1"] + } + } + }, + "kafka": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-kafka-0.5.0-message" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.5.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-kafka-0.5.0-message" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.4.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-kafka-0.4.0-message" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.3.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-kafka-0.3.0-message" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.5.0", "0.4.0", "0.3.0"] + } + } + }, + "mqtt": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-mqtt-0.2.0-message" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.2.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-mqtt-0.2.0-message" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.2.0"] + } + } + }, + "nats": {}, + "redis": {}, + "sns": {}, + "solace": {}, + "sqs": {}, + "stomp": {}, + "ws": {} + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false + }, + "bindings-amqp-0.3.0-message": { + "title": "AMQP message bindings object", + "description": "This object contains information about the message representation in AMQP.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "contentEncoding": { + "type": "string", + "description": "A MIME encoding for the message content." + }, + "messageType": { + "type": "string", + "description": "Application-specific message type." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.3.0"], + "description": "The version of this binding. If omitted, \"latest\" MUST be assumed." + } + }, + "examples": [ + { + "contentEncoding": "gzip", + "messageType": "user.signup", + "bindingVersion": "0.3.0" + } + ] + }, + "bindings-anypointmq-0.0.1-message": { + "title": "Anypoint MQ message bindings object", + "description": "This object contains configuration for describing an Anypoint MQ message as an AsyncAPI message. This objects only contains configuration that can not be provided in the AsyncAPI standard message object.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "headers": { + "oneOf": [ + { + "$ref": "#/definitions/schema" + }, + { + "$ref": "#/definitions/Reference" + } + ], + "description": "A Schema object containing the definitions for Anypoint MQ-specific headers (protocol headers). This schema MUST be of type 'object' and have a 'properties' key. Examples of Anypoint MQ protocol headers are 'messageId' and 'messageGroupId'." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.0.1"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "headers": { + "type": "object", + "properties": { + "messageId": { + "type": "string" + } + } + }, + "bindingVersion": "0.0.1" + } + ] + }, + "bindings-googlepubsub-0.2.0-message": { + "title": "Cloud Pub/Sub Channel Schema", + "description": "This object contains information about the message representation for Google Cloud Pub/Sub.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "bindingVersion": { + "type": "string", + "enum": ["0.2.0"], + "description": "The version of this binding." + }, + "attributes": { + "type": "object" + }, + "orderingKey": { + "type": "string" + }, + "schema": { + "type": "object", + "additionalItems": false, + "properties": { + "name": { + "type": "string" + } + }, + "required": ["name"] + } + }, + "examples": [ + { + "schema": { + "name": "projects/your-project-id/schemas/your-avro-schema-id" + } + }, + { + "schema": { + "name": "projects/your-project-id/schemas/your-protobuf-schema-id" + } + } + ] + }, + "bindings-http-0.3.0-message": { + "title": "HTTP message bindings object", + "description": "This object contains information about the message representation in HTTP.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "headers": { + "$ref": "#/definitions/schema", + "description": "\tA Schema object containing the definitions for HTTP-specific headers. This schema MUST be of type 'object' and have a 'properties' key." + }, + "statusCode": { + "type": "number", + "description": "The HTTP response status code according to [RFC 9110](https://httpwg.org/specs/rfc9110.html#overview.of.status.codes). `statusCode` is only relevant for messages referenced by the [Operation Reply Object](https://www.asyncapi.com/docs/reference/specification/v3.0.0#operationReplyObject), as it defines the status code for the response. In all other cases, this value can be safely ignored." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.3.0"], + "description": "The version of this binding. If omitted, \"latest\" MUST be assumed." + } + }, + "examples": [ + { + "headers": { + "type": "object", + "properties": { + "Content-Type": { + "type": "string", + "enum": ["application/json"] + } + } + }, + "bindingVersion": "0.3.0" + } + ] + }, + "bindings-http-0.2.0-message": { + "title": "HTTP message bindings object", + "description": "This object contains information about the message representation in HTTP.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "headers": { + "$ref": "#/definitions/schema", + "description": "\tA Schema object containing the definitions for HTTP-specific headers. This schema MUST be of type 'object' and have a 'properties' key." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.2.0"], + "description": "The version of this binding. If omitted, \"latest\" MUST be assumed." + } + }, + "examples": [ + { + "headers": { + "type": "object", + "properties": { + "Content-Type": { + "type": "string", + "enum": ["application/json"] + } + } + }, + "bindingVersion": "0.2.0" + } + ] + }, + "bindings-ibmmq-0.1.0-message": { + "title": "IBM MQ message bindings object", + "description": "This object contains information about the message representation in IBM MQ.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "type": { + "type": "string", + "enum": ["string", "jms", "binary"], + "default": "string", + "description": "The type of the message." + }, + "headers": { + "type": "string", + "description": "Defines the IBM MQ message headers to include with this message. More than one header can be specified as a comma separated list. Supporting information on IBM MQ message formats can be found on this [page](https://www.ibm.com/docs/en/ibm-mq/9.2?topic=mqmd-format-mqchar8) in the IBM MQ Knowledge Center." + }, + "description": { + "type": "string", + "description": "Provides additional information for application developers: describes the message type or format." + }, + "expiry": { + "type": "integer", + "minimum": 0, + "default": 0, + "description": "The recommended setting the client should use for the TTL (Time-To-Live) of the message. This is a period of time expressed in milliseconds and set by the application that puts the message. 'expiry' values are API dependant e.g., MQI and JMS use different units of time and default values for 'unlimited'. General information on IBM MQ message expiry can be found on this [page](https://www.ibm.com/docs/en/ibm-mq/9.2?topic=mqmd-expiry-mqlong) in the IBM MQ Knowledge Center." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.1.0"], + "description": "The version of this binding." + } + }, + "oneOf": [ + { + "properties": { + "type": { + "const": "binary" + } + } + }, + { + "properties": { + "type": { + "const": "jms" + } + }, + "not": { + "required": ["headers"] + } + }, + { + "properties": { + "type": { + "const": "string" + } + }, + "not": { + "required": ["headers"] + } + } + ], + "examples": [ + { + "type": "string", + "bindingVersion": "0.1.0" + }, + { + "type": "jms", + "description": "JMS stream message", + "bindingVersion": "0.1.0" + } + ] + }, + "bindings-jms-0.0.1-message": { + "title": "Message Schema", + "description": "This object contains configuration for describing a JMS message as an AsyncAPI message. This objects only contains configuration that can not be provided in the AsyncAPI standard message object.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "headers": { + "$ref": "#/definitions/schema", + "description": "A Schema object containing the definitions for JMS headers (protocol headers). This schema MUST be of type 'object' and have a 'properties' key. Examples of JMS protocol headers are 'JMSMessageID', 'JMSTimestamp', and 'JMSCorrelationID'." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.0.1"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "headers": { + "type": "object", + "required": ["JMSMessageID"], + "properties": { + "JMSMessageID": { + "type": ["string", "null"], + "description": "A unique message identifier. This may be set by your JMS Provider on your behalf." + }, + "JMSTimestamp": { + "type": "integer", + "description": "The time the message was sent. This may be set by your JMS Provider on your behalf. The time the message was sent. The value of the timestamp is the amount of time, measured in milliseconds, that has elapsed since midnight, January 1, 1970, UTC." + }, + "JMSDeliveryMode": { + "type": "string", + "enum": ["PERSISTENT", "NON_PERSISTENT"], + "default": "PERSISTENT", + "description": "Denotes the delivery mode for the message. This may be set by your JMS Provider on your behalf." + }, + "JMSPriority": { + "type": "integer", + "default": 4, + "description": "The priority of the message. This may be set by your JMS Provider on your behalf." + }, + "JMSExpires": { + "type": "integer", + "description": "The time at which the message expires. This may be set by your JMS Provider on your behalf. A value of zero means that the message does not expire. Any non-zero value is the amount of time, measured in milliseconds, that has elapsed since midnight, January 1, 1970, UTC, at which the message will expire." + }, + "JMSType": { + "type": ["string", "null"], + "description": "The type of message. Some JMS providers use a message repository that contains the definitions of messages sent by applications. The 'JMSType' header field may reference a message's definition in the provider's repository. The JMS API does not define a standard message definition repository, nor does it define a naming policy for the definitions it contains. Some messaging systems require that a message type definition for each application message be created and that each message specify its type. In order to work with such JMS providers, JMS clients should assign a value to 'JMSType', whether the application makes use of it or not. This ensures that the field is properly set for those providers that require it." + }, + "JMSCorrelationID": { + "type": ["string", "null"], + "description": "The correlation identifier of the message. A client can use the 'JMSCorrelationID' header field to link one message with another. A typical use is to link a response message with its request message. Since each message sent by a JMS provider is assigned a message ID value, it is convenient to link messages via message ID, such message ID values must start with the 'ID:' prefix. Conversely, application-specified values must not start with the 'ID:' prefix; this is reserved for provider-generated message ID values." + }, + "JMSReplyTo": { + "type": "string", + "description": "The queue or topic that the message sender expects replies to." + } + } + }, + "bindingVersion": "0.0.1" + } + ] + }, + "bindings-kafka-0.5.0-message": { + "title": "Message Schema", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "key": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/schema" + } + ], + "description": "The message key." + }, + "schemaIdLocation": { + "type": "string", + "description": "If a Schema Registry is used when performing this operation, tells where the id of schema is stored.", + "enum": ["header", "payload"] + }, + "schemaIdPayloadEncoding": { + "type": "string", + "description": "Number of bytes or vendor specific values when schema id is encoded in payload." + }, + "schemaLookupStrategy": { + "type": "string", + "description": "Freeform string for any naming strategy class to use. Clients should default to the vendor default if not supplied." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.5.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "key": { + "type": "string", + "enum": ["myKey"] + }, + "schemaIdLocation": "payload", + "schemaIdPayloadEncoding": "apicurio-new", + "schemaLookupStrategy": "TopicIdStrategy", + "bindingVersion": "0.5.0" + }, + { + "key": { + "$ref": "path/to/user-create.avsc#/UserCreate" + }, + "schemaIdLocation": "payload", + "schemaIdPayloadEncoding": "4", + "bindingVersion": "0.5.0" + } + ] + }, + "bindings-kafka-0.4.0-message": { + "title": "Message Schema", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "key": { + "anyOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/schema" + }, + { + "$ref": "#/definitions/avroSchema_v1" + } + ], + "description": "The message key." + }, + "schemaIdLocation": { + "type": "string", + "description": "If a Schema Registry is used when performing this operation, tells where the id of schema is stored.", + "enum": ["header", "payload"] + }, + "schemaIdPayloadEncoding": { + "type": "string", + "description": "Number of bytes or vendor specific values when schema id is encoded in payload." + }, + "schemaLookupStrategy": { + "type": "string", + "description": "Freeform string for any naming strategy class to use. Clients should default to the vendor default if not supplied." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.4.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "key": { + "type": "string", + "enum": ["myKey"] + }, + "schemaIdLocation": "payload", + "schemaIdPayloadEncoding": "apicurio-new", + "schemaLookupStrategy": "TopicIdStrategy", + "bindingVersion": "0.4.0" + }, + { + "key": { + "$ref": "path/to/user-create.avsc#/UserCreate" + }, + "schemaIdLocation": "payload", + "schemaIdPayloadEncoding": "4", + "bindingVersion": "0.4.0" + } + ] + }, + "avroSchema_v1": { + "definitions": { + "avroSchema": { + "title": "Avro Schema", + "description": "Root Schema", + "oneOf": [ + { + "$ref": "#/definitions/avroSchema_v1/definitions/types" + } + ] + }, + "types": { + "title": "Avro Types", + "description": "Allowed Avro types", + "oneOf": [ + { + "$ref": "#/definitions/avroSchema_v1/definitions/primitiveType" + }, + { + "$ref": "#/definitions/avroSchema_v1/definitions/primitiveTypeWithMetadata" + }, + { + "$ref": "#/definitions/avroSchema_v1/definitions/customTypeReference" + }, + { + "$ref": "#/definitions/avroSchema_v1/definitions/avroRecord" + }, + { + "$ref": "#/definitions/avroSchema_v1/definitions/avroEnum" + }, + { + "$ref": "#/definitions/avroSchema_v1/definitions/avroArray" + }, + { + "$ref": "#/definitions/avroSchema_v1/definitions/avroMap" + }, + { + "$ref": "#/definitions/avroSchema_v1/definitions/avroFixed" + }, + { + "$ref": "#/definitions/avroSchema_v1/definitions/avroUnion" + } + ] + }, + "primitiveType": { + "title": "Primitive Type", + "description": "Basic type primitives.", + "type": "string", + "enum": [ + "null", + "boolean", + "int", + "long", + "float", + "double", + "bytes", + "string" + ] + }, + "primitiveTypeWithMetadata": { + "title": "Primitive Type With Metadata", + "description": "A primitive type with metadata attached.", + "type": "object", + "properties": { + "type": { + "$ref": "#/definitions/avroSchema_v1/definitions/primitiveType" + } + }, + "required": ["type"] + }, + "customTypeReference": { + "title": "Custom Type", + "description": "Reference to a ComplexType", + "not": { + "$ref": "#/definitions/avroSchema_v1/definitions/primitiveType" + }, + "type": "string", + "pattern": "^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)*$" + }, + "avroUnion": { + "title": "Union", + "description": "A Union of types", + "type": "array", + "items": { + "$ref": "#/definitions/avroSchema_v1/definitions/avroSchema" + }, + "minItems": 1 + }, + "avroField": { + "title": "Field", + "description": "A field within a Record", + "type": "object", + "properties": { + "name": { + "$ref": "#/definitions/avroSchema_v1/definitions/name" + }, + "type": { + "$ref": "#/definitions/avroSchema_v1/definitions/types" + }, + "doc": { + "type": "string" + }, + "default": true, + "order": { + "enum": ["ascending", "descending", "ignore"] + }, + "aliases": { + "type": "array", + "items": { + "$ref": "#/definitions/avroSchema_v1/definitions/name" + } + } + }, + "required": ["name", "type"] + }, + "avroRecord": { + "title": "Record", + "description": "A Record", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "record" + }, + "name": { + "$ref": "#/definitions/avroSchema_v1/definitions/name" + }, + "namespace": { + "$ref": "#/definitions/avroSchema_v1/definitions/namespace" + }, + "doc": { + "type": "string" + }, + "aliases": { + "type": "array", + "items": { + "$ref": "#/definitions/avroSchema_v1/definitions/name" + } + }, + "fields": { + "type": "array", + "items": { + "$ref": "#/definitions/avroSchema_v1/definitions/avroField" + } + } + }, + "required": ["type", "name", "fields"] + }, + "avroEnum": { + "title": "Enum", + "description": "An enumeration", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "enum" + }, + "name": { + "$ref": "#/definitions/avroSchema_v1/definitions/name" + }, + "namespace": { + "$ref": "#/definitions/avroSchema_v1/definitions/namespace" + }, + "doc": { + "type": "string" + }, + "aliases": { + "type": "array", + "items": { + "$ref": "#/definitions/avroSchema_v1/definitions/name" + } + }, + "symbols": { + "type": "array", + "items": { + "$ref": "#/definitions/avroSchema_v1/definitions/name" + } + } + }, + "required": ["type", "name", "symbols"] + }, + "avroArray": { + "title": "Array", + "description": "An array", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "array" + }, + "name": { + "$ref": "#/definitions/avroSchema_v1/definitions/name" + }, + "namespace": { + "$ref": "#/definitions/avroSchema_v1/definitions/namespace" + }, + "doc": { + "type": "string" + }, + "aliases": { + "type": "array", + "items": { + "$ref": "#/definitions/avroSchema_v1/definitions/name" + } + }, + "items": { + "$ref": "#/definitions/avroSchema_v1/definitions/types" + } + }, + "required": ["type", "items"] + }, + "avroMap": { + "title": "Map", + "description": "A map of values", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "map" + }, + "name": { + "$ref": "#/definitions/avroSchema_v1/definitions/name" + }, + "namespace": { + "$ref": "#/definitions/avroSchema_v1/definitions/namespace" + }, + "doc": { + "type": "string" + }, + "aliases": { + "type": "array", + "items": { + "$ref": "#/definitions/avroSchema_v1/definitions/name" + } + }, + "values": { + "$ref": "#/definitions/avroSchema_v1/definitions/types" + } + }, + "required": ["type", "values"] + }, + "avroFixed": { + "title": "Fixed", + "description": "A fixed sized array of bytes", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "fixed" + }, + "name": { + "$ref": "#/definitions/avroSchema_v1/definitions/name" + }, + "namespace": { + "$ref": "#/definitions/avroSchema_v1/definitions/namespace" + }, + "doc": { + "type": "string" + }, + "aliases": { + "type": "array", + "items": { + "$ref": "#/definitions/avroSchema_v1/definitions/name" + } + }, + "size": { + "type": "number" + } + }, + "required": ["type", "name", "size"] + }, + "name": { + "type": "string", + "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" + }, + "namespace": { + "type": "string", + "pattern": "^([A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)*)*$" + } + }, + "description": "Json-Schema definition for Avro AVSC files.", + "oneOf": [ + { + "$ref": "#/definitions/avroSchema_v1/definitions/avroSchema" + } + ], + "title": "Avro Schema Definition" + }, + "bindings-kafka-0.3.0-message": { + "title": "Message Schema", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "key": { + "$ref": "#/definitions/schema", + "description": "The message key." + }, + "schemaIdLocation": { + "type": "string", + "description": "If a Schema Registry is used when performing this operation, tells where the id of schema is stored.", + "enum": ["header", "payload"] + }, + "schemaIdPayloadEncoding": { + "type": "string", + "description": "Number of bytes or vendor specific values when schema id is encoded in payload." + }, + "schemaLookupStrategy": { + "type": "string", + "description": "Freeform string for any naming strategy class to use. Clients should default to the vendor default if not supplied." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.3.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "key": { + "type": "string", + "enum": ["myKey"] + }, + "schemaIdLocation": "payload", + "schemaIdPayloadEncoding": "apicurio-new", + "schemaLookupStrategy": "TopicIdStrategy", + "bindingVersion": "0.3.0" + }, + { + "key": { + "$ref": "path/to/user-create.avsc#/UserCreate" + }, + "schemaIdLocation": "payload", + "schemaIdPayloadEncoding": "4", + "bindingVersion": "0.3.0" + } + ] + }, + "bindings-mqtt-0.2.0-message": { + "title": "MQTT message bindings object", + "description": "This object contains information about the message representation in MQTT.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "payloadFormatIndicator": { + "type": "integer", + "enum": [0, 1], + "description": "1 indicates that the payload is UTF-8 encoded character data. 0 indicates that the payload format is unspecified.", + "default": 0 + }, + "correlationData": { + "oneOf": [ + { + "$ref": "#/definitions/schema" + }, + { + "$ref": "#/definitions/Reference" + } + ], + "description": "Correlation Data is used by the sender of the request message to identify which request the response message is for when it is received." + }, + "contentType": { + "type": "string", + "description": "String describing the content type of the message payload. This should not conflict with the contentType field of the associated AsyncAPI Message object." + }, + "responseTopic": { + "oneOf": [ + { + "type": "string", + "format": "uri-template", + "minLength": 1 + }, + { + "$ref": "#/definitions/schema" + }, + { + "$ref": "#/definitions/Reference" + } + ], + "description": "The topic (channel URI) to be used for a response message." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.2.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "bindingVersion": "0.2.0" + }, + { + "contentType": "application/json", + "correlationData": { + "type": "string", + "format": "uuid" + }, + "responseTopic": "application/responses", + "bindingVersion": "0.2.0" + } + ] + }, + "correlationId": { + "description": "An object that specifies an identifier at design time that can used for message tracing and correlation.", + "type": "object", + "required": ["location"], + "properties": { + "description": { + "description": "A optional description of the correlation ID. GitHub Flavored Markdown is allowed.", + "type": "string" + }, + "location": { + "description": "A runtime expression that specifies the location of the correlation ID", + "type": "string", + "pattern": "^\\$message\\.(header|payload)#(\\/(([^\\/~])|(~[01]))*)*" + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "description": "Default Correlation ID", + "location": "$message.header#/correlationId" + } + ] + }, + "anySchema": { + "description": "An object representing either a schema or a multiFormatSchema based on the existence of the 'schema' property. If the property 'schema' is present, use the multi-format schema. Use the default AsyncAPI Schema otherwise.", + "if": { + "required": ["schema"] + }, + "then": { + "$ref": "#/definitions/multiFormatSchema" + }, + "else": { + "$ref": "#/definitions/schema" + } + }, + "multiFormatSchema": { + "description": "The Multi Format Schema Object represents a schema definition. It differs from the Schema Object in that it supports multiple schema formats or languages (e.g., JSON Schema, Avro, etc.).", + "type": "object", + "if": { + "not": { + "type": "object" + } + }, + "then": { + "$ref": "#/definitions/schema" + }, + "else": { + "allOf": [ + { + "if": { + "not": { + "description": "If no schemaFormat has been defined, default to schema or reference", + "required": ["schemaFormat"] + } + }, + "then": { + "properties": { + "schema": { + "$ref": "#/definitions/schema" + } + } + } + }, + { + "if": { + "description": "If schemaFormat has been defined check if it's one of the AsyncAPI Schema Object formats", + "required": ["schemaFormat"], + "properties": { + "schemaFormat": { + "enum": [ + "application/vnd.aai.asyncapi;version=2.0.0", + "application/vnd.aai.asyncapi+json;version=2.0.0", + "application/vnd.aai.asyncapi+yaml;version=2.0.0", + "application/vnd.aai.asyncapi;version=2.1.0", + "application/vnd.aai.asyncapi+json;version=2.1.0", + "application/vnd.aai.asyncapi+yaml;version=2.1.0", + "application/vnd.aai.asyncapi;version=2.2.0", + "application/vnd.aai.asyncapi+json;version=2.2.0", + "application/vnd.aai.asyncapi+yaml;version=2.2.0", + "application/vnd.aai.asyncapi;version=2.3.0", + "application/vnd.aai.asyncapi+json;version=2.3.0", + "application/vnd.aai.asyncapi+yaml;version=2.3.0", + "application/vnd.aai.asyncapi;version=2.4.0", + "application/vnd.aai.asyncapi+json;version=2.4.0", + "application/vnd.aai.asyncapi+yaml;version=2.4.0", + "application/vnd.aai.asyncapi;version=2.5.0", + "application/vnd.aai.asyncapi+json;version=2.5.0", + "application/vnd.aai.asyncapi+yaml;version=2.5.0", + "application/vnd.aai.asyncapi;version=2.6.0", + "application/vnd.aai.asyncapi+json;version=2.6.0", + "application/vnd.aai.asyncapi+yaml;version=2.6.0", + "application/vnd.aai.asyncapi;version=3.0.0", + "application/vnd.aai.asyncapi+json;version=3.0.0", + "application/vnd.aai.asyncapi+yaml;version=3.0.0", + "application/vnd.aai.asyncapi;version=3.1.0", + "application/vnd.aai.asyncapi+json;version=3.1.0", + "application/vnd.aai.asyncapi+yaml;version=3.1.0" + ] + } + } + }, + "then": { + "properties": { + "schema": { + "$ref": "#/definitions/schema" + } + } + } + }, + { + "if": { + "required": ["schemaFormat"], + "properties": { + "schemaFormat": { + "enum": [ + "application/schema+json;version=draft-07", + "application/schema+yaml;version=draft-07" + ] + } + } + }, + "then": { + "properties": { + "schema": { + "$ref": "#/definitions/json-schema-draft-07-schema" + } + } + } + }, + { + "if": { + "required": ["schemaFormat"], + "properties": { + "schemaFormat": { + "enum": [ + "application/vnd.oai.openapi;version=3.0.0", + "application/vnd.oai.openapi+json;version=3.0.0", + "application/vnd.oai.openapi+yaml;version=3.0.0" + ] + } + } + }, + "then": { + "properties": { + "schema": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/openapiSchema_3_0" + } + ] + } + } + } + }, + { + "if": { + "required": ["schemaFormat"], + "properties": { + "schemaFormat": { + "enum": [ + "application/vnd.apache.avro;version=1.9.0", + "application/vnd.apache.avro+json;version=1.9.0", + "application/vnd.apache.avro+yaml;version=1.9.0" + ] + } + } + }, + "then": { + "properties": { + "schema": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/avroSchema_v1" + } + ] + } + } + } + } + ], + "properties": { + "schemaFormat": { + "description": "A string containing the name of the schema format that is used to define the information. If schemaFormat is missing, it MUST default to application/vnd.aai.asyncapi+json;version={{asyncapi}} where {{asyncapi}} matches the AsyncAPI Version String. In such a case, this would make the Multi Format Schema Object equivalent to the Schema Object. When using Reference Object within the schema, the schemaFormat of the resource being referenced MUST match the schemaFormat of the schema that contains the initial reference. For example, if you reference Avro schema, then schemaFormat of referencing resource and the resource being reference MUST match.", + "anyOf": [ + { + "type": "string" + }, + { + "description": "All the schema formats tooling MUST support", + "enum": [ + "application/schema+json;version=draft-07", + "application/schema+yaml;version=draft-07", + "application/vnd.aai.asyncapi;version=3.0.0", + "application/vnd.aai.asyncapi+json;version=3.0.0", + "application/vnd.aai.asyncapi+yaml;version=3.0.0", + "application/vnd.aai.asyncapi;version=3.1.0", + "application/vnd.aai.asyncapi+json;version=3.1.0", + "application/vnd.aai.asyncapi+yaml;version=3.1.0" + ] + }, + { + "description": "All the schema formats tools are RECOMMENDED to support", + "enum": [ + "application/vnd.oai.openapi;version=3.0.0", + "application/vnd.oai.openapi+json;version=3.0.0", + "application/vnd.oai.openapi+yaml;version=3.0.0", + "application/vnd.apache.avro;version=1.9.0", + "application/vnd.apache.avro+json;version=1.9.0", + "application/vnd.apache.avro+yaml;version=1.9.0", + "application/raml+yaml;version=1.0" + ] + } + ] + } + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + } + }, + "openapiSchema_3_0": { + "type": "object", + "definitions": { + "ExternalDocumentation": { + "type": "object", + "required": ["url"], + "properties": { + "description": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri-reference" + } + }, + "patternProperties": { + "^x-": {} + }, + "additionalProperties": false + }, + "Discriminator": { + "type": "object", + "required": ["propertyName"], + "properties": { + "propertyName": { + "type": "string" + }, + "mapping": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + }, + "Reference": { + "type": "object", + "required": ["$ref"], + "patternProperties": { + "^\\$ref$": { + "type": "string", + "format": "uri-reference" + } + } + }, + "XML": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "namespace": { + "type": "string", + "format": "uri" + }, + "prefix": { + "type": "string" + }, + "attribute": { + "type": "boolean", + "default": false + }, + "wrapped": { + "type": "boolean", + "default": false + } + }, + "patternProperties": { + "^x-": {} + }, + "additionalProperties": false + } + }, + "properties": { + "title": { + "type": "string" + }, + "multipleOf": { + "type": "number", + "exclusiveMinimum": 0 + }, + "maximum": { + "type": "number" + }, + "exclusiveMaximum": { + "type": "boolean", + "default": false + }, + "minimum": { + "type": "number" + }, + "exclusiveMinimum": { + "type": "boolean", + "default": false + }, + "maxLength": { + "type": "integer", + "minimum": 0 + }, + "minLength": { + "type": "integer", + "minimum": 0, + "default": 0 + }, + "pattern": { + "type": "string", + "format": "regex" + }, + "maxItems": { + "type": "integer", + "minimum": 0 + }, + "minItems": { + "type": "integer", + "minimum": 0, + "default": 0 + }, + "uniqueItems": { + "type": "boolean", + "default": false + }, + "maxProperties": { + "type": "integer", + "minimum": 0 + }, + "minProperties": { + "type": "integer", + "minimum": 0, + "default": 0 + }, + "required": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "uniqueItems": true + }, + "enum": { + "type": "array", + "items": true, + "minItems": 1, + "uniqueItems": false + }, + "type": { + "type": "string", + "enum": ["array", "boolean", "integer", "number", "object", "string"] + }, + "not": { + "oneOf": [ + { + "$ref": "#/definitions/openapiSchema_3_0" + }, + { + "$ref": "#/definitions/openapiSchema_3_0/definitions/Reference" + } + ] + }, + "allOf": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/definitions/openapiSchema_3_0" + }, + { + "$ref": "#/definitions/openapiSchema_3_0/definitions/Reference" + } + ] + } + }, + "oneOf": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/definitions/openapiSchema_3_0" + }, + { + "$ref": "#/definitions/openapiSchema_3_0/definitions/Reference" + } + ] + } + }, + "anyOf": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/definitions/openapiSchema_3_0" + }, + { + "$ref": "#/definitions/openapiSchema_3_0/definitions/Reference" + } + ] + } + }, + "items": { + "oneOf": [ + { + "$ref": "#/definitions/openapiSchema_3_0" + }, + { + "$ref": "#/definitions/openapiSchema_3_0/definitions/Reference" + } + ] + }, + "properties": { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "$ref": "#/definitions/openapiSchema_3_0" + }, + { + "$ref": "#/definitions/openapiSchema_3_0/definitions/Reference" + } + ] + } + }, + "additionalProperties": { + "oneOf": [ + { + "$ref": "#/definitions/openapiSchema_3_0" + }, + { + "$ref": "#/definitions/openapiSchema_3_0/definitions/Reference" + }, + { + "type": "boolean" + } + ], + "default": true + }, + "description": { + "type": "string" + }, + "format": { + "type": "string" + }, + "default": true, + "nullable": { + "type": "boolean", + "default": false + }, + "discriminator": { + "$ref": "#/definitions/openapiSchema_3_0/definitions/Discriminator" + }, + "readOnly": { + "type": "boolean", + "default": false + }, + "writeOnly": { + "type": "boolean", + "default": false + }, + "example": true, + "externalDocs": { + "$ref": "#/definitions/openapiSchema_3_0/definitions/ExternalDocumentation" + }, + "deprecated": { + "type": "boolean", + "default": false + }, + "xml": { + "$ref": "#/definitions/openapiSchema_3_0/definitions/XML" + } + }, + "patternProperties": { + "^x-": true + }, + "additionalProperties": false + }, + "tag": { + "description": "Allows adding metadata to a single tag.", + "type": "object", + "required": ["name"], + "properties": { + "description": { + "description": "A short description for the tag. CommonMark syntax can be used for rich text representation.", + "type": "string" + }, + "externalDocs": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/externalDocs" + } + ] + }, + "name": { + "description": "The name of the tag.", + "type": "string" + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "name": "user", + "description": "User-related messages" + } + ] + }, + "messageTrait": { + "description": "Describes a trait that MAY be applied to a Message Object. This object MAY contain any property from the Message Object, except payload and traits.", + "type": "object", + "properties": { + "title": { + "description": "A human-friendly title for the message.", + "type": "string" + }, + "description": { + "description": "A longer description of the message. CommonMark is allowed.", + "type": "string" + }, + "examples": { + "description": "List of examples.", + "type": "array", + "items": { + "$ref": "#/definitions/messageExampleObject" + } + }, + "deprecated": { + "default": false, + "type": "boolean" + }, + "bindings": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/messageBindingsObject" + } + ] + }, + "contentType": { + "description": "The content type to use when encoding/decoding a message's payload. The value MUST be a specific media type (e.g. application/json). When omitted, the value MUST be the one specified on the defaultContentType field.", + "type": "string" + }, + "correlationId": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/correlationId" + } + ] + }, + "externalDocs": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/externalDocs" + } + ] + }, + "headers": { + "$ref": "#/definitions/anySchema" + }, + "name": { + "description": "Name of the message.", + "type": "string" + }, + "summary": { + "description": "A brief summary of the message.", + "type": "string" + }, + "tags": { + "type": "array", + "uniqueItems": true, + "items": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/tag" + } + ] + } + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "contentType": "application/json" + } + ] + }, + "parameters": { + "description": "JSON objects describing re-usable channel parameters.", + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/parameter" + } + ] + }, + "examples": [ + { + "address": "user/{userId}/signedup", + "parameters": { + "userId": { + "description": "Id of the user." + } + } + } + ] + }, + "parameter": { + "description": "Describes a parameter included in a channel address.", + "properties": { + "description": { + "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed.", + "type": "string" + }, + "examples": { + "description": "An array of examples of the parameter value.", + "type": "array", + "items": { + "type": "string" + } + }, + "default": { + "description": "The default value to use for substitution, and to send, if an alternate value is not supplied.", + "type": "string" + }, + "enum": { + "description": "An enumeration of string values to be used if the substitution options are from a limited set.", + "type": "array", + "items": { + "type": "string" + } + }, + "location": { + "description": "A runtime expression that specifies the location of the parameter value", + "type": "string", + "pattern": "^\\$message\\.(header|payload)#(\\/(([^\\/~])|(~[01]))*)*" + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "address": "user/{userId}/signedup", + "parameters": { + "userId": { + "description": "Id of the user.", + "location": "$message.payload#/user/id" + } + } + } + ] + }, + "components": { + "description": "An object to hold a set of reusable objects for different aspects of the AsyncAPI specification. All objects defined within the components object will have no effect on the API unless they are explicitly referenced from properties outside the components object.", + "type": "object", + "properties": { + "channelBindings": { + "description": "An object to hold reusable Channel Bindings Objects.", + "type": "object", + "patternProperties": { + "^[\\w\\d\\.\\-_]+$": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/channelBindingsObject" + } + ] + } + } + }, + "channels": { + "description": "An object to hold reusable Channel Objects.", + "type": "object", + "patternProperties": { + "^[\\w\\d\\.\\-_]+$": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/channel" + } + ] + } + } + }, + "correlationIds": { + "description": "An object to hold reusable Correlation ID Objects.", + "type": "object", + "patternProperties": { + "^[\\w\\d\\.\\-_]+$": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/correlationId" + } + ] + } + } + }, + "externalDocs": { + "description": "An object to hold reusable External Documentation Objects.", + "type": "object", + "patternProperties": { + "^[\\w\\d\\.\\-_]+$": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/externalDocs" + } + ] + } + } + }, + "messageBindings": { + "description": "An object to hold reusable Message Bindings Objects.", + "type": "object", + "patternProperties": { + "^[\\w\\d\\.\\-_]+$": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/messageBindingsObject" + } + ] + } + } + }, + "messageTraits": { + "description": "An object to hold reusable Message Trait Objects.", + "type": "object", + "patternProperties": { + "^[\\w\\d\\.\\-_]+$": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/messageTrait" + } + ] + } + } + }, + "messages": { + "description": "An object to hold reusable Message Objects.", + "type": "object", + "patternProperties": { + "^[\\w\\d\\.\\-_]+$": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/messageObject" + } + ] + } + } + }, + "operationBindings": { + "description": "An object to hold reusable Operation Bindings Objects.", + "type": "object", + "patternProperties": { + "^[\\w\\d\\.\\-_]+$": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/operationBindingsObject" + } + ] + } + } + }, + "operationTraits": { + "description": "An object to hold reusable Operation Trait Objects.", + "type": "object", + "patternProperties": { + "^[\\w\\d\\.\\-_]+$": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/operationTrait" + } + ] + } + } + }, + "operations": { + "type": "object", + "patternProperties": { + "^[\\w\\d\\.\\-_]+$": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/operation" + } + ] + } + } + }, + "parameters": { + "description": "An object to hold reusable Parameter Objects.", + "type": "object", + "patternProperties": { + "^[\\w\\d\\.\\-_]+$": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/parameter" + } + ] + } + } + }, + "replies": { + "description": "An object to hold reusable Operation Reply Objects.", + "type": "object", + "patternProperties": { + "^[\\w\\d\\.\\-_]+$": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/operationReply" + } + ] + } + } + }, + "replyAddresses": { + "description": "An object to hold reusable Operation Reply Address Objects.", + "type": "object", + "patternProperties": { + "^[\\w\\d\\.\\-_]+$": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/operationReplyAddress" + } + ] + } + } + }, + "schemas": { + "description": "An object to hold reusable Schema Object. If this is a Schema Object, then the schemaFormat will be assumed to be 'application/vnd.aai.asyncapi+json;version=asyncapi' where the version is equal to the AsyncAPI Version String.", + "type": "object", + "patternProperties": { + "^[\\w\\d\\.\\-_]+$": { + "$ref": "#/definitions/anySchema" + } + } + }, + "securitySchemes": { + "description": "An object to hold reusable Security Scheme Objects.", + "type": "object", + "patternProperties": { + "^[\\w\\d\\.\\-_]+$": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/SecurityScheme" + } + ] + } + } + }, + "serverBindings": { + "description": "An object to hold reusable Server Bindings Objects.", + "type": "object", + "patternProperties": { + "^[\\w\\d\\.\\-_]+$": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/serverBindingsObject" + } + ] + } + } + }, + "serverVariables": { + "description": "An object to hold reusable Server Variable Objects.", + "type": "object", + "patternProperties": { + "^[\\w\\d\\.\\-_]+$": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/serverVariable" + } + ] + } + } + }, + "servers": { + "description": "An object to hold reusable Server Objects.", + "type": "object", + "patternProperties": { + "^[\\w\\d\\.\\-_]+$": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/server" + } + ] + } + } + }, + "tags": { + "description": "An object to hold reusable Tag Objects.", + "type": "object", + "patternProperties": { + "^[\\w\\d\\.\\-_]+$": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/tag" + } + ] + } + } + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "components": { + "schemas": { + "Category": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + } + }, + "Tag": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + } + }, + "AvroExample": { + "schemaFormat": "application/vnd.apache.avro+json;version=1.9.0", + "schema": { + "$ref": "path/to/user-create.avsc#/UserCreate" + } + } + }, + "servers": { + "development": { + "host": "{stage}.in.mycompany.com:{port}", + "description": "RabbitMQ broker", + "protocol": "amqp", + "protocolVersion": "0-9-1", + "variables": { + "stage": { + "$ref": "#/components/serverVariables/stage" + }, + "port": { + "$ref": "#/components/serverVariables/port" + } + } + } + }, + "serverVariables": { + "stage": { + "default": "demo", + "description": "This value is assigned by the service provider, in this example `mycompany.com`" + }, + "port": { + "enum": ["5671", "5672"], + "default": "5672" + } + }, + "channels": { + "user/signedup": { + "subscribe": { + "message": { + "$ref": "#/components/messages/userSignUp" + } + } + } + }, + "messages": { + "userSignUp": { + "summary": "Action to sign a user up.", + "description": "Multiline description of what this action does.\nHere you have another line.\n", + "tags": [ + { + "name": "user" + }, + { + "name": "signup" + } + ], + "headers": { + "type": "object", + "properties": { + "applicationInstanceId": { + "description": "Unique identifier for a given instance of the publishing application", + "type": "string" + } + } + }, + "payload": { + "type": "object", + "properties": { + "user": { + "$ref": "#/components/schemas/userCreate" + }, + "signup": { + "$ref": "#/components/schemas/signup" + } + } + } + } + }, + "parameters": { + "userId": { + "description": "Id of the user." + } + }, + "correlationIds": { + "default": { + "description": "Default Correlation ID", + "location": "$message.header#/correlationId" + } + }, + "messageTraits": { + "commonHeaders": { + "headers": { + "type": "object", + "properties": { + "my-app-header": { + "type": "integer", + "minimum": 0, + "maximum": 100 + } + } + } + } + } + } + } + ] + }, + "operationBindingsObject": { + "description": "Map describing protocol-specific definitions for an operation.", + "type": "object", + "properties": { + "amqp": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-amqp-0.3.0-operation" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.3.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-amqp-0.3.0-operation" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.3.0"] + } + } + }, + "amqp1": {}, + "anypointmq": {}, + "googlepubsub": {}, + "http": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-http-0.3.0-operation" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.2.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-http-0.2.0-operation" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.3.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-http-0.3.0-operation" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.2.0", "0.3.0"] + } + } + }, + "ibmmq": {}, + "jms": {}, + "kafka": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-kafka-0.5.0-operation" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.5.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-kafka-0.5.0-operation" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.4.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-kafka-0.4.0-operation" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.3.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-kafka-0.3.0-operation" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.5.0", "0.4.0", "0.3.0"] + } + } + }, + "mqtt": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-mqtt-0.2.0-operation" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.2.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-mqtt-0.2.0-operation" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.2.0"] + } + } + }, + "nats": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-nats-0.1.0-operation" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.1.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-nats-0.1.0-operation" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.1.0"] + } + } + }, + "redis": {}, + "ros2": { + "properties": { + "bindingVersion": { + "enum": ["0.1.0"] + } + }, + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-ros2-0.1.0-operation" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.1.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-ros2-0.1.0-operation" + } + } + ] + }, + "sns": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-sns-0.1.0-operation" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.1.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-sns-0.1.0-operation" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.1.0"] + } + } + }, + "solace": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-solace-0.4.0-operation" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.4.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-solace-0.4.0-operation" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.3.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-solace-0.3.0-operation" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.2.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-solace-0.2.0-operation" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.4.0", "0.3.0", "0.2.0"] + } + } + }, + "sqs": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-sqs-0.2.0-operation" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.2.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-sqs-0.2.0-operation" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.2.0"] + } + } + }, + "stomp": {}, + "ws": {} + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false + }, + "bindings-amqp-0.3.0-operation": { + "title": "AMQP operation bindings object", + "description": "This object contains information about the operation representation in AMQP.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "expiration": { + "type": "integer", + "minimum": 0, + "description": "TTL (Time-To-Live) for the message. It MUST be greater than or equal to zero." + }, + "userId": { + "type": "string", + "description": "Identifies the user who has sent the message." + }, + "cc": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The routing keys the message should be routed to at the time of publishing." + }, + "priority": { + "type": "integer", + "description": "A priority for the message." + }, + "deliveryMode": { + "type": "integer", + "enum": [1, 2], + "description": "Delivery mode of the message. Its value MUST be either 1 (transient) or 2 (persistent)." + }, + "mandatory": { + "type": "boolean", + "description": "Whether the message is mandatory or not." + }, + "bcc": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Like cc but consumers will not receive this information." + }, + "timestamp": { + "type": "boolean", + "description": "Whether the message should include a timestamp or not." + }, + "ack": { + "type": "boolean", + "description": "Whether the consumer should ack the message or not." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.3.0"], + "description": "The version of this binding. If omitted, \"latest\" MUST be assumed." + } + }, + "examples": [ + { + "expiration": 100000, + "userId": "guest", + "cc": ["user.logs"], + "priority": 10, + "deliveryMode": 2, + "mandatory": false, + "bcc": ["external.audit"], + "timestamp": true, + "ack": false, + "bindingVersion": "0.3.0" + } + ] + }, + "bindings-http-0.3.0-operation": { + "title": "HTTP operation bindings object", + "description": "This object contains information about the operation representation in HTTP.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "method": { + "type": "string", + "enum": [ + "GET", + "PUT", + "POST", + "PATCH", + "DELETE", + "HEAD", + "OPTIONS", + "CONNECT", + "TRACE" + ], + "description": "When 'type' is 'request', this is the HTTP method, otherwise it MUST be ignored. Its value MUST be one of 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS', 'CONNECT', and 'TRACE'." + }, + "query": { + "$ref": "#/definitions/schema", + "description": "A Schema object containing the definitions for each query parameter. This schema MUST be of type 'object' and have a properties key." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.3.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "query": { + "type": "object", + "required": ["companyId"], + "properties": { + "companyId": { + "type": "number", + "minimum": 1, + "description": "The Id of the company." + } + }, + "additionalProperties": false + }, + "bindingVersion": "0.3.0" + }, + { + "method": "GET", + "query": { + "type": "object", + "required": ["companyId"], + "properties": { + "companyId": { + "type": "number", + "minimum": 1, + "description": "The Id of the company." + } + }, + "additionalProperties": false + }, + "bindingVersion": "0.3.0" + } + ] + }, + "bindings-http-0.2.0-operation": { + "title": "HTTP operation bindings object", + "description": "This object contains information about the operation representation in HTTP.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "method": { + "type": "string", + "enum": [ + "GET", + "PUT", + "POST", + "PATCH", + "DELETE", + "HEAD", + "OPTIONS", + "CONNECT", + "TRACE" + ], + "description": "When 'type' is 'request', this is the HTTP method, otherwise it MUST be ignored. Its value MUST be one of 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS', 'CONNECT', and 'TRACE'." + }, + "query": { + "$ref": "#/definitions/schema", + "description": "A Schema object containing the definitions for each query parameter. This schema MUST be of type 'object' and have a properties key." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.2.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "query": { + "type": "object", + "required": ["companyId"], + "properties": { + "companyId": { + "type": "number", + "minimum": 1, + "description": "The Id of the company." + } + }, + "additionalProperties": false + }, + "bindingVersion": "0.2.0" + }, + { + "method": "GET", + "query": { + "type": "object", + "required": ["companyId"], + "properties": { + "companyId": { + "type": "number", + "minimum": 1, + "description": "The Id of the company." + } + }, + "additionalProperties": false + }, + "bindingVersion": "0.2.0" + } + ] + }, + "bindings-kafka-0.5.0-operation": { + "title": "Operation Schema", + "description": "This object contains information about the operation representation in Kafka.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "groupId": { + "$ref": "#/definitions/schema", + "description": "Id of the consumer group." + }, + "clientId": { + "$ref": "#/definitions/schema", + "description": "Id of the consumer inside a consumer group." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.5.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "groupId": { + "type": "string", + "enum": ["myGroupId"] + }, + "clientId": { + "type": "string", + "enum": ["myClientId"] + }, + "bindingVersion": "0.5.0" + } + ] + }, + "bindings-kafka-0.4.0-operation": { + "title": "Operation Schema", + "description": "This object contains information about the operation representation in Kafka.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "groupId": { + "$ref": "#/definitions/schema", + "description": "Id of the consumer group." + }, + "clientId": { + "$ref": "#/definitions/schema", + "description": "Id of the consumer inside a consumer group." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.4.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "groupId": { + "type": "string", + "enum": ["myGroupId"] + }, + "clientId": { + "type": "string", + "enum": ["myClientId"] + }, + "bindingVersion": "0.4.0" + } + ] + }, + "bindings-kafka-0.3.0-operation": { + "title": "Operation Schema", + "description": "This object contains information about the operation representation in Kafka.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "groupId": { + "$ref": "#/definitions/schema", + "description": "Id of the consumer group." + }, + "clientId": { + "$ref": "#/definitions/schema", + "description": "Id of the consumer inside a consumer group." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.3.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "groupId": { + "type": "string", + "enum": ["myGroupId"] + }, + "clientId": { + "type": "string", + "enum": ["myClientId"] + }, + "bindingVersion": "0.3.0" + } + ] + }, + "bindings-mqtt-0.2.0-operation": { + "title": "MQTT operation bindings object", + "description": "This object contains information about the operation representation in MQTT.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "qos": { + "type": "integer", + "enum": [0, 1, 2], + "description": "Defines the Quality of Service (QoS) levels for the message flow between client and server. Its value MUST be either 0 (At most once delivery), 1 (At least once delivery), or 2 (Exactly once delivery)." + }, + "retain": { + "type": "boolean", + "description": "Whether the broker should retain the message or not." + }, + "messageExpiryInterval": { + "oneOf": [ + { + "type": "integer", + "minimum": 0, + "maximum": 4294967295 + }, + { + "$ref": "#/definitions/schema" + }, + { + "$ref": "#/definitions/Reference" + } + ], + "description": "Lifetime of the message in seconds" + }, + "bindingVersion": { + "type": "string", + "enum": ["0.2.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "qos": 2, + "retain": true, + "messageExpiryInterval": 60, + "bindingVersion": "0.2.0" + } + ] + }, + "bindings-nats-0.1.0-operation": { + "title": "NATS operation bindings object", + "description": "This object contains information about the operation representation in NATS.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "queue": { + "type": "string", + "description": "Defines the name of the queue to use. It MUST NOT exceed 255 characters.", + "maxLength": 255 + }, + "bindingVersion": { + "type": "string", + "enum": ["0.1.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "queue": "MyCustomQueue", + "bindingVersion": "0.1.0" + } + ] + }, + "bindings-ros2-0.1.0-operation": { + "description": "This object contains information about the operation representation in ROS 2.", + "examples": [ + { + "node": "/turtlesim", + "qosPolicies": { + "deadline": "-1", + "durability": "volatile", + "history": "unknown", + "leaseDuration": "-1", + "lifespan": "-1", + "liveliness": "automatic", + "reliability": "reliable" + }, + "role": "subscriber" + } + ], + "type": "object", + "required": ["role", "node"], + "properties": { + "bindingVersion": { + "description": "The version of this binding. If omitted, 'latest' MUST be assumed.", + "type": "string", + "enum": ["0.1.0"] + }, + "node": { + "description": "The name of the ROS 2 node that implements this operation.", + "type": "string" + }, + "qosPolicies": { + "type": "object", + "properties": { + "deadline": { + "description": "The expected maximum amount of time between subsequent messages being published to a topic. -1 means infinite.", + "type": "integer" + }, + "durability": { + "description": "Persistence specification that determines message availability for late-joining subscribers", + "type": "string", + "enum": ["transient_local", "volatile"] + }, + "history": { + "description": "Policy parameter that defines the maximum number of samples maintained in the middleware queue", + "type": "string", + "enum": ["keep_last", "keep_all", "unknown"] + }, + "leaseDuration": { + "description": "The maximum period of time a publisher has to indicate that it is alive before the system considers it to have lost liveliness. -1 means infinite.", + "type": "integer" + }, + "lifespan": { + "description": "The maximum amount of time between the publishing and the reception of a message without the message being considered stale or expired. -1 means infinite.", + "type": "integer" + }, + "liveliness": { + "description": "Defines the mechanism by which the system monitors and determines the operational status of communication entities within the network.", + "type": "string", + "enum": ["automatic", "manual"] + }, + "reliability": { + "description": "Specifies the communication guarantee model that determines whether message delivery confirmation between publisher and subscriber is required.", + "type": "string", + "enum": ["best_effort", "realiable"] + } + } + }, + "role": { + "description": "Specifies the ROS 2 type of the node for this operation.", + "type": "string", + "enum": [ + "publisher", + "action_client", + "service_client", + "subscriber", + "action_server", + "service_server" + ] + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false + }, + "bindings-sns-0.1.0-operation": { + "title": "Operation Schema", + "description": "This object contains information about the operation representation in SNS.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "topic": { + "$ref": "#/definitions/bindings-sns-0.1.0-operation/definitions/identifier", + "description": "Often we can assume that the SNS Topic is the channel name-we provide this field in case the you need to supply the ARN, or the Topic name is not the channel name in the AsyncAPI document." + }, + "consumers": { + "type": "array", + "description": "The protocols that listen to this topic and their endpoints.", + "items": { + "$ref": "#/definitions/bindings-sns-0.1.0-operation/definitions/consumer" + }, + "minItems": 1 + }, + "deliveryPolicy": { + "$ref": "#/definitions/bindings-sns-0.1.0-operation/definitions/deliveryPolicy", + "description": "Policy for retries to HTTP. The field is the default for HTTP receivers of the SNS Topic which may be overridden by a specific consumer." + }, + "bindingVersion": { + "type": "string", + "description": "The version of this binding.", + "default": "latest" + } + }, + "required": ["consumers"], + "definitions": { + "identifier": { + "type": "object", + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "url": { + "type": "string", + "description": "The endpoint is a URL." + }, + "email": { + "type": "string", + "description": "The endpoint is an email address." + }, + "phone": { + "type": "string", + "description": "The endpoint is a phone number." + }, + "arn": { + "type": "string", + "description": "The target is an ARN. For example, for SQS, the identifier may be an ARN, which will be of the form: arn:aws:sqs:{region}:{account-id}:{queueName}" + }, + "name": { + "type": "string", + "description": "The endpoint is identified by a name, which corresponds to an identifying field called 'name' of a binding for that protocol on this publish Operation Object. For example, if the protocol is 'sqs' then the name refers to the name field sqs binding. We don't use $ref because we are referring, not including." + } + } + }, + "consumer": { + "type": "object", + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "protocol": { + "description": "The protocol that this endpoint receives messages by.", + "type": "string", + "enum": [ + "http", + "https", + "email", + "email-json", + "sms", + "sqs", + "application", + "lambda", + "firehose" + ] + }, + "endpoint": { + "description": "The endpoint messages are delivered to.", + "$ref": "#/definitions/bindings-sns-0.1.0-operation/definitions/identifier" + }, + "filterPolicy": { + "type": "object", + "description": "Only receive a subset of messages from the channel, determined by this policy. Depending on the FilterPolicyScope, a map of either a message attribute or message body to an array of possible matches. The match may be a simple string for an exact match, but it may also be an object that represents a constraint and values for that constraint.", + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": { + "oneOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + }, + { + "type": "object" + } + ] + } + }, + "filterPolicyScope": { + "type": "string", + "description": "Determines whether the FilterPolicy applies to MessageAttributes or MessageBody.", + "enum": ["MessageAttributes", "MessageBody"], + "default": "MessageAttributes" + }, + "rawMessageDelivery": { + "type": "boolean", + "description": "If true AWS SNS attributes are removed from the body, and for SQS, SNS message attributes are copied to SQS message attributes. If false the SNS attributes are included in the body." + }, + "redrivePolicy": { + "$ref": "#/definitions/bindings-sns-0.1.0-operation/definitions/redrivePolicy" + }, + "deliveryPolicy": { + "$ref": "#/definitions/bindings-sns-0.1.0-operation/definitions/deliveryPolicy", + "description": "Policy for retries to HTTP. The parameter is for that SNS Subscription and overrides any policy on the SNS Topic." + }, + "displayName": { + "type": "string", + "description": "The display name to use with an SNS subscription" + } + }, + "required": ["protocol", "endpoint", "rawMessageDelivery"] + }, + "deliveryPolicy": { + "type": "object", + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "minDelayTarget": { + "type": "integer", + "description": "The minimum delay for a retry in seconds." + }, + "maxDelayTarget": { + "type": "integer", + "description": "The maximum delay for a retry in seconds." + }, + "numRetries": { + "type": "integer", + "description": "The total number of retries, including immediate, pre-backoff, backoff, and post-backoff retries." + }, + "numNoDelayRetries": { + "type": "integer", + "description": "The number of immediate retries (with no delay)." + }, + "numMinDelayRetries": { + "type": "integer", + "description": "The number of immediate retries (with delay)." + }, + "numMaxDelayRetries": { + "type": "integer", + "description": "The number of post-backoff phase retries, with the maximum delay between retries." + }, + "backoffFunction": { + "type": "string", + "description": "The algorithm for backoff between retries.", + "enum": ["arithmetic", "exponential", "geometric", "linear"] + }, + "maxReceivesPerSecond": { + "type": "integer", + "description": "The maximum number of deliveries per second, per subscription." + } + } + }, + "redrivePolicy": { + "type": "object", + "description": "Prevent poison pill messages by moving un-processable messages to an SQS dead letter queue.", + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "deadLetterQueue": { + "$ref": "#/definitions/bindings-sns-0.1.0-operation/definitions/identifier", + "description": "The SQS queue to use as a dead letter queue (DLQ)." + }, + "maxReceiveCount": { + "type": "integer", + "description": "The number of times a message is delivered to the source queue before being moved to the dead-letter queue.", + "default": 10 + } + }, + "required": ["deadLetterQueue"] + } + }, + "examples": [ + { + "topic": { + "name": "someTopic" + }, + "consumers": [ + { + "protocol": "sqs", + "endpoint": { + "name": "someQueue" + }, + "filterPolicy": { + "store": ["asyncapi_corp"], + "event": [ + { + "anything-but": "order_cancelled" + } + ], + "customer_interests": ["rugby", "football", "baseball"] + }, + "filterPolicyScope": "MessageAttributes", + "rawMessageDelivery": false, + "redrivePolicy": { + "deadLetterQueue": { + "arn": "arn:aws:SQS:eu-west-1:0000000:123456789" + }, + "maxReceiveCount": 25 + }, + "deliveryPolicy": { + "minDelayTarget": 10, + "maxDelayTarget": 100, + "numRetries": 5, + "numNoDelayRetries": 2, + "numMinDelayRetries": 3, + "numMaxDelayRetries": 5, + "backoffFunction": "linear", + "maxReceivesPerSecond": 2 + } + } + ] + } + ] + }, + "bindings-solace-0.4.0-operation": { + "title": "Solace operation bindings object", + "description": "This object contains information about the operation representation in Solace.", + "type": "object", + "additionalProperties": false, + "properties": { + "bindingVersion": { + "type": "string", + "enum": ["0.4.0"], + "description": "The version of this binding. If omitted, \"latest\" MUST be assumed." + }, + "destinations": { + "description": "The list of Solace destinations referenced in the operation.", + "type": "array", + "items": { + "type": "object", + "properties": { + "deliveryMode": { + "type": "string", + "enum": ["direct", "persistent"] + } + }, + "oneOf": [ + { + "properties": { + "destinationType": { + "type": "string", + "const": "queue", + "description": "If the type is queue, then the subscriber can bind to the queue. The queue subscribes to the given topicSubscriptions. If no topicSubscriptions are provied, the queue will subscribe to the topic as represented by the channel name." + }, + "queue": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the queue" + }, + "topicSubscriptions": { + "type": "array", + "description": "The list of topics that the queue subscribes to.", + "items": { + "type": "string" + } + }, + "accessType": { + "type": "string", + "enum": ["exclusive", "nonexclusive"] + }, + "maxTtl": { + "type": "string", + "description": "The maximum TTL to apply to messages to be spooled." + }, + "maxMsgSpoolUsage": { + "type": "string", + "description": "The maximum amount of message spool that the given queue may use" + } + } + } + } + }, + { + "properties": { + "destinationType": { + "type": "string", + "const": "topic", + "description": "If the type is topic, then the subscriber subscribes to the given topicSubscriptions. If no topicSubscriptions are provided, the client will subscribe to the topic as represented by the channel name." + }, + "topicSubscriptions": { + "type": "array", + "description": "The list of topics that the client subscribes to.", + "items": { + "type": "string" + } + } + } + } + ] + } + }, + "timeToLive": { + "type": "integer", + "description": "Interval in milliseconds or a Schema Object containing the definition of the lifetime of the message." + }, + "priority": { + "type": "integer", + "minimum": 0, + "maximum": 255, + "description": "The valid priority value range is 0-255 with 0 as the lowest priority and 255 as the highest or a Schema Object containing the definition of the priority." + }, + "dmqEligible": { + "type": "boolean", + "description": "Set the message to be eligible to be moved to a Dead Message Queue. The default value is false." + } + }, + "examples": [ + { + "bindingVersion": "0.4.0", + "destinations": [ + { + "destinationType": "queue", + "queue": { + "name": "sampleQueue", + "topicSubscriptions": ["samples/*"], + "accessType": "nonexclusive" + } + }, + { + "destinationType": "topic", + "topicSubscriptions": ["samples/*"] + } + ] + } + ] + }, + "bindings-solace-0.3.0-operation": { + "title": "Solace operation bindings object", + "description": "This object contains information about the operation representation in Solace.", + "type": "object", + "additionalProperties": false, + "properties": { + "destinations": { + "description": "The list of Solace destinations referenced in the operation.", + "type": "array", + "items": { + "type": "object", + "properties": { + "deliveryMode": { + "type": "string", + "enum": ["direct", "persistent"] + } + }, + "oneOf": [ + { + "properties": { + "destinationType": { + "type": "string", + "const": "queue", + "description": "If the type is queue, then the subscriber can bind to the queue. The queue subscribes to the given topicSubscriptions. If no topicSubscriptions are provied, the queue will subscribe to the topic as represented by the channel name." + }, + "queue": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the queue" + }, + "topicSubscriptions": { + "type": "array", + "description": "The list of topics that the queue subscribes to.", + "items": { + "type": "string" + } + }, + "accessType": { + "type": "string", + "enum": ["exclusive", "nonexclusive"] + }, + "maxTtl": { + "type": "string", + "description": "The maximum TTL to apply to messages to be spooled." + }, + "maxMsgSpoolUsage": { + "type": "string", + "description": "The maximum amount of message spool that the given queue may use" + } + } + } + } + }, + { + "properties": { + "destinationType": { + "type": "string", + "const": "topic", + "description": "If the type is topic, then the subscriber subscribes to the given topicSubscriptions. If no topicSubscriptions are provided, the client will subscribe to the topic as represented by the channel name." + }, + "topicSubscriptions": { + "type": "array", + "description": "The list of topics that the client subscribes to.", + "items": { + "type": "string" + } + } + } + } + ] + } + }, + "bindingVersion": { + "type": "string", + "enum": ["0.3.0"], + "description": "The version of this binding. If omitted, \"latest\" MUST be assumed." + } + }, + "examples": [ + { + "bindingVersion": "0.3.0", + "destinations": [ + { + "destinationType": "queue", + "queue": { + "name": "sampleQueue", + "topicSubscriptions": ["samples/*"], + "accessType": "nonexclusive" + } + }, + { + "destinationType": "topic", + "topicSubscriptions": ["samples/*"] + } + ] + } + ] + }, + "bindings-solace-0.2.0-operation": { + "title": "Solace operation bindings object", + "description": "This object contains information about the operation representation in Solace.", + "type": "object", + "additionalProperties": false, + "properties": { + "destinations": { + "description": "The list of Solace destinations referenced in the operation.", + "type": "array", + "items": { + "type": "object", + "properties": { + "deliveryMode": { + "type": "string", + "enum": ["direct", "persistent"] + } + }, + "oneOf": [ + { + "properties": { + "destinationType": { + "type": "string", + "const": "queue", + "description": "If the type is queue, then the subscriber can bind to the queue. The queue subscribes to the given topicSubscriptions. If no topicSubscriptions are provied, the queue will subscribe to the topic as represented by the channel name." + }, + "queue": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the queue" + }, + "topicSubscriptions": { + "type": "array", + "description": "The list of topics that the queue subscribes to.", + "items": { + "type": "string" + } + }, + "accessType": { + "type": "string", + "enum": ["exclusive", "nonexclusive"] + } + } + } + } + }, + { + "properties": { + "destinationType": { + "type": "string", + "const": "topic", + "description": "If the type is topic, then the subscriber subscribes to the given topicSubscriptions. If no topicSubscriptions are provided, the client will subscribe to the topic as represented by the channel name." + }, + "topicSubscriptions": { + "type": "array", + "description": "The list of topics that the client subscribes to.", + "items": { + "type": "string" + } + } + } + } + ] + } + }, + "bindingVersion": { + "type": "string", + "enum": ["0.2.0"], + "description": "The version of this binding. If omitted, \"latest\" MUST be assumed." + } + }, + "examples": [ + { + "bindingVersion": "0.2.0", + "destinations": [ + { + "destinationType": "queue", + "queue": { + "name": "sampleQueue", + "topicSubscriptions": ["samples/*"], + "accessType": "nonexclusive" + } + }, + { + "destinationType": "topic", + "topicSubscriptions": ["samples/*"] + } + ] + } + ] + }, + "bindings-sqs-0.2.0-operation": { + "title": "Operation Schema", + "description": "This object contains information about the operation representation in SQS.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "queues": { + "type": "array", + "description": "Queue objects that are either the endpoint for an SNS Operation Binding Object, or the deadLetterQueue of the SQS Operation Binding Object.", + "items": { + "$ref": "#/definitions/bindings-sqs-0.2.0-operation/definitions/queue" + } + }, + "bindingVersion": { + "type": "string", + "enum": ["0.1.0", "0.2.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed.", + "default": "latest" + } + }, + "required": ["queues"], + "definitions": { + "queue": { + "type": "object", + "description": "A definition of a queue.", + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "$ref": { + "type": "string", + "description": "Allows for an external definition of a queue. The referenced structure MUST be in the format of a Queue. If there are conflicts between the referenced definition and this Queue's definition, the behavior is undefined." + }, + "name": { + "type": "string", + "description": "The name of the queue. When an SNS Operation Binding Object references an SQS queue by name, the identifier should be the one in this field." + }, + "fifoQueue": { + "type": "boolean", + "description": "Is this a FIFO queue?", + "default": false + }, + "deduplicationScope": { + "type": "string", + "enum": ["queue", "messageGroup"], + "description": "Specifies whether message deduplication occurs at the message group or queue level. Valid values are messageGroup and queue (default).", + "default": "queue" + }, + "fifoThroughputLimit": { + "type": "string", + "enum": ["perQueue", "perMessageGroupId"], + "description": "Specifies whether the FIFO queue throughput quota applies to the entire queue or per message group. Valid values are perQueue (default) and perMessageGroupId.", + "default": "perQueue" + }, + "deliveryDelay": { + "type": "integer", + "description": "The number of seconds to delay before a message sent to the queue can be received. Used to create a delay queue.", + "minimum": 0, + "maximum": 900, + "default": 0 + }, + "visibilityTimeout": { + "type": "integer", + "description": "The length of time, in seconds, that a consumer locks a message - hiding it from reads - before it is unlocked and can be read again.", + "minimum": 0, + "maximum": 43200, + "default": 30 + }, + "receiveMessageWaitTime": { + "type": "integer", + "description": "Determines if the queue uses short polling or long polling. Set to zero the queue reads available messages and returns immediately. Set to a non-zero integer, long polling waits the specified number of seconds for messages to arrive before returning.", + "default": 0 + }, + "messageRetentionPeriod": { + "type": "integer", + "description": "How long to retain a message on the queue in seconds, unless deleted.", + "minimum": 60, + "maximum": 1209600, + "default": 345600 + }, + "redrivePolicy": { + "$ref": "#/definitions/bindings-sqs-0.2.0-operation/definitions/redrivePolicy" + }, + "policy": { + "$ref": "#/definitions/bindings-sqs-0.2.0-operation/definitions/policy" + }, + "tags": { + "type": "object", + "description": "Key-value pairs that represent AWS tags on the queue." + } + }, + "required": ["name"] + }, + "redrivePolicy": { + "type": "object", + "description": "Prevent poison pill messages by moving un-processable messages to an SQS dead letter queue.", + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "deadLetterQueue": { + "$ref": "#/definitions/bindings-sqs-0.2.0-operation/definitions/identifier" + }, + "maxReceiveCount": { + "type": "integer", + "description": "The number of times a message is delivered to the source queue before being moved to the dead-letter queue.", + "default": 10 + } + }, + "required": ["deadLetterQueue"] + }, + "identifier": { + "type": "object", + "description": "The SQS queue to use as a dead letter queue (DLQ).", + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "arn": { + "type": "string", + "description": "The target is an ARN. For example, for SQS, the identifier may be an ARN, which will be of the form: arn:aws:sqs:{region}:{account-id}:{queueName}" + }, + "name": { + "type": "string", + "description": "The endpoint is identified by a name, which corresponds to an identifying field called 'name' of a binding for that protocol on this publish Operation Object. For example, if the protocol is 'sqs' then the name refers to the name field sqs binding." + } + } + }, + "policy": { + "type": "object", + "description": "The security policy for the SQS Queue", + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "statements": { + "type": "array", + "description": "An array of statement objects, each of which controls a permission for this queue.", + "items": { + "$ref": "#/definitions/bindings-sqs-0.2.0-operation/definitions/statement" + } + } + }, + "required": ["statements"] + }, + "statement": { + "type": "object", + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "effect": { + "type": "string", + "enum": ["Allow", "Deny"] + }, + "principal": { + "description": "The AWS account or resource ARN that this statement applies to.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "action": { + "description": "The SQS permission being allowed or denied e.g. sqs:ReceiveMessage", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + }, + "required": ["effect", "principal", "action"] + } + }, + "examples": [ + { + "queues": [ + { + "name": "myQueue", + "fifoQueue": true, + "deduplicationScope": "messageGroup", + "fifoThroughputLimit": "perMessageGroupId", + "deliveryDelay": 10, + "redrivePolicy": { + "deadLetterQueue": { + "name": "myQueue_error" + }, + "maxReceiveCount": 15 + }, + "policy": { + "statements": [ + { + "effect": "Deny", + "principal": "arn:aws:iam::123456789012:user/dec.kolakowski", + "action": ["sqs:SendMessage", "sqs:ReceiveMessage"] + } + ] + } + }, + { + "name": "myQueue_error", + "deliveryDelay": 10 + } + ] + } + ] + }, + "operationTrait": { + "description": "Describes a trait that MAY be applied to an Operation Object. This object MAY contain any property from the Operation Object, except the action, channel and traits ones.", + "type": "object", + "properties": { + "title": { + "description": "A human-friendly title for the operation.", + "$ref": "#/definitions/operation/properties/title" + }, + "description": { + "description": "A verbose explanation of the operation. CommonMark syntax can be used for rich text representation.", + "$ref": "#/definitions/operation/properties/description" + }, + "bindings": { + "description": "A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the operation.", + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/operationBindingsObject" + } + ] + }, + "externalDocs": { + "description": "Additional external documentation for this operation.", + "$ref": "#/definitions/operation/properties/externalDocs" + }, + "security": { + "description": "A declaration of which security schemes are associated with this operation. Only one of the security scheme objects MUST be satisfied to authorize an operation. In cases where Server Security also applies, it MUST also be satisfied.", + "$ref": "#/definitions/operation/properties/security" + }, + "summary": { + "description": "A short summary of what the operation is about.", + "$ref": "#/definitions/operation/properties/summary" + }, + "tags": { + "description": "A list of tags for logical grouping and categorization of operations.", + "$ref": "#/definitions/operation/properties/tags" + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "bindings": { + "amqp": { + "ack": false + } + } + } + ] + }, + "operation": { + "description": "Describes a specific operation.", + "type": "object", + "required": ["action", "channel"], + "properties": { + "title": { + "description": "A human-friendly title for the operation.", + "type": "string" + }, + "description": { + "description": "A longer description of the operation. CommonMark is allowed.", + "type": "string" + }, + "action": { + "description": "Allowed values are send and receive. Use send when it's expected that the application will send a message to the given channel, and receive when the application should expect receiving messages from the given channel.", + "type": "string", + "enum": ["send", "receive"] + }, + "bindings": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/operationBindingsObject" + } + ] + }, + "channel": { + "$ref": "#/definitions/Reference" + }, + "externalDocs": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/externalDocs" + } + ] + }, + "messages": { + "description": "A list of $ref pointers pointing to the supported Message Objects that can be processed by this operation. It MUST contain a subset of the messages defined in the channel referenced in this operation. Every message processed by this operation MUST be valid against one, and only one, of the message objects referenced in this list. Please note the messages property value MUST be a list of Reference Objects and, therefore, MUST NOT contain Message Objects. However, it is RECOMMENDED that parsers (or other software) dereference this property for a better development experience.", + "type": "array", + "items": { + "$ref": "#/definitions/Reference" + } + }, + "reply": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/operationReply" + } + ] + }, + "security": { + "$ref": "#/definitions/securityRequirements" + }, + "summary": { + "description": "A brief summary of the operation.", + "type": "string" + }, + "tags": { + "description": "A list of tags for logical grouping and categorization of operations.", + "type": "array", + "uniqueItems": true, + "items": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/tag" + } + ] + } + }, + "traits": { + "description": "A list of traits to apply to the operation object. Traits MUST be merged using traits merge mechanism. The resulting object MUST be a valid Operation Object.", + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/operationTrait" + } + ] + } + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "title": "User sign up", + "summary": "Action to sign a user up.", + "description": "A longer description", + "channel": { + "$ref": "#/channels/userSignup" + }, + "action": "send", + "security": [ + { + "petstore_auth": ["write:pets", "read:pets"] + } + ], + "tags": [ + { + "name": "user" + }, + { + "name": "signup" + }, + { + "name": "register" + } + ], + "bindings": { + "amqp": { + "ack": false + } + }, + "traits": [ + { + "$ref": "#/components/operationTraits/kafka" + } + ], + "messages": [ + { + "$ref": "/components/messages/userSignedUp" + } + ], + "reply": { + "address": { + "location": "$message.header#/replyTo" + }, + "channel": { + "$ref": "#/channels/userSignupReply" + }, + "messages": [ + { + "$ref": "/components/messages/userSignedUpReply" + } + ] + } + } + ] + }, + "securityRequirements": { + "description": "An array representing security requirements.", + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/SecurityScheme" + } + ] + } + }, + "SecurityScheme": { + "description": "Defines a security scheme that can be used by the operations.", + "oneOf": [ + { + "$ref": "#/definitions/userPassword" + }, + { + "$ref": "#/definitions/apiKey" + }, + { + "$ref": "#/definitions/X509" + }, + { + "$ref": "#/definitions/symmetricEncryption" + }, + { + "$ref": "#/definitions/asymmetricEncryption" + }, + { + "$ref": "#/definitions/HTTPSecurityScheme" + }, + { + "$ref": "#/definitions/oauth2Flows" + }, + { + "$ref": "#/definitions/openIdConnect" + }, + { + "$ref": "#/definitions/SaslSecurityScheme" + } + ], + "examples": [ + { + "type": "userPassword" + } + ] + }, + "userPassword": { + "type": "object", + "required": ["type"], + "properties": { + "description": { + "type": "string" + }, + "type": { + "type": "string", + "enum": ["userPassword"] + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "type": "userPassword" + } + ] + }, + "apiKey": { + "type": "object", + "required": ["type", "in"], + "properties": { + "description": { + "description": "A short description for security scheme. CommonMark syntax MAY be used for rich text representation.", + "type": "string" + }, + "type": { + "description": "The type of the security scheme", + "type": "string", + "enum": ["apiKey"] + }, + "in": { + "description": " The location of the API key.", + "type": "string", + "enum": ["user", "password"] + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "type": "apiKey", + "in": "user" + } + ] + }, + "X509": { + "type": "object", + "required": ["type"], + "properties": { + "description": { + "type": "string" + }, + "type": { + "type": "string", + "enum": ["X509"] + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "type": "X509" + } + ] + }, + "symmetricEncryption": { + "type": "object", + "required": ["type"], + "properties": { + "description": { + "type": "string" + }, + "type": { + "type": "string", + "enum": ["symmetricEncryption"] + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "type": "symmetricEncryption" + } + ] + }, + "asymmetricEncryption": { + "type": "object", + "required": ["type"], + "properties": { + "description": { + "description": "A short description for security scheme.", + "type": "string" + }, + "type": { + "description": "The type of the security scheme.", + "type": "string", + "enum": ["asymmetricEncryption"] + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false + }, + "HTTPSecurityScheme": { + "oneOf": [ + { + "$ref": "#/definitions/NonBearerHTTPSecurityScheme" + }, + { + "$ref": "#/definitions/BearerHTTPSecurityScheme" + }, + { + "$ref": "#/definitions/APIKeyHTTPSecurityScheme" + } + ] + }, + "NonBearerHTTPSecurityScheme": { + "type": "object", + "not": { + "type": "object", + "properties": { + "scheme": { + "description": "A short description for security scheme.", + "type": "string", + "enum": ["bearer"] + } + } + }, + "required": ["scheme", "type"], + "properties": { + "description": { + "description": "A short description for security scheme.", + "type": "string" + }, + "type": { + "description": "The type of the security scheme.", + "type": "string", + "enum": ["http"] + }, + "scheme": { + "description": "The name of the HTTP Authorization scheme to be used in the Authorization header as defined in RFC7235.", + "type": "string" + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false + }, + "BearerHTTPSecurityScheme": { + "type": "object", + "required": ["type", "scheme"], + "properties": { + "description": { + "description": "A short description for security scheme. CommonMark syntax MAY be used for rich text representation.", + "type": "string" + }, + "type": { + "description": "The type of the security scheme.", + "type": "string", + "enum": ["http"] + }, + "bearerFormat": { + "description": "A hint to the client to identify how the bearer token is formatted. Bearer tokens are usually generated by an authorization server, so this information is primarily for documentation purposes.", + "type": "string" + }, + "scheme": { + "description": "The name of the HTTP Authorization scheme to be used in the Authorization header as defined in RFC7235.", + "type": "string", + "enum": ["bearer"] + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false + }, + "APIKeyHTTPSecurityScheme": { + "type": "object", + "required": ["type", "name", "in"], + "properties": { + "description": { + "description": "A short description for security scheme. CommonMark syntax MAY be used for rich text representation.", + "type": "string" + }, + "type": { + "description": "The type of the security scheme.", + "type": "string", + "enum": ["httpApiKey"] + }, + "in": { + "description": "The location of the API key", + "type": "string", + "enum": ["header", "query", "cookie"] + }, + "name": { + "description": "The name of the header, query or cookie parameter to be used.", + "type": "string" + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "type": "httpApiKey", + "name": "api_key", + "in": "header" + } + ] + }, + "oauth2Flows": { + "description": "Allows configuration of the supported OAuth Flows.", + "type": "object", + "required": ["type", "flows"], + "properties": { + "description": { + "description": "A short description for security scheme.", + "type": "string" + }, + "type": { + "description": "The type of the security scheme.", + "type": "string", + "enum": ["oauth2"] + }, + "flows": { + "type": "object", + "properties": { + "authorizationCode": { + "description": "Configuration for the OAuth Authorization Code flow.", + "allOf": [ + { + "$ref": "#/definitions/oauth2Flow" + }, + { + "required": [ + "authorizationUrl", + "tokenUrl", + "availableScopes" + ] + } + ] + }, + "clientCredentials": { + "description": "Configuration for the OAuth Client Credentials flow.", + "allOf": [ + { + "$ref": "#/definitions/oauth2Flow" + }, + { + "required": ["tokenUrl", "availableScopes"] + }, + { + "not": { + "required": ["authorizationUrl"] + } + } + ] + }, + "implicit": { + "description": "Configuration for the OAuth Implicit flow.", + "allOf": [ + { + "$ref": "#/definitions/oauth2Flow" + }, + { + "required": ["authorizationUrl", "availableScopes"] + }, + { + "not": { + "required": ["tokenUrl"] + } + } + ] + }, + "password": { + "description": "Configuration for the OAuth Resource Owner Protected Credentials flow.", + "allOf": [ + { + "$ref": "#/definitions/oauth2Flow" + }, + { + "required": ["tokenUrl", "availableScopes"] + }, + { + "not": { + "required": ["authorizationUrl"] + } + } + ] + } + }, + "additionalProperties": false + }, + "scopes": { + "description": "List of the needed scope names.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + } + }, + "oauth2Flow": { + "description": "Configuration details for a supported OAuth Flow", + "type": "object", + "properties": { + "authorizationUrl": { + "description": "The authorization URL to be used for this flow. This MUST be in the form of an absolute URL.", + "type": "string", + "format": "uri" + }, + "availableScopes": { + "description": "The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it.", + "$ref": "#/definitions/oauth2Scopes" + }, + "refreshUrl": { + "description": "The URL to be used for obtaining refresh tokens. This MUST be in the form of an absolute URL.", + "type": "string", + "format": "uri" + }, + "tokenUrl": { + "description": "The token URL to be used for this flow. This MUST be in the form of an absolute URL.", + "type": "string", + "format": "uri" + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "authorizationUrl": "https://example.com/api/oauth/dialog", + "tokenUrl": "https://example.com/api/oauth/token", + "availableScopes": { + "write:pets": "modify pets in your account", + "read:pets": "read your pets" + } + } + ] + }, + "oauth2Scopes": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "openIdConnect": { + "type": "object", + "required": ["type", "openIdConnectUrl"], + "properties": { + "description": { + "description": "A short description for security scheme. CommonMark syntax MAY be used for rich text representation.", + "type": "string" + }, + "type": { + "description": "The type of the security scheme.", + "type": "string", + "enum": ["openIdConnect"] + }, + "openIdConnectUrl": { + "description": "OpenId Connect URL to discover OAuth2 configuration values. This MUST be in the form of an absolute URL.", + "type": "string", + "format": "uri" + }, + "scopes": { + "description": "List of the needed scope names. An empty array means no scopes are needed.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false + }, + "SaslSecurityScheme": { + "oneOf": [ + { + "$ref": "#/definitions/SaslPlainSecurityScheme" + }, + { + "$ref": "#/definitions/SaslScramSecurityScheme" + }, + { + "$ref": "#/definitions/SaslGssapiSecurityScheme" + } + ] + }, + "SaslPlainSecurityScheme": { + "type": "object", + "required": ["type"], + "properties": { + "description": { + "description": "A short description for security scheme.", + "type": "string" + }, + "type": { + "description": "The type of the security scheme. Valid values", + "type": "string", + "enum": ["plain"] + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "type": "scramSha512" + } + ] + }, + "SaslScramSecurityScheme": { + "type": "object", + "required": ["type"], + "properties": { + "description": { + "description": "A short description for security scheme.", + "type": "string" + }, + "type": { + "description": "The type of the security scheme.", + "type": "string", + "enum": ["scramSha256", "scramSha512"] + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "type": "scramSha512" + } + ] + }, + "SaslGssapiSecurityScheme": { + "type": "object", + "required": ["type"], + "properties": { + "description": { + "description": "A short description for security scheme.", + "type": "string" + }, + "type": { + "description": "The type of the security scheme.", + "type": "string", + "enum": ["gssapi"] + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "type": "scramSha512" + } + ] + }, + "operationReply": { + "description": "Describes the reply part that MAY be applied to an Operation Object. If an operation implements the request/reply pattern, the reply object represents the response message.", + "type": "object", + "properties": { + "address": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/operationReplyAddress" + } + ] + }, + "channel": { + "$ref": "#/definitions/Reference" + }, + "messages": { + "description": "A list of $ref pointers pointing to the supported Message Objects that can be processed by this operation as reply. It MUST contain a subset of the messages defined in the channel referenced in this operation reply. Every message processed by this operation MUST be valid against one, and only one, of the message objects referenced in this list. Please note the messages property value MUST be a list of Reference Objects and, therefore, MUST NOT contain Message Objects. However, it is RECOMMENDED that parsers (or other software) dereference this property for a better development experience.", + "type": "array", + "items": { + "$ref": "#/definitions/Reference" + } + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false + }, + "operationReplyAddress": { + "description": "An object that specifies where an operation has to send the reply", + "type": "object", + "required": ["location"], + "properties": { + "description": { + "description": "An optional description of the address. CommonMark is allowed.", + "type": "string" + }, + "location": { + "description": "A runtime expression that specifies the location of the reply address.", + "type": "string", + "pattern": "^\\$message\\.(header|payload)#(\\/(([^\\/~])|(~[01]))*)*" + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "description": "Consumer inbox", + "location": "$message.header#/replyTo" + } + ] + }, + "serverBindingsObject": { + "description": "Map describing protocol-specific definitions for a server.", + "type": "object", + "properties": { + "amqp": {}, + "amqp1": {}, + "anypointmq": {}, + "googlepubsub": {}, + "http": {}, + "ibmmq": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-ibmmq-0.1.0-server" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.1.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-ibmmq-0.1.0-server" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.1.0"] + } + } + }, + "jms": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-jms-0.0.1-server" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.0.1" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-jms-0.0.1-server" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.0.1"] + } + } + }, + "kafka": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-kafka-0.5.0-server" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.5.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-kafka-0.5.0-server" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.4.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-kafka-0.4.0-server" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.3.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-kafka-0.3.0-server" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.5.0", "0.4.0", "0.3.0"] + } + } + }, + "mqtt": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-mqtt-0.2.0-server" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.2.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-mqtt-0.2.0-server" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.2.0"] + } + } + }, + "nats": {}, + "pulsar": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-pulsar-0.1.0-server" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.1.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-pulsar-0.1.0-server" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.1.0"] + } + } + }, + "redis": {}, + "ros2": { + "properties": { + "bindingVersion": { + "enum": ["0.1.0"] + } + }, + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-ros2-0.1.0-server" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.1.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-ros2-0.1.0-server" + } + } + ] + }, + "sns": {}, + "solace": { + "allOf": [ + { + "description": "If no bindingVersion specified, use the latest binding", + "if": { + "not": { + "required": ["bindingVersion"] + } + }, + "then": { + "$ref": "#/definitions/bindings-solace-0.4.0-server" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.4.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-solace-0.4.0-server" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.3.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-solace-0.3.0-server" + } + }, + { + "if": { + "required": ["bindingVersion"], + "properties": { + "bindingVersion": { + "const": "0.2.0" + } + } + }, + "then": { + "$ref": "#/definitions/bindings-solace-0.2.0-server" + } + } + ], + "properties": { + "bindingVersion": { + "enum": ["0.4.0", "0.3.0", "0.2.0"] + } + } + }, + "sqs": {}, + "stomp": {}, + "ws": {} + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false + }, + "bindings-ibmmq-0.1.0-server": { + "title": "IBM MQ server bindings object", + "description": "This object contains server connection information about the IBM MQ server, referred to as an IBM MQ queue manager. This object contains additional connectivity information not possible to represent within the core AsyncAPI specification.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "groupId": { + "type": "string", + "description": "Defines a logical group of IBM MQ server objects. This is necessary to specify multi-endpoint configurations used in high availability deployments. If omitted, the server object is not part of a group." + }, + "ccdtQueueManagerName": { + "type": "string", + "default": "*", + "description": "The name of the IBM MQ queue manager to bind to in the CCDT file." + }, + "cipherSpec": { + "type": "string", + "description": "The recommended cipher specification used to establish a TLS connection between the client and the IBM MQ queue manager. More information on SSL/TLS cipher specifications supported by IBM MQ can be found on this page in the IBM MQ Knowledge Center." + }, + "multiEndpointServer": { + "type": "boolean", + "default": false, + "description": "If 'multiEndpointServer' is 'true' then multiple connections can be workload balanced and applications should not make assumptions as to where messages are processed. Where message ordering, or affinity to specific message resources is necessary, a single endpoint ('multiEndpointServer' = 'false') may be required." + }, + "heartBeatInterval": { + "type": "integer", + "minimum": 0, + "maximum": 999999, + "default": 300, + "description": "The recommended value (in seconds) for the heartbeat sent to the queue manager during periods of inactivity. A value of zero means that no heart beats are sent. A value of 1 means that the client will use the value defined by the queue manager. More information on heart beat interval can be found on this page in the IBM MQ Knowledge Center." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.1.0"], + "description": "The version of this binding." + } + }, + "examples": [ + { + "groupId": "PRODCLSTR1", + "cipherSpec": "ANY_TLS12_OR_HIGHER", + "bindingVersion": "0.1.0" + }, + { + "groupId": "PRODCLSTR1", + "bindingVersion": "0.1.0" + } + ] + }, + "bindings-jms-0.0.1-server": { + "title": "Server Schema", + "description": "This object contains configuration for describing a JMS broker as an AsyncAPI server. This objects only contains configuration that can not be provided in the AsyncAPI standard server object.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "required": ["jmsConnectionFactory"], + "properties": { + "jmsConnectionFactory": { + "type": "string", + "description": "The classname of the ConnectionFactory implementation for the JMS Provider." + }, + "properties": { + "type": "array", + "items": { + "$ref": "#/definitions/bindings-jms-0.0.1-server/definitions/property" + }, + "description": "Additional properties to set on the JMS ConnectionFactory implementation for the JMS Provider." + }, + "clientID": { + "type": "string", + "description": "A client identifier for applications that use this JMS connection factory. If the Client ID Policy is set to 'Restricted' (the default), then configuring a Client ID on the ConnectionFactory prevents more than one JMS client from using a connection from this factory." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.0.1"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "definitions": { + "property": { + "type": "object", + "required": ["name", "value"], + "properties": { + "name": { + "type": "string", + "description": "The name of a property" + }, + "value": { + "type": ["string", "boolean", "number", "null"], + "description": "The name of a property" + } + } + } + }, + "examples": [ + { + "jmsConnectionFactory": "org.apache.activemq.ActiveMQConnectionFactory", + "properties": [ + { + "name": "disableTimeStampsByDefault", + "value": false + } + ], + "clientID": "my-application-1", + "bindingVersion": "0.0.1" + } + ] + }, + "bindings-kafka-0.5.0-server": { + "title": "Server Schema", + "description": "This object contains server connection information to a Kafka broker. This object contains additional information not possible to represent within the core AsyncAPI specification.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "schemaRegistryUrl": { + "type": "string", + "description": "API URL for the Schema Registry used when producing Kafka messages (if a Schema Registry was used)." + }, + "schemaRegistryVendor": { + "type": "string", + "description": "The vendor of the Schema Registry and Kafka serdes library that should be used." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.5.0"], + "description": "The version of this binding." + } + }, + "examples": [ + { + "schemaRegistryUrl": "https://my-schema-registry.com", + "schemaRegistryVendor": "confluent", + "bindingVersion": "0.5.0" + } + ] + }, + "bindings-kafka-0.4.0-server": { + "title": "Server Schema", + "description": "This object contains server connection information to a Kafka broker. This object contains additional information not possible to represent within the core AsyncAPI specification.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "schemaRegistryUrl": { + "type": "string", + "description": "API URL for the Schema Registry used when producing Kafka messages (if a Schema Registry was used)." + }, + "schemaRegistryVendor": { + "type": "string", + "description": "The vendor of the Schema Registry and Kafka serdes library that should be used." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.4.0"], + "description": "The version of this binding." + } + }, + "examples": [ + { + "schemaRegistryUrl": "https://my-schema-registry.com", + "schemaRegistryVendor": "confluent", + "bindingVersion": "0.4.0" + } + ] + }, + "bindings-kafka-0.3.0-server": { + "title": "Server Schema", + "description": "This object contains server connection information to a Kafka broker. This object contains additional information not possible to represent within the core AsyncAPI specification.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "schemaRegistryUrl": { + "type": "string", + "description": "API URL for the Schema Registry used when producing Kafka messages (if a Schema Registry was used)." + }, + "schemaRegistryVendor": { + "type": "string", + "description": "The vendor of the Schema Registry and Kafka serdes library that should be used." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.3.0"], + "description": "The version of this binding." + } + }, + "examples": [ + { + "schemaRegistryUrl": "https://my-schema-registry.com", + "schemaRegistryVendor": "confluent", + "bindingVersion": "0.3.0" + } + ] + }, + "bindings-mqtt-0.2.0-server": { + "title": "Server Schema", + "description": "This object contains information about the server representation in MQTT.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "clientId": { + "type": "string", + "description": "The client identifier." + }, + "cleanSession": { + "type": "boolean", + "description": "Whether to create a persistent connection or not. When 'false', the connection will be persistent. This is called clean start in MQTTv5." + }, + "lastWill": { + "type": "object", + "description": "Last Will and Testament configuration.", + "properties": { + "topic": { + "type": "string", + "description": "The topic where the Last Will and Testament message will be sent." + }, + "qos": { + "type": "integer", + "enum": [0, 1, 2], + "description": "Defines how hard the broker/client will try to ensure that the Last Will and Testament message is received. Its value MUST be either 0, 1 or 2." + }, + "message": { + "type": "string", + "description": "Last Will message." + }, + "retain": { + "type": "boolean", + "description": "Whether the broker should retain the Last Will and Testament message or not." + } + } + }, + "keepAlive": { + "type": "integer", + "description": "Interval in seconds of the longest period of time the broker and the client can endure without sending a message." + }, + "sessionExpiryInterval": { + "oneOf": [ + { + "type": "integer", + "minimum": 0 + }, + { + "$ref": "#/definitions/schema" + }, + { + "$ref": "#/definitions/Reference" + } + ], + "description": "Interval time in seconds or a Schema Object containing the definition of the interval. The broker maintains a session for a disconnected client until this interval expires." + }, + "maximumPacketSize": { + "oneOf": [ + { + "type": "integer", + "minimum": 1, + "maximum": 4294967295 + }, + { + "$ref": "#/definitions/schema" + }, + { + "$ref": "#/definitions/Reference" + } + ], + "description": "Number of bytes or a Schema Object representing the Maximum Packet Size the Client is willing to accept." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.2.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "clientId": "guest", + "cleanSession": true, + "lastWill": { + "topic": "/last-wills", + "qos": 2, + "message": "Guest gone offline.", + "retain": false + }, + "keepAlive": 60, + "sessionExpiryInterval": 120, + "maximumPacketSize": 1024, + "bindingVersion": "0.2.0" + } + ] + }, + "bindings-pulsar-0.1.0-server": { + "title": "Server Schema", + "description": "This object contains server information of Pulsar broker, which covers cluster and tenant admin configuration. This object contains additional information not possible to represent within the core AsyncAPI specification.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "tenant": { + "type": "string", + "description": "The pulsar tenant. If omitted, 'public' MUST be assumed." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.1.0"], + "description": "The version of this binding. If omitted, 'latest' MUST be assumed." + } + }, + "examples": [ + { + "tenant": "contoso", + "bindingVersion": "0.1.0" + } + ] + }, + "bindings-ros2-0.1.0-server": { + "description": "This object contains information about the server representation in ROS 2.", + "examples": [ + { + "domainId": "0", + "rmwImplementation": "rmw_fastrtps_cpp" + } + ], + "type": "object", + "properties": { + "bindingVersion": { + "description": "The version of this binding. If omitted, 'latest' MUST be assumed.", + "type": "string", + "enum": ["0.1.0"] + }, + "domainId": { + "description": "All ROS 2 nodes use domain ID 0 by default. To prevent interference between different groups of computers running ROS 2 on the same network, a group can be set with a unique domain ID.", + "type": "integer", + "maximum": 231, + "minimum": 0 + }, + "rmwImplementation": { + "description": "Specifies the ROS 2 middleware implementation to be used. This determines the underlying middleware implementation that handles communication.", + "type": "string" + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + } + }, + "bindings-solace-0.4.0-server": { + "title": "Solace server bindings object", + "description": "This object contains server connection information about the Solace broker. This object contains additional connectivity information not possible to represent within the core AsyncAPI specification.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "msgVpn": { + "type": "string", + "description": "The name of the Virtual Private Network to connect to on the Solace broker." + }, + "clientName": { + "type": "string", + "minLength": 1, + "maxLength": 160, + "description": "A unique client name to use to register to the appliance. If specified, it must be a valid Topic name, and a maximum of 160 bytes in length when encoded as UTF-8." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.4.0"], + "description": "The version of this binding." + } + }, + "examples": [ + { + "msgVpn": "ProdVPN", + "bindingVersion": "0.4.0" + } + ] + }, + "bindings-solace-0.3.0-server": { + "title": "Solace server bindings object", + "description": "This object contains server connection information about the Solace broker. This object contains additional connectivity information not possible to represent within the core AsyncAPI specification.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "msgVpn": { + "type": "string", + "description": "The name of the Virtual Private Network to connect to on the Solace broker." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.3.0"], + "description": "The version of this binding." + } + }, + "examples": [ + { + "msgVpn": "ProdVPN", + "bindingVersion": "0.3.0" + } + ] + }, + "bindings-solace-0.2.0-server": { + "title": "Solace server bindings object", + "description": "This object contains server connection information about the Solace broker. This object contains additional connectivity information not possible to represent within the core AsyncAPI specification.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "properties": { + "msvVpn": { + "type": "string", + "description": "The name of the Virtual Private Network to connect to on the Solace broker." + }, + "bindingVersion": { + "type": "string", + "enum": ["0.2.0"], + "description": "The version of this binding." + } + }, + "examples": [ + { + "msgVpn": "ProdVPN", + "bindingVersion": "0.2.0" + } + ] + }, + "serverVariable": { + "description": "An object representing a Server Variable for server URL template substitution.", + "type": "object", + "properties": { + "description": { + "description": "An optional description for the server variable. CommonMark syntax MAY be used for rich text representation.", + "type": "string" + }, + "examples": { + "description": "An array of examples of the server variable.", + "type": "array", + "items": { + "type": "string" + } + }, + "default": { + "description": "The default value to use for substitution, and to send, if an alternate value is not supplied.", + "type": "string" + }, + "enum": { + "description": "An enumeration of string values to be used if the substitution options are from a limited set.", + "type": "array", + "uniqueItems": true, + "items": { + "type": "string" + } + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "host": "rabbitmq.in.mycompany.com:5672", + "pathname": "/{env}", + "protocol": "amqp", + "description": "RabbitMQ broker. Use the `env` variable to point to either `production` or `staging`.", + "variables": { + "env": { + "description": "Environment to connect to. It can be either `production` or `staging`.", + "enum": ["production", "staging"] + } + } + } + ] + }, + "server": { + "description": "An object representing a message broker, a server or any other kind of computer program capable of sending and/or receiving data.", + "type": "object", + "required": ["host", "protocol"], + "properties": { + "title": { + "description": "A human-friendly title for the server.", + "type": "string" + }, + "description": { + "description": "A longer description of the server. CommonMark is allowed.", + "type": "string" + }, + "bindings": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/serverBindingsObject" + } + ] + }, + "externalDocs": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/externalDocs" + } + ] + }, + "host": { + "description": "The server host name. It MAY include the port. This field supports Server Variables. Variable substitutions will be made when a variable is named in {braces}.", + "type": "string" + }, + "pathname": { + "description": "The path to a resource in the host. This field supports Server Variables. Variable substitutions will be made when a variable is named in {braces}.", + "type": "string" + }, + "protocol": { + "description": "The protocol this server supports for connection.", + "type": "string" + }, + "protocolVersion": { + "description": "An optional string describing the server. CommonMark syntax MAY be used for rich text representation.", + "type": "string" + }, + "security": { + "$ref": "#/definitions/securityRequirements" + }, + "summary": { + "description": "A brief summary of the server.", + "type": "string" + }, + "tags": { + "type": "array", + "uniqueItems": true, + "items": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/tag" + } + ] + } + }, + "variables": { + "$ref": "#/definitions/serverVariables" + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "host": "kafka.in.mycompany.com:9092", + "description": "Production Kafka broker.", + "protocol": "kafka", + "protocolVersion": "3.2" + }, + { + "host": "rabbitmq.in.mycompany.com:5672", + "pathname": "/production", + "protocol": "amqp", + "description": "Production RabbitMQ broker (uses the `production` vhost)." + } + ] + }, + "serverVariables": { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/serverVariable" + } + ] + } + }, + "info": { + "description": "The object provides metadata about the API. The metadata can be used by the clients if needed.", + "allOf": [ + { + "type": "object", + "required": ["version", "title"], + "properties": { + "title": { + "description": "A unique and precise title of the API.", + "type": "string" + }, + "description": { + "description": "A longer description of the API. Should be different from the title. CommonMark is allowed.", + "type": "string" + }, + "contact": { + "$ref": "#/definitions/contact" + }, + "externalDocs": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/externalDocs" + } + ] + }, + "license": { + "$ref": "#/definitions/license" + }, + "tags": { + "description": "A list of tags for application API documentation control. Tags can be used for logical grouping of applications.", + "type": "array", + "uniqueItems": true, + "items": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/tag" + } + ] + } + }, + "termsOfService": { + "description": "A URL to the Terms of Service for the API. MUST be in the format of a URL.", + "type": "string", + "format": "uri" + }, + "version": { + "description": "A semantic version number of the API.", + "type": "string" + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false + }, + { + "$ref": "#/definitions/infoExtensions" + } + ], + "examples": [ + { + "title": "AsyncAPI Sample App", + "version": "1.0.1", + "description": "This is a sample app.", + "termsOfService": "https://asyncapi.org/terms/", + "contact": { + "name": "API Support", + "url": "https://www.asyncapi.org/support", + "email": "support@asyncapi.org" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "externalDocs": { + "description": "Find more info here", + "url": "https://www.asyncapi.org" + }, + "tags": [ + { + "name": "e-commerce" + } + ] + } + ] + }, + "contact": { + "description": "Contact information for the exposed API.", + "type": "object", + "properties": { + "email": { + "description": "The email address of the contact person/organization.", + "type": "string", + "format": "email" + }, + "name": { + "description": "The identifying name of the contact person/organization.", + "type": "string" + }, + "url": { + "description": "The URL pointing to the contact information.", + "type": "string", + "format": "uri" + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + } + ] + }, + "license": { + "type": "object", + "required": ["name"], + "properties": { + "name": { + "description": "The name of the license type. It's encouraged to use an OSI compatible license.", + "type": "string" + }, + "url": { + "description": "The URL pointing to the license.", + "type": "string", + "format": "uri" + } + }, + "patternProperties": { + "^x-[\\w\\d\\.\\x2d_]+$": { + "$ref": "#/definitions/specificationExtension" + } + }, + "additionalProperties": false, + "examples": [ + { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + } + ] + }, + "infoExtensions": { + "description": "The object that lists all the extensions of Info", + "type": "object", + "properties": { + "x-linkedin": { + "$ref": "#/definitions/extensions-linkedin-0.1.0-schema" + }, + "x-x": { + "$ref": "#/definitions/extensions-x-0.1.0-schema" + } + } + }, + "extensions-linkedin-0.1.0-schema": { + "type": "string", + "pattern": "^http(s)?://(www\\.)?linkedin\\.com.*$", + "description": "This extension allows you to provide the Linkedin profile URL of the account representing the team/company of the API.", + "example": [ + "https://www.linkedin.com/company/asyncapi/", + "https://www.linkedin.com/in/sambhavgupta0705/" + ] + }, + "extensions-x-0.1.0-schema": { + "type": "string", + "description": "This extension allows you to provide the Twitter username of the account representing the team/company of the API.", + "example": ["sambhavgupta75", "AsyncAPISpec"] + }, + "operations": { + "description": "Holds a dictionary with all the operations this application MUST implement.", + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/operation" + } + ] + }, + "examples": [ + { + "onUserSignUp": { + "title": "User sign up", + "summary": "Action to sign a user up.", + "description": "A longer description", + "channel": { + "$ref": "#/channels/userSignup" + }, + "action": "send", + "tags": [ + { + "name": "user" + }, + { + "name": "signup" + }, + { + "name": "register" + } + ], + "bindings": { + "amqp": { + "ack": false + } + }, + "traits": [ + { + "$ref": "#/components/operationTraits/kafka" + } + ] + } + } + ] + }, + "servers": { + "description": "An object representing multiple servers.", + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "$ref": "#/definitions/Reference" + }, + { + "$ref": "#/definitions/server" + } + ] + }, + "examples": [ + { + "development": { + "host": "localhost:5672", + "description": "Development AMQP broker.", + "protocol": "amqp", + "protocolVersion": "0-9-1", + "tags": [ + { + "name": "env:development", + "description": "This environment is meant for developers to run their own tests." + } + ] + }, + "staging": { + "host": "rabbitmq-staging.in.mycompany.com:5672", + "description": "RabbitMQ broker for the staging environment.", + "protocol": "amqp", + "protocolVersion": "0-9-1", + "tags": [ + { + "name": "env:staging", + "description": "This environment is a replica of the production environment." + } + ] + }, + "production": { + "host": "rabbitmq.in.mycompany.com:5672", + "description": "RabbitMQ broker for the production environment.", + "protocol": "amqp", + "protocolVersion": "0-9-1", + "tags": [ + { + "name": "env:production", + "description": "This environment is the live environment available for final users." + } + ] + } + } + ] + } + }, + "description": "!!Auto generated!! \n Do not manually edit. " +} diff --git a/config/AMBASSADORS_MEMBERS.json b/config/AMBASSADORS_MEMBERS.json index be1bbd02746f..929c061e9ce7 100644 --- a/config/AMBASSADORS_MEMBERS.json +++ b/config/AMBASSADORS_MEMBERS.json @@ -1,68 +1,18 @@ [ - { - "name": "Quetzalli Writes", - "img": "https://avatars.githubusercontent.com/u/19964402?v=4", - "bio": "Quetzalli Writes is an author of the book titled 'Docs-as-Ecosystem', which was published by the Apress Publishing Company. Quetzalli has been in tech for 9 years, working with SEO, Paid Search, Full-Stack development, UX, Developer Relations, and Technical Writing (Engineering Documentation). She's currently a core OSS contributor for Docs, DevRel, and Community Building at AsyncAPI Initiative. She's also a member of the AsyncAPI Technical Steering Committee (TSC).", - "title": "DevRel & DevDocs @AsyncAPI", - "github": "quetzalliwrites", - "githubID": 19964402, - "slack": "U02AKC14WAJ", - "twitter": "QuetzalliWrites", - "linkedin": "quetzalli-writes", - "company": "Postman", - "country": "\ud83c\uddf2\ud83c\uddfd", - "contributions": [ - { - "type": "presentation", - "title": "How to contribute to AsyncAPI Dev Docs, AsyncAPI Conference", - "date": { - "year": 2021, - "month": "November" - }, - "link": "https://www.youtube.com/watch?v=xAzbDDEbQ18" - }, - { - "type": "workshop", - "title": "Workshop on contributing to AsyncAPI, CCOSS", - "date": { - "year": 2021, - "month": "October" - }, - "link": "https://ccoss.org/sessions/2021/taller-contribucion-asyncapi/" - }, - { - "type": "article", - "title": "Change is coming to our AsyncAPI Developer Documentation", - "date": { - "year": 2021, - "month": "December" - }, - "link": "https://www.asyncapi.com/blog/changes-coming-docs" - }, - { - "type": "initiative_driver", - "title": "Driver and promoter of Google Season of Docs at AsyncAPI", - "date": { - "year": 2022, - "month": "December" - }, - "link": "https://www.asyncapi.com/blog/google-season-of-docs-2022" - } - ] - }, { "name": "Daniel Kocot", "img": "https://avatars.githubusercontent.com/u/466609?v=4", - "bio": "Daniel has been part of the codecentric team since October 2016. Since the beginning of 2022 he works as Senior Solution Architect at the Dortmund branch. Starting as a consultant with a focus on application lifecycle management, his focus shifted more and more towards APIs. In addition to numerous customer projects and his involvement in the open source world around APIs, our Head of API Experience & Operations is also a frequent speaker at conferences.", - "title": "Senior Solution Architect / Head of API Experience and Operations", + "bio": "Daniel joined the team at adorsys GmbH & Co. KG as Principal Integration Architect in January 2026. He has been dedicated to integration-related topics for almost 10 years. Initially focusing on gateways and the early days of APIOps, he later shifted his focus to methodologies, strategy, and enterprise architecture. In his daily work with his customers, he attaches particular importance to ensuring that interfaces are not only understood as technical tools.", + "title": "Principal Integration Architect", "github": "danielkocot", "githubID": 466609, "slack": "U029F3XUYM8", - "twitter": "dk_1977", + "twitter": "", "linkedin": "danielkocot", - "company": "codecentric AG", + "company": "adorsys GmbH & Co. KG", "country": "\ud83c\udde9\ud83c\uddea", "isTscMember": true, + "tscMemberSince": "2025-05-28", "contributions": [ { "type": "article", @@ -166,6 +116,7 @@ "company": "Kong", "country": "\ud83c\uddf2\ud83c\uddfd", "isTscMember": true, + "tscMemberSince": "2025-06-10", "isBoardMember": true, "contributions": [ { @@ -223,7 +174,7 @@ "twitter": "ivangsa", "bio": "Java Architect with a deep understanding of Java, Spring-Boot, Spring-Cloud technologies, specializing in Domain-Driven Design (DDD) and Event-Driven Architectures creating Software Easy to Understand. Building ZenWave 360\u00ba. ZenWave 360\u00ba is a set of tools built on the foundations of Domain Driven Design and API-First principles for Event-Driven Architectures, to help you create software easy to understand. https://www.zenwave360.io/", "linkedin": "ivangarciasainzaja", - "company": "IZERTIS", + "company": "ZenWave360", "title": "Java Architect. Speaker. Building ZenWave 360\u00b0.", "img": "https://avatars.githubusercontent.com/u/1246876?v=4", "contributions": [ @@ -298,6 +249,60 @@ "month": "October" }, "link": "https://www.youtube.com/watch?v=gUsoD8RaCuw" + }, + { + "type": "talk", + "title": "AsyncAPI Full Code Generation for Java with ZenWave SDK", + "date": { + "year": 2024, + "month": "October" + }, + "link": "https://www.youtube.com/watch?v=q5vt2TLGoaQ" + }, + { + "type": "article", + "title": "Transactional OutBox With AsyncAPI, SpringModulith and ZenWaveSDK (full project and tutorial)", + "date": { + "year": 2025, + "month": "April" + }, + "link": "https://www.zenwave360.io/posts/TransactionalOutBoxWithAsyncAPIAndSpringModulith/" + }, + { + "type": "talk", + "title": "Arquitecturas Event-Driven y Monolitos Modulares con AsyncAPI", + "date": { + "year": 2025, + "month": "May" + }, + "link": "https://www.youtube.com/watch?v=08MWIWljbIQ" + }, + { + "type": "talk", + "title": "Event-Driven Architectures with Spring Modulith and AsyncAPI", + "date": { + "year": 2025, + "month": "May" + }, + "link": "https://2025.springio.net/sessions/event-driven-architectures-with-spring-modulith-and-asyncapi/" + }, + { + "type": "article", + "title": "ZenWave AsyncAPI Generator", + "date": { + "year": 2025, + "month": "October" + }, + "link": "https://www.zenwave360.io/zenwave-sdk/plugins/asyncapi-generator/" + }, + { + "type": "article", + "title": "ShoppingCart with AsyncAPI (full project and tutorial)", + "date": { + "year": 2026, + "month": "Jan" + }, + "link": "https://www.zenwave360.io/docs/examples/eda-examples/asyncapi-shopping-cart/" } ] }, @@ -445,6 +450,7 @@ "title": "Founder, and CEO at Polarizer Technologies", "img": "https://raw.githubusercontent.com/harikrishnan83/harikrishnan83/master/HariKrishnan-profile.jpg", "isTscMember": true, + "tscMemberSince": "2025-01-21", "contributions": [ { "type": "talk", @@ -511,126 +517,6 @@ } ] }, - { - "name": "Manuel Ottlik", - "github": "manuelottlik", - "githubID": 28919003, - "slack": "U07GXSEH0E6", - "twitter": "", - "linkedin": "manuelottlik", - "country": "\ud83c\udde9\ud83c\uddea", - "bio": "Manuel is the Product Owner of the Global Integration Platform at HDI Global SE. He sold his first software at the age of thirteen and has been developing software ever since. After graduating, he joined the financial industry in API management and eventually moved to HDI Global SE to merge a service bus, API management and an event broker into an integration platform for the cloud division. In addition to his work at HDI Global SE, he is co-founder of a small company in the education software sector and freelance writer for heise.de and its magazines.", - "company": "HDI Global SE", - "title": "Product Owner Integration Platform & PBAC Platform", - "img": "https://avatars.githubusercontent.com/u/28919003?v=4", - "contributions": [ - { - "type": "talk", - "title": "Event-Driven Architecture und REST-APIs: Es gibt keine Konkurrenz!", - "date": { - "year": 2023, - "month": "April" - }, - "link": "" - }, - { - "type": "talk", - "title": "Event-driven Architecture and REST-APIs: It's not a competition", - "date": { - "year": 2023, - "month": "May" - }, - "link": "" - }, - { - "type": "talk", - "title": "Event-driven Architecture and REST-APIs: It's not a competition", - "date": { - "year": 2023, - "month": "September" - }, - "link": "" - }, - { - "type": "talk", - "title": "Event-Driven Architecture und REST-APIs: Es gibt keine Konkurrenz!", - "date": { - "year": 2023, - "month": "October" - }, - "link": "" - }, - { - "type": "talk", - "title": "Event-driven Architecture and REST-APIs: It's not a competition", - "date": { - "year": 2023, - "month": "December" - }, - "link": "https://drive.google.com/file/d/1KN-iuw0P4nOYNhnT15RQvgq5YqGy4ECC/view?usp=sharing" - }, - { - "type": "talk", - "title": "Eine Registry, sie alle zu knechten: Schemata von Entit\u00e4ten mit xRegistry f\u00fcr alle Integrationsprodukte zentralisieren", - "date": { - "year": 2024, - "month": "April" - }, - "link": "" - }, - { - "type": "article", - "title": "AsyncAPI - HDI Global SE Case Study", - "date": { - "year": 2024, - "month": "July" - }, - "link": "https://www.asyncapi.com/casestudies/hdiglobal" - } - ] - }, - { - "name": "Lorna Mitchell", - "bio": "Lorna is based in Yorkshire, UK; she is a technology leader and expert in developer experience, passionate about enhancing APIs and developer tools. In her day job as VP of Developer Experience at Redocly, she works on API and documentation tools for technical teams. Lorna is a published author and a regular speaker at conferences, sharing her insights on a variety of tech-related topics. Lorna serves on the OpenUK board, is on the Technical Steering Committee for OpenAPI specification, and maintains open source projects. To learn more about Lorna's activities, visit her website at https://lornajane.net.", - "title": "APIs and Open Source", - "img": "https://lornajane.net/wp-content/uploads/2011/08/IMG_9410-smaller.jpg", - "github": "lornajane", - "githubID": 172607, - "slack": "U017NCG83AQ", - "twitter": "lornajane", - "linkedin": "lornajane", - "company": "Redocly", - "country": "UK", - "contributions": [ - { - "type": "presentation", - "title": "API Governance for AsyncAPI", - "date": { - "year": 2023, - "month": "September" - }, - "link": "https://noti.st/lornajane/aOuXwe/api-governance-for-asyncapi" - }, - { - "type": "presentation", - "title": "AsyncAPI for Apache Kafka", - "date": { - "year": 2021, - "month": "May" - }, - "link": "https://videos.confluent.io/watch/hzjXP8QmLtYRNPukNFUu2D?" - }, - { - "type": "article", - "title": "Lint AsyncAPI with Redocly CLI", - "date": { - "year": 2023, - "month": "August" - }, - "link": "https://redocly.com/docs/cli/guides/lint-asyncapi" - } - ] - }, { "name": "Laurent Broudoux", "github": "lbroudoux", @@ -709,6 +595,7 @@ "linkedin": "http://linkedin.com/in/nareshjain/", "country": "\ud83c\uddee\ud83c\uddf3", "isTscMember": true, + "tscMemberSince": "2025-05-28", "bio": "Naresh is an internationally recognised Technology & Product Development Expert. Over the last 25 years, he has played a key role in streamlining the product engineering culture at many unicorns and fortune 500 companies. Naresh is the Founder, CEO of several companies - Xnsio, ConfEngine and Specmatic. Naresh is also the local organiser of API Days India. In 2004, Naresh started the Agile movement in India. More details: https://nareshjain.com", "company": "Specmatic, Xnsio, ConfEngine", "title": "Founder, CEO at Specmatic, Xnsio and ConfEngine", diff --git a/config/MAINTAINERS.json b/config/MAINTAINERS.json index 2f28f4c9a5a8..243640f42470 100644 --- a/config/MAINTAINERS.json +++ b/config/MAINTAINERS.json @@ -7,6 +7,7 @@ "twitter": "maya_ux_ui", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2023-07-13", "repos": [ "website", "conference-website", @@ -22,6 +23,7 @@ "twitter": "aayushmau5", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "diff" ], @@ -35,7 +37,9 @@ "twitter": "Aayush__Saini_", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2025-01-13", "repos": [ + "openapi-schema-parser", "cli" ], "githubID": 60972989 @@ -48,6 +52,7 @@ "github": "imabp", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "problem" ], @@ -61,6 +66,7 @@ "twitter": "AksNema", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "website" ], @@ -74,6 +80,7 @@ "twitter": "thisisanshg", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2024-05-29", "repos": [ "website" ], @@ -99,6 +106,7 @@ "twitter": "Shurtu_Gal", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2024-01-26", "repos": [ "studio", ".github", @@ -129,6 +137,7 @@ "twitter": "dalelane", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2023-07-05", "company": "IBM", "repos": [ "spec", @@ -158,6 +167,7 @@ "availableForHire": false, "linkedin": "fmvilas", "isTscMember": true, + "tscMemberSince": "2023-07-05", "isBoardMember": true, "repos": [ "spec", @@ -197,6 +207,7 @@ "company": "EventStack", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "spec-json-schemas", "generator", @@ -215,11 +226,10 @@ "slack": "U01RVRD1TCL", "availableForHire": false, "company": "Postman", - "isTscMember": true, + "isTscMember": false, "repos": [ "spec-json-schemas", - "studio", - "optimizer" + "studio" ], "githubID": 32505158 }, @@ -260,6 +270,7 @@ "twitter": "derberq", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "spec", "website", @@ -289,6 +300,7 @@ "slack": "U01EB02BP7A", "company": "Travelping GmbH", "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "generator", "asyncapi-react", @@ -314,6 +326,7 @@ "slack": "U01RWDD69PZ", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "asyncapi-react", "conference-website", @@ -342,6 +355,7 @@ "twitter": "pbodiachevskii", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "spec-json-schemas", "tck", @@ -357,6 +371,7 @@ "twitter": "philschlesinger", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "jasyncapi-idea-plugin" ], @@ -370,6 +385,7 @@ "twitter": "iamPrince_2003", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2023-11-30", "repos": [ "website", "studio" @@ -384,6 +400,7 @@ "availableForHire": false, "company": "IBM", "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "spec-json-schemas", "bindings" @@ -399,6 +416,7 @@ "company": "Apideck", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2024-01-26", "repos": [ "studio", "cli" @@ -430,6 +448,7 @@ "company": "Xane AI", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "cli", "bundler" @@ -442,7 +461,7 @@ "slack": "U02FP8WBFQE", "linkedin": "danielr", "availableForHire": false, - "isTscMember": true, + "isTscMember": false, "repos": [ "java-template" ], @@ -480,6 +499,7 @@ "availableForHire": true, "slack": "U011D1DAU6S", "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "java-spring-template" ], @@ -493,6 +513,7 @@ "availableForHire": false, "company": "ThoughtWorks", "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "modelina" ], @@ -506,6 +527,7 @@ "availableForHire": false, "company": "SNGULAR", "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "vs-asyncapi-preview" ], @@ -519,6 +541,7 @@ "twitter": "njericodes", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "generator", ".github" @@ -534,6 +557,7 @@ "availableForHire": false, "company": "Google", "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "spec-json-schemas", "bindings" @@ -563,7 +587,7 @@ "slack": "U04C58GB8TF", "availableForHire": false, "company": "The LEGO Group", - "isTscMember": true, + "isTscMember": false, "repos": [ "spec-json-schemas", "bindings" @@ -578,6 +602,7 @@ "availableForHire": false, "company": "Sportradar", "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "modelina" ], @@ -589,7 +614,7 @@ "slack": "U03AC4G51H8", "availableForHire": false, "company": "mtrail GmbH", - "isTscMember": true, + "isTscMember": false, "repos": [ "spec", "spec-json-schemas", @@ -631,6 +656,7 @@ "availableForHire": false, "company": "AsyncAPI Initiative", "isTscMember": true, + "tscMemberSince": "2023-07-05", "isBoardMember": true, "repos": [ "website", @@ -639,20 +665,6 @@ ], "githubID": 66913810 }, - { - "name": "Ashmit JaiSarita Gupta", - "github": "devilkiller-ag", - "linkedin": "jaisarita", - "twitter": "jaisarita", - "slack": "U062LA14E58", - "availableForHire": true, - "isTscMember": true, - "repos": [ - "website", - "modelina" - ], - "githubID": 43639341 - }, { "name": "Sambhav Gupta", "github": "sambhavgupta0705", @@ -660,7 +672,7 @@ "twitter": "sambhavgupta75", "slack": "U04630DU3N3", "availableForHire": true, - "isTscMember": true, + "isTscMember": false, "repos": [ "website" ], @@ -686,6 +698,7 @@ "twitter": "TRRohit20", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2025-02-17", "repos": [ "website" ], @@ -855,19 +868,6 @@ ], "githubID": 758568 }, - { - "name": "Ashmit Jagtap", - "github": "ashmit-coder", - "linkedin": "ashmit-jagtap", - "twitter": "AshmitJagtap", - "slack": "U06RA7GDHU1", - "availableForHire": true, - "isTscMember": true, - "repos": [ - "conference-website" - ], - "githubID": 69006513 - }, { "name": "HariKrishnan", "github": "harikrishnan83", @@ -876,6 +876,7 @@ "slack": "U067JPY0UH5", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2025-01-21", "repos": [ "jasyncapi" ], @@ -888,6 +889,7 @@ "slack": "U02MRF09BL1", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2025-03-25", "repos": [ "net-sdk" ], @@ -900,6 +902,7 @@ "linkedin": "jean-baptiste-bianchi-aa42b914", "slack": "U08K91GKK8T", "isTscMember": true, + "tscMemberSince": "2025-03-25", "availableForHire": false, "repos": [ "net-sdk" @@ -914,9 +917,9 @@ "slack": "U05FM7WRKU4", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2025-03-25", "repos": [ - "website", - "conference-website" + "website" ], "githubID": 90895835 }, @@ -950,6 +953,7 @@ "slack": "U0867GV384D", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2025-08-27", "repos": [ "generator" ], @@ -960,10 +964,52 @@ "github": "Ruchip16", "twitter": "Ruchicodess", "availableForHire": true, - "isTscMember": true, + "isTscMember": false, "repos": [ "vs-asyncapi-preview" ], "githubID": 72685035 + }, + { + "name": "amparosancho", + "github": "amparosancho", + "isTscMember": false, + "repos": [ + "spec-json-schemas", + "bindings" + ], + "githubID": 214812239 + }, + { + "name": "Florian Gram\u00df", + "github": "gramss", + "isTscMember": false, + "repos": [ + "spec-json-schemas", + "bindings" + ], + "githubID": 6034322 + }, + { + "name": "TenzDelek", + "github": "TenzDelek", + "linkedin": "tenzdelek", + "slack": "U06SWFWLLQG", + "availableForHire": true, + "isTscMember": true, + "tscMemberSince": "2026-02-17", + "repos": [ + "conference-website" + ], + "githubID": 122612557 + }, + { + "name": "Mohammed Mehdi", + "github": "catosaurusrex2003", + "isTscMember": false, + "repos": [ + "asyncapi-react" + ], + "githubID": 96487647 } ] \ No newline at end of file diff --git a/config/TSC_BOARD_MEMBERS.json b/config/TSC_BOARD_MEMBERS.json index 1929dd41c532..90b45829e063 100644 --- a/config/TSC_BOARD_MEMBERS.json +++ b/config/TSC_BOARD_MEMBERS.json @@ -7,6 +7,7 @@ "twitter": "maya_ux_ui", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2023-07-13", "repos": [ "website", "conference-website", @@ -22,6 +23,7 @@ "twitter": "aayushmau5", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "diff" ], @@ -35,7 +37,9 @@ "twitter": "Aayush__Saini_", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2025-01-13", "repos": [ + "openapi-schema-parser", "cli" ], "githubID": 60972989 @@ -48,6 +52,7 @@ "github": "imabp", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "problem" ], @@ -61,6 +66,7 @@ "twitter": "AksNema", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "website" ], @@ -74,6 +80,7 @@ "twitter": "thisisanshg", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2024-05-29", "repos": [ "website" ], @@ -87,6 +94,7 @@ "twitter": "Shurtu_Gal", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2024-01-26", "repos": [ "studio", ".github", @@ -102,6 +110,7 @@ "twitter": "dalelane", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2023-07-05", "company": "IBM", "repos": [ "spec", @@ -119,6 +128,7 @@ "availableForHire": false, "linkedin": "fmvilas", "isTscMember": true, + "tscMemberSince": "2023-07-05", "isBoardMember": true, "repos": [ "spec", @@ -145,6 +155,7 @@ "company": "EventStack", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "spec-json-schemas", "generator", @@ -155,22 +166,6 @@ ], "githubID": 13396189 }, - { - "name": "Khuda Dad Nomani", - "github": "KhudaDad414", - "twitter": "KhudaDadNomani", - "linkedin": "khudadadnomani", - "slack": "U01RVRD1TCL", - "availableForHire": false, - "company": "Postman", - "isTscMember": true, - "repos": [ - "spec-json-schemas", - "studio", - "optimizer" - ], - "githubID": 32505158 - }, { "name": "Lukasz Gornicki", "github": "derberg", @@ -179,6 +174,7 @@ "twitter": "derberq", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "spec", "website", @@ -208,6 +204,7 @@ "slack": "U01EB02BP7A", "company": "Travelping GmbH", "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "generator", "asyncapi-react", @@ -233,6 +230,7 @@ "slack": "U01RWDD69PZ", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "asyncapi-react", "conference-website", @@ -247,6 +245,7 @@ "twitter": "pbodiachevskii", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "spec-json-schemas", "tck", @@ -262,6 +261,7 @@ "twitter": "philschlesinger", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "jasyncapi-idea-plugin" ], @@ -275,6 +275,7 @@ "twitter": "iamPrince_2003", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2023-11-30", "repos": [ "website", "studio" @@ -289,6 +290,7 @@ "availableForHire": false, "company": "IBM", "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "spec-json-schemas", "bindings" @@ -304,6 +306,7 @@ "company": "Apideck", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2024-01-26", "repos": [ "studio", "cli" @@ -319,24 +322,13 @@ "company": "Xane AI", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "cli", "bundler" ], "githubID": 41781438 }, - { - "name": "Daniel Raper", - "github": "dan-r", - "slack": "U02FP8WBFQE", - "linkedin": "danielr", - "availableForHire": false, - "isTscMember": true, - "repos": [ - "java-template" - ], - "githubID": 1384852 - }, { "name": "Semen Tenishchev", "github": "Tenischev", @@ -344,6 +336,7 @@ "availableForHire": true, "slack": "U011D1DAU6S", "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "java-spring-template" ], @@ -357,6 +350,7 @@ "availableForHire": false, "company": "ThoughtWorks", "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "modelina" ], @@ -368,8 +362,9 @@ "linkedin": "ivangarciasainzaja", "slack": "UTCN3ET4M", "availableForHire": false, - "company": "IZERTIS", + "company": "ZenWave360", "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "vs-asyncapi-preview" ], @@ -450,6 +445,60 @@ "month": "October" }, "link": "https://www.youtube.com/watch?v=gUsoD8RaCuw" + }, + { + "type": "talk", + "title": "AsyncAPI Full Code Generation for Java with ZenWave SDK", + "date": { + "year": 2024, + "month": "October" + }, + "link": "https://www.youtube.com/watch?v=q5vt2TLGoaQ" + }, + { + "type": "article", + "title": "Transactional OutBox With AsyncAPI, SpringModulith and ZenWaveSDK (full project and tutorial)", + "date": { + "year": 2025, + "month": "April" + }, + "link": "https://www.zenwave360.io/posts/TransactionalOutBoxWithAsyncAPIAndSpringModulith/" + }, + { + "type": "talk", + "title": "Arquitecturas Event-Driven y Monolitos Modulares con AsyncAPI", + "date": { + "year": 2025, + "month": "May" + }, + "link": "https://www.youtube.com/watch?v=08MWIWljbIQ" + }, + { + "type": "talk", + "title": "Event-Driven Architectures with Spring Modulith and AsyncAPI", + "date": { + "year": 2025, + "month": "May" + }, + "link": "https://2025.springio.net/sessions/event-driven-architectures-with-spring-modulith-and-asyncapi/" + }, + { + "type": "article", + "title": "ZenWave AsyncAPI Generator", + "date": { + "year": 2025, + "month": "October" + }, + "link": "https://www.zenwave360.io/zenwave-sdk/plugins/asyncapi-generator/" + }, + { + "type": "article", + "title": "ShoppingCart with AsyncAPI (full project and tutorial)", + "date": { + "year": 2026, + "month": "Jan" + }, + "link": "https://www.zenwave360.io/docs/examples/eda-examples/asyncapi-shopping-cart/" } ] }, @@ -461,6 +510,7 @@ "twitter": "njericodes", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "generator", ".github" @@ -476,26 +526,13 @@ "availableForHire": false, "company": "Google", "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "spec-json-schemas", "bindings" ], "githubID": 98899 }, - { - "name": "Alexander Wichmann", - "github": "VisualBean", - "linkedin": "alexcarlsen", - "slack": "U04C58GB8TF", - "availableForHire": false, - "company": "The LEGO Group", - "isTscMember": true, - "repos": [ - "spec-json-schemas", - "bindings" - ], - "githubID": 5294032 - }, { "name": "Kenneth Aasan", "github": "kennethaasan", @@ -504,26 +541,12 @@ "availableForHire": false, "company": "Sportradar", "isTscMember": true, + "tscMemberSince": "2023-07-05", "repos": [ "modelina" ], "githubID": 1437394 }, - { - "name": "Heiko Henning", - "github": "GreenRover", - "slack": "U03AC4G51H8", - "availableForHire": false, - "company": "mtrail GmbH", - "isTscMember": true, - "repos": [ - "spec", - "spec-json-schemas", - "bindings", - "protobuf-schema-parser" - ], - "githubID": 512850 - }, { "name": "Thulisile Sibanda", "github": "thulieblack", @@ -533,6 +556,7 @@ "availableForHire": false, "company": "AsyncAPI Initiative", "isTscMember": true, + "tscMemberSince": "2023-07-05", "isBoardMember": true, "repos": [ "website", @@ -541,33 +565,6 @@ ], "githubID": 66913810 }, - { - "name": "Ashmit JaiSarita Gupta", - "github": "devilkiller-ag", - "linkedin": "jaisarita", - "twitter": "jaisarita", - "slack": "U062LA14E58", - "availableForHire": true, - "isTscMember": true, - "repos": [ - "website", - "modelina" - ], - "githubID": 43639341 - }, - { - "name": "Sambhav Gupta", - "github": "sambhavgupta0705", - "linkedin": "sambhavgupta0705", - "twitter": "sambhavgupta75", - "slack": "U04630DU3N3", - "availableForHire": true, - "isTscMember": true, - "repos": [ - "website" - ], - "githubID": 81870866 - }, { "name": "Rohit T", "github": "TRohit20", @@ -576,24 +573,12 @@ "twitter": "TRRohit20", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2025-02-17", "repos": [ "website" ], "githubID": 108233235 }, - { - "name": "Ashmit Jagtap", - "github": "ashmit-coder", - "linkedin": "ashmit-jagtap", - "twitter": "AshmitJagtap", - "slack": "U06RA7GDHU1", - "availableForHire": true, - "isTscMember": true, - "repos": [ - "conference-website" - ], - "githubID": 69006513 - }, { "name": "Hari Krishnan", "github": "harikrishnan83", @@ -602,6 +587,7 @@ "slack": "U067JPY0UH5", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2025-01-21", "repos": [ "jasyncapi" ], @@ -684,6 +670,7 @@ "slack": "U02MRF09BL1", "availableForHire": false, "isTscMember": true, + "tscMemberSince": "2025-03-25", "repos": [ "net-sdk" ], @@ -696,6 +683,7 @@ "linkedin": "jean-baptiste-bianchi-aa42b914", "slack": "U08K91GKK8T", "isTscMember": true, + "tscMemberSince": "2025-03-25", "availableForHire": false, "repos": [ "net-sdk" @@ -710,9 +698,9 @@ "slack": "U05FM7WRKU4", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2025-03-25", "repos": [ - "website", - "conference-website" + "website" ], "githubID": 90895835 }, @@ -724,35 +712,39 @@ "slack": "U0867GV384D", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2025-08-27", "repos": [ "generator" ], "githubID": 114283933 }, { - "name": "Ruchi Pakhle", - "github": "Ruchip16", - "twitter": "Ruchicodess", + "name": "TenzDelek", + "github": "TenzDelek", + "linkedin": "tenzdelek", + "slack": "U06SWFWLLQG", "availableForHire": true, "isTscMember": true, + "tscMemberSince": "2026-02-17", "repos": [ - "vs-asyncapi-preview" + "conference-website" ], - "githubID": 72685035 + "githubID": 122612557 }, { "name": "Daniel Kocot", "img": "https://avatars.githubusercontent.com/u/466609?v=4", - "bio": "Daniel has been part of the codecentric team since October 2016. Since the beginning of 2022 he works as Senior Solution Architect at the Dortmund branch. Starting as a consultant with a focus on application lifecycle management, his focus shifted more and more towards APIs. In addition to numerous customer projects and his involvement in the open source world around APIs, our Head of API Experience & Operations is also a frequent speaker at conferences.", - "title": "Senior Solution Architect / Head of API Experience and Operations", + "bio": "Daniel joined the team at adorsys GmbH & Co. KG as Principal Integration Architect in January 2026. He has been dedicated to integration-related topics for almost 10 years. Initially focusing on gateways and the early days of APIOps, he later shifted his focus to methodologies, strategy, and enterprise architecture. In his daily work with his customers, he attaches particular importance to ensuring that interfaces are not only understood as technical tools.", + "title": "Principal Integration Architect", "github": "danielkocot", "githubID": 466609, "slack": "U029F3XUYM8", - "twitter": "dk_1977", + "twitter": "", "linkedin": "danielkocot", - "company": "codecentric AG", + "company": "adorsys GmbH & Co. KG", "country": "\ud83c\udde9\ud83c\uddea", "isTscMember": true, + "tscMemberSince": "2025-05-28", "contributions": [ { "type": "article", @@ -805,6 +797,7 @@ "company": "Kong", "country": "\ud83c\uddf2\ud83c\uddfd", "isTscMember": true, + "tscMemberSince": "2025-06-10", "isBoardMember": true, "contributions": [ { @@ -863,6 +856,7 @@ "linkedin": "http://linkedin.com/in/nareshjain/", "country": "\ud83c\uddee\ud83c\uddf3", "isTscMember": true, + "tscMemberSince": "2025-05-28", "bio": "Naresh is an internationally recognised Technology & Product Development Expert. Over the last 25 years, he has played a key role in streamlining the product engineering culture at many unicorns and fortune 500 companies. Naresh is the Founder, CEO of several companies - Xnsio, ConfEngine and Specmatic. Naresh is also the local organiser of API Days India. In 2004, Naresh started the Agile movement in India. More details: https://nareshjain.com", "company": "Specmatic, Xnsio, ConfEngine", "title": "Founder, CEO at Specmatic, Xnsio and ConfEngine", diff --git a/config/all-tags.json b/config/all-tags.json index e11eb435641c..79f9f1783833 100644 --- a/config/all-tags.json +++ b/config/all-tags.json @@ -277,23 +277,18 @@ "color": "bg-[#61d0f2]", "borderColor": "border-[#40ccf7]" }, - { - "name": "AsyncAPI CLI", - "color": "bg-[#61d0f2]", - "borderColor": "border-[#40ccf7]" - }, { "name": "AsyncAPI Generator", "color": "bg-[#61d0f2]", "borderColor": "border-[#40ccf7]" }, { - "name": "JavaScript", + "name": "AsyncAPI CLI", "color": "bg-[#61d0f2]", "borderColor": "border-[#40ccf7]" }, { - "name": "VSCode", + "name": "JavaScript", "color": "bg-[#61d0f2]", "borderColor": "border-[#40ccf7]" }, @@ -302,18 +297,13 @@ "color": "bg-[#61d0f2]", "borderColor": "border-[#40ccf7]" }, - { - "name": "JetBrains", - "color": "bg-[#61d0f2]", - "borderColor": "border-[#40ccf7]" - }, { "name": "SmartPaste", "color": "bg-[#61d0f2]", "borderColor": "border-[#40ccf7]" }, { - "name": "SmartPaste", + "name": "JetBrains", "color": "bg-[#61d0f2]", "borderColor": "border-[#40ccf7]" }, @@ -327,16 +317,6 @@ "color": "bg-[#61d0f2]", "borderColor": "border-[#40ccf7]" }, - { - "name": "HTML", - "color": "bg-[#61d0f2]", - "borderColor": "border-[#40ccf7]" - }, - { - "name": "HTML", - "color": "bg-[#61d0f2]", - "borderColor": "border-[#40ccf7]" - }, { "name": "Watermill", "color": "bg-[#61d0f2]", diff --git a/config/edit-page-config.json b/config/edit-page-config.json index 48dcae513a11..d6d0287a693e 100644 --- a/config/edit-page-config.json +++ b/config/edit-page-config.json @@ -1,4 +1,8 @@ [ + { + "value": "reference/bindings/", + "href": "https://github.com/asyncapi/bindings/tree/master" + }, { "value": "/tools/generator", "href": "https://github.com/asyncapi/generator/tree/master/apps/generator/docs" diff --git a/config/meetings.json b/config/meetings.json index 95f3e07e98ef..b427f81afc77 100644 --- a/config/meetings.json +++ b/config/meetings.json @@ -1,107 +1,142 @@ [ { - "title": "Marketing WG Meeting", - "calLink": "https://www.google.com/calendar/event?eid=MnNmMmtnbzI2MDdicXZmbWtsMnYyZWNrYTAgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/1925", + "title": "AsyncAPI Spec Triage", + "calLink": "https://www.google.com/calendar/event?eid=bzhsODIxZWYxdDk3cnQyNGJ0ZGZhYTY3YXMgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/2244", "banner": "", - "date": "2025-10-06T14:00:00.000Z" + "date": "2026-01-22T16:00:00.000Z" }, { - "title": "AsyncAPI Webinar With Lukasz", - "calLink": "https://www.google.com/calendar/event?eid=YWU2Nzc3aW9uaG1jMG4wMzlyZXIwZnZrYzggY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/2052", - "banner": "", - "date": "2025-09-30T16:00:00.000Z" + "title": "Provide updates on the progress the builders are making on the different programs they're leading.", + "calLink": "https://www.google.com/calendar/event?eid=dTl1aDk1M3BzZmYzNThvZGxqNmZ0NnM5MHMgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/2248", + "banner": "https://github.com/user-attachments/assets/b4e255b8-5c7e-4821-82c9-3bcbc18b68ef", + "date": "2026-02-03T15:00:00.000Z" }, { "title": "AsyncAPI Community WG Meeting", - "calLink": "https://www.google.com/calendar/event?eid=N3A1ajdoOHFwdnM1MGVpNG9yYmNqaDBvNDQgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/2066", - "banner": "https://github.com/user-attachments/assets/e0c22c5a-94a8-488c-970c-14aa1697283c", - "date": "2025-09-23T15:00:00.000Z" + "calLink": "https://www.google.com/calendar/event?eid=NDdnbm5wbXYzdmh1NjM4NzQxNDkydHNlNGsgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/2249", + "banner": "https://github.com/user-attachments/assets/b4e255b8-5c7e-4821-82c9-3bcbc18b68ef", + "date": "2026-02-03T15:00:00.000Z" }, { "title": "Governance Board Meeting", - "calLink": "https://www.google.com/calendar/event?eid=ZmpvZTljZzdkY2pkcXZiczV2MmM1YnE4Y2MgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/2074", + "calLink": "https://www.google.com/calendar/event?eid=a2QzdDBwNzk3bDk3M3NodnY0NDdhdGM3aTggY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/2256", "banner": "", - "date": "2025-09-29T16:00:00.000Z" + "date": "2026-01-26T16:00:00.000Z" }, { - "title": "AsyncAPI Online Conference 2025", - "calLink": "https://www.google.com/calendar/event?eid=MzBrbmNtbDRqYWcyMDQ2YmwycTE0bTRpYmcgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/2077", - "banner": "", - "date": "2025-10-29T10:00:00.000Z" + "title": "AsyncAPI Community WG Meeting", + "calLink": "https://www.google.com/calendar/event?eid=aXQwdHFudTgyMzA1ZDZrMmtjajVxbzUzcm8gY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/2277", + "banner": "https://github.com/user-attachments/assets/b4e255b8-5c7e-4821-82c9-3bcbc18b68ef", + "date": "2026-02-17T15:00:00.000Z" }, { - "title": "AsyncAPI Community WG Meeting", - "calLink": "https://www.google.com/calendar/event?eid=cDduNWJzOWI0NWloNm5wc2ljdTZ0NGd0azQgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/2087", - "banner": "https://github.com/user-attachments/assets/e0c22c5a-94a8-488c-970c-14aa1697283c", - "date": "2025-10-21T15:00:00.000Z" + "title": "Community WG Meeting", + "calLink": "https://www.google.com/calendar/event?eid=ZDVpZ3FyNm11N21xamlrOHI3M2IwcGhoMDggY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/2295", + "banner": "https://github.com/user-attachments/assets/b4e255b8-5c7e-4821-82c9-3bcbc18b68ef", + "date": "2026-03-03T15:00:00.000Z" }, { - "title": "AsyncAPI Community WG Meeting", - "calLink": "https://www.google.com/calendar/event?eid=a29zYnNtaXFxbG9waDM2MG8wbGxmNmRnaGsgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/2107", - "banner": "https://github.com/user-attachments/assets/e0c22c5a-94a8-488c-970c-14aa1697283c", - "date": "2025-11-11T15:00:00.000Z" + "title": "AsyncAPI Governance Board Meeting", + "calLink": "https://www.google.com/calendar/event?eid=Mms3bnA3dXZkbjNpaGJmcTdjMW9iYjd2bTQgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/2300", + "banner": "", + "date": "2026-02-24T15:00:00.000Z" }, { - "title": "Governance Board Meeting", - "calLink": "https://www.google.com/calendar/event?eid=NXFkZ3FpOWRrNnNranM5aHZvMm9vbDM2ZzAgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/2116", + "title": "AsyncAPI Website Triage Meeting | 15:30 UTC Friday February 27, 2026", + "calLink": "https://www.google.com/calendar/event?eid=czM2MWk2bDU4bTIzdnAwbjZvc202MHRoc2cgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/2304", "banner": "", - "date": "2025-11-03T16:00:00.000Z" + "date": "2026-02-27T15:30:00.000Z" + }, + { + "title": "AsyncAPI Website Triage Meeting", + "calLink": "https://www.google.com/calendar/event?eid=ODQzNjFsODRvZ3ZhdmphMXAyN2x0djNkbm8gY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/2306", + "banner": "https://github.com/user-attachments/assets/87b2d7cf-5fc1-4a69-800b-a78e3182e5ea", + "date": "2026-03-04T15:30:00.000Z" }, { "title": "AsyncAPI Community WG Meeting", - "calLink": "https://www.google.com/calendar/event?eid=ZDdxdDBxNGUxaWNic2kzNWZwbmRybmZrY2MgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/2131", - "banner": "https://github.com/user-attachments/assets/e0c22c5a-94a8-488c-970c-14aa1697283c", - "date": "2025-12-02T15:00:00.000Z" + "calLink": "https://www.google.com/calendar/event?eid=cW1udG5wZnZnbnMycDZjNm9lanJmbGVybWMgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/2311", + "banner": "https://github.com/user-attachments/assets/b4e255b8-5c7e-4821-82c9-3bcbc18b68ef", + "date": "2026-03-17T15:00:00.000Z" }, { - "title": "AsyncAPI Spec Triage ", - "calLink": "https://www.google.com/calendar/event?eid=NXYzamZpYW9lajZjMWk1aWtnNzY1NWhidWcgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/2141", + "title": "AsyncAPI Governance Board Meeting", + "calLink": "https://www.google.com/calendar/event?eid=aXZzOGlxbDFzdmUwdDdtbWVrb3Fvb3EzMm8gY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/2314", "banner": "", - "date": "2025-11-19T14:00:00.000Z" + "date": "2026-03-10T15:00:00.000Z" + }, + { + "title": "AsyncAPI Website Triage Meeting", + "calLink": "https://www.google.com/calendar/event?eid=c3A0dmJmbzI0Z3Ria2hkYWVhMG90OW5mZDAgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/2315", + "banner": "https://private-user-images.githubusercontent.com/44585452/556327345-f493d033-e266-4b71-9ff0-d801130a8af3.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzI2NDUzNzAsIm5iZiI6MTc3MjY0NTA3MCwicGF0aCI6Ii80NDU4NTQ1Mi81NTYzMjczNDUtZjQ5M2QwMzMtZTI2Ni00YjcxLTlmZjAtZDgwMTEzMGE4YWYzLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNjAzMDQlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjYwMzA0VDE3MjQzMFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTk4ZmZlZDI0YWNkOTViNzRkNWRkZTI1MTM0YTMzMTgwZmExMjIwYzFjNWE3NWU1MzFkOWZjYzc4YjE1NTk1ZDYmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.-IpfxZKndu6O50VInyiT9vMSQXpMyn5ejXieaGIYTqw", + "date": "2026-03-18T15:30:00.000Z" }, { - "title": "Worfklow Test", - "calLink": "https://www.google.com/calendar/event?eid=MXRuYjBibTNjcXZpcmtvaXF2cDQ5M2ZncDQgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/2183", + "title": "Spec meeting", + "calLink": "https://www.google.com/calendar/event?eid=OHFvMG9icDluOXBvcTlsOG9xdDltaTZkcmcgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/2319", "banner": "", - "date": "2025-12-11T15:00:00.000Z" + "date": "2026-03-25T16:00:00.000Z" }, { - "title": "Governance Board Meeting", - "calLink": "https://www.google.com/calendar/event?eid=NmlyYW5pZWhzbzJnYTlkdm1uMHRubjZsMm8gY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/2186", + "title": "Docs Meeting", + "calLink": "https://www.google.com/calendar/event?eid=Y2o0dm5xa3FtYnM1djNodml1ajBybXQ1dmsgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/2323", "banner": "", - "date": "2025-12-15T16:00:00.000Z" + "date": "2026-03-25T15:00:00.000Z" }, { - "title": "AsyncAPI Spec Triage", - "calLink": "https://www.google.com/calendar/event?eid=dDY0M2M3bDIwOGg0N2ViYTlxdXAwNm02aTAgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/2187", + "title": "AsyncAPI Governance Board Meeting", + "calLink": "https://www.google.com/calendar/event?eid=Y21zaXBzbWY1N2dlNXRpcGk4MjJjcmY0bTQgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/2328", "banner": "", - "date": "2025-12-18T16:00:00.000Z" + "date": "2026-03-24T15:00:00.000Z" + }, + { + "title": "AsyncAPI Community WG Meeting", + "calLink": "https://www.google.com/calendar/event?eid=cDRyamVpZjFra29raGkyam4zbXBjajJuNG8gY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/2329", + "banner": "https://github.com/user-attachments/assets/b4e255b8-5c7e-4821-82c9-3bcbc18b68ef", + "date": "2026-03-31T15:00:00.000Z" }, { - "title": "AsyncAPI Conference Triaging ", - "calLink": "https://www.google.com/calendar/event?eid=aWFucGhpc2xqbTViYWRkNjBkbDMzcWc0cmMgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/2189", + "title": "AsyncAPI Community WG Meeting", + "calLink": "https://www.google.com/calendar/event?eid=NmVic2libGpzbzY0ZTZoN29ramFvNWswbTggY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/3498", + "banner": "https://github.com/user-attachments/assets/b4e255b8-5c7e-4821-82c9-3bcbc18b68ef", + "date": "2026-04-14T15:00:00.000Z" + }, + { + "title": "AsyncAPI Docs Meeting", + "calLink": "https://www.google.com/calendar/event?eid=ZzlqcTcyYzhnYmI0bzlnbG9qbnZsczlwaGMgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/3507", "banner": "", - "date": "2025-12-16T13:00:00.000Z" + "date": "2026-04-29T16:00:00.000Z" }, { - "title": "AsyncAPI Conference Triage", - "calLink": "https://www.google.com/calendar/event?eid=NWFhcGJtNjk2bmE0OTIwdTQ0OTNtcjRwa3MgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", - "url": "https://github.com/asyncapi/community/issues/2193", + "title": "Let's talk about contributing The State of Maintainership ", + "calLink": "https://www.google.com/calendar/event?eid=OXVmaXB0djdraGthdnFoNTNzcDBxYWc2MzggY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/3513", "banner": "", - "date": "2025-12-23T13:00:00.000Z" + "date": "2026-04-21T14:00:00.000Z" + }, + { + "title": "AsyncAPI Community WG Meeting", + "calLink": "https://www.google.com/calendar/event?eid=NWs4N2hyNnFjZDM5b3N1ZnZkbGNtaWxicXMgY19xOXRzZWlnbG9tZHNqNm5qdWh2YnB0czExY0Bn", + "url": "https://github.com/asyncapi/community/issues/3514", + "banner": "https://github.com/user-attachments/assets/b4e255b8-5c7e-4821-82c9-3bcbc18b68ef", + "date": "2026-04-28T15:00:00.000Z" } ] \ No newline at end of file diff --git a/config/newsroom_videos.json b/config/newsroom_videos.json index 71a2d4782383..c14f9e39ee39 100644 --- a/config/newsroom_videos.json +++ b/config/newsroom_videos.json @@ -1,32 +1,32 @@ [ { - "image_url": "https://i.ytimg.com/vi/WuYQSYaWk1g/hqdefault.jpg", - "title": "AsyncAPI Spec Triage, 16:00 UTC Thursday December 18th 2025", - "description": "https://github.com/asyncapi/community/issues/2187.", - "videoId": "WuYQSYaWk1g" + "image_url": "https://i.ytimg.com/vi/8fkwstMaggI/hqdefault.jpg", + "title": "Let's talk about contributing: The State of Maintainership", + "description": "https://github.com/asyncapi/community/issues/3513.", + "videoId": "8fkwstMaggI" }, { - "image_url": "https://i.ytimg.com/vi/yRjdA0DYvBM/hqdefault.jpg", - "title": "AsyncAPI Community WG Meeting", - "description": "", - "videoId": "yRjdA0DYvBM" + "image_url": "https://i.ytimg.com/vi/Cy_yCrwtXGY/hqdefault.jpg", + "title": "AsyncAPI Community WG Meeting, 15:00 UTC Tuesday April 14th 2026", + "description": "https://github.com/asyncapi/community/issues/3498#issuecomment-4243180197.", + "videoId": "Cy_yCrwtXGY" }, { - "image_url": "https://i.ytimg.com/vi/G2JTsDe0h-g/hqdefault.jpg", - "title": "AsyncAPI Spec Triage, 14:00 UTC Wednesday November 19th 2025", - "description": "https://github.com/asyncapi/community/issues/2141.", - "videoId": "G2JTsDe0h-g" + "image_url": "https://i.ytimg.com/vi/hvUOm9OIpgI/hqdefault.jpg", + "title": "AsyncAPI Community WG Meeting, 15:00 UTC Tuesday March 31st 2026", + "description": "https://github.com/asyncapi/community/issues/2329.", + "videoId": "hvUOm9OIpgI" }, { - "image_url": "https://i.ytimg.com/vi/zOkWc886ZZI/hqdefault.jpg", - "title": "AsyncAPI Community WG Meeting, Tuesday November 11th 2025", - "description": "https://github.com/asyncapi/community/issues/2107.", - "videoId": "zOkWc886ZZI" + "image_url": "https://i.ytimg.com/vi/ku-WyyCT9I8/hqdefault.jpg", + "title": "Spec Meeting, 16:00 UTC Wednesday March 25th 2026", + "description": "https://github.com/asyncapi/community/issues/2319.", + "videoId": "ku-WyyCT9I8" }, { - "image_url": "https://i.ytimg.com/vi/KnXXiv0HEMA/hqdefault.jpg", - "title": "Governance Board Meeting, Monday November 3rd 2025", - "description": "https://github.com/asyncapi/community/issues/2116.", - "videoId": "KnXXiv0HEMA" + "image_url": "https://i.ytimg.com/vi/CkfW2GAMTI0/hqdefault.jpg", + "title": "Docs Meeting, 15:00 UTC Wednesday March 25th 2026", + "description": "https://github.com/asyncapi/community/issues/2323.", + "videoId": "CkfW2GAMTI0" } ] \ No newline at end of file diff --git a/config/tools-automated.json b/config/tools-automated.json index 4dba616ae8d7..ab577aa13f58 100644 --- a/config/tools-automated.json +++ b/config/tools-automated.json @@ -29,6 +29,28 @@ "Code-first tools": { "description": "The following is a list of tools that generate AsyncAPI documents from your code.", "toolsList": [ + { + "title": "AsyncAPI.NET", + "description": "The officially maintained fork of the AsyncAPI.NET SDK contains a useful object model for AsyncAPI documents in .NET along with common (de)serializers to extract raw AsyncApi JSON and YAML documents from the model.", + "links": { + "websiteUrl": "https://github.com/ByteBardOrg/AsyncAPI.NET/", + "repoUrl": "https://github.com/ByteBardOrg/AsyncAPI.NET" + }, + "filters": { + "language": "C#", + "technology": [ + ".NET", + "ASP.NET" + ], + "categories": [ + "converters", + "code-first", + "validator" + ], + "hasCommercial": false, + "isAsyncAPIOwner": false + } + }, { "title": "AsyncAPI.Net", "description": "The AsyncAPI.NET SDK contains a useful object model for AsyncAPI documents in .NET along with common serializers to extract raw OpenAPI JSON and YAML documents from the model.", @@ -73,6 +95,27 @@ "isAsyncAPIOwner": false } }, + { + "title": "ChanX", + "description": "WebSocket framework for Django/FastAPI with AsyncAPI 3.0 spec generation and Python client generation from AsyncAPI schemas", + "links": { + "docsUrl": "https://chanx.readthedocs.io/", + "repoUrl": "https://github.com/huynguyengl99/chanx" + }, + "filters": { + "language": "python", + "technology": [ + "Django", + "FastAPI" + ], + "categories": [ + "code-first", + "code-generator" + ], + "hasCommercial": false, + "isAsyncAPIOwner": false + } + }, { "title": "nestjs-asyncapi", "description": "Utilize decorators to generate AsyncAPI document utilizing DTOs (similar to @nestjs/swagger) and a web UI.", @@ -115,20 +158,43 @@ } }, { - "title": "ChanX", - "description": "WebSocket framework for Django/FastAPI with AsyncAPI 3.0 spec generation and Python client generation from AsyncAPI schemas", + "title": "Bielu.AspNetCore.AsyncApi", + "description": "A library that provides built-in support for generating AsyncAPI documents from minimal or controller-based APIs in ASP.NET Core, bringing the same developer experience as Microsoft.AspNetCore.OpenApi but for AsyncAPI specifications.", "links": { - "docsUrl": "https://chanx.readthedocs.io/", - "repoUrl": "https://github.com/huynguyengl99/chanx" + "repoUrl": "https://github.com/bielu/Bielu.AspNetCore.AsyncApi" }, "filters": { - "language": "python", + "language": "C#", "technology": [ - "Django", - "FastAPI" + "ASP.NET", + ".NET" ], "categories": [ "code-first", + "documentation-generator", + "cli", + "framework", + "ui-component", + "bundler" + ], + "hasCommercial": false, + "isAsyncAPIOwner": false + } + } + ] + }, + "Code Generators": { + "description": "The following is a list of tools that generate code from an AsyncAPI document; not the other way around.", + "toolsList": [ + { + "title": "Golang AsyncAPI Code Generator", + "description": "Generate Go user and application boilerplate from AsyncAPI specifications. Can be called from `go generate` without requirements.\n", + "links": { + "repoUrl": "https://github.com/lerenn/asyncapi-codegen" + }, + "filters": { + "language": "golang", + "categories": [ "code-generator" ], "hasCommercial": false, @@ -136,40 +202,41 @@ } }, { - "title": "AsyncAPI.NET", - "description": "The officially maintained fork of the AsyncAPI.NET SDK contains a useful object model for AsyncAPI documents in .NET along with common (de)serializers to extract raw AsyncApi JSON and YAML documents from the model.", + "title": "ChanX", + "description": "WebSocket framework for Django/FastAPI with AsyncAPI 3.0 spec generation and Python client generation from AsyncAPI schemas", "links": { - "websiteUrl": "https://github.com/ByteBardOrg/AsyncAPI.NET/", - "repoUrl": "https://github.com/ByteBardOrg/AsyncAPI.NET" + "docsUrl": "https://chanx.readthedocs.io/", + "repoUrl": "https://github.com/huynguyengl99/chanx" }, "filters": { - "language": "C#", + "language": "python", "technology": [ - ".NET", - "ASP.NET" + "Django", + "FastAPI" ], "categories": [ - "converters", "code-first", - "validator" + "code-generator" ], "hasCommercial": false, "isAsyncAPIOwner": false } - } - ] - }, - "Code Generators": { - "description": "The following is a list of tools that generate code from an AsyncAPI document; not the other way around.", - "toolsList": [ + }, { - "title": "Golang AsyncAPI Code Generator", - "description": "Generate Go user and application boilerplate from AsyncAPI specifications. Can be called from `go generate` without requirements.\n", + "title": "PHP AsyncAPI Annotations", + "description": "A comprehensive PHP library providing annotations/attributes for the AsyncAPI 3.0.0 specification. This library enables you to define AsyncAPI specifications using modern PHP 8.3+ attributes with strict typing, PSR compliance, and support for all protocol bindings.", "links": { - "repoUrl": "https://github.com/lerenn/asyncapi-codegen" + "websiteUrl": "https://github.com/drmmr763/php-asyncapi-annotations", + "docsUrl": "https://github.com/drmmr763/php-asyncapi-annotations#readme", + "repoUrl": "https://github.com/drmmr763/php-asyncapi-annotations" }, "filters": { - "language": "golang", + "language": "php", + "technology": [ + "php", + "laravel", + "symfony" + ], "categories": [ "code-generator" ], @@ -242,27 +309,6 @@ "hasCommercial": false, "isAsyncAPIOwner": true } - }, - { - "title": "ChanX", - "description": "WebSocket framework for Django/FastAPI with AsyncAPI 3.0 spec generation and Python client generation from AsyncAPI schemas", - "links": { - "docsUrl": "https://chanx.readthedocs.io/", - "repoUrl": "https://github.com/huynguyengl99/chanx" - }, - "filters": { - "language": "python", - "technology": [ - "Django", - "FastAPI" - ], - "categories": [ - "code-first", - "code-generator" - ], - "hasCommercial": false, - "isAsyncAPIOwner": false - } } ] }, @@ -270,11 +316,11 @@ "description": "The following is a list of tools that do not yet belong to any specific category but are also useful for the community.", "toolsList": [ { - "title": "AsyncAPI.Net", - "description": "The AsyncAPI.NET SDK contains a useful object model for AsyncAPI documents in .NET along with common serializers to extract raw OpenAPI JSON and YAML documents from the model.", + "title": "AsyncAPI.NET", + "description": "The officially maintained fork of the AsyncAPI.NET SDK contains a useful object model for AsyncAPI documents in .NET along with common (de)serializers to extract raw AsyncApi JSON and YAML documents from the model.", "links": { - "websiteUrl": "https://github.com/LEGO/AsyncAPI.NET/", - "repoUrl": "https://github.com/LEGO/AsyncAPI.NET" + "websiteUrl": "https://github.com/ByteBardOrg/AsyncAPI.NET/", + "repoUrl": "https://github.com/ByteBardOrg/AsyncAPI.NET" }, "filters": { "language": "C#", @@ -292,11 +338,11 @@ } }, { - "title": "AsyncAPI.NET", - "description": "The officially maintained fork of the AsyncAPI.NET SDK contains a useful object model for AsyncAPI documents in .NET along with common (de)serializers to extract raw AsyncApi JSON and YAML documents from the model.", + "title": "AsyncAPI.Net", + "description": "The AsyncAPI.NET SDK contains a useful object model for AsyncAPI documents in .NET along with common serializers to extract raw OpenAPI JSON and YAML documents from the model.", "links": { - "websiteUrl": "https://github.com/ByteBardOrg/AsyncAPI.NET/", - "repoUrl": "https://github.com/ByteBardOrg/AsyncAPI.NET" + "websiteUrl": "https://github.com/LEGO/AsyncAPI.NET/", + "repoUrl": "https://github.com/LEGO/AsyncAPI.NET" }, "filters": { "language": "C#", @@ -340,6 +386,30 @@ "hasCommercial": false, "isAsyncAPIOwner": false } + }, + { + "title": "Bielu.AspNetCore.AsyncApi", + "description": "A library that provides built-in support for generating AsyncAPI documents from minimal or controller-based APIs in ASP.NET Core, bringing the same developer experience as Microsoft.AspNetCore.OpenApi but for AsyncAPI specifications.", + "links": { + "repoUrl": "https://github.com/bielu/Bielu.AspNetCore.AsyncApi" + }, + "filters": { + "language": "C#", + "technology": [ + "ASP.NET", + ".NET" + ], + "categories": [ + "code-first", + "documentation-generator", + "cli", + "framework", + "ui-component", + "bundler" + ], + "hasCommercial": false, + "isAsyncAPIOwner": false + } } ] }, @@ -408,6 +478,30 @@ "UI components": { "description": "The following is a list of UI components to view AsyncAPI documents.", "toolsList": [ + { + "title": "Bielu.AspNetCore.AsyncApi", + "description": "A library that provides built-in support for generating AsyncAPI documents from minimal or controller-based APIs in ASP.NET Core, bringing the same developer experience as Microsoft.AspNetCore.OpenApi but for AsyncAPI specifications.", + "links": { + "repoUrl": "https://github.com/bielu/Bielu.AspNetCore.AsyncApi" + }, + "filters": { + "language": "C#", + "technology": [ + "ASP.NET", + ".NET" + ], + "categories": [ + "code-first", + "documentation-generator", + "cli", + "framework", + "ui-component", + "bundler" + ], + "hasCommercial": false, + "isAsyncAPIOwner": false + } + }, { "title": "AsyncAPI React component", "description": "React component for rendering documentation from your specification in real-time in the browser. It also provides a WebComponent and bundle for Angular and Vue", @@ -432,6 +526,28 @@ "DSL": { "description": "Writing YAML by hand is no fun, and maybe you don't want a GUI, so use a Domain Specific Language to write AsyncAPI in your language of choice.", "toolsList": [ + { + "title": "Zod Sockets", + "description": "Socket.IO solution with I/O validation and the ability to generate AsyncAPI specification and a contract for consumers.", + "links": { + "websiteUrl": "https://www.npmjs.com/package/zod-sockets", + "repoUrl": "https://github.com/RobinTail/zod-sockets" + }, + "filters": { + "language": "TypeScript", + "technology": [ + "Node.js", + "TypeScript" + ], + "categories": [ + "code-first", + "dsl", + "framework" + ], + "hasCommercial": false, + "isAsyncAPIOwner": false + } + }, { "title": "ZenWave SDK", "description": "DDD and API-First for Event-Driven Microservices", @@ -457,7 +573,12 @@ "hasCommercial": false, "isAsyncAPIOwner": false } - }, + } + ] + }, + "Frameworks": { + "description": "The following is a list of API/application frameworks that make use of AsyncAPI.", + "toolsList": [ { "title": "Zod Sockets", "description": "Socket.IO solution with I/O validation and the ability to generate AsyncAPI specification and a contract for consumers.", @@ -479,29 +600,26 @@ "hasCommercial": false, "isAsyncAPIOwner": false } - } - ] - }, - "Frameworks": { - "description": "The following is a list of API/application frameworks that make use of AsyncAPI.", - "toolsList": [ + }, { - "title": "Zod Sockets", - "description": "Socket.IO solution with I/O validation and the ability to generate AsyncAPI specification and a contract for consumers.", + "title": "Bielu.AspNetCore.AsyncApi", + "description": "A library that provides built-in support for generating AsyncAPI documents from minimal or controller-based APIs in ASP.NET Core, bringing the same developer experience as Microsoft.AspNetCore.OpenApi but for AsyncAPI specifications.", "links": { - "websiteUrl": "https://www.npmjs.com/package/zod-sockets", - "repoUrl": "https://github.com/RobinTail/zod-sockets" + "repoUrl": "https://github.com/bielu/Bielu.AspNetCore.AsyncApi" }, "filters": { - "language": "TypeScript", + "language": "C#", "technology": [ - "Node.js", - "TypeScript" + "ASP.NET", + ".NET" ], "categories": [ "code-first", - "dsl", - "framework" + "documentation-generator", + "cli", + "framework", + "ui-component", + "bundler" ], "hasCommercial": false, "isAsyncAPIOwner": false @@ -513,37 +631,37 @@ "description": "The following is a list of GitHub Actions that you can use in your workflows", "toolsList": [ { - "title": "GitHub Action for CLI", - "description": null, + "title": "GitHub Action for Generator", + "description": "CLI to work with your AsyncAPI files. You can validate them and in the future use a generator and even bootstrap a new file. Contributions are welcomed!", "links": { - "repoUrl": "https://github.com/actions-marketplace-validations/asyncapi_github-action-for-generator" + "repoUrl": "https://github.com/asyncapi/cli" }, "filters": { "technology": [ - "AsyncAPI CLI" + "AsyncAPI Generator" ], "categories": [ - "github-action" + "github-actions" ], "hasCommercial": false, - "isAsyncAPIOwner": false + "isAsyncAPIOwner": true } }, { - "title": "GitHub Action for Generator", - "description": "CLI to work with your AsyncAPI files. You can validate them and in the future use a generator and even bootstrap a new file. Contributions are welcomed!", + "title": "GitHub Action for CLI", + "description": null, "links": { - "repoUrl": "https://github.com/asyncapi/cli" + "repoUrl": "https://github.com/actions-marketplace-validations/asyncapi_github-action-for-generator" }, "filters": { "technology": [ - "AsyncAPI Generator" + "AsyncAPI CLI" ], "categories": [ - "github-actions" + "github-action" ], "hasCommercial": false, - "isAsyncAPIOwner": true + "isAsyncAPIOwner": false } } ] @@ -552,33 +670,59 @@ "description": "The tools below take specification documents as input, then publish fake messages to broker destinations for simulation purposes. They may also check that publisher messages are compliant with schemas.", "toolsList": [ { - "title": "Specmatic", - "description": "Transform your API Specs into Executable Contracts with #NoCode in Seconds. Experience the power of Contract-Driven Development to confidently develop and independently deploy your Microservices and Microfrontends faster", + "title": "AsyncAPI Payload Validator", + "description": "A Python library and CLI for validating message payloads against AsyncAPI 2.x and 3.x specifications written in JSON or YAML format. Performs detailed JSON Schema validation including type checking, required fields, string patterns, enums, numeric constraints, and composition rules. Supports HTML reports, Jinja2 template validation, and is CI/CD ready with GitHub Actions and GitLab CI examples.", "links": { - "websiteUrl": "https://specmatic.io", - "docsUrl": "https://specmatic.io/documentation/", - "repoUrl": "https://github.com/specmatic/specmatic" + "websiteUrl": "https://pypi.org/project/asyncapi-payload-validator/", + "docsUrl": "https://github.com/ingka-group/asyncapi-payload-validator#readme", + "repoUrl": "https://github.com/ingka-group/asyncapi-payload-validator" }, "filters": { - "language": "kotlin", + "language": "Python", "technology": [ - "Docker", - "maven" + "asyncapi-spec" ], "categories": [ + "validator", "mocking-and-testing", - "CLIs" + "cli" ], - "hasCommercial": true, + "hasCommercial": false, "isAsyncAPIOwner": false } }, { - "title": "Mokapi", - "description": "Your API Mocking Tool for Agile Development. Mock and simulate AsyncAPI and OpenAPI services for local testing, development, and CI pipelines — with a visual dashboard to inspect your mocks and a powerful test data generator fully customizable with JavaScript.", + "title": "ZenWave SDK", + "description": "DDD and API-First for Event-Driven Microservices", + "links": { + "websiteUrl": "https://zenwave360.github.io/", + "docsUrl": "https://zenwave360.github.io/zenwave-sdk/plugins/asyncapi-spring-cloud-streams3/", + "repoUrl": "https://github.com/zenwave360/zenwave-sdk" + }, + "filters": { + "language": "Java", + "technology": [ + "Maven", + "CLI", + "Spring Cloud Streams", + "JHipster JDL" + ], + "categories": [ + "code-generator", + "dsl", + "mocking-and-testing", + "cli" + ], + "hasCommercial": false, + "isAsyncAPIOwner": false + } + }, + { + "title": "Mokapi", + "description": "Your API Mocking Tool for Agile Development. Mock and simulate AsyncAPI and OpenAPI services for local testing, development, and CI pipelines — with a visual dashboard to inspect your mocks and a powerful test data generator fully customizable with JavaScript.", "links": { "websiteUrl": "https://mokapi.io", - "docsUrl": "https://mokapi.io/docs/guides/welcome", + "docsUrl": "https://mokapi.io/docs/welcome", "repoUrl": "https://github.com/marle3003/mokapi" }, "filters": { @@ -597,28 +741,24 @@ } }, { - "title": "ZenWave SDK", - "description": "DDD and API-First for Event-Driven Microservices", + "title": "Specmatic", + "description": "Transform your API Specs into Executable Contracts with #NoCode in Seconds. Experience the power of Contract-Driven Development to confidently develop and independently deploy your Microservices and Microfrontends faster", "links": { - "websiteUrl": "https://zenwave360.github.io/", - "docsUrl": "https://zenwave360.github.io/zenwave-sdk/plugins/asyncapi-spring-cloud-streams3/", - "repoUrl": "https://github.com/zenwave360/zenwave-sdk" + "websiteUrl": "https://specmatic.io", + "docsUrl": "https://specmatic.io/documentation/", + "repoUrl": "https://github.com/specmatic/specmatic" }, "filters": { - "language": "Java", + "language": "kotlin", "technology": [ - "Maven", - "CLI", - "Spring Cloud Streams", - "JHipster JDL" + "Docker", + "maven" ], "categories": [ - "code-generator", - "dsl", "mocking-and-testing", - "cli" + "CLIs" ], - "hasCommercial": false, + "hasCommercial": true, "isAsyncAPIOwner": false } } @@ -627,6 +767,28 @@ "Validators": { "description": "The following is a list of tools that validate AsyncAPI documents.", "toolsList": [ + { + "title": "AsyncAPI.NET", + "description": "The officially maintained fork of the AsyncAPI.NET SDK contains a useful object model for AsyncAPI documents in .NET along with common (de)serializers to extract raw AsyncApi JSON and YAML documents from the model.", + "links": { + "websiteUrl": "https://github.com/ByteBardOrg/AsyncAPI.NET/", + "repoUrl": "https://github.com/ByteBardOrg/AsyncAPI.NET" + }, + "filters": { + "language": "C#", + "technology": [ + ".NET", + "ASP.NET" + ], + "categories": [ + "converters", + "code-first", + "validator" + ], + "hasCommercial": false, + "isAsyncAPIOwner": false + } + }, { "title": "AsyncAPI.Net", "description": "The AsyncAPI.NET SDK contains a useful object model for AsyncAPI documents in .NET along with common serializers to extract raw OpenAPI JSON and YAML documents from the model.", @@ -650,39 +812,39 @@ } }, { - "title": "AsyncAPI Validation", - "description": "Message validation package for YAML and JSON AsyncAPI documents.", + "title": "AsyncAPI Payload Validator", + "description": "A Python library and CLI for validating message payloads against AsyncAPI 2.x and 3.x specifications written in JSON or YAML format. Performs detailed JSON Schema validation including type checking, required fields, string patterns, enums, numeric constraints, and composition rules. Supports HTML reports, Jinja2 template validation, and is CI/CD ready with GitHub Actions and GitLab CI examples.", "links": { - "repoUrl": "https://github.com/Elhebert/asyncapi-validation" + "websiteUrl": "https://pypi.org/project/asyncapi-payload-validator/", + "docsUrl": "https://github.com/ingka-group/asyncapi-payload-validator#readme", + "repoUrl": "https://github.com/ingka-group/asyncapi-payload-validator" }, "filters": { - "language": "TypeScript", + "language": "Python", "technology": [ - "Node.js" + "asyncapi-spec" ], "categories": [ - "validator" + "validator", + "mocking-and-testing", + "cli" ], "hasCommercial": false, "isAsyncAPIOwner": false } }, { - "title": "AsyncAPI.NET", - "description": "The officially maintained fork of the AsyncAPI.NET SDK contains a useful object model for AsyncAPI documents in .NET along with common (de)serializers to extract raw AsyncApi JSON and YAML documents from the model.", + "title": "AsyncAPI Validation", + "description": "Message validation package for YAML and JSON AsyncAPI documents.", "links": { - "websiteUrl": "https://github.com/ByteBardOrg/AsyncAPI.NET/", - "repoUrl": "https://github.com/ByteBardOrg/AsyncAPI.NET" + "repoUrl": "https://github.com/Elhebert/asyncapi-validation" }, "filters": { - "language": "C#", + "language": "TypeScript", "technology": [ - ".NET", - "ASP.NET" + "Node.js" ], "categories": [ - "converters", - "code-first", "validator" ], "hasCommercial": false, @@ -737,28 +899,6 @@ "CLIs": { "description": "The following is a list of tools that you can work with in terminal or do some CI/CD automation.", "toolsList": [ - { - "title": "Specmatic", - "description": "Transform your API Specs into Executable Contracts with #NoCode in Seconds. Experience the power of Contract-Driven Development to confidently develop and independently deploy your Microservices and Microfrontends faster", - "links": { - "websiteUrl": "https://specmatic.io", - "docsUrl": "https://specmatic.io/documentation/", - "repoUrl": "https://github.com/specmatic/specmatic" - }, - "filters": { - "language": "kotlin", - "technology": [ - "Docker", - "maven" - ], - "categories": [ - "mocking-and-testing", - "CLIs" - ], - "hasCommercial": true, - "isAsyncAPIOwner": false - } - }, { "title": "AsyncAPI CLI", "description": "One CLI to rule them all. \nThis is a CLI that aims to integrate all AsyncAPI tools that you need while AsyncAPI document development and maintainance. \nYou can use it to generate docs or code, validate AsyncAPI document and event create new documents.\n", @@ -779,21 +919,20 @@ } }, { - "title": "Mokapi", - "description": "Your API Mocking Tool for Agile Development. Mock and simulate AsyncAPI and OpenAPI services for local testing, development, and CI pipelines — with a visual dashboard to inspect your mocks and a powerful test data generator fully customizable with JavaScript.", + "title": "AsyncAPI Payload Validator", + "description": "A Python library and CLI for validating message payloads against AsyncAPI 2.x and 3.x specifications written in JSON or YAML format. Performs detailed JSON Schema validation including type checking, required fields, string patterns, enums, numeric constraints, and composition rules. Supports HTML reports, Jinja2 template validation, and is CI/CD ready with GitHub Actions and GitLab CI examples.", "links": { - "websiteUrl": "https://mokapi.io", - "docsUrl": "https://mokapi.io/docs/guides/welcome", - "repoUrl": "https://github.com/marle3003/mokapi" + "websiteUrl": "https://pypi.org/project/asyncapi-payload-validator/", + "docsUrl": "https://github.com/ingka-group/asyncapi-payload-validator#readme", + "repoUrl": "https://github.com/ingka-group/asyncapi-payload-validator" }, "filters": { - "language": "Go/Golang", + "language": "Python", "technology": [ - "JavaScript", - "TypeScript", - "Docker" + "asyncapi-spec" ], "categories": [ + "validator", "mocking-and-testing", "cli" ], @@ -827,6 +966,75 @@ "isAsyncAPIOwner": false } }, + { + "title": "Bielu.AspNetCore.AsyncApi", + "description": "A library that provides built-in support for generating AsyncAPI documents from minimal or controller-based APIs in ASP.NET Core, bringing the same developer experience as Microsoft.AspNetCore.OpenApi but for AsyncAPI specifications.", + "links": { + "repoUrl": "https://github.com/bielu/Bielu.AspNetCore.AsyncApi" + }, + "filters": { + "language": "C#", + "technology": [ + "ASP.NET", + ".NET" + ], + "categories": [ + "code-first", + "documentation-generator", + "cli", + "framework", + "ui-component", + "bundler" + ], + "hasCommercial": false, + "isAsyncAPIOwner": false + } + }, + { + "title": "Mokapi", + "description": "Your API Mocking Tool for Agile Development. Mock and simulate AsyncAPI and OpenAPI services for local testing, development, and CI pipelines — with a visual dashboard to inspect your mocks and a powerful test data generator fully customizable with JavaScript.", + "links": { + "websiteUrl": "https://mokapi.io", + "docsUrl": "https://mokapi.io/docs/welcome", + "repoUrl": "https://github.com/marle3003/mokapi" + }, + "filters": { + "language": "Go/Golang", + "technology": [ + "JavaScript", + "TypeScript", + "Docker" + ], + "categories": [ + "mocking-and-testing", + "cli" + ], + "hasCommercial": false, + "isAsyncAPIOwner": false + } + }, + { + "title": "Specmatic", + "description": "Transform your API Specs into Executable Contracts with #NoCode in Seconds. Experience the power of Contract-Driven Development to confidently develop and independently deploy your Microservices and Microfrontends faster", + "links": { + "websiteUrl": "https://specmatic.io", + "docsUrl": "https://specmatic.io/documentation/", + "repoUrl": "https://github.com/specmatic/specmatic" + }, + "filters": { + "language": "kotlin", + "technology": [ + "Docker", + "maven" + ], + "categories": [ + "mocking-and-testing", + "CLIs" + ], + "hasCommercial": true, + "isAsyncAPIOwner": false + } + }, { "title": "AsyncAPI CLI", "description": "One CLI to rule them all. \nThis is a CLI that aims to integrate all AsyncAPI tools that you need while AsyncAPI document development and maintainance. \nYou can use it to generate docs or code, validate AsyncAPI document and event create new documents.\n", @@ -868,6 +1076,30 @@ "hasCommercial": false, "isAsyncAPIOwner": true } + }, + { + "title": "Bielu.AspNetCore.AsyncApi", + "description": "A library that provides built-in support for generating AsyncAPI documents from minimal or controller-based APIs in ASP.NET Core, bringing the same developer experience as Microsoft.AspNetCore.OpenApi but for AsyncAPI specifications.", + "links": { + "repoUrl": "https://github.com/bielu/Bielu.AspNetCore.AsyncApi" + }, + "filters": { + "language": "C#", + "technology": [ + "ASP.NET", + ".NET" + ], + "categories": [ + "code-first", + "documentation-generator", + "cli", + "framework", + "ui-component", + "bundler" + ], + "hasCommercial": false, + "isAsyncAPIOwner": false + } } ] }, @@ -875,18 +1107,15 @@ "description": "The following is a list of extensions for different IDEs like VSCode, IntelliJ IDEA and others", "toolsList": [ { - "title": "jAsyncAPI - IDEA plugin", - "description": "Idea plugin for the java-asyncapi - Helps to edit and validate AsyncAPI schemas.", + "title": "asyncapi-preview", + "description": "VSCode extension that enables you to:\n - Preview documentation generated using you AsyncAPI document. It uses AsyncAPI React component under the hood,\n - Create AsyncAPI documents faster using SmartPaste functionality\n", "links": { - "websiteUrl": "https://plugins.jetbrains.com/plugin/15673-asyncapi", - "docsUrl": "https://github.com/asyncapi/jasyncapi-idea-plugin#usage", - "repoUrl": "https://github.com/asyncapi/jasyncapi-idea-plugin" + "repoUrl": "https://github.com/asyncapi/vs-asyncapi-preview" }, "filters": { - "language": "Kotlin", "technology": [ - "JetBrains", - "IntelliJ IDEA" + "VSCode", + "SmartPaste" ], "categories": [ "ide-extension" @@ -896,15 +1125,18 @@ } }, { - "title": "asyncapi-preview", - "description": "VSCode extension that enables you to:\n - Preview documentation generated using you AsyncAPI document. It uses AsyncAPI React component under the hood,\n - Create AsyncAPI documents faster using SmartPaste functionality\n", + "title": "jAsyncAPI - IDEA plugin", + "description": "Idea plugin for the java-asyncapi - Helps to edit and validate AsyncAPI schemas.", "links": { - "repoUrl": "https://github.com/asyncapi/vs-asyncapi-preview" + "websiteUrl": "https://plugins.jetbrains.com/plugin/15673-asyncapi", + "docsUrl": "https://github.com/asyncapi/jasyncapi-idea-plugin#usage", + "repoUrl": "https://github.com/asyncapi/jasyncapi-idea-plugin" }, "filters": { + "language": "Kotlin", "technology": [ - "VSCode", - "SmartPaste" + "JetBrains", + "IntelliJ IDEA" ], "categories": [ "ide-extension" @@ -937,19 +1169,17 @@ "description": "The following is a list of templates compatible with AsyncAPI Generator. You can use them to generate apps, clients or documentation from your AsyncAPI documents.", "toolsList": [ { - "title": "Java Spring Template", - "description": "Java Spring template for the AsyncAPI Generator", + "title": "Java Template", + "description": "Java template for the AsyncAPI Generator", "links": { - "repoUrl": "https://github.com/asyncapi/java-spring-template" + "repoUrl": "https://github.com/asyncapi/java-template" }, "filters": { "language": [ "javascript" ], "technology": [ - "Springboot", - "Maven", - "Gradle" + "Java" ], "categories": [ "generator-template" @@ -959,15 +1189,15 @@ } }, { - "title": "Node.js Multiprotocol Template", - "description": "This template generates a server using your AsyncAPI document. It supports multiple different protocols, like Kafka or MQTT. It is designed in the way that generated code is a library and with it's API you can start the server, send messages or register a middleware for listening incoming messages. Runtime message validation included.", + "title": "HTML Template", + "description": "HTML template for AsyncAPI Generator. Use it to generate a static docs. It is using AsyncAPI React component under the hood.", "links": { - "repoUrl": "https://github.com/asyncapi/nodejs-template" + "repoUrl": "https://github.com/asyncapi/html-template" }, "filters": { "language": "javascript", "technology": [ - "Node.js" + "HTML" ], "categories": [ "generator-template" @@ -980,7 +1210,7 @@ "title": "HTML Template", "description": null, "links": { - "repoUrl": "https://github.com/dipaksodani/async-gen" + "repoUrl": "https://github.com/WSOL12/html-template" }, "filters": { "language": "javascript", @@ -995,17 +1225,18 @@ } }, { - "title": "Java Template", - "description": "Java template for the AsyncAPI Generator", + "title": "Java Spring Cloud Stream Template", + "description": "Java Spring Cloud Stream template for the AsyncAPI Generator", "links": { - "repoUrl": "https://github.com/asyncapi/java-template" + "repoUrl": "https://github.com/asyncapi/java-spring-cloud-stream-template" }, "filters": { "language": [ "javascript" ], "technology": [ - "Java" + "Spring Cloud Streams", + "Maven" ], "categories": [ "generator-template" @@ -1016,9 +1247,9 @@ }, { "title": "HTML Template", - "description": "HTML template for AsyncAPI Generator. Use it to generate a static docs. It is using AsyncAPI React component under the hood.", + "description": null, "links": { - "repoUrl": "https://github.com/asyncapi/html-template" + "repoUrl": "https://github.com/dipaksodani/async-gen" }, "filters": { "language": "javascript", @@ -1029,22 +1260,19 @@ "generator-template" ], "hasCommercial": false, - "isAsyncAPIOwner": true + "isAsyncAPIOwner": false } }, { - "title": "Java Spring Cloud Stream Template", - "description": "Java Spring Cloud Stream template for the AsyncAPI Generator", + "title": "Node.js Websockets Template", + "description": "Node.js WebSockets template for the AsyncAPI Generator. It showcases how from a single AsyncAPI document you can generate a server and a client at the same time.", "links": { - "repoUrl": "https://github.com/asyncapi/java-spring-cloud-stream-template" + "repoUrl": "https://github.com/asyncapi/nodejs-ws-template" }, "filters": { - "language": [ - "javascript" - ], + "language": "javascript", "technology": [ - "Spring Cloud Streams", - "Maven" + "Node.js" ], "categories": [ "generator-template" @@ -1054,15 +1282,19 @@ } }, { - "title": "Node.js Websockets Template", - "description": "Node.js WebSockets template for the AsyncAPI Generator. It showcases how from a single AsyncAPI document you can generate a server and a client at the same time.", + "title": "Java Spring Template", + "description": "Java Spring template for the AsyncAPI Generator", "links": { - "repoUrl": "https://github.com/asyncapi/nodejs-ws-template" + "repoUrl": "https://github.com/asyncapi/java-spring-template" }, "filters": { - "language": "javascript", + "language": [ + "javascript" + ], "technology": [ - "Node.js" + "Springboot", + "Maven", + "Gradle" ], "categories": [ "generator-template" @@ -1072,21 +1304,21 @@ } }, { - "title": "HTML Template", - "description": null, + "title": "Node.js Multiprotocol Template", + "description": "This template generates a server using your AsyncAPI document. It supports multiple different protocols, like Kafka or MQTT. It is designed in the way that generated code is a library and with it's API you can start the server, send messages or register a middleware for listening incoming messages. Runtime message validation included.", "links": { - "repoUrl": "https://github.com/WSOL12/html-template" + "repoUrl": "https://github.com/asyncapi/nodejs-template" }, "filters": { "language": "javascript", "technology": [ - "HTML" + "Node.js" ], "categories": [ "generator-template" ], "hasCommercial": false, - "isAsyncAPIOwner": false + "isAsyncAPIOwner": true } } ] diff --git a/config/tools-ignore.json b/config/tools-ignore.json new file mode 100644 index 000000000000..7610bc35e70e --- /dev/null +++ b/config/tools-ignore.json @@ -0,0 +1,31 @@ +{ + "description": "List of tools to exclude from the final tools.json during the combine step. Each entry must have at least 'title' or 'repoUrl' (or both). When only 'repoUrl' is provided, all tools with that repo are ignored regardless of title. When only 'title' is provided, all tools with that title are ignored. When both are provided, both must match. When 'categories' is provided, the tool is only removed from those specific categories; omit it to remove from all categories.", + "tools": [ + { + "repoUrl": "https://github.com/hkirat/asyncapi-fork", + "reason": "Duplicate of asyncapi/cli, not an independent tool" + }, + { + "title": "AsyncAPI Studio", + "repoUrl": "https://github.com/Shurtu-gal/action-test-bed", + "reason": "Duplicate of asyncapi/studio, not an independent tool" + }, + { + "repoUrl": "https://github.com/WSOL12/html-template", + "reason": "Duplicate of asyncapi/html-template, not an independent tool" + }, + { + "title": "HTML Template", + "repoUrl": "https://github.com/dipaksodani/async-gen", + "reason": "Duplicate of asyncapi/html-template, not an independent tool" + }, + { + "repoUrl": "https://github.com/TahaShahid203/async-api-issue", + "reason": "Duplicate of asyncapi/studio, not an independent tool" + }, + { + "repoUrl": "https://github.com/Savio629/testing2", + "reason": "Duplicate of asyncapi/vs-asyncapi-preview, not an independent tool" + } + ] +} diff --git a/config/tools-manual.json b/config/tools-manual.json index 33027a428355..2bc866f31a76 100644 --- a/config/tools-manual.json +++ b/config/tools-manual.json @@ -6,7 +6,7 @@ "title": "AsyncAPI-Directory by APIs.guru", "description": "Directory of asynchronous API specifications in AsyncAPI format.", "links": { - "websiteUrl": "https://apis.guru/asyncapi-directory/", + "websiteUrl": "https://apis.guru/", "repoUrl": "https://github.com/APIs-guru/asyncapi-directory" }, "filters": { @@ -346,7 +346,7 @@ "title": "AsyncAPI-Directory by APIs.guru", "description": "Directory of asynchronous API specifications in AsyncAPI format.", "links": { - "websiteUrl": "https://apis.guru/asyncapi-directory/", + "websiteUrl": "https://apis.guru/", "repoUrl": "https://github.com/APIs-guru/asyncapi-directory" }, "filters": { diff --git a/config/tools.json b/config/tools.json index 241c37102a1b..453b1dfcca64 100644 --- a/config/tools.json +++ b/config/tools.json @@ -23,7 +23,7 @@ "title": "AsyncAPI-Directory by APIs.guru", "description": "Directory of asynchronous API specifications in AsyncAPI format.", "links": { - "websiteUrl": "https://apis.guru/asyncapi-directory/", + "websiteUrl": "https://apis.guru/", "repoUrl": "https://github.com/APIs-guru/asyncapi-directory" }, "filters": { @@ -195,6 +195,43 @@ "hasCommercial": false } }, + { + "title": "Bielu.AspNetCore.AsyncApi", + "description": "A library that provides built-in support for generating AsyncAPI documents from minimal or controller-based APIs in ASP.NET Core, bringing the same developer experience as Microsoft.AspNetCore.OpenApi but for AsyncAPI specifications.", + "links": { + "repoUrl": "https://github.com/bielu/Bielu.AspNetCore.AsyncApi" + }, + "filters": { + "language": [ + { + "name": "C#", + "color": "bg-[#E3AFE0]", + "borderColor": "border-[#9B4F96]" + } + ], + "technology": [ + { + "name": "ASP.NET", + "color": "bg-[#71C2FB]", + "borderColor": "border-[#1577BC]" + }, + { + "name": ".NET", + "color": "bg-[#A184FF]", + "borderColor": "border-[#5026D4]" + } + ], + "categories": [ + "code-first", + "documentation-generator", + "cli", + "framework", + "ui-component", + "bundler" + ], + "hasCommercial": false + } + }, { "title": "ChanX", "description": "WebSocket framework for Django/FastAPI with AsyncAPI 3.0 spec generation and Python client generation from AsyncAPI schemas", @@ -813,6 +850,45 @@ "hasCommercial": false } }, + { + "title": "PHP AsyncAPI Annotations", + "description": "A comprehensive PHP library providing annotations/attributes for the AsyncAPI 3.0.0 specification. This library enables you to define AsyncAPI specifications using modern PHP 8.3+ attributes with strict typing, PSR compliance, and support for all protocol bindings.", + "links": { + "websiteUrl": "https://github.com/drmmr763/php-asyncapi-annotations", + "docsUrl": "https://github.com/drmmr763/php-asyncapi-annotations#readme", + "repoUrl": "https://github.com/drmmr763/php-asyncapi-annotations" + }, + "filters": { + "language": [ + { + "name": "PHP", + "color": "bg-[#B0B3D6]", + "borderColor": "border-[#787CB5]" + } + ], + "technology": [ + { + "name": "PHP", + "color": "bg-[#B0B3D6]", + "borderColor": "border-[#787CB5]" + }, + { + "name": "Laravel", + "color": "bg-[#F55247]", + "borderColor": "border-[#F43B2F]" + }, + { + "name": "Symfony", + "color": "bg-[#666666]", + "borderColor": "border-[#333333]" + } + ], + "categories": [ + "code-generator" + ], + "hasCommercial": false + } + }, { "title": "The Codegen Project", "description": "Stop wasting time on manual code. Generate Payloads, parameters, headers, types, channel wrappers, and more from your AsyncAPI document! Works with Kafka, NATS, MQTT, event-source, AMQP, HTTP Client!", @@ -1067,7 +1143,7 @@ "title": "AsyncAPI-Directory by APIs.guru", "description": "Directory of asynchronous API specifications in AsyncAPI format.", "links": { - "websiteUrl": "https://apis.guru/asyncapi-directory/", + "websiteUrl": "https://apis.guru/", "repoUrl": "https://github.com/APIs-guru/asyncapi-directory" }, "filters": { @@ -1164,6 +1240,43 @@ "hasCommercial": false } }, + { + "title": "Bielu.AspNetCore.AsyncApi", + "description": "A library that provides built-in support for generating AsyncAPI documents from minimal or controller-based APIs in ASP.NET Core, bringing the same developer experience as Microsoft.AspNetCore.OpenApi but for AsyncAPI specifications.", + "links": { + "repoUrl": "https://github.com/bielu/Bielu.AspNetCore.AsyncApi" + }, + "filters": { + "language": [ + { + "name": "C#", + "color": "bg-[#E3AFE0]", + "borderColor": "border-[#9B4F96]" + } + ], + "technology": [ + { + "name": "ASP.NET", + "color": "bg-[#71C2FB]", + "borderColor": "border-[#1577BC]" + }, + { + "name": ".NET", + "color": "bg-[#A184FF]", + "borderColor": "border-[#5026D4]" + } + ], + "categories": [ + "code-first", + "documentation-generator", + "cli", + "framework", + "ui-component", + "bundler" + ], + "hasCommercial": false + } + }, { "title": "Bump.sh", "description": "OpenAPI 2 & 3 / AsyncAPI 2 documentation generator, with automatic changelog and visual diff.", @@ -1371,60 +1484,6 @@ ], "hasCommercial": false } - }, - { - "title": "AsyncAPI Studio", - "description": null, - "links": { - "websiteUrl": "https://studio.asyncapi.com", - "repoUrl": "https://github.com/TahaShahid203/async-api-issue" - }, - "filters": { - "language": [], - "technology": [ - { - "name": "React JS", - "color": "bg-[#9FECFA]", - "borderColor": "border-[#08D8FE]" - }, - { - "name": "TypeScript", - "color": "bg-[#61d0f2]", - "borderColor": "border-[#40ccf7]" - } - ], - "categories": [ - "editor" - ], - "hasCommercial": false - } - }, - { - "title": "AsyncAPI Studio", - "description": null, - "links": { - "websiteUrl": "https://studio.asyncapi.com", - "repoUrl": "https://github.com/Shurtu-gal/action-test-bed" - }, - "filters": { - "language": [], - "technology": [ - { - "name": "React JS", - "color": "bg-[#9FECFA]", - "borderColor": "border-[#08D8FE]" - }, - { - "name": "TypeScript", - "color": "bg-[#61d0f2]", - "borderColor": "border-[#40ccf7]" - } - ], - "categories": [ - "editor" - ], - "hasCommercial": false - } } ] }, @@ -1500,6 +1559,43 @@ ], "hasCommercial": false } + }, + { + "title": "Bielu.AspNetCore.AsyncApi", + "description": "A library that provides built-in support for generating AsyncAPI documents from minimal or controller-based APIs in ASP.NET Core, bringing the same developer experience as Microsoft.AspNetCore.OpenApi but for AsyncAPI specifications.", + "links": { + "repoUrl": "https://github.com/bielu/Bielu.AspNetCore.AsyncApi" + }, + "filters": { + "language": [ + { + "name": "C#", + "color": "bg-[#E3AFE0]", + "borderColor": "border-[#9B4F96]" + } + ], + "technology": [ + { + "name": "ASP.NET", + "color": "bg-[#71C2FB]", + "borderColor": "border-[#1577BC]" + }, + { + "name": ".NET", + "color": "bg-[#A184FF]", + "borderColor": "border-[#5026D4]" + } + ], + "categories": [ + "code-first", + "documentation-generator", + "cli", + "framework", + "ui-component", + "bundler" + ], + "hasCommercial": false + } } ] }, @@ -1648,6 +1744,43 @@ "hasCommercial": false } }, + { + "title": "Bielu.AspNetCore.AsyncApi", + "description": "A library that provides built-in support for generating AsyncAPI documents from minimal or controller-based APIs in ASP.NET Core, bringing the same developer experience as Microsoft.AspNetCore.OpenApi but for AsyncAPI specifications.", + "links": { + "repoUrl": "https://github.com/bielu/Bielu.AspNetCore.AsyncApi" + }, + "filters": { + "language": [ + { + "name": "C#", + "color": "bg-[#E3AFE0]", + "borderColor": "border-[#9B4F96]" + } + ], + "technology": [ + { + "name": "ASP.NET", + "color": "bg-[#71C2FB]", + "borderColor": "border-[#1577BC]" + }, + { + "name": ".NET", + "color": "bg-[#A184FF]", + "borderColor": "border-[#5026D4]" + } + ], + "categories": [ + "code-first", + "documentation-generator", + "cli", + "framework", + "ui-component", + "bundler" + ], + "hasCommercial": false + } + }, { "title": "FastStream", "description": "A powerful and easy-to-use Python framework for building asynchronous services interacting with event streams such as Apache Kafka, RabbitMQ and NATS.", @@ -1837,6 +1970,37 @@ "Mocking and Testing": { "description": "The tools below take specification documents as input, then publish fake messages to broker destinations for simulation purposes. They may also check that publisher messages are compliant with schemas.", "toolsList": [ + { + "title": "AsyncAPI Payload Validator", + "description": "A Python library and CLI for validating message payloads against AsyncAPI 2.x and 3.x specifications written in JSON or YAML format. Performs detailed JSON Schema validation including type checking, required fields, string patterns, enums, numeric constraints, and composition rules. Supports HTML reports, Jinja2 template validation, and is CI/CD ready with GitHub Actions and GitLab CI examples.", + "links": { + "websiteUrl": "https://pypi.org/project/asyncapi-payload-validator/", + "docsUrl": "https://github.com/ingka-group/asyncapi-payload-validator#readme", + "repoUrl": "https://github.com/ingka-group/asyncapi-payload-validator" + }, + "filters": { + "language": [ + { + "name": "Python", + "color": "bg-[#A8D0EF]", + "borderColor": "border-[#3878AB]" + } + ], + "technology": [ + { + "name": "AsyncAPI Generator", + "color": "bg-[#61d0f2]", + "borderColor": "border-[#40ccf7]" + } + ], + "categories": [ + "validator", + "mocking-and-testing", + "cli" + ], + "hasCommercial": false + } + }, { "title": "Microcks", "description": "Mocking and testing platform for API and microservices. Turn your AsyncAPI, OpenAPI contract examples, or Postman collections into ready-to-use mocks. Use examples to simulate and validate received messages according to schema elements.", @@ -1880,7 +2044,7 @@ "description": "Your API Mocking Tool for Agile Development. Mock and simulate AsyncAPI and OpenAPI services for local testing, development, and CI pipelines — with a visual dashboard to inspect your mocks and a powerful test data generator fully customizable with JavaScript.", "links": { "websiteUrl": "https://mokapi.io", - "docsUrl": "https://mokapi.io/docs/guides/welcome", + "docsUrl": "https://mokapi.io/docs/welcome", "repoUrl": "https://github.com/marle3003/mokapi" }, "filters": { @@ -2171,6 +2335,37 @@ "hasCommercial": false } }, + { + "title": "AsyncAPI Payload Validator", + "description": "A Python library and CLI for validating message payloads against AsyncAPI 2.x and 3.x specifications written in JSON or YAML format. Performs detailed JSON Schema validation including type checking, required fields, string patterns, enums, numeric constraints, and composition rules. Supports HTML reports, Jinja2 template validation, and is CI/CD ready with GitHub Actions and GitLab CI examples.", + "links": { + "websiteUrl": "https://pypi.org/project/asyncapi-payload-validator/", + "docsUrl": "https://github.com/ingka-group/asyncapi-payload-validator#readme", + "repoUrl": "https://github.com/ingka-group/asyncapi-payload-validator" + }, + "filters": { + "language": [ + { + "name": "Python", + "color": "bg-[#A8D0EF]", + "borderColor": "border-[#3878AB]" + } + ], + "technology": [ + { + "name": "AsyncAPI Generator", + "color": "bg-[#61d0f2]", + "borderColor": "border-[#40ccf7]" + } + ], + "categories": [ + "validator", + "mocking-and-testing", + "cli" + ], + "hasCommercial": false + } + }, { "title": "AsyncAPI Validation", "description": "Message validation package for YAML and JSON AsyncAPI documents.", @@ -2461,23 +2656,31 @@ } }, { - "title": "AsyncAPI CLI", - "description": "One CLI to rule them all. \nThis is a CLI that aims to integrate all AsyncAPI tools that you need while AsyncAPI document development and maintainance. \nYou can use it to generate docs or code, validate AsyncAPI document and event create new documents.\n", + "title": "AsyncAPI Payload Validator", + "description": "A Python library and CLI for validating message payloads against AsyncAPI 2.x and 3.x specifications written in JSON or YAML format. Performs detailed JSON Schema validation including type checking, required fields, string patterns, enums, numeric constraints, and composition rules. Supports HTML reports, Jinja2 template validation, and is CI/CD ready with GitHub Actions and GitLab CI examples.", "links": { - "websiteUrl": "https://www.asyncapi.com/tools/cli", - "repoUrl": "https://github.com/hkirat/asyncapi-fork" + "websiteUrl": "https://pypi.org/project/asyncapi-payload-validator/", + "docsUrl": "https://github.com/ingka-group/asyncapi-payload-validator#readme", + "repoUrl": "https://github.com/ingka-group/asyncapi-payload-validator" }, "filters": { - "language": [], + "language": [ + { + "name": "Python", + "color": "bg-[#A8D0EF]", + "borderColor": "border-[#3878AB]" + } + ], "technology": [ { - "name": "TypeScript", + "name": "AsyncAPI Generator", "color": "bg-[#61d0f2]", "borderColor": "border-[#40ccf7]" } ], "categories": [ - "others", + "validator", + "mocking-and-testing", "cli" ], "hasCommercial": false @@ -2511,12 +2714,49 @@ "hasCommercial": false } }, + { + "title": "Bielu.AspNetCore.AsyncApi", + "description": "A library that provides built-in support for generating AsyncAPI documents from minimal or controller-based APIs in ASP.NET Core, bringing the same developer experience as Microsoft.AspNetCore.OpenApi but for AsyncAPI specifications.", + "links": { + "repoUrl": "https://github.com/bielu/Bielu.AspNetCore.AsyncApi" + }, + "filters": { + "language": [ + { + "name": "C#", + "color": "bg-[#E3AFE0]", + "borderColor": "border-[#9B4F96]" + } + ], + "technology": [ + { + "name": "ASP.NET", + "color": "bg-[#71C2FB]", + "borderColor": "border-[#1577BC]" + }, + { + "name": ".NET", + "color": "bg-[#A184FF]", + "borderColor": "border-[#5026D4]" + } + ], + "categories": [ + "code-first", + "documentation-generator", + "cli", + "framework", + "ui-component", + "bundler" + ], + "hasCommercial": false + } + }, { "title": "Mokapi", "description": "Your API Mocking Tool for Agile Development. Mock and simulate AsyncAPI and OpenAPI services for local testing, development, and CI pipelines — with a visual dashboard to inspect your mocks and a powerful test data generator fully customizable with JavaScript.", "links": { "websiteUrl": "https://mokapi.io", - "docsUrl": "https://mokapi.io/docs/guides/welcome", + "docsUrl": "https://mokapi.io/docs/welcome", "repoUrl": "https://github.com/marle3003/mokapi" }, "filters": { @@ -2691,43 +2931,54 @@ ], "hasCommercial": false } - } - ] - }, - "IDE Extensions": { - "description": "The following is a list of extensions for different IDEs like VSCode, IntelliJ IDEA and others", - "toolsList": [ + }, { - "title": "asyncapi-preview", - "description": "VSCode extension that enables you to:\n - Preview documentation generated using you AsyncAPI document. It uses AsyncAPI React component under the hood,\n - Create AsyncAPI documents faster using SmartPaste functionality\n", + "title": "Bielu.AspNetCore.AsyncApi", + "description": "A library that provides built-in support for generating AsyncAPI documents from minimal or controller-based APIs in ASP.NET Core, bringing the same developer experience as Microsoft.AspNetCore.OpenApi but for AsyncAPI specifications.", "links": { - "repoUrl": "https://github.com/asyncapi/vs-asyncapi-preview" + "repoUrl": "https://github.com/bielu/Bielu.AspNetCore.AsyncApi" }, "filters": { - "language": [], + "language": [ + { + "name": "C#", + "color": "bg-[#E3AFE0]", + "borderColor": "border-[#9B4F96]" + } + ], "technology": [ { - "name": "VSCode", - "color": "bg-[#61d0f2]", - "borderColor": "border-[#40ccf7]" + "name": "ASP.NET", + "color": "bg-[#71C2FB]", + "borderColor": "border-[#1577BC]" }, { - "name": "SmartPaste", - "color": "bg-[#61d0f2]", - "borderColor": "border-[#40ccf7]" + "name": ".NET", + "color": "bg-[#A184FF]", + "borderColor": "border-[#5026D4]" } ], "categories": [ - "ide-extension" + "code-first", + "documentation-generator", + "cli", + "framework", + "ui-component", + "bundler" ], "hasCommercial": false } - }, + } + ] + }, + "IDE Extensions": { + "description": "The following is a list of extensions for different IDEs like VSCode, IntelliJ IDEA and others", + "toolsList": [ { "title": "asyncapi-preview", "description": "VSCode extension that enables you to:\n - Preview documentation generated using you AsyncAPI document. It uses AsyncAPI React component under the hood,\n - Create AsyncAPI documents faster using SmartPaste functionality\n", "links": { - "repoUrl": "https://github.com/Savio629/testing2" + "repoUrl": "https://github.com/asyncapi/vs-asyncapi-preview" }, "filters": { "language": [], @@ -2842,33 +3093,6 @@ "hasCommercial": false } }, - { - "title": "HTML Template", - "description": null, - "links": { - "repoUrl": "https://github.com/dipaksodani/async-gen" - }, - "filters": { - "language": [ - { - "name": "JavaScript", - "color": "bg-[#F2F1C7]", - "borderColor": "border-[#BFBE86]" - } - ], - "technology": [ - { - "name": "HTML", - "color": "bg-[#61d0f2]", - "borderColor": "border-[#40ccf7]" - } - ], - "categories": [ - "generator-template" - ], - "hasCommercial": false - } - }, { "title": "HTML Template", "description": "HTML template for AsyncAPI Generator. Use it to generate a static docs. It is using AsyncAPI React component under the hood.", @@ -2896,33 +3120,6 @@ "hasCommercial": false } }, - { - "title": "HTML Template", - "description": null, - "links": { - "repoUrl": "https://github.com/WSOL12/html-template" - }, - "filters": { - "language": [ - { - "name": "JavaScript", - "color": "bg-[#F2F1C7]", - "borderColor": "border-[#BFBE86]" - } - ], - "technology": [ - { - "name": "HTML", - "color": "bg-[#61d0f2]", - "borderColor": "border-[#40ccf7]" - } - ], - "categories": [ - "generator-template" - ], - "hasCommercial": false - } - }, { "title": "Java Spring Cloud Stream Template", "description": "Java Spring Cloud Stream template for the AsyncAPI Generator", @@ -3202,29 +3399,6 @@ ], "hasCommercial": false } - }, - { - "title": "AsyncAPI CLI", - "description": "One CLI to rule them all. \nThis is a CLI that aims to integrate all AsyncAPI tools that you need while AsyncAPI document development and maintainance. \nYou can use it to generate docs or code, validate AsyncAPI document and event create new documents.\n", - "links": { - "websiteUrl": "https://www.asyncapi.com/tools/cli", - "repoUrl": "https://github.com/hkirat/asyncapi-fork" - }, - "filters": { - "language": [], - "technology": [ - { - "name": "TypeScript", - "color": "bg-[#61d0f2]", - "borderColor": "border-[#40ccf7]" - } - ], - "categories": [ - "others", - "cli" - ], - "hasCommercial": false - } } ] } diff --git a/cypress/ambassadors.cy.js b/cypress/ambassadors.cy.js new file mode 100644 index 000000000000..bb5566b07df2 --- /dev/null +++ b/cypress/ambassadors.cy.js @@ -0,0 +1,51 @@ +import HomePage from './pages/homepage'; +import AmbassadorsPage from './pages/ambassadors'; + +let homePage; +let ambassadorsPage; + +beforeEach(() => { + homePage = new HomePage(); + ambassadorsPage = new AmbassadorsPage(); + homePage.visit(); + homePage.goToAmbassadorsPage(); +}); + +describe('Ambassadors Page', () => { + it('verifies key sections and links', () => { + ambassadorsPage.verifyKeySectionsAndLinks(); + }); + + it('verifies social links for selected Ambassadors', () => { + const ambassadors = [ + { + name: 'Giri Venkatesan', + links: { + github: 'https://www.github.com/gvensan', + twitter: 'https://www.twitter.com/giri_venkatesan', + linkedin: 'https://www.linkedin.com/in/girivenkatesan' + } + }, + { + name: 'Daniel Kocot', + links: { + github: 'https://www.github.com/danielkocot', + linkedin: 'https://www.linkedin.com/in/danielkocot' + } + }, + { + name: 'Hugo Guerrero', + links: { + github: 'https://www.github.com/hguerrero', + twitter: 'https://www.twitter.com/hguerreroo', + linkedin: 'https://www.linkedin.com/in/hugoguerrero' + } + } + ]; + + ambassadors.forEach(({ name, links }) => { + ambassadorsPage.verifyAmbassadorSocialLinks(name, links); + }); + }); +}); + diff --git a/cypress/dashboard.cy.js b/cypress/dashboard.cy.js new file mode 100644 index 000000000000..a0ee320b2f2b --- /dev/null +++ b/cypress/dashboard.cy.js @@ -0,0 +1,25 @@ +import DashboardPage from './pages/dashboard'; + +describe('Dashboard Page', () => { + const dashboard = new DashboardPage(); + + beforeEach(() => { + dashboard.visit(); + }); + + it('should display the header', () => { + dashboard.verifyHeader(); + }); + + it('should display the Hot Topics section', () => { + dashboard.verifyHotTopicsSection(); + }); + + it('should display the Good First Issues section', () => { + dashboard.verifyGoodFirstIssuesSection(); + }); + + it('should display header links with correct URLs', () => { + dashboard.verifyHeaderLinks(); + }); +}); diff --git a/cypress/docspage.cy.js b/cypress/docspage.cy.js index caf6e61640b1..75f34b4a5ca6 100644 --- a/cypress/docspage.cy.js +++ b/cypress/docspage.cy.js @@ -12,7 +12,7 @@ beforeEach(() => { }); describe('Docs Page Tests', () => { - it('User navigates SideBar containing various sections', () => { + it('verifying navigation to SideBar containing various sections', () => { docsPage.goToConceptsSection(); cy.get('@subsections').then((subsections) => { @@ -29,7 +29,7 @@ describe('Docs Page Tests', () => { docsPage.goToMigrationsSection(); docsPage.goToCommunitySection(); - it('User verifies Card Links present on the Docs Page', () => { + it('verifying Card Links present on the Docs Page', () => { const cards = [ { href: '/docs/concepts' }, { href: '/docs/tutorials' }, @@ -38,7 +38,7 @@ describe('Docs Page Tests', () => { { href: '/docs/reference' }, { href: '/docs/migration' }, { href: '/docs/community' }, - { href: '/docs/reference/specification/v3.0.0-explorer' }, + { href: '/docs/reference/specification/v3.1.0-explorer' }, ]; cards.forEach((card) => { diff --git a/cypress/events.cy.js b/cypress/events.cy.js new file mode 100644 index 000000000000..6547d94ab279 --- /dev/null +++ b/cypress/events.cy.js @@ -0,0 +1,53 @@ +import EventsPage from './pages/events'; + +describe('Events Page', () => { + const events = new EventsPage(); + + beforeEach(() => { + events.visit(); + }); + + it('should display main sections and action buttons', () => { + events.verifyMainVisible(); + events.verifyActionButtons(); + }); + + it('should display Google Calendar and ICS file button links', () => { + events.verifyEventButtonsLinks(); + }); + + it('should display recordings section with correct link', () => { + events.verifyRecordingsSection(); + events.verifyRecordingsLinkHref(); + }); + + it('should display all event recording links', () => { + events.verifyEventRecordingLinks(); + }); + + it('should display event types section', () => { + events.verifyEventTypes(); + }); + + it('should display FAQ link pointing to correct documentation', () => { + events.verifyFaqLink(); + }); + + it('should display all host profile links', () => { + events.verifyHostLinks(); + }); + + it('should display event cards with valid links on All tab', () => { + events.verifyEventCards(); + }); + + it('should display event cards with valid links on Upcoming tab', () => { + events.switchToUpcoming(); + events.verifyEventCards(); + }); + + it('should display event cards with valid links on Recorded tab', () => { + events.switchToRecorded(); + events.verifyEventCards(); + }); +}); diff --git a/cypress/fixtures/docsSections.json b/cypress/fixtures/docsSections.json index a03315b9af31..20afb69dd09e 100644 --- a/cypress/fixtures/docsSections.json +++ b/cypress/fixtures/docsSections.json @@ -104,9 +104,9 @@ "heading": "Overview" }, { - "href": "/docs/reference/specification/v3.0.0", + "href": "/docs/reference/specification/v3.1.0", "label": "Specification", - "heading": "3.0.0" + "heading": "3.1.0" }, { "href": "/docs/reference/specification/v2.x", diff --git a/cypress/fixtures/footerPageData.json b/cypress/fixtures/footerPageData.json index 1c6c2cd08a55..c01c41b46785 100644 --- a/cypress/fixtures/footerPageData.json +++ b/cypress/fixtures/footerPageData.json @@ -18,7 +18,7 @@ { "href": "https://www.twitch.tv/asyncapi", "text": "Twitch" } ], "newsLinks": [ - { "href": "mailto:press@asyncapi.io", "text": "Email Us" } + { "href": "mailto:info@asyncapi.com", "text": "Email Us" } ], "netlifyLink": "https://netlify.com" } \ No newline at end of file diff --git a/cypress/fixtures/toolsPages.json b/cypress/fixtures/toolsPages.json new file mode 100644 index 000000000000..314e03512102 --- /dev/null +++ b/cypress/fixtures/toolsPages.json @@ -0,0 +1,37 @@ +{ + "generator": { + "path": "/tools/generator", + "heading": "Docs, Code, Anything!", + "image": "generator diagram", + "github": "https://www.github.com/asyncapi/generator", + "docs": "/docs/tools/generator" + }, + "cli": { + "path": "/tools/cli", + "heading": "Interact with AsyncAPI from the comfort of your CLI", + "install": "npm install -g @asyncapi/cli", + "github": "https://www.github.com/asyncapi/cli", + "docs": "/docs/tools/cli" + }, + "parsers": { + "path": "/tools/parsers", + "heading": "Build your own tools", + "install": "npm install @asyncapi/parser", + "github": "https://www.github.com/asyncapi/parser-js" + }, + "githubActions": { + "path": "/tools/github-actions", + "heading": "Automate using GitHub Actions", + "github": "https://www.github.com/asyncapi/github-action-for-generator" + }, + "modelina": { + "path": "/tools/modelina", + "heading": "Modelina", + "install": "npm install @asyncapi/modelina", + "tryIt": { + "text": "Try it now", + "href": "https://modelina.org/playground" + }, + "github": "https://www.github.com/asyncapi/modelina" + } +} \ No newline at end of file diff --git a/cypress/header.cy.js b/cypress/header.cy.js index c08e6a079264..e5656e59b286 100644 --- a/cypress/header.cy.js +++ b/cypress/header.cy.js @@ -8,15 +8,15 @@ describe('Header Links Validation', () => { header.visit(); }); - it('User hovers over Docs dropdown and sees the dropdown', () => { + it('Verifying if user hovers over Docs dropdown and sees the dropdown', () => { header.verifyDocsDropdown(); }); - it('User hovers over Tools dropdown and sees the dropdown', () => { + it('Verifying if user hovers over Tools dropdown and sees the dropdown', () => { header.verifyToolsDropdown(); }); - it('User hovers over Community dropdown and sees the dropdown', () => { + it('Verifying if user hovers over Community dropdown and sees the dropdown', () => { header.verifyCommunityDropdown(); }); }); diff --git a/cypress/pages/BaseFooterPage.js b/cypress/pages/BaseFooterPage.js index 21fd6fe7ffb0..3793093545aa 100644 --- a/cypress/pages/BaseFooterPage.js +++ b/cypress/pages/BaseFooterPage.js @@ -7,7 +7,7 @@ class BasePage { const chain = cy .get(`a[${attr}="${href}"]`) .should('be.visible') - .and('have.attr', attr, href); + .should('have.attr', attr, href); return text ? chain.and('contain', text) : chain; } } diff --git a/cypress/pages/BaseHeaderPage.js b/cypress/pages/BaseHeaderPage.js index 69b2d2a340e7..c13f94d0d390 100644 --- a/cypress/pages/BaseHeaderPage.js +++ b/cypress/pages/BaseHeaderPage.js @@ -1,8 +1,7 @@ class BasePage { - visit(path = '/') { - cy.visit(path) - return this; + visit() { + cy.visit('/') } getElement(selector) { @@ -11,8 +10,8 @@ class BasePage { hoverElement(selector) { return this.getElement(selector) - .trigger('mouseover') - .trigger('mouseenter'); + .trigger('mouseover') + .trigger('mouseenter'); } } diff --git a/cypress/pages/BasePage.js b/cypress/pages/BasePage.js new file mode 100644 index 000000000000..5a4388e8bd9b --- /dev/null +++ b/cypress/pages/BasePage.js @@ -0,0 +1,54 @@ +class BasePage { + visit(url = '/') { + cy.visit(url); + } + + getElement(selector) { + return cy.get(selector); + } + + hoverElement(selector) { + return this.getElement(selector) + .trigger('mouseover') + .trigger('mouseenter'); + } + + verifyElementIsVisible(selector) { + return this.getElement(selector).should('be.visible'); + } + + verifyElementHasAttribute(selector, attribute, value) { + return this.getElement(selector).should('have.attr', attribute, value); + } + + verifyHeadingExists(headingText) { + return cy.contains('h1, h2, h3, h4, h5, h6', headingText).should('be.visible'); + } + + verifyLink(href, text, { findByText = false } = {}) { + if (findByText && text) { + const chain = cy.contains('a', text).should('be.visible'); + return href ? chain.and('have.attr', 'href', href) : chain; + } + const chain = cy.get(`a[href="${href}"]`).should('be.visible').and('have.attr', 'href', href); + return text ? chain.and('contain', text) : chain; + } + + verifyButtonLink(href, buttonText) { + return this.verifyLink(href, buttonText, { findByText: true }); + } + + verifyElementContainsText(selector, text) { + return cy.contains(selector, text).should('exist'); + } + + verifyImageVisible(altText) { + return cy.get(`img[alt="${altText}"]`) + .should('be.visible') + .and('have.attr', 'src') + .should('not.be.empty'); + } + +} + +export default BasePage; diff --git a/cypress/pages/BasePageTools.js b/cypress/pages/BasePageTools.js index 901575308550..f291fde985d4 100644 --- a/cypress/pages/BasePageTools.js +++ b/cypress/pages/BasePageTools.js @@ -1,14 +1,29 @@ class BasePage { - visit(path) { + visit(path = '/') { cy.visit(path); } + verifyElementIsVisible(selector) { + cy.get(selector).should('be.visible'); + } + + verifyTextVisible(text) { + cy.contains(text).should('be.visible'); + } + + verifyLinkWithText(selector, text, expectedHrefPart) { + cy.contains(selector, text) + .should('be.visible') + .and('have.attr', 'href') + .and('include', expectedHrefPart); + } + getHeaderText(selector, expectedText) { cy.get(selector).should('contain.text', expectedText); } getLink(href, text) { - return cy.contains(`a[href="${href}"]`, text) + return cy.contains(`a[href="${href}"]`, text) .should('be.visible') .and('have.attr', 'href', href); } diff --git a/cypress/pages/BlogPage.js b/cypress/pages/BlogPage.js index bf1d2046ac7c..b244c5094c8d 100644 --- a/cypress/pages/BlogPage.js +++ b/cypress/pages/BlogPage.js @@ -1,6 +1,9 @@ -class BlogPage { +import BasePage from './BasePage'; + +class BlogPage extends BasePage { verifyPageLoaded() { - cy.contains('h1', 'Welcome to our blog!').should('be.visible'); + this.verifyHeadingExists('Welcome to our blog!'); } } + export default BlogPage; diff --git a/cypress/pages/CaseStudiesPage.js b/cypress/pages/CaseStudiesPage.js index 65fa2d6eb7a8..c8b0aead1a11 100644 --- a/cypress/pages/CaseStudiesPage.js +++ b/cypress/pages/CaseStudiesPage.js @@ -1,6 +1,9 @@ -class CaseStudiesPage { +import BasePage from './BasePage'; + +class CaseStudiesPage extends BasePage { verifyPageLoaded() { - cy.contains('h1', 'Case Studies').should('be.visible'); + this.verifyHeadingExists('Case Studies'); } } + export default CaseStudiesPage; diff --git a/cypress/pages/CommunityPage.js b/cypress/pages/CommunityPage.js index f83ec1311d46..910db4501262 100644 --- a/cypress/pages/CommunityPage.js +++ b/cypress/pages/CommunityPage.js @@ -1,7 +1,9 @@ -class CommunityPage { +import BasePage from './BasePage'; + +class CommunityPage extends BasePage { verifyPageLoaded() { - cy.contains('h1','Home of #CommunityOps') - .should('be.visible'); + this.verifyHeadingExists('Home of #CommunityOps'); } } + export default CommunityPage; \ No newline at end of file diff --git a/cypress/pages/Footer.js b/cypress/pages/Footer.js index 3125388bb6b9..77a181f28795 100644 --- a/cypress/pages/Footer.js +++ b/cypress/pages/Footer.js @@ -1,14 +1,14 @@ import BasePage from './BaseFooterPage'; class Footer extends BasePage { - + constructor() { super(); - this.footerSelector = 'footer'; + this.footerSelector = 'footer'; } verifyFooterLink(href, text, attr = 'href') { - cy.get(this.footerSelector).within(() => { + cy.get(this.footerSelector).filter(':visible').first().within(() => { this.verifyLink(href, text, attr); }); } diff --git a/cypress/pages/RoadmapPage.js b/cypress/pages/RoadmapPage.js index d5930abbaf46..ee880b751cf2 100644 --- a/cypress/pages/RoadmapPage.js +++ b/cypress/pages/RoadmapPage.js @@ -1,6 +1,9 @@ -class RoadmapPage { +import BasePage from './BasePage'; + +class RoadmapPage extends BasePage { verifyPageLoaded() { - cy.contains('h1', 'AsyncAPI becomes the #1 API specification for defining and developing APIs.').should('be.visible'); + this.verifyHeadingExists('AsyncAPI becomes the #1 API specification for defining and developing APIs.'); } } + export default RoadmapPage; diff --git a/cypress/pages/ToolsPage.js b/cypress/pages/ToolsPage.js index 8dbc058b708e..97b3035c424e 100644 --- a/cypress/pages/ToolsPage.js +++ b/cypress/pages/ToolsPage.js @@ -1,12 +1,11 @@ -import BasePage from './BasePageTools'; - +import BasePage from './BasePage'; class ToolsPage extends BasePage { visitToolsPage() { super.visit('/tools'); } verifyPageLoaded() { - cy.contains('h1', 'Tools').should('be.visible'); + this.verifyHeadingExists('Tools'); } verifyHeader() { @@ -24,21 +23,8 @@ class ToolsPage extends BasePage { .parents('.rounded-lg.border.shadow-md') .first() .within(() => { - cy.get('h2').should('contain', heading); + this.verifyHeadingExists(heading); }); } - - verifyWebsiteLinks(href, heading) { - this.verifyToolLink(href, heading, 'website'); - } - - verifyGithubLinks(href, heading) { - this.verifyToolLink(href, heading, 'github'); - } - - verifyDocsLinks(href, heading) { - this.verifyToolLink(href, heading, 'docs'); - } } - export default ToolsPage; diff --git a/cypress/pages/ambassadors.js b/cypress/pages/ambassadors.js new file mode 100644 index 000000000000..157b0fae956d --- /dev/null +++ b/cypress/pages/ambassadors.js @@ -0,0 +1,32 @@ +class AmbassadorsPage { + visit() { + cy.visit('/community/ambassadors'); + } + + verifyKeySectionsAndLinks() { + cy.get('a[href="https://github.com/asyncapi/community/blob/master/docs/020-governance-and-policies/AMBASSADOR_PROGRAM.md"]' + ) + .should('be.visible'); + cy.get('[data-testid="Ambassadors-Iframe"]') + .should('be.visible'); + cy.get('[data-testid="Ambassadors-members-main"]') + .should('be.visible'); + cy.get('[data-testid="Events-ambassadors"]') + .scrollIntoView() + .should('be.visible'); + cy.get('a[href="https://www.asyncapi.com/blog/asyncapi-ambassador-program"]') + .should('be.visible'); + } + + verifyAmbassadorSocialLinks(name, links) { + cy.contains('[data-testid="Ambassadors-members-details"]', name) + .closest('[data-testid="Ambassadors-members"]') + .within(() => { + if (links.twitter) cy.get(`a[href="${links.twitter}"]`).should('be.visible'); + if (links.github) cy.get(`a[href="${links.github}"]`).should('be.visible'); + if (links.linkedin) cy.get(`a[href="${links.linkedin}"]`).should('be.visible'); + }); + } +} + +export default AmbassadorsPage; diff --git a/cypress/pages/basepagedocs.js b/cypress/pages/basepagedocs.js index 87afa5557972..e80e18dd2e2a 100644 --- a/cypress/pages/basepagedocs.js +++ b/cypress/pages/basepagedocs.js @@ -1,6 +1,6 @@ class BasePage { - visit(path = '/') { - cy.visit(path); + visit() { + cy.visit('/'); } verifyLinkByHref(href) { @@ -11,9 +11,9 @@ class BasePage { const wrap = cy.wrap($a); return $a.prop('target') === '_self' ? wrap.invoke('removeAttr', 'target').click() - : wrap.click(); - }); - } + : wrap.click(); + }); + } verifyLinkByLabel(href, label) { cy.get(`a[href="${href}"]`).contains(label).click(); diff --git a/cypress/pages/dashboard.js b/cypress/pages/dashboard.js new file mode 100644 index 000000000000..0d14f05b1917 --- /dev/null +++ b/cypress/pages/dashboard.js @@ -0,0 +1,40 @@ +import BasePage from './BasePageTools'; + +class DashboardPage extends BasePage { + visit() { + super.visit('/community/dashboard'); + } + + verifyHeader() { + this.verifyElementIsVisible('[data-testid="Header-heading"]'); + } + + verifyGoodFirstIssuesSection() { + this.verifyTextVisible('Good First Issues'); + } + + verifyHotTopicsSection() { + this.verifyTextVisible('Hot Topics'); + } + + verifyHeaderLinks() { + cy.contains('[data-testid="Button-link"]', 'Contribution Guide') + .should('be.visible') + .and('have.attr', 'href') + .and('include', 'docs/community'); + + this.verifyLinkWithText( + '[data-testid="Button-link"]', + 'View on Github', + 'github.com/asyncapi', + ); + + this.verifyLinkWithText( + '[data-testid="Button-link"]', + 'Join on Slack', + 'slack-invite', + ); + } +} + +export default DashboardPage; diff --git a/cypress/pages/events.js b/cypress/pages/events.js new file mode 100644 index 000000000000..5087b8ab2974 --- /dev/null +++ b/cypress/pages/events.js @@ -0,0 +1,109 @@ +import BasePage from './BasePageTools'; + +class EventsPage extends BasePage { + visit() { + super.visit('/community/events'); + } + + verifyMainVisible() { + this.verifyElementIsVisible('[data-testid="Events-main"]'); + } + + verifyActionButtons() { + this.verifyElementIsVisible('[data-testid="Events-Button"]'); + } + + verifyRecordingsSection() { + this.verifyElementIsVisible('[data-testid="Recordings-Link"]'); + this.verifyElementIsVisible('[data-testid="RecordingsCard-img"]'); + } + + verifyEventTypes() { + this.verifyElementIsVisible('[data-testid="EventTypesCard"]'); + this.verifyElementIsVisible('[data-testid="EventTypesCard-others"]'); + this.verifyElementIsVisible('[data-testid="CommunityMeeting-Card"]'); + } + + switchToFilter(label) { + cy.get('[data-testid="EventFilters-main"]') + .contains( + '[data-testid="EventFilter-click"]', + new RegExp(`^${label}$`, 'i'), + ) + .click(); + cy.get('[data-testid="EventPostItem-main"]').should('be.visible'); + } + + verifyEventCards() { + cy.get('[data-testid="EventPostItem-main"]') + .should('have.length.greaterThan', 0) + .each(($card) => { + cy.wrap($card) + .find('a[data-testid="EventPostItem-link"]') + .should('have.attr', 'href') + .and('match', /github\.com\/asyncapi\/community\/issues\/\d+/); + }); + } + + switchToAll() { + this.switchToFilter('All'); + } + + switchToUpcoming() { + this.switchToFilter('Upcoming'); + } + + switchToRecorded() { + this.switchToFilter('Recorded'); + } + + verifyEventButtonsLinks() { + cy.get('[data-testid="Events-Button"] a[data-testid="Button-link"]') + .eq(0) + .should('be.visible') + .and('have.attr', 'href') + .and('include', 'calendar.google.com'); + + cy.get('[data-testid="Events-Button"] a[data-testid="Button-link"]') + .eq(1) + .should('be.visible') + .and('have.attr', 'href') + .and('include', 'calendar.google.com/calendar/ical'); + } + + verifyFaqLink() { + cy.contains('a', 'read our FAQ') + .should('be.visible') + .and('have.attr', 'href') + .and('include', 'MEETINGS_ORGANIZATION.md'); + } + + verifyRecordingsLinkHref() { + cy.get('[data-testid="Recordings-Link"]') + .should('have.attr', 'href') + .and('include', 'playlist?list='); + } + + verifyEventRecordingLinks() { + cy.get('a[data-testid="Meeting-link"]') + .should('have.length.greaterThan', 0) + .each(($link) => { + cy.wrap($link) + .should('have.attr', 'href') + .and('match', /youtube\.com|youtu\.be/); + }); + } + + verifyHostLinks() { + cy.get('a[data-testid="TextLink-href"]') + .should('have.length.greaterThan', 0) + .each(($link) => { + cy.wrap($link) + .should('have.attr', 'href') + .and('not.be.empty') + .and('match', /^https?:\/\/.+/); + }); + } +} + +export default EventsPage; diff --git a/cypress/pages/homepage.js b/cypress/pages/homepage.js index fdd8c45777e8..705088e67b29 100644 --- a/cypress/pages/homepage.js +++ b/cypress/pages/homepage.js @@ -1,9 +1,12 @@ +import BasePage from './BasePage'; import CaseStudiesPage from './CaseStudiesPage'; import DocsPage from './DocsPage'; import RoadmapPage from './RoadmapPage'; import CommunityPage from './CommunityPage'; import ToolsPage from './ToolsPage'; import BlogPage from './BlogPage'; +import AmbassadorsPage from './ambassadors'; +import TSCPage from './tscpage'; import { features } from '../../components/features/FeatureList'; import packageJson from '../../package.json'; @@ -34,30 +37,9 @@ const homepageLinks = features.flatMap((feature) => })), ); -class HomePage { +class HomePage extends BasePage { visit() { - cy.visit('/'); - } - - verifyElementIsVisible(selector) { - cy.get(selector).should('be.visible'); - } - - verifyElementHasAttribute(selector, attribute, value) { - cy.get(selector).should('have.attr', attribute, value); - } - - verifyHeadingExists(headingText) { - cy.contains('h1, h2, h3, h4, h5, h6', headingText).should('be.visible'); - } - - verifyLinkExists(linkName, linkUrl) { - cy.get('a') - .contains(linkName, { matchCase: false }) - .should('exist') - .then(($el) => { - cy.wrap($el).invoke('attr', 'href').should('include', linkUrl); - }); + return super.visit('/'); } verifyCardTitles(customTitles, testId = null) { @@ -71,21 +53,20 @@ class HomePage { } verifyNavbarLogo() { - this.verifyElementIsVisible('[data-testid="Navbar-logo"]'); + return this.verifyElementIsVisible('[data-testid="Navbar-logo"]'); } verifyHeader(text = headerText) { - this.verifyHeadingExists(text); + return this.verifyHeadingExists(text); } verifyGithubStarButton(link = githubStarLink) { const selector = '[data-testid="Navbar-main"] [data-testid="Button-link"]'; - this.verifyElementIsVisible(selector); - this.verifyElementHasAttribute(selector, 'href', link); + return this.verifyElementIsVisible(selector).and('have.attr', 'href', link); } verifyReadTheDocsButton(link = readDocsLink) { - cy.get(`[data-testid="Button-link"][href="${link}"]`).should('be.visible'); + return cy.get(`[data-testid="Button-link"][href="${link}"]`).should('be.visible'); } verifyHomepageCards( @@ -140,6 +121,16 @@ class HomePage { cy.contains('a', 'Roadmap').click(); return new RoadmapPage(); } + + goToTSCPage() { + cy.visit('/community/tsc'); + return new TSCPage(); + } + + goToAmbassadorsPage() { + cy.visit('/community/ambassadors'); + return new AmbassadorsPage(); + } } -export default HomePage; +export default HomePage; \ No newline at end of file diff --git a/cypress/pages/slack.js b/cypress/pages/slack.js new file mode 100644 index 000000000000..3c8ebc361456 --- /dev/null +++ b/cypress/pages/slack.js @@ -0,0 +1,85 @@ +class SlackPage { + visitSlack() { + cy.visit( + 'https://asyncapi.slack.com/join/shared_invite/zt-3clk6rmc0-Cujl2fChHYnHDUwFKRlQCw#/shared-invite/email', + ); + } + + waitForPageLoad() { + cy.get('body', { timeout: 10000 }).should(($body) => { + const hasInactiveMessage = + $body.find('.p-refreshed_page__heading').length > 0; + const hasLoginButton = + $body.find('[data-qa="base_google_login_button"]').length > 0; + expect(hasInactiveMessage || hasLoginButton).to.be.true; + }); + } + + checkLinkStatus(callback) { + cy.get('body').then(($body) => { + const isInactive = + $body.find('.p-refreshed_page__heading').length > 0 && + $body.text().includes('This link is no longer active'); + callback(isInactive); + }); + } + + verifyInactiveLinkMessage() { + cy.get('.p-refreshed_page__heading') + .should('be.visible') + .and('have.text', 'This link is no longer active'); + } + + verifyAllLoginMethods() { + this.verifyGoogleLoginButton(); + this.verifyAppleLoginButton(); + this.verifyContinueWithEmail(); + } + + verifyAllFooterLinks() { + this.verifyPrivacyAndTerms(); + this.verifyContactUs(); + this.verifyChangeRegion(); + } + + verifyGoogleLoginButton() { + cy.get('[data-qa="base_google_login_button"]') + .should('be.visible') + .and('have.id', 'google_login_button') + .and('have.attr', 'type', 'button'); + } + + verifyAppleLoginButton() { + cy.get('[data-qa="base_apple_login_button"]') + .should('be.visible') + .and('have.id', 'apple_login_button') + .and('have.attr', 'href') + .and('include', 'slack.com/shared-invite/oauth/apple/start'); + } + + verifyContinueWithEmail() { + cy.get('[data-qa="join_with_email"]') + .should('be.visible') + .and('have.attr', 'type', 'button'); + } + + verifyPrivacyAndTerms() { + cy.get('[href="/legal"]') + .should('be.visible') + .and('have.attr', 'href', '/legal'); + } + + verifyContactUs() { + cy.get('[href="/help/requests/new"]') + .should('be.visible') + .and('have.attr', 'href', '/help/requests/new'); + } + + verifyChangeRegion() { + cy.get('a[href="#"]') + .should('be.visible') + .and('contain.text', 'Change region'); + } +} + +export default SlackPage; diff --git a/cypress/pages/toolsGenerator.js b/cypress/pages/toolsGenerator.js new file mode 100644 index 000000000000..dd11b3ce6a15 --- /dev/null +++ b/cypress/pages/toolsGenerator.js @@ -0,0 +1,11 @@ +import BasePage from './BasePage'; +import toolsData from '../fixtures/toolsPages.json'; + +class ToolsGenerator extends BasePage { + verifyGeneratorWorkflowDiagram() { + return this.verifyImageVisible(toolsData.generator.image); + } + +} + +export default ToolsGenerator; \ No newline at end of file diff --git a/cypress/pages/toolsModelina.js b/cypress/pages/toolsModelina.js new file mode 100644 index 000000000000..6d6a82a6cae0 --- /dev/null +++ b/cypress/pages/toolsModelina.js @@ -0,0 +1,14 @@ +import toolsData from '../fixtures/toolsPages.json'; +import BasePage from './BasePage'; + +class ToolsModelina extends BasePage { + verifyTryItNowLink() { + return this.verifyLink(toolsData.modelina.tryIt.href, toolsData.modelina.tryIt.text, { findByText: true }); + } + + verifyInstallSnippet() { + return this.verifyElementContainsText('code', toolsData.modelina.install); + } +} + +export default ToolsModelina; \ No newline at end of file diff --git a/cypress/pages/tscpage.js b/cypress/pages/tscpage.js new file mode 100644 index 000000000000..9667a0229f04 --- /dev/null +++ b/cypress/pages/tscpage.js @@ -0,0 +1,36 @@ +class TSCPage { + hoverCommunityLink() { + cy.get('[data-testid="NavItem-Link"]').contains('Community').trigger('mouseover'); + } + + fillNewsletterForm(name, email) { + cy.get('[data-testid="NewsletterSubscribe-text-input"]').type(name); + cy.get('[data-testid="NewsletterSubscribe-email-input"]').type(email); + } + + submitNewsletter() { + cy.get('[data-testid="Button-main"]').click(); + } + + getSuccessMessage() { + return cy.get('[data-testid="Paragraph-test"]').contains( + `You'll receive an email whenever someone requests the TSC to vote.` + ); + } + + getFailureMessage() { + return cy.get('[data-testid="Paragraph-test"]').contains(`Subscription failed, please let us know about it by submitting a bug`); + } + verifyTSCMemberSocialLinks(name, links) { + cy.contains('[data-testid="UserInfo-name"]', name) + .closest('[data-testid="UserInfo-list"]') + .within(() => { + if (links.GitHub) cy.get(`a[href="${links.GitHub}"]`).should('be.visible'); + if (links.Twitter) cy.get(`a[href="${links.Twitter}"]`).should('be.visible'); + if (links.Linkedin) cy.get(`a[href="${links.Linkedin}"]`).should('be.visible'); + }); + } +} + +export default TSCPage; + diff --git a/cypress/slackworkspace.cy.js b/cypress/slackworkspace.cy.js new file mode 100644 index 000000000000..fb806fc134b7 --- /dev/null +++ b/cypress/slackworkspace.cy.js @@ -0,0 +1,34 @@ +import SlackPage from './pages/slack'; + +describe('Slack workspace tests', () => { + const slackPage = new SlackPage(); + + beforeEach(() => { + slackPage.visitSlack(); + slackPage.waitForPageLoad(); + }); + + it('Should show all login methods when the Slack invite link is active', () => { + cy.get('body').then(($body) => { + const isInactive = + $body.find('.p-refreshed_page__heading').length > 0 && + $body.text().includes('This link is no longer active'); + + if (!isInactive) { + slackPage.verifyGoogleLoginButton(); + slackPage.verifyAppleLoginButton(); + slackPage.verifyContinueWithEmail(); + } else { + cy.log('Slack invite link is inactive - skipping login method tests'); + expect(isInactive).to.be.true; + } + }); + }); + + it('Should show links for Privacy, Contact Us, and Region Change', () => { + slackPage.verifyPrivacyAndTerms(); + slackPage.verifyContactUs(); + slackPage.verifyChangeRegion(); + }); + +}); diff --git a/cypress/tools_cli.cy.js b/cypress/tools_cli.cy.js new file mode 100644 index 000000000000..baf59946c7f3 --- /dev/null +++ b/cypress/tools_cli.cy.js @@ -0,0 +1,27 @@ +import BasePage from './pages/BasePage'; +import toolsData from './fixtures/toolsPages.json'; + +describe('Tools - CLI', () => { + const page = new BasePage(); + + beforeEach(() => { + page.visit(toolsData.cli.path); + }); + + it('should verify if the CLI header is visible', () => { + page.verifyHeadingExists(toolsData.cli.heading); + }); + + it('should verify if CLI GitHub link works', () => { + page.verifyButtonLink(toolsData.cli.github, 'View on Github'); + }); + + it('should verify if CLI Docs link works', () => { + page.verifyButtonLink(toolsData.cli.docs, 'View Docs'); + }); + + it('should verify if CLI install snippet is visible', () => { + page.verifyElementContainsText('code', toolsData.cli.install); + }); + +}); \ No newline at end of file diff --git a/cypress/tools_generator.cy.js b/cypress/tools_generator.cy.js new file mode 100644 index 000000000000..019115eda132 --- /dev/null +++ b/cypress/tools_generator.cy.js @@ -0,0 +1,26 @@ +import toolsGenerator from './pages/toolsGenerator'; +import toolsData from './fixtures/toolsPages.json'; + +describe('Tools - Generator Page', () => { + const page = new toolsGenerator(); + + beforeEach(() => { + page.visit(toolsData.generator.path); + }); + + it('Verifying if the main header is visible', () => { + page.verifyHeadingExists(toolsData.generator.heading); + }); + + it('Verifying if the generator diagram image is visible', () => { + page.verifyGeneratorWorkflowDiagram(); + }); + + it('Verifying if GitHub button link works', () => { + page.verifyButtonLink(toolsData.generator.github, 'View on Github'); + }); + + it('Verifying if Docs button link works', () => { + page.verifyButtonLink(toolsData.generator.docs, 'View Docs'); + }); +}); diff --git a/cypress/tools_github_actions.cy.js b/cypress/tools_github_actions.cy.js new file mode 100644 index 000000000000..47285426a80c --- /dev/null +++ b/cypress/tools_github_actions.cy.js @@ -0,0 +1,19 @@ +import BasePage from './pages/BasePage'; +import toolsData from './fixtures/toolsPages.json'; + +describe('Tools - GitHub Actions', () => { + const page = new BasePage(); + + beforeEach(() => { + cy.viewport(1280, 720); + page.visit(toolsData.githubActions.path); + }); + + it('Verifying if the GitHub Actions header is visible', () => { + page.verifyHeadingExists(toolsData.githubActions.heading); + }); + + it('Verifying if GitHub Actions GitHub link works', () => { + page.verifyButtonLink(toolsData.githubActions.github, 'View on Github'); + }); +}); diff --git a/cypress/tools_modelina.cy.js b/cypress/tools_modelina.cy.js new file mode 100644 index 000000000000..a5a8d039900a --- /dev/null +++ b/cypress/tools_modelina.cy.js @@ -0,0 +1,26 @@ +import ToolsModelina from './pages/toolsModelina'; +import toolsData from './fixtures/toolsPages.json'; + +describe('Tools - Modelina Page', () => { + const page = new ToolsModelina(); + + beforeEach(() => { + page.visit(toolsData.modelina.path); + }); + + it('should display the main header and intro', () => { + page.verifyHeadingExists(toolsData.modelina.heading); + }); + + it('should show the install snippet', () => { + page.verifyInstallSnippet(); + }); + + it('should verify the GitHub button link', () => { + page.verifyButtonLink(toolsData.modelina.github, 'View on Github'); + }); + + it('should verify the Try it now link', () => { + page.verifyTryItNowLink(); + }); +}); diff --git a/cypress/tools_parsers.cy.js b/cypress/tools_parsers.cy.js new file mode 100644 index 000000000000..8e4f1b46a416 --- /dev/null +++ b/cypress/tools_parsers.cy.js @@ -0,0 +1,23 @@ +import BasePage from './pages/BasePage'; +import toolsData from './fixtures/toolsPages.json'; + +describe('Tools - Parsers', () => { + const page = new BasePage(); + + beforeEach(() => { + cy.viewport(1280, 720); + page.visit(toolsData.parsers.path); + }); + + it('Verifying if the Parsers header is visible', () => { + page.verifyHeadingExists(toolsData.parsers.heading); + }); + + it('Verifying if Parsers GitHub link works', () => { + page.verifyButtonLink(toolsData.parsers.github, 'View on Github'); + }); + + it('Verifying if Parsers install snippet is visible', () => { + page.verifyElementContainsText('code', toolsData.parsers.install); + }); +}); diff --git a/cypress/toolspage.cy.js b/cypress/toolspage.cy.js index 5a98b07075cd..77d11c905c99 100644 --- a/cypress/toolspage.cy.js +++ b/cypress/toolspage.cy.js @@ -15,19 +15,19 @@ describe('Tools Page E2E Tests', () => { describe(`${sectionName} section`, () => { it('verifies Website links', () => { (linksData.WebsiteLinks || []).forEach((link) => { - toolsPage.verifyWebsiteLinks(link.href, link.heading); + toolsPage.verifyToolLink(link.href, link.heading, 'website'); }); }); it('verifies GitHub links', () => { (linksData.GithubLinks || []).forEach((link) => { - toolsPage.verifyGithubLinks(link.href, link.heading); + toolsPage.verifyToolLink(link.href, link.heading, 'github'); }); }); it('verifies Docs links', () => { (linksData.DocsLinks || []).forEach((link) => { - toolsPage.verifyDocsLinks(link.href, link.heading); + toolsPage.verifyToolLink(link.href, link.heading, 'docs'); }); }); }); diff --git a/cypress/tscpage.cy.js b/cypress/tscpage.cy.js new file mode 100644 index 000000000000..d6565cce6f98 --- /dev/null +++ b/cypress/tscpage.cy.js @@ -0,0 +1,80 @@ +import HomePage from './pages/homepage'; +import TSCPage from './pages/tscpage'; + +let homePage; +let tscpage; + +beforeEach(() => { + homePage = new HomePage(); + tscpage = new TSCPage(); + homePage.visit(); + homePage.goToTSCPage(); +}); + +describe('TSC Page', () => { + it('should succeed in subscribing to the newsletter', () => { + tscpage.fillNewsletterForm('anushka', 'valid@example.com'); + tscpage.submitNewsletter(); + tscpage.getSuccessMessage().should('be.visible'); + }); + + it('should show correct failure message', () => { + tscpage.fillNewsletterForm('aditi', 'kerghjh@fhgj'); + tscpage.submitNewsletter(); + tscpage.getFailureMessage().should('be.visible'); + }); + + it('verifies key links on the TSC page', () => { + const linksToVerify = [ + { + href: 'https://github.com/asyncapi/community/blob/master/docs/020-governance-and-policies/TSC_MEMBERSHIP.md', + label: 'Link', + }, + { + href: 'https://github.com/asyncapi/community/blob/master/docs/020-governance-and-policies/CHARTER.md', + label: 'Open Governance Model', + }, + { + href: 'https://www.asyncapi.com/blog/governance-motivation', + label: 'this', + }, + ]; + + linksToVerify.forEach(({ href, label }) => { + cy.get(`a[href="${href}"]`).contains(label).should('be.visible'); + }); + }); + + it('verifies social links for selected TSC members', () => { + const members = [ + { + name: 'Aishat Muibudeen', + links: { + GitHub: 'https://www.github.com/Mayaleeeee', + Twitter: 'https://www.twitter.com/maya_ux_ui', + Linkedin: 'https://www.linkedin.com/in/aishatmuibudeen' + } + }, + { + name: 'Khuda Dad Nomani', + links: { + GitHub: 'https://www.github.com/KhudaDad414', + Twitter: 'https://www.twitter.com/KhudaDadNomani', + Linkedin: 'https://www.linkedin.com/in/khudadadnomani' + } + }, + { + name: 'Lukasz Gornicki', + links: { + GitHub: 'https://www.github.com/derberg', + Twitter: 'https://www.twitter.com/derberq', + Linkedin: 'https://www.linkedin.com/in/lukasz-gornicki-a621914' + } + } + ]; + + members.forEach(({ name, links }) => { + tscpage.verifyTSCMemberSocialLinks(name, links); + }); + }); +}); diff --git a/docs/tools-ignore-design.md b/docs/tools-ignore-design.md new file mode 100644 index 000000000000..fa78f3ae8079 --- /dev/null +++ b/docs/tools-ignore-design.md @@ -0,0 +1,391 @@ +# Tools Ignore System -- Design Document + +## Table of Contents + +1. [Problem Statement](#problem-statement) +2. [Architecture Overview](#architecture-overview) +3. [Data Flow](#data-flow) +4. [File Map](#file-map) +5. [Schema Design](#schema-design) + - [tools-ignore.json](#tools-ignorejson) + - [tools-ignored.json (Audit Log)](#tools-ignoredjson-audit-log) +6. [Matching Algorithm](#matching-algorithm) + - [Ignore Variations](#ignore-variations) + - [Decision Flowchart](#decision-flowchart) +7. [Usage Guide](#usage-guide) + - [Variation 1: Ignore by Title](#variation-1-ignore-by-title) + - [Variation 2: Ignore by repoUrl (Quick Remove)](#variation-2-ignore-by-repourl-quick-remove) + - [Variation 3: Ignore by Title + repoUrl (Specific Fork)](#variation-3-ignore-by-title--repourl-specific-fork) + - [Variation 4: Ignore by Title with Category Scope](#variation-4-ignore-by-title-with-category-scope) + - [Variation 5: Ignore by repoUrl with Category Scope](#variation-5-ignore-by-repourl-with-category-scope) + - [Variation 6: Ignore by Title + repoUrl + Category Scope](#variation-6-ignore-by-title--repourl--category-scope) +8. [Why This Design?](#why-this-design) + +--- + +## Problem Statement + +The AsyncAPI website displays a curated list of community tools. These tools are gathered from two sources: + +1. **Automated** -- A GitHub Actions workflow runs on a schedule, fetches tool metadata via the GitHub API, and writes `tools-automated.json`. +2. **Manual** -- Maintainers hand-curate entries in `tools-manual.json`. + +A combine script merges both sources into a single `tools.json` that the website reads. + +**The problem:** Everything fetched from the GitHub API is included without any filtering. If a fork, a deprecated project, or a spam entry appears in the automated data, there is no mechanism to exclude it from the final output. The tools-ignore system solves this by introducing a declarative ignore list that filters out unwanted entries during the combine step. + +--- + +## Architecture Overview + +``` + GitHub API + | + v + +-------------------------+ + | extract-tools-github.ts | (fetch .asyncapi-tool files) + +-------------------------+ + | + v + +--------------------+ + | tools-object.ts | (convert to standard format) + +--------------------+ + | + v + +------------------------+ + | tools-automated.json | (raw automated tools) + +------------------------+ + | + +--------------------+--------------------+ + | | + v v ++---------------------+ +---------------------+ +| tools-manual.json | | tools-ignore.json | <-- NEW ++---------------------+ +---------------------+ + | | + +---------+ +---------------------+ + | | + v v + +-------------------------+ + | combine-tools.ts | (merge + filter) + +-------------------------+ + | | + v v + +-------------+ +------------------+ + | tools.json | | tools-ignored.json| <-- NEW (audit log) + +-------------+ +------------------+ + | + v + Website UI +``` + +The new `tools-ignore.json` file sits alongside the existing config files and is read during the combine step. Any tool matching an ignore rule is filtered out **before** merging. A companion `tools-ignored.json` audit log is written to record exactly what was filtered and why. + +--- + +## Data Flow + +Here is the step-by-step flow when `npm run generate:tools` executes: + +``` +1. build-tools.ts is invoked + | +2. getData() fetches .asyncapi-tool files from GitHub repos + | +3. convertTools() normalizes the raw data into ToolsListObject format + | +4. Result is written to config/tools-automated.json + | +5. config/tools-manual.json is read from disk + | +6. config/tools-ignore.json is read from disk (if it exists) + | +7. combineTools() is called with all three inputs + | + +---> For each category: + | | + | +---> Filter automated tools against the ignore list + | | (shouldIgnoreTool() called per tool) + | | Ignored tools are recorded in the audit array + | | + | +---> Process kept automated tools (getFinalTool) + | | - Match language/technology tags + | | - Assign display colors + | | + | +---> Filter manual tools against the ignore list + | | (shouldIgnoreTool() called per tool) + | | Ignored tools are recorded in the audit array + | | + | +---> Validate & process kept manual tools + | | - JSON schema validation (Ajv) + | | - getFinalTool processing + | | + | +---> Merge automated + manual results + | | + | +---> Sort alphabetically by title + | +8. Write config/tools.json (combined output) + | +9. Write config/all-tags.json (language + technology tags) + | +10. Write config/tools-ignored.json (audit log of what was filtered) + | +11. Log ignored tools summary to stdout (visible in workflow logs) +``` + +--- + +## File Map + +| File | Role | Committed to Git? | +|------|------|:-:| +| `config/tools-automated.json` | Raw automated tools from GitHub API | Yes | +| `config/tools-manual.json` | Hand-curated manual tool entries | Yes | +| `config/tools-ignore.json` | Declarative ignore rules | Yes | +| `config/tools.json` | Final combined output for the website | Yes | +| `config/all-tags.json` | Aggregated language/technology tags | Yes | +| `config/tools-ignored.json` | Auto-generated audit log | No (.gitignore) | +| `scripts/build-tools.ts` | Orchestrator / entry point | Yes | +| `scripts/tools/combine-tools.ts` | Core merge + filter logic | Yes | +| `types/scripts/tools.ts` | TypeScript type definitions | Yes | +| `tests/tools/combine-tools.test.ts` | Unit tests | Yes | +| `tests/fixtures/combineToolsData.ts` | Test fixture data | Yes | + +--- + +## Schema Design + +### tools-ignore.json + +Located at `config/tools-ignore.json`. This is the file maintainers edit to control which tools are excluded. + +```json +{ + "description": "Human-readable description of this file's purpose.", + "tools": [ + { + "title": "Tool Name", + "repoUrl": "https://github.com/owner/repo", + "reason": "Why this tool is being ignored", + "categories": ["Editors", "CLIs"] + } + ] +} +``` + +**Field reference:** + +| Field | Type | Required | Description | +|-------|------|:--------:|-------------| +| `title` | `string` | No* | Exact title of the tool to match. | +| `repoUrl` | `string` | No* | Repository URL to match. When used alone, all tools with this repo are ignored regardless of title. | +| `reason` | `string` | Yes | Documents why this tool is being excluded. Appears in the audit log. | +| `categories` | `string[]` | No | When provided, the tool is only removed from these specific categories. When omitted, the tool is removed from **all** categories it appears in. Values must match category names exactly (e.g., `"Editors"`, `"Code-first tools"`, `"AsyncAPI Generator Templates"`). | + +> *At least one of `title` or `repoUrl` must be provided. Entries with neither are skipped. + +### tools-ignored.json (Audit Log) + +Auto-generated at `config/tools-ignored.json` on every combine run. This file is in `.gitignore` and serves as a local verification artifact. + +```json +{ + "description": "Auto-generated audit log of tools ignored during the last combine run.", + "generatedAt": "2026-02-22T10:27:48.978Z", + "totalIgnored": 7, + "ignoredTools": [ + { + "title": "SIO-AsyncAPI", + "repoUrl": "https://github.com/daler-rahimov/sio-asyncapi", + "reason": "Deprecated tool", + "category": "APIs", + "source": "automated", + "ignoredAt": "2026-02-22T10:27:48.922Z" + } + ] +} +``` + +**Field reference for each entry in `ignoredTools`:** + +| Field | Description | +|-------|-------------| +| `title` | Title of the tool that was ignored. | +| `repoUrl` | The tool's repository URL (for identification). | +| `reason` | The reason string from the matching ignore rule. | +| `category` | Which category this specific removal happened in. | +| `source` | Whether the tool came from `"automated"` or `"manual"` data. | +| `ignoredAt` | ISO 8601 timestamp of when the ignore was applied. | + +A single ignore rule can produce multiple audit records if the tool appears in several categories. + +--- + +## Matching Algorithm + +### Ignore Variations + +The system supports six distinct ignore strategies, each providing a different level of precision: + +| # | Strategy | Fields Used | What Gets Removed | +|---|----------|-------------|-------------------| +| 1 | Title only | `title` | All tools with that title, in all categories | +| 2 | repoUrl only | `repoUrl` | All tools with that repo, in all categories (quick remove) | +| 3 | Title + repoUrl | `title`, `repoUrl` | Only the exact title+repo combination, in all categories | +| 4 | Title + categories | `title`, `categories` | All tools with that title, but only in the listed categories | +| 5 | repoUrl + categories | `repoUrl`, `categories` | All tools with that repo, but only in the listed categories | +| 6 | Title + repoUrl + categories | `title`, `repoUrl`, `categories` | Only the exact title+repo combination, only in the listed categories | + +### Decision Flowchart + +For each tool in each category, the `shouldIgnoreTool()` function evaluates every entry in the ignore list: + +``` +For each ignore entry: + | + +---> Does the entry have at least `title` or `repoUrl`? + | | + | No --> SKIP (invalid entry) + | | + | Yes --> continue + | + +---> Does the entry have `categories`? + | | + | Yes --> Is the current category in that list? + | | | + | | No --> SKIP this entry, move to next + | | | + | | Yes --> continue + | | + | No --> continue (applies to all categories) + | + +---> Does the entry have BOTH `title` and `repoUrl`? + | | + | Yes --> Do both match the tool? + | | | + | | Yes --> MATCH -> ignore this tool + | | No --> SKIP + | | + | No --> continue + | + +---> Does the entry have only `title`? + | | + | Yes --> Does `tool.title === entry.title`? + | | | + | | Yes --> MATCH -> ignore this tool + | | No --> SKIP + | | + | No --> continue + | + +---> Does the entry have only `repoUrl`? + | + Yes --> Does `tool.links.repoUrl === entry.repoUrl`? + | + Yes --> MATCH -> ignore this tool + No --> SKIP + +If no entry matches after checking all: KEEP the tool +``` + +--- + +## Usage Guide + +### Variation 1: Ignore by Title + +Remove a tool from **every** category it appears in. Use when the tool itself is the problem (deprecated, spam, etc.). + +```json +{ + "title": "SIO-AsyncAPI", + "reason": "Project is deprecated and no longer maintained" +} +``` + +**Effect:** Every entry with `title === "SIO-AsyncAPI"` is removed from all categories (APIs, Code-first tools, etc.). + +### Variation 2: Ignore by repoUrl (Quick Remove) + +Remove a tool by its repo URL alone, without needing to know or specify its title. Useful for quickly blocking a fork or spam repo. + +```json +{ + "repoUrl": "https://github.com/hkirat/asyncapi-fork", + "reason": "Unauthorized fork" +} +``` + +**Effect:** Every entry whose `repoUrl` matches `"https://github.com/hkirat/asyncapi-fork"` is removed from all categories, regardless of what title the tool has. + +### Variation 3: Ignore by Title + repoUrl (Specific Fork) + +Remove only a specific fork/clone while keeping the original. Use when multiple tools share the same title but have different repositories, and you want maximum precision. + +```json +{ + "title": "AsyncAPI Studio", + "repoUrl": "https://github.com/Shurtu-gal/action-test-bed", + "reason": "Fork repository, not the official AsyncAPI Studio" +} +``` + +**Effect:** Only the entry with title `"AsyncAPI Studio"` AND repo `"https://github.com/Shurtu-gal/action-test-bed"` is removed. The official `asyncapi/studio` and any other forks with different repos are untouched. + +### Variation 4: Ignore by Title with Category Scope + +Remove a tool from specific categories only. Use when a tool is correctly listed in some categories but incorrectly appears in others. + +```json +{ + "title": "Zod Sockets", + "reason": "Not primarily a framework, better categorized as code-first and DSL", + "categories": ["Frameworks"] +} +``` + +**Effect:** `"Zod Sockets"` is removed from the `"Frameworks"` category only. It remains in `"Code-first tools"` and `"DSL"`. + +### Variation 5: Ignore by repoUrl with Category Scope + +Remove a repo from specific categories only, without needing the title. Useful when a repo auto-populates into wrong categories. + +```json +{ + "repoUrl": "https://github.com/example/some-tool", + "reason": "Incorrectly categorized in CLIs", + "categories": ["CLIs"] +} +``` + +**Effect:** The tool with that repo URL is removed only from `"CLIs"`. It remains in all other categories. + +### Variation 6: Ignore by Title + repoUrl + Category Scope + +The most precise option. Targets a specific repo in specific categories. + +```json +{ + "title": "HTML Template", + "repoUrl": "https://github.com/dipaksodani/async-gen", + "reason": "Fork, only remove from templates listing", + "categories": ["AsyncAPI Generator Templates"] +} +``` + +**Effect:** Only the specific fork is removed, and only from the `"AsyncAPI Generator Templates"` category. + +--- + +## Why This Design? + +### Why are both title and repoUrl optional? + +Either field can serve as the primary identifier depending on the use case. `title` makes the ignore file human-readable and reviewable. `repoUrl` enables quick, precise removal when you have a repo URL at hand (e.g., from a GitHub notification) without needing to look up the tool's display title. When both are provided, they form an AND condition for maximum precision. + +### Why exact matching instead of fuzzy/regex? + +Exact matching is predictable and auditable. When a maintainer adds an ignore rule, they can be certain it will only affect the exact tool they specified. Fuzzy matching could produce surprising results (e.g., ignoring "AsyncAPI" could match "AsyncAPI CLI", "AsyncAPI Studio", etc.). + +### Why category scoping? + +The same tool frequently appears in multiple categories (e.g., a tool categorized as both `code-first` and `framework`). Category scoping lets maintainers make precise corrections to categorization without removing the tool entirely. diff --git a/markdown/about/index.md b/markdown/about/index.md index 19718b8b048f..67021f1b8182 100644 --- a/markdown/about/index.md +++ b/markdown/about/index.md @@ -18,7 +18,7 @@ The AsyncAPI project started at Hitch (a.k.a. API Changelog). Hitch needed a mac Free software allows users to apply, modify, and continue in the chain by distributing copies to help others and, in this case, disseminating modified versions of the specification. -Transferring AsyncAPI to the Linux Foundation and forming [an open governance model](https://github.com/asyncapi/community/blob/master/CHARTER.md) assures the community that a single company does not control AsyncAPI Initiative. This move takes the project to a higher level of transparency. +Transferring AsyncAPI to the Linux Foundation and forming [an open governance model](https://github.com/asyncapi/community/blob/master/docs/020-governance-and-policies/CHARTER.md) assures the community that a single company does not control AsyncAPI Initiative. This move takes the project to a higher level of transparency. In doing so, we achieve: diff --git a/markdown/blog/2022Q1-summary.md b/markdown/blog/2022Q1-summary.md index 7d4393219071..328f7630264e 100644 --- a/markdown/blog/2022Q1-summary.md +++ b/markdown/blog/2022Q1-summary.md @@ -60,7 +60,7 @@ Because of the community's growth and the growing number of topic-specific meeti Huge thanks to [Krishna Kumar](https://github.com/Krishks369) and [Shreyansh Jain](https://github.com/sudoshreyansh), who helped research the implementation. :heart: -If you want to learn more about becoming a meeting host, or something else related to meetings, get familiar with our [dedicated meetings FAQ](https://github.com/asyncapi/community/blob/master/MEETINGS_ORGANIZATION.md). +If you want to learn more about becoming a meeting host, or something else related to meetings, get familiar with our [dedicated meetings FAQ](https://github.com/asyncapi/community/blob/master/docs/060-meetings-and-communication/MEETINGS_ORGANIZATION.md). Oh, and I almost forgot, look at this. :point_down: :star: All [info about AsyncAPI-related meetings](https://www.asyncapi.com/community/meetings) is in one beautiful place! :heart: diff --git a/markdown/blog/2023-mentorship-summary.md b/markdown/blog/2023-mentorship-summary.md index b594ff5b4bbc..662252d307ca 100644 --- a/markdown/blog/2023-mentorship-summary.md +++ b/markdown/blog/2023-mentorship-summary.md @@ -79,9 +79,9 @@ While all the selected projects received outstanding contributions from the ment - **Active Contributors**: With the dedication and guidance provided by our mentorship program, many mentees have grown into active contributors, driving positive change and making significant impacts within our community. Their journeys from eager learners to influential leaders stand as a testament to the power of mentorship and the potential within each participant. - **Full Circle**: A few of these mentees have come full circle and now serve as mentors in this year’s Google Summer of Code (GSoC). Their transition from mentees to mentors is a testament to their exceptional growth and dedication. Once guided and nurtured through our program, these individuals are now giving back by sharing their knowledge and experience with the next generation of mentees. We are incredibly proud of their achievements and commitment to fostering a culture of learning and mentorship. Here's the list of mentees who became mentors: - - [AISHAT MUIBUDEEN](https://github.com/Mayaleeeee): GSoC mentor for the [AsyncAPI Website UI Kit Development](https://github.com/asyncapi/community/blob/master/mentorship/summerofcode/2024/asyncapi-gsoc-ideas-page.md#5-asyncapi-website-ui-kit-development) - - [Ansh Goyal](https://github.com/anshgoyalevil/): GSoC mentor for [Script Stability Enhancement for AsyncAPI Website](https://github.com/asyncapi/community/blob/master/mentorship/summerofcode/2024/asyncapi-gsoc-ideas-page.md#2-script-stability-enhancement-for-asyncapi-website) - - [Sambhav Gupta](https://github.com/anshgoyalevil/): GSoC co-mentor for [Script Stability Enhancement for AsyncAPI Website](https://github.com/asyncapi/community/blob/master/mentorship/summerofcode/2024/asyncapi-gsoc-ideas-page.md#2-script-stability-enhancement-for-asyncapi-website) + - [AISHAT MUIBUDEEN](https://github.com/Mayaleeeee): GSoC mentor for the [AsyncAPI Website UI Kit Development](https://github.com/asyncapi/community/blob/master/docs/050-mentorship-program/summerofcode-2024-asyncapi-gsoc-ideas-page.md#5-asyncapi-website-ui-kit-development) + - [Ansh Goyal](https://github.com/anshgoyalevil/): GSoC mentor for [Script Stability Enhancement for AsyncAPI Website](https://github.com/asyncapi/community/blob/master/docs/050-mentorship-program/summerofcode-2024-asyncapi-gsoc-ideas-page.md#2-script-stability-enhancement-for-asyncapi-website) + - [Sambhav Gupta](https://github.com/anshgoyalevil/): GSoC co-mentor for [Script Stability Enhancement for AsyncAPI Website](https://github.com/asyncapi/community/blob/master/docs/050-mentorship-program/summerofcode-2024-asyncapi-gsoc-ideas-page.md#2-script-stability-enhancement-for-asyncapi-website) - **Outside the community benefit**: Thanks to the invaluable support and guidance from the program, some mentees received job offers and sought-after internships. diff --git a/markdown/blog/2023-summary.md b/markdown/blog/2023-summary.md index 78bce07df1e5..14258ef829a5 100644 --- a/markdown/blog/2023-summary.md +++ b/markdown/blog/2023-summary.md @@ -155,7 +155,7 @@ We achieved so much this year, and here are some of the highlights from the Asyn - We launched the [AsyncAPI Bounty Program](https://github.com/asyncapi/community/pull/897/files#diff-25ecb20a61754c225d6511ca08d7e7c9a14b9ca5a93e89bd42331e51c9ebf26dR155), where we successfully resolved and paid out a total of 11 out of 16 issues during the initial trial and 2023 Q4 round. - Established our very first [AsyncAPI Code of Conduct Committee](https://github.com/orgs/asyncapi/discussions/682#discussioncomment-7498209). - Barbaño González shared a detailed article on [Why Women Are Underrepresented In Open-Source](https://thenewstack.io/why-women-are-underrepresented-in-open-source/). -- Participated in [GSoC'23](https://github.com/orgs/asyncapi/discussions/997) and [GSoD'23](https://github.com/orgs/asyncapi/discussions/961), while kickstarting the [AsyncAPI Mentorship Program II](https://github.com/asyncapi/community/tree/master/mentorship/asyncapi-mentorship/2023). +- Participated in [GSoC'23](https://github.com/orgs/asyncapi/discussions/997) and [GSoD'23](https://github.com/orgs/asyncapi/discussions/961), while kickstarting the [AsyncAPI Mentorship Program II](https://github.com/asyncapi/community/blob/master/docs/050-mentorship-program/asyncapi-mentorship-2023-project-ideas.md). - Held our first in-person [AsyncAPI Conference on Tour](https://conference.asyncapi.com/) in London, Madrid, Bangalore and Paris. - Released the [AsyncAPI v3](https://www.asyncapi.com/blog/release-notes-3.0.0). - Launched the [AsyncAPI Store](https://asyncapi-store.com/). diff --git a/markdown/blog/2024-Q1-docs-report.md b/markdown/blog/2024-Q1-docs-report.md index abac050f3e07..6e0126827add 100644 --- a/markdown/blog/2024-Q1-docs-report.md +++ b/markdown/blog/2024-Q1-docs-report.md @@ -126,4 +126,4 @@ E --> H ## Contribute to AsyncAPI Documentation -To get started as a docs contributor, follow the steps in the [AsyncAPI Technical Writer Onboarding Checklist](https://github.com/asyncapi/community/blob/master/docs/onboarding-guide/docs-onboarding-checklist.md). \ No newline at end of file +To get started as a docs contributor, follow the steps in the [AsyncAPI Technical Writer Onboarding Checklist](https://github.com/asyncapi/community/blob/master/docs/000-onboarding/docs-onboarding-checklist.md). \ No newline at end of file diff --git a/markdown/blog/2024-annual-summary.md b/markdown/blog/2024-annual-summary.md index ec11e2dc0d79..c83f7f2ab965 100644 --- a/markdown/blog/2024-annual-summary.md +++ b/markdown/blog/2024-annual-summary.md @@ -169,7 +169,7 @@ These are some of the few highlights for 2024, and we have more planned for 2025 We are starting the year with [an open discussion on establishing our first AsyncAPI Governance Board](https://github.com/asyncapi/community/pull/1634), so please join the conversation. -You can also check out the [2025 AsyncAPI Community Building Goals](https://github.com/asyncapi/community/blob/master/annual-goals/2025_Community_Goals.md) to see what's in store for this year. +You can also check out the [2025 AsyncAPI Community Building Goals](https://github.com/asyncapi/community/blob/master/docs/030-project-vision-strategy-goals/2025_Community_Goals.md) to see what's in store for this year. > Image by Canva diff --git a/markdown/blog/2024-april-summary.md b/markdown/blog/2024-april-summary.md index a680906c33cb..ad481dee7444 100644 --- a/markdown/blog/2024-april-summary.md +++ b/markdown/blog/2024-april-summary.md @@ -41,7 +41,7 @@ After some weeks of discussing the marketing efforts, we are now looking for som We have a new Conference Coordination Working Group that focuses on planning, managing, and creating a seamless way to enhance the conference experience. If you want to join the working group or read more about their work, please check out the [Conference Coordination Working Group discussion](https://github.com/orgs/asyncapi/discussions/1170). ## TSC x Ambassadors -We're thrilled to announce a new automated TSC voting system! We want to thank [Aayush Saini](https://github.com/AayushSaini101) for working on the implementation, as this will make the voting process smoother, more efficient, and more transparent. With this new system, we hope to encourage greater participation and engagement. Please make sure to [read the voting docs](https://github.com/asyncapi/community/blob/master/voting.md) to familiarize yourself with the new voting system. +We're thrilled to announce a new automated TSC voting system! We want to thank [Aayush Saini](https://github.com/AayushSaini101) for working on the implementation, as this will make the voting process smoother, more efficient, and more transparent. With this new system, we hope to encourage greater participation and engagement. Please make sure to [read the voting docs](https://github.com/asyncapi/community/blob/master/docs/020-governance-and-policies/voting.md) to familiarize yourself with the new voting system. ## Coming in May - **AACoT'24 Helsinki** - The Helsinki Edition will take place on May 28th and 29th. Please keep an eye out for announcements on community tickets on Slack and our social channels. diff --git a/markdown/blog/2024-february-summary.md b/markdown/blog/2024-february-summary.md index 7bf7ba79e025..80cb688f6d06 100644 --- a/markdown/blog/2024-february-summary.md +++ b/markdown/blog/2024-february-summary.md @@ -13,7 +13,7 @@ authors: excerpt: 'Community update for February' --- -We are starting the year off with a bang as we got accepted to the [Google Summer of Code 2024](https://summerofcode.withgoogle.com/programs/2024/organizations/asyncapi) program after two years of rejections. It is an incredible achievement for the community, and we wouldn't have done it without our Doc's Lead, [Quetzalli Writes](https://www.linkedin.com/in/quetzalli-writes), who crafted an excellent proposal, and [Elegbede Azeez](https://twitter.com/_acebuild). We are very excited to have received this opportunity, and you can read [the AsyncAPI Project Ideas Page](https://github.com/asyncapi/community/blob/master/mentorship/summerofcode/2024/asyncapi-gsoc-ideas-page.md) for in-depth details on participating projects. +We are starting the year off with a bang as we got accepted to the [Google Summer of Code 2024](https://summerofcode.withgoogle.com/programs/2024/organizations/asyncapi) program after two years of rejections. It is an incredible achievement for the community, and we wouldn't have done it without our Doc's Lead, [Quetzalli Writes](https://www.linkedin.com/in/quetzalli-writes), who crafted an excellent proposal, and [Elegbede Azeez](https://twitter.com/_acebuild). We are very excited to have received this opportunity, and you can read [the AsyncAPI Project Ideas Page](https://github.com/asyncapi/community/blob/master/docs/050-mentorship-program/summerofcode-2024-asyncapi-gsoc-ideas-page.md) for in-depth details on participating projects. ## AsyncAPI Conf on Tour 2024 The planning of AACoT'24 is already underway as we prepare for our first conference in Helsinki on the 28th - 29th of May. We are putting in the final touches to update our conference website with the latest details, and we will soon announce the Call for Speakers. In the meantime, be sure to start crafting those proposals and get ready to share your expertise with the community. @@ -45,7 +45,7 @@ We have important discussions that require the community's attention: - ### Cupid is Looking For Maintainers We're on the lookout for maintainers for the AsyncAPI Cupid. The library focuses on finding and analyzing the relationships between AsyncAPI documents. If you're well-versed in Event-Driven Architecture and AsyncAPI, please [join the Cupid repository discussion](https://github.com/asyncapi/cupid/issues/182) and help us drive its development. - ### AsyncAPI Working Groups - We are finally officializing working groups throughout the AsyncAPI community. A working group will be a community where people share similar interests beyond GitHub repositories. You can read the [Working Groups docs](https://github.com/asyncapi/community/blob/master/WORKING_GROUPS.md) or view the [Working Group public discussion](https://github.com/orgs/asyncapi/discussions/1037) for more comprehensive details. + We are finally officializing working groups throughout the AsyncAPI community. A working group will be a community where people share similar interests beyond GitHub repositories. You can read the [Working Groups docs](https://github.com/asyncapi/community/blob/master/docs/020-governance-and-policies/WORKING_GROUPS.md) or view the [Working Group public discussion](https://github.com/orgs/asyncapi/discussions/1037) for more comprehensive details. ## TSC Members x Ambassadors diff --git a/markdown/blog/2024-july-summary.md b/markdown/blog/2024-july-summary.md index 07bedd27b559..06529c901c5a 100644 --- a/markdown/blog/2024-july-summary.md +++ b/markdown/blog/2024-july-summary.md @@ -57,7 +57,7 @@ Our Google Summer of Code'24 mentors have recently submitted their mid-term eval [You can check out the accepted AsyncAPI project list](https://summerofcode.withgoogle.com/programs/2024/organizations/asyncapi) and see what the mentees are working on. ## Technical Steering Committee -To improve transparency in the project and ensure regular monitoring of the TSC's participation, we have implemented an automated report of TSC voting with support from [Aayush Saini](https://github.com/AayushSaini101). The report provides detailed information about the voting process, and [you can check out the first version of the TSC Overview doc report](https://github.com/asyncapi/community/blob/master/TSC_VOTING_OVERVIEW.md). +To improve transparency in the project and ensure regular monitoring of the TSC's participation, we have implemented an automated report of TSC voting with support from [Aayush Saini](https://github.com/AayushSaini101). The report provides detailed information about the voting process, and [you can check out the first version of the TSC Overview doc report](https://github.com/asyncapi/community/blob/master/docs/020-governance-and-policies/TSC_VOTING_OVERVIEW.md). As a TSC member, if you identify incorrect data, [please create an issue in the community repository](https://github.com/asyncapi/community/issues) with the correct information, as it will allow us to review and address any issues with the automation process or voting discrepancies. diff --git a/markdown/blog/2025-Q1-marketing-report.md b/markdown/blog/2025-Q1-marketing-report.md index 5d0838c2eb0e..c002d5224987 100644 --- a/markdown/blog/2025-Q1-marketing-report.md +++ b/markdown/blog/2025-Q1-marketing-report.md @@ -98,7 +98,7 @@ Similarly, "Understanding AsyncAPIs with a Practical Example" drew good engageme Over the next few months, we will begin rolling out initiatives aligned with the strategy, and our progress will be tracked through clearly defined KPIs, and consistent quarterly reports will be shared to ensure transparency and accountability. -[Read the 2025 AsyncAPI Marketing Strategy](https://github.com/asyncapi/community/blob/master/annual-goals/2025_marketing_strategy.md) +[Read the 2025 AsyncAPI Marketing Strategy](https://github.com/asyncapi/community/blob/master/docs/030-project-vision-strategy-goals/2025_marketing_strategy.md) ## Event & Community Engagement diff --git a/markdown/blog/2025-annual-summary.md b/markdown/blog/2025-annual-summary.md new file mode 100644 index 000000000000..741437bf3527 --- /dev/null +++ b/markdown/blog/2025-annual-summary.md @@ -0,0 +1,176 @@ +--- +title: "State of AsyncAPI Initiative: 2025 Annual Review" +date: 2026-01-10T06:00:00+01:00 +type: Communication +tags: + - Project Status +cover: /img/posts/2025-blog-banner/banner-annual.webp +authors: + - name: Thulisile Sibanda + photo: /img/avatars/thulieblack.webp + link: https://www.linkedin.com/in/v-thulisile-sibanda/ + byline: Community Builder and Open Source Fanatic! +excerpt: 'AsyncAPI Annual Review for 2025 in Numbers' +--- + +Happy 2026 to the AsyncAPI community! + +Starting the new year by looking back at our community’s growth. Let’s review the numbers to see our progress, where we can do better, and how we can improve. These metrics help us understand our impact and guide us in the direction to take when working towards the community goals. + +For the past achievements, [please read the previous Project Status updates](https://www.asyncapi.com/blog?tags=Project+Status). + +> As a disclaimer, all analytics you’ll read here are collected from the 1st of January 2025 to the 30th of December 2025. + +## Slack + +The AsyncAPI Slack workspace is our primary channel for most communications and updates, where contributors and adopters join to collaborate with others, understand how we work as a community, and chat with maintainers of the specifications and tooling. + +In 2025, we welcomed **1857** new joiners and have a total of **7964** members. + +
    + +Our weekly activity reduced by 19% this year, with the intention of reducing noise in channels by disabling some workflow notifications and pausing certain channels. Also, we ran one mentorship program instead of multiple as we did in previous years, and had fewer active working groups. + +
    + +## Social Media +Our social media platforms help us to share community news, updates, and announcements. We don’t use any premium or paid marketing, and we only maintain LinkedIn, X/Twitter, Mastodon, and YouTube platforms. We use Buffer to publish and manage content across social media. + +### Buffer +We began using Buffer in July 2024 and switched to paid services in September. This gave us more tools to track and report on our social media management. The analytics below cover LinkedIn and X/Twitter, which Buffer currently supports. + +We also have some analytics recorded dating back to 2023. + +
    + +### LinkedIn + +We gained **945** followers on LinkedIn in 2025, bringing our overall following to **4928**. + +
    + +### YouTube +We had **272** new subscribers to our YouTube channel this year, bringing our total subscribers to **1,983**. While our views and watch time dropped by 29% compared to last year, the community continues to grow and engage. + +
    + +### Newsletter +The community summary newsletter continues to grow and still serves the community as a summary of our monthly blogs, events, and important updates. We sent 10 emails this year, and our average open rate was 41%, while clicks averaged 4.7%. Bringing the overall engagement rate to 22.7%. + +
    + +The number of new users referred to the AsyncAPI through our monthly newsletter increased, though session time dropped slightly. + +
    + +## Google Analytics +The overall site performance declined this year, with users by 4.4%, sessions by 9.1%, and pageviews by 15.8%. Docs continue to be a great contributor to the performance in sessions. + +
    + +The contributing factor leading to the drop in analytics is due to several factors, including users blocking tracking, privacy tools, and browser extensions. This trend affects the traffic recorded, and user behaviour data does not fully reflect the actual audience, as they’re excluded from the analytics reports. + +## Google Search Console + +We saw a 6.9% increase in impressions in Google Search Console, although we had a decrease in clicks. + +
    + +## GitHub +We use LF Insights to get detailed analytics for all our repos across the org on GitHub. The community keeps growing, with **1,131** active contributors. + +
    + +We also improved issue resolution across the project, with the average issue now taking just one month to close, a clear sign of our maintainers' responsiveness. + +
    + +In the past year, a total of **2,770** pull requests were opened, and **2,390** were merged, highlighting the pace of development and community contributions. + +
    + +The AsyncAPI community is driven by contributors and maintainers who dedicate their time and expertise outside their regular jobs. Kudos to everyone for your commitment and impact! + +
    + + +## NPM +AsyncAPI's top packages are hosted under the Node Package Manager. The package downloads continue to increase, and the `asyncapi/spec` saw **54M** downloads in the past year. + +
    + + +## Community Achievements + +We had so many achievements this year, and here are a few highlights: + + +- We transitioned and nominated our first [Governance Board](https://www.asyncapi.com/community/board). +- We published our [second case study](https://www.asyncapi.com/casestudies/transfergo) by TransferGo. +- The AsyncAPI Bounty Program turned 2 with over [36 issues resolved](https://github.com/orgs/asyncapi/projects/36/views/4?filterQuery=-no%3Alevel+status%3ACompleted). +- We had six in-person conferences, an online conference, and over 30 speakers. +- Welcomed [two ambassadors](https://www.asyncapi.com/community/ambassadors) and introduced monthly meetings. +- Expanded our [community docs](https://www.asyncapi.com/docs/community) and content. +- Surpassed [5,000 stars on the Spec repo](https://github.com/asyncapi/spec/stargazers) in GitHub. + + +These are just a few, but we have so much planned for 2026. Be sure [to read the community goals](https://www.asyncapi.com/docs/community/030-project-vision-strategy-goals/2026_Community_Goals) to gain insight into what we will be focusing on. + + +> Image Generated by Nano Banana diff --git a/markdown/blog/2025-conference-summary.md b/markdown/blog/2025-conference-summary.md new file mode 100644 index 000000000000..eaffccad28e3 --- /dev/null +++ b/markdown/blog/2025-conference-summary.md @@ -0,0 +1,153 @@ +--- +title: "AsyncAPI Conference 2025 Report" +date: 2026-02-03T06:00:00+01:00 +type: Communication +tags: + - Project Status +cover: /img/posts/2025-blog-banner/banner-conf.webp +authors: + - name: Thulisile Sibanda + photo: /img/avatars/thulieblack.webp + link: https://www.linkedin.com/in/v-thulisile-sibanda/ + byline: Community Builder and Open Source Fanatic! +excerpt: 'AsyncAPI Conference Report for 2025' +--- + +Celebrating the third year of planning the in-person conferences brought growth this year. We rebranded to AsyncAPI Conference, doing away with the `On Tour` branding for a more unified brand while still keeping the same vision we had from the beginning. + +We expanded to six venues plus the online conference, and some worked better than others, but each taught us something valuable. We gained better knowledge, new case studies, stronger community bonds, and people connecting in person to share ideas. + +Here’s how it went. + +## Planning +With the growing partnership we have with APIdays, we had the opportunity to run the AsyncAPI track at five venues, and API Conf Lagos hosted it in Lagos. The experience wouldn’t be complete without the Online Conference. + +So in 2025, we were present in three new locations, expanding our reach, and had 41% of new speakers share their expertise at each conference, bringing the total to 39 speakers across all the events. + +For detailed summaries of each event, please read: + +- [Singapore Edition](https://www.asyncapi.com/blog/2025-singapore-conf-summary) +- [Munich + Lagos Edition](https://www.asyncapi.com/blog/2025-july-summary) +- [London Edition](https://www.asyncapi.com/blog/2025-september-summary) +- [Bangalore + Online Edition](https://www.asyncapi.com/blog/2025-october-summary) +- [Paris Edition](https://www.asyncapi.com/blog/2025-december-summary) + +## Challenges +We are growing in capacity, so there were instances when we had great talks but limited slots, and we had to sacrifice introductory talks on what exactly AsyncAPI is, especially in new venues or for folks encountering us for the first time. + +Secondly, there were instances when communication was slow, and most planning and scheduling happened at the last minute. Huge thanks to the speakers for understanding and to the community members for stepping up. + +## Attendance +The turnout at most events was amazing, and we had full rooms with attendees engaging with the speakers, asking questions. But the real conference usually happens in the hallway and at the API Standards booth, where our maintainers and community members have conversations, ask questions about the community, and share how they can get involved. + +The Online Conference garnered around **380** views. If you haven’t had the chance to watch, please be sure to catch up on the recordings. + +## Conference Sponsors +The success of the 2025 conference edition was due to the amazing sponsors who supported our vision. + +### Host Sponsors +Thank you to [APIdays](https://www.apidays.global) and [APIConf Lagos](https://apiconf.net) for hosting us and sponsoring space for the API Standards booth and lunch. + + +apidays + + + + +apiconflagos + + +### Financial Sponsors +To facilitate travel, have MCs on-site to support the events and cover logistics for shipping swag, we received support from [Gravitee](https://www.gravitee.io) and [IBM](https://www.ibm.com) who were our Financial sponsors. We appreciate them for their support. + + +gravitee.io + + + + +ibm + + +### Where The Funds Went + +We sponsored travel for **13 individuals** to attend the conferences, both locally and internationally. We also reimbursed for the cheat sheet printing and shipped swags to major locations. + +## API Standards Booth + +The API Standards booth in Paris was super busy. We had representatives from AsyncAPI, GraphQL, and JSON Schema. Our initiative of having a vendor-neutral booth with open source API standards reached momentum, where there are too many of us, which is good; this means we want to share space together and have discussions. + +You can also join at https://groups.io/g/api-standards and help drive the initiative further. See the messages and discussion on the Paris retrospective. + +## Special Thank You + +Big thanks to our speakers for taking the time to share their knowledge and insights. Also, thank you to everyone who volunteered at the API Standards booth. Your effort to help didn’t go unnoticed. + +And a huge thanks to the behind-the-scenes crew who made everything work and led parts of the conference together as the Conference Coordination WG. + + + + +## Where To In 2026 + +For our first conference for the year, we will be heading to DeveloperWeek February 19 – 20 in San Jose, CA, where the [AsyncAPI track](https://conference.asyncapi.com/venue/California) will be at the Frontend World + Dev Innovation World Stage. + +We have [Free Open Passes](https://link.devnetwork.com/1Uvd6FUb). Please help us share and spread the word, and see you there! + + +Additionally, we are looking to complement our large conference tracks with intimate, community-led meetups. If your company has a venue to share or would like to host an AsyncAPI meetup in 2026, please reach out! + +More venues to follow, [keep an eye out on the Conference website](https://conference.asyncapi.com). + + + + + + diff --git a/markdown/blog/2025-december-summary.md b/markdown/blog/2025-december-summary.md index 039f437e06ef..99974e6bc0eb 100644 --- a/markdown/blog/2025-december-summary.md +++ b/markdown/blog/2025-december-summary.md @@ -11,7 +11,6 @@ authors: link: https://www.linkedin.com/in/v-thulisile-sibanda/ byline: Community Builder and Open Source Fanatic! excerpt: 'AsyncAPI community and project updates for November and December 2025' -featured: true --- Well, believe it or not, we are in the final weeks of 2025! It's been a great year as we navigated crucial growth in the community and, of course, some challenges along the way. Most importantly, we have new experiences that continuously make us better. diff --git a/markdown/blog/2025-february-summary.md b/markdown/blog/2025-february-summary.md index bbfc7d37bdea..5e520cf5e2db 100644 --- a/markdown/blog/2025-february-summary.md +++ b/markdown/blog/2025-february-summary.md @@ -14,7 +14,7 @@ excerpt: 'AsyncAPI community status and project updates for February 2025' --- It's been a busy few weeks in the community, and we are establishing an organizational structure as we continue to grow. -[We now have the Community Working Group](https://github.com/asyncapi/community/blob/master/annual-goals/2025_Community_Goals.md#community-working-group-umbrella), which serves as an umbrella for the initiatives and programs under AsyncAPI while increasing visibility for our community builder's efforts to sustain the community. +[We now have the Community Working Group](https://github.com/asyncapi/community/blob/master/docs/030-project-vision-strategy-goals/2025_Community_Goals.md#community-working-group-umbrella), which serves as an umbrella for the initiatives and programs under AsyncAPI while increasing visibility for our community builder's efforts to sustain the community. In light of that, we are also discussing the introduction of a Governance Board to replace the Executive Director position with a board of 3 to 5 members. The board aims to share community responsibilities, reduce the risk of key-person dependency (bus factor), and work towards sustaining the community in the long term. [Please participate in this discussion and share your thoughts and ideas on establishing our first AsyncAPI Governance Board](https://github.com/asyncapi/community/pull/1634). diff --git a/markdown/blog/2025-gsoc-phase-1.md b/markdown/blog/2025-gsoc-phase-1.md index 6fd912b3be6d..13e5db9d3117 100644 --- a/markdown/blog/2025-gsoc-phase-1.md +++ b/markdown/blog/2025-gsoc-phase-1.md @@ -37,7 +37,7 @@ Here’s how we laid the groundwork for a successful GSoC 2025 first phase: Mentors are the heart of a successful GSoC experience. Rather than manage a separate process, we used the same discussion thread to invite experienced contributors and maintainers to step forward as potential mentors. This approach helped us keep all conversations in one place and encouraged mentors to engage with idea proposals, provide feedback, and collaboratively shape the project scope. - **Curating and Centralizing Ideas:** - From the 15 suggestions we received, we curated 9 project ideas that best aligned with AsyncAPI’s community goals and roadmap. These were published in our community repository under the mentorship directory, as seen [here](https://github.com/asyncapi/community/blob/master/mentorship/summerofcode/2025/asyncapi-gsoc-ideas-page.md). This centralized format made our GSoC application seamless because we simply shared the link with program organizers, making it easy for them to review our proposals. + From the 15 suggestions we received, we curated 9 project ideas that best aligned with AsyncAPI’s community goals and roadmap. These were published in our community repository under the mentorship directory, as seen [here](https://github.com/asyncapi/community/blob/master/docs/050-mentorship-program/summerofcode-2025-asyncapi-gsoc-ideas-page.md). This centralized format made our GSoC application seamless because we simply shared the link with program organizers, making it easy for them to review our proposals. - **Hosting a GSoC Livestream:** After being formally accepted as a mentoring organization, we hosted an [introductory livestream](https://www.youtube.com/watch?v=R7pl1F2dYLo) for potential GSoC contributors. In this session, we walked students/contributors through everything they needed to know, from selecting the right project and understanding the application timeline, to crafting strong proposals and making meaningful contributions to AsyncAPI. diff --git a/markdown/blog/2025-gsoc-summary.md b/markdown/blog/2025-gsoc-summary.md new file mode 100644 index 000000000000..03ec4655b51f --- /dev/null +++ b/markdown/blog/2025-gsoc-summary.md @@ -0,0 +1,174 @@ +--- +title: "2025 Google Summer of Code: Summary" +date: 2026-01-20T18:00:00+01:00 +type: Community +tags: + - Mentorship + - GSoC + - AsyncAPI + - OSS +cover: /img/posts/gsoc-25.webp +authors: + - name: Azeez Elegbede + photo: /img/avatars/ace.webp + link: https://www.linkedin.com/in/aelegbede/ + byline: AsyncAPI Preacher +--- + +**Celebrating real impact, strong mentorship, and a growing community** + +AsyncAPI participated in Google Summer of Code (GSoC) for the fourth time in 2025, a significant milestone that speaks to our commitment to nurturing the next generation of open-source contributors. Seven contributors invested months building meaningful projects within the AsyncAPI ecosystem. As with previous years, project timelines varied, with some wrapping up in early October and others extending into late November. + +We're thrilled to report that **6 out of 7 projects were successfully completed**, with the remaining one still actively progressing. Each project brings its own story of growth, collaboration, and impact. + +We worked with an incredible group of contributors, connecting regularly through group video calls to discuss their GSoC projects and tackle blockers together, helping ensure a smooth and productive summer for everyone. Throughout their time with AsyncAPI, contributors picked up new skills, made meaningful improvements to our tooling, and helped shape our ecosystem. We’re deeply grateful for their contributions and the energy they brought to the program. + +**Fun news:** Some of our GSoC 2025 contributors have continued working on their projects even after the program concluded. Even more exciting, two former GSoC contributors have stepped into [Technical Steering Committee](https://www.asyncapi.com/community/tsc) roles, highlighting both the impact of their work and the level of responsibility and ownership they’ve grown into. + +
    + + +Google Summer of Code was a big success for AsyncAPI this year, with a higher number of projects, an encouraging sign of what’s ahead in the coming years. GSoC has consistently proven to be a great entry point into the AsyncAPI community, something we know firsthand from participating in the program over multiple years. We’re excited to continue taking part in GSoC this year and in many more to come. + +If you’re interested in becoming a GSoC contributor, check out our [**GSoC project ideas list**](https://github.com/asyncapi/community/blob/master/docs/050-mentorship-program/summerofcode-2025-asyncapi-gsoc-ideas-page.md) and our [**guide for new contributors**](https://github.com/asyncapi/community/blob/master/docs/010-contribution-guidelines/contribution-flow.md) to get started. + +## Project Highlight + +Below, we’ve put together a brief summary of all our GSoC projects to give you insight into each project’s goals and the current status of any unfinished work. You can find more details about the original project objectives in the linked resources. + +### AsyncAPI Generator Maintainership +- **Contributor:** [Adi Boghawala](https://github.com/Adi-204) +- **Mentor:** [Lukasz Gornicki](https://github.com/derberg) +- **Final report:** [Read here](https://gist.github.com/Adi-204/a4040124ed8cb510465e8e38b1fd422d) + +One of the ongoing challenges at AsyncAPI is the shortage of maintainers across some of our most widely used tools, including the [**AsyncAPI Generator**](https://github.com/asyncapi/generator). The Generator plays a critical role in the ecosystem: it enables developers to generate a wide range of outputs directly from an AsyncAPI specification and ships with a rich set of officially supported templates. Several other core tools within the initiative, such as the CLI and Studio, are built on top of it, making its long-term maintainability essential. + +This made bringing in new maintainers a priority, and Adi proved to be an excellent fit for the role. + +During GSoC, Adi made impactful contributions that addressed both architectural and ecosystem-level challenges: + +- **Unified Integration Testing for WebSocket Clients:** Adi tackled a major scalability issue in our WebSocket client testing setup, where over 80% of the integration test code was duplicated across Dart, Python, and JavaScript clients. He introduced a unified and flexible integration test suite powered by shared helpers and a scalable structure that cleanly separates common and client-specific logic. This work eliminated duplicate test files and cleanup scripts, centralized test setup, and significantly improved maintainability across clients. + +- **A New Message Validation Library – [`@asyncapi/keeper`](http://npmjs.com/package/@asyncapi/keeper):** Recognizing the need for robust and developer-friendly message validation, Adi initiated the development of `@asyncapi/keeper`. This new library provides reusable and extensible utilities for validating message payloads against JSON Schema Draft-07 and AsyncAPI specifications, built on top of `@hyperjump/json-schema` and the AsyncAPI parser. It fills a critical gap in the ecosystem by offering a clearer and more accessible validation experience. + +Adi’s contributions throughout GSoC went far beyond writing code. He actively engaged in community discussions, contributed to process improvements, and demonstrated strong ownership of the tools he worked on. This growth and commitment ultimately led to Adi joining the **Technical Steering Committee**, reflecting both the impact of his work and the responsibility he took on within the initiative. + +We’d like to sincerely thank Adi for his outstanding contributions and congratulate him on becoming a Technical Steering Committee member. + +### VS Code Extension Maintainership + +- **Contributor:** [Ruchi Pakhle](https://github.com/Ruchip16) +- **Mentor:** [Iván García Sainz-Aja](https://github.com/ivangsa) +- **Final report:** [Read here](https://github.com/Ruchip16/website/blob/new_blog/markdown/blog/vsasyncapi-preview-extension.md) + +The [AsyncAPI VS Code Extension](https://github.com/asyncapi/vs-asyncapi-preview) is the official tool for previewing AsyncAPI documents directly within VS Code. Prior to GSoC, the extension was close to entering maintenance mode due to a lack of active maintainers. During the program, Ruchi stepped in as a co-maintainer alongside Iván and quickly took ownership of a critical new feature that significantly expanded the reach of the tool. + +Historically, previewing an AsyncAPI document required a locally configured VS Code environment. Ruchi’s work removed this limitation by making the extension **web-compatible**, enabling AsyncAPI documents to be previewed directly in web-based IDEs such as GitHub and GitLab. This means contributors and reviewers can now view `YAML` files straight from repositories, without cloning code or setting up a local environment, greatly improving accessibility and developer experience. + +Ruchi delivered this functionality through a series of thoughtful and impactful improvements: + +- **Removed Node.js-specific modules** such as `fs`, `path`, and other runtime dependencies that are incompatible with browser environments, unblocking support for VS Code Web. +- **Introduced lightweight browser-friendly utilities** (`pathUtils`) to replace Node-based file handling, ensuring consistent behavior across desktop and web-based IDEs. +- **Removed the EDAVisualizer integration**, which was unmaintained and incompatible with web mode, simplifying the extension’s architecture and reducing technical debt. +- **Updated core VS Code dependencies** (`vscode` and `@types/vscode`) to align with modern extension APIs and ensure long-term compatibility with VS Code Web. + +Through this work, Ruchi not only helped keep the VS Code extension actively maintained but also unlocked a new class of usage for the AsyncAPI ecosystem. Her contributions meaningfully improved accessibility, reduced friction for contributors, and strengthened the long-term sustainability of one of AsyncAPI’s most important tools. + +Ruchi’s impactful work on the VS Code extension led to her joining the Technical Steering Committee. We were truly impressed by what she accomplished and greatly enjoyed working with her throughout the summer. Thank you for all your contributions, Ruchi! + +### Extending AsyncAPI’s Generator Java Templates with Quarkus + +- **Contributor:** [Shuaib Salad](https://github.com/ssala034) +- **Mentors:** [Aayush Saini](https://github.com/AayushSaini101) [Souvik De](https://github.com/Souvikns) +- **Final report:** [Read here](https://gist.github.com/ssala034/4f90f4695a34d0e6bb897d2551aea973) + +Shuaib’s work during GSoC was nothing short of outstanding. He was not only the first contributor to complete his project for the summer, but he also delivered a highly impactful contribution that significantly extends AsyncAPI’s suite of production-ready templates. His project focused on designing, building, and maintaining a [**Java Quarkus template**](https://github.com/asyncapi/generator/tree/master/packages/templates/clients/websocket/java/quarkus) within the AsyncAPI Generator, bringing first-class support for Kubernetes-native, event-driven Java applications. + +Throughout the program, Shuaib introduced a scalable and modular template architecture inside the Generator monorepo, making it easier to extend, maintain, and evolve Java-based templates over time. His work added support for **AsyncAPI v3 specifications**, enabling developers to generate modern event-driven applications directly from their AsyncAPI documents. + +Key highlights of Shuaib’s contributions include: + +- **Java Quarkus Template Infrastructure:** Built a production-ready template with Maven-based builds, Docker support for JVM mode, Kubernetes manifest generation, and a clean package structure, laying a strong foundation for future Java templates. +- **WebSocket Client Generation:** Enabled generation of WebSocket-based microservices capable of connecting to dynamic endpoints defined in AsyncAPI schemas, improving flexibility for real-time use cases. +- **Kafka Protocol Support:** Added Kafka-based microservice generation with built-in producer and consumer templates, topic configuration, and support for event-driven architectures. +- **Acceptance & Contract Testing:** Implemented automated acceptance tests using Podman Compose and Microcks to validate generated code against AsyncAPI contracts, ensuring correctness and real-world readiness. + +Beyond feature development, Shuaib tackled complex architectural challenges such as modular component design, AsyncAPI schema parsing, and dynamic endpoint and topic configuration. His work makes reuse of existing Generator components while extending them to support framework-specific and role-based logic, helping improve consistency across templates. + +Shuaib’s contributions meaningfully strengthened the AsyncAPI Generator ecosystem, expanded its Java and cloud-native capabilities, and set a solid foundation for future template development. We’re incredibly grateful for his dedication, technical depth, and early delivery, and we’re excited to see how this work continues to evolve within the community. + +### AsyncAPI Conference Website UI Kit Development + +- **Contributor:** [TenzDelek](https://github.com/TenzDelek) +- **Mentors:** [Azeez Elegbede](https://github.com/AceTheCreator)  [Ashmit Jagtap](https://github.com/ashmit-coder) +- **Final report:** [Read here](https://gist.github.com/TenzDelek/a6e653cfaae6eb2bca793374ce1695a9) + +The goal of this project was to develop a Storybook-based UI component library for the conference website to ensure design consistency, modularity, and maintainability. + +Tenzin has been a long-term contributor to the conference website before GSoC, and it was a no-brainer for him to work on the Storybook implementation of the conference website. + +Over the coding period, Tenzin methodically built out the UI Kit through multiple pull requests, establishing foundational patterns that will significantly streamline future development. He did some amazing work, such as: + +- **Design System Foundation:** Tenzin started by establishing the architectural backbone of the entire design system. He built the initial Storybook setup, configured the design system infrastructure, and documented the comprehensive color palette and typography system. + +- **Component Development & Reusability:** The real impact came through systematic component work. Tenzin modernized the Button component with significant architectural improvements, refactoring it to accept flexible props (including text, outline, and, crucially, icon positioning), and then created comprehensive Storybook stories showcasing all variations. He systematically updated all Button usage across the codebase; in forms, headers, and CTAs. + +- **Infrastructure & Tooling Excellence:** Tenzin executed a Storybook 9 migration while simultaneously introducing a comprehensive icon system as React components. Rather than relying on image files scattered throughout the codebase, he created modular icon components (GitHub, LinkedIn, X, YouTube social icons, map pointers, arrows, and more). This refactor touched 24 files, replacing all image-based icons with clean, scalable React component equivalents, a subtle but significant improvement to maintainability and performance. + +Each PR wasn't just about adding features; it was about establishing patterns. By making the Dropdown generic, he created a blueprint for component reusability across different data types. + +In Tezin's words... "Working with AsyncAPI during GSoC has been a transformative experience. Beyond the code, I gained a profound understanding of what open-source really is. It’s about the incredible community and the chance to learn alongside people who share the same passions." Thank you for your great work! + +### Redesign the AsyncAPI Website and Implement Dark Theme + +- **Contributor:** [Shriya Chauhan](https://github.com/Shriya-Chauhan) +- **Mentors:** [Ashmit JaiSarita Gupta](https://github.com/devilkiller-ag) & [Aishat Muibudeen](https://github.com/Mayaleeeee) +- **Final report:** [Read here](https://gist.github.com/Shriya-Chauhan/d4ef9904b83cf88d3d9554b8afa1903e) + +This GSoC project tackled one of the most visible aspects of the AsyncAPI community, the website itself. The scope was ambitious: redesign the entire website with a modern visual language, extend designs across all pages, and implement full dark mode support. + +And Shriya is doing just that while following the [design implementation](https://www.figma.com/design/ZDmqYdLfqbW4Jj4yxzhgQH/GSoc-25-website-redesign?node-id=7801-3660&p=f). She made meaningful contributions to several parts of the implementation. Starting with only the homepage and community page designs, the contributor expanded the redesign to 10 pages in Figma, meticulously creating both light and dark mode variants. This wasn't simply applying a color scheme; it required rethinking layouts, typography, component hierarchies, and icon systems for both themes. The work spanned the entire site: navbar, homepage, docs, case studies, blog, roadmap, TSC, ambassadors, events, newsroom, tools dashboard, and community page. + +Shriya's contribution can be categorized into two: + +- **Implementation at Scale:** The code work translated these designs into 12 implemented pages across three major pull requests. Beyond pixel-perfect implementation, the contributor built reusable component patterns, refactored redundant code, and ensured accessible contrast ratios throughout. Key additions included an interactive "Sneak Peek" showcase on the Docs page, redesigned member profile cards for TSC, responsive blog pagination and category filters, and a completely rebuilt Ambassadors page with improved card layouts. + +- **Managing Complexity:** What became clear early on was that the project scope extended far beyond initial estimates. Juggling both design and development simultaneously, managing design approvals, iterating on feedback, implementing changes, and maintaining consistency across 12+ pages proved demanding. The extended review cycle with limited maintainer availability added complexity, but the contributor adapted by continuing post-GSoC through November 30th to ensure quality. + +As of now, the [final implementation](https://github.com/asyncapi/website/pull/4553) remains under review. Remaining work includes dark mode refinements on the CLI page, sponsor logo contrast fixes, icon reviews, and design updates to the board members page to match the new theme. + +Thanks to Shriya, the website will have a refined, fresh look, and we can't wait to have the implementation merged into `master`. + +### Refactor the Scripts inside the website and add Integration tests + +- **Contributor:** [Sagar Kori](https://github.com/sagarkori143) +- **Mentor:** [Akshat Nema](https://github.com/akshatnema) +- **Final report:** [Read here](https://docs.google.com/document/d/1gx7uGdJvUEM5M8KgPV1V-eC_bPSoj8Y8pJ80e0VHaQs/edit?usp=sharing) + +Sagar took on a critical challenge: modernizing the AsyncAPI website's build infrastructure. The website relied on Node.js and TypeScript scripts to generate static .mdx and .json files during builds and scheduled cron jobs, but it had become fragile and difficult to maintain. + +When Sagar started, the script system had multiple pain points: scripts executed immediately upon import (making testing nearly impossible), paths were hardcoded throughout, error handling was inconsistent, and there were zero integration tests to verify real behavior. Debugging was risky, and refactoring was dangerous. + +Sagar's contribution to modernizing the website's build spanned three main areas: + +- **Script Refactoring & Architecture:** Sagar systematically refactored 10+ scripts to remove direct execution patterns, converting them into pure functions that accept configuration through parameters instead of relying on hardcoded paths. This separation of business logic from execution logic made everything reusable, testable, and maintainable, laying the foundation for the entire system redesign. + +- **The Runner System: Centralized Execution:** With a new `npm/runners` folder containing 10 runner files, Sagar introduced a consistent script execution layer. Each runner provides sensible production defaults while allowing configuration overrides, uses a shared error handling pattern based on CustomError, executes safely from the command line, and crucially, doesn't auto-run during tests. Existing npm scripts were updated to use these runners internally, making the system the single source of truth for how scripts execute. + +- **Integration Tests & CI Integration:** Sagar built 10+ integration test suites that run real runners, verify files are generated correctly on disk, validate content and structure, test error scenarios and path handling, and manage concurrency between tests. He updated GitHub Actions so integration tests run automatically on pull requests, ensuring script changes don't break the build system. Jest configuration was refined to support running unit and integration tests separately and together. + +Sagar's work represents crucial foundational progress for AsyncAPI's build infrastructure. By successfully refactoring the script system and establishing a comprehensive testing framework, he has positioned the codebase for safe, confident development moving forward. His architecture and testing patterns will undoubtedly influence how the AsyncAPI team maintains and extends this critical system as it continues to grow. Thank you very much, Sagar! + +## Conclusion + +We want to extend our heartfelt gratitude to every contributor who dedicated their summer to AsyncAPI through Google Summer of Code 2025. Your energy, creativity, and commitment have left a lasting impact on our community. We're already excited about the innovations you'll bring in future seasons. + +A huge thank you to Google for making GSoC possible and granting us a spot. Your investment in open-source mentorship continues to shape the next generation of developers. + +Finally, to our mentors... your patience, guidance, and unwavering support were the backbone of every contributor's success. You went above and beyond, spanning time zones and challenges, to help bring these projects to life. AsyncAPI's GSoC journey simply wouldn't exist without you. + +Here's to an incredible summer of code, collaboration, and community. We can't wait to see what's next. \ No newline at end of file diff --git a/markdown/blog/2026-february-summary.md b/markdown/blog/2026-february-summary.md new file mode 100644 index 000000000000..0e2d67bcb206 --- /dev/null +++ b/markdown/blog/2026-february-summary.md @@ -0,0 +1,98 @@ +--- +title: "Monthly Community Update: February 2026" +date: 2026-03-03T06:00:00+01:00 +type: Communication +tags: + - Project Status +cover: /img/posts/2026-blog-banner/feb-banner.webp +authors: + - name: Thulisile Sibanda + photo: /img/avatars/thulieblack.webp + link: https://www.linkedin.com/in/v-thulisile-sibanda/ + byline: Community Builder and Open Source Fanatic! +excerpt: 'AsyncAPI community and project updates for February 2026' +--- + +It's been a busy few weeks as we lay some groundwork, plan for the rest of the year, and align with the goals we have as a community. +We recently held our first conference for 2026, announced our latest spec release, and we have an update on our Google Summer of Code application. So let's dive into the updates that happened this month. + +## AsyncAPI Conference 2026 + +While we are still finalizing the venues for the AsyncAPI Conference 2026 and communicating with our host sponsors, we have also been working on the AsyncAPI Meetups section, which will be part of the Conference Initiative but on a smaller scale. We have been busy over the past year adding the details that will be integrated into the website and also sharing the news by word of mouth. + +Once the [meetups section pull request is merged](https://deploy-preview-721--peaceful-ramanujan-288045.netlify.app/meetups), we look forward to finally sharing more details with the rest of the community. In the meantime, please keep an eye out for announcements about where we might be going next this year and start planning to submit those proposals. + +### DeveloperWeek 2026 Recap +We recently went to California, where we held our first-ever conference in the US and the first conference of the year as part of DeveloperWeek 2026. We had a full track spanning the 2-day conference, with an agenda full of expert speakers sharing case studies, use cases, and the community work behind AsyncAPI. + +But the biggest highlight for us was the API Standards Booth, where all of our speakers had time to volunteer and answer popular questions about what AsyncAPI is and its use cases. + +
    + +Aside from this, it was also an opportunity to network and share ideas on how to improve. Huge thank you to everyone who attended and [to our host sponsor, DeveloperWeek](https://www.developerweek.com), for having us there. And finally, a huge thank you to the speakers who also volunteered at the API Standards Booth. + + + +## Spec x Tooling + +The AsyncAPI spec maintainers now meet monthly to coordinate specification work and are seeking community input on key proposals: +- [Late/out-of-sequence events](https://github.com/asyncapi/spec/issues/1143): Adding event delivery latency specifications for streaming frameworks like Apache Flink and Spark. +- [Multiple security schemes](https://github.com/asyncapi/spec/issues/1129): Enabling AND logic so multiple security mechanisms can be required simultaneously. +- [Discriminator alignment](https://github.com/asyncapi/spec/issues/1073): Expanding beyond string-only discriminators to align with the OpenAPI Discriminator Object. + +Additionally, we recently released the AsyncAPI Spec 3.1. Be sure to [read the release notes](https://www.asyncapi.com/blog/release-notes-3.1.0) on what’s new and what needs to be updated as well. + +## GSoC 2026 +Our application for Google Summer of Code 2026 was not accepted for this year. While we anticipated being part of the program this year, we will also explore other options and programs, and some maintainers are considering doing the Maintainership outside the paid programs. + +Be sure to attend the next Community WG meetings as we navigate the next steps. + +## Coming in March +- AsyncAPI Community Updates Newsletter - The March Edition will arrive in your inbox on the 5th. [Please subscribe to the AsyncAPI Newsletter to stay up-to-date with the latest updates](https://www.asyncapi.com/newsletter). +- The list for conference venues will be finalized this month. Please start planning to submit proposals. \ No newline at end of file diff --git a/markdown/blog/2026-march-summary.md b/markdown/blog/2026-march-summary.md new file mode 100644 index 000000000000..41dfeddf95db --- /dev/null +++ b/markdown/blog/2026-march-summary.md @@ -0,0 +1,66 @@ +--- +title: "Monthly Community Update: March 2026" +date: 2026-04-02T06:00:00+01:00 +type: Communication +tags: + - Project Status +cover: /img/posts/2026-blog-banner/march-banner.webp +authors: + - name: Thulisile Sibanda + photo: /img/avatars/thulieblack.webp + link: https://www.linkedin.com/in/v-thulisile-sibanda/ + byline: Community Builder and Open Source Fanatic! +excerpt: 'AsyncAPI community and project updates for March 2026' +--- +As different parts of the world are ushering in new seasons, with the arrival of Spring in the Northern Hemisphere and Autumn in the Southern Hemisphere, change is in the air, and here at AsyncAPI, we're embracing that energy! +The community is continuing with its commitment as we work to strengthen sustainability and improve initiatives. + + +## Governance Board Nominations +It’s time to expand the Governance Board and for community members to nominate members who will serve the community and help sustain the Initiatives. +We have 3 seats open, and nominations will be open for the next 3 weeks. For more details on the timeline, eligibility, and requirements, [please read the Governance Board Nomination](https://www.asyncapi.com/blog/board-nomination). + +## AsyncAPI Conference 2026 + +The rest of the venues of 2026 have been finalized, and we’ll be heading to: + +- APIdays Amsterdam, 9 - 10 June +- API World, September 1-3, 2026 +- APIdays London, 30 September - 1 October 2026 +- APIdays Paris, 1 - 3 December 2026 + +[Call for speakers for Amsterdam is now open until the 12th of April](https://conference.asyncapi.com/venue/Amsterdam). Be sure to submit your proposal, and we look forward to seeing you there. When submitting your proposal, please select **AsyncAPI** in the question about the **FOST Partner Conferences**. + +### AsyncAPI Meetups +We added the [AsyncAPI Meetups](https://conference.asyncapi.com/meetups) to the conference to expand our reach, get more community members involved in community building, and provide an intimate setting that maximizes learning, encourages open discussion, and ensures everyone has a chance to contribute their ideas and experiences. + +We are looking for sponsors, partners, and community members to lead and organize a meetup in their local area, or to partner with others to share more knowledge about AsyncAPI and learn from a diverse audience. + +## Social Media +We’re happy to share that [Aishat Muibudeen](https://www.linkedin.com/in/aishatmuibudeen) (Maya) will be handling publishing on our official AsyncAPI social media accounts. + + + +## TSC x Ambassadors + +In the spirit of celebrating real impact, a growing community, and Maintainership, we’re happy to welcome [Tenzin Delek](https://www.linkedin.com/in/tenzin-delek-8a157724b) as the maintainer of the conference website and newest addition to the TSC. + + + +## Coming in April +- Governance Board Nominations for 2026 are now open. For more details, [please read the blog on requirements](https://www.asyncapi.com/blog/board-nomination). +- AsyncAPI Community Updates Newsletter - The April Edition will arrive in your inbox on the 8th. [Please subscribe to the AsyncAPI Newsletter to stay up-to-date with the latest updates](https://www.asyncapi.com/newsletter). +- [The Call for Proposals for the Amsterdam Edition](https://conference.asyncapi.com/venue/Amsterdam) will close on the **12th of April**. \ No newline at end of file diff --git a/markdown/blog/april-2021-at-asyncapi.md b/markdown/blog/april-2021-at-asyncapi.md index 8640275b35c3..207ff29dcd85 100644 --- a/markdown/blog/april-2021-at-asyncapi.md +++ b/markdown/blog/april-2021-at-asyncapi.md @@ -32,7 +32,7 @@ I'm super happy to share that we removed the last roadblock for the next AsyncAP I hope you noticed a pattern. We do not want to do releases during the summer holidays and stay away from December :smiley:. -In June 2021, we will release 2.1.0 version of the specification. It is going to be the first release under [open governance model](https://github.com/asyncapi/community/blob/master/CHARTER.md), under Linux Foundation and new [contribution guide](https://github.com/asyncapi/spec/blob/master/CONTRIBUTING.md). So many new things, a lot to organize around. It means we probably won't accept too many changes as logistics will consume a lot of time. We welcome any help. Join our [Slack](https://www.asyncapi.com/slack-invite/) for more details. +In June 2021, we will release 2.1.0 version of the specification. It is going to be the first release under [open governance model](https://github.com/asyncapi/community/blob/master/docs/020-governance-and-policies/CHARTER.md), under Linux Foundation and new [contribution guide](https://github.com/asyncapi/spec/blob/master/CONTRIBUTING.md). So many new things, a lot to organize around. It means we probably won't accept too many changes as logistics will consume a lot of time. We welcome any help. Join our [Slack](https://www.asyncapi.com/slack-invite/) for more details. ## AsyncAPI use case at eBay diff --git a/markdown/blog/asyncapi-ambassador-program.md b/markdown/blog/asyncapi-ambassador-program.md index b4c89987814b..33880c944d34 100644 --- a/markdown/blog/asyncapi-ambassador-program.md +++ b/markdown/blog/asyncapi-ambassador-program.md @@ -48,7 +48,7 @@ The Ambassador Program is a transparent system, just like any other management i heart&brain

    -The process of recruiting ambassadors is completely open. If anyone meets the requirements, they only need to add themselves to this [document](https://github.com/asyncapi/community/blob/master/AMBASSADORS_MEMBERS.json), attaching their personal information along with their contributions. The TSC members will then approve the proposal. +The process of recruiting ambassadors is completely open. If anyone meets the requirements, they only need to add themselves to this [document](https://github.com/asyncapi/community/blob/master/AMBASSADORS_MEMBERS.yaml), attaching their personal information along with their contributions. The TSC members will then approve the proposal. Subsequently, all ambassador information will be displayed on the AsyncAPI website once the PR has been merged. The process tries to be simple, collaborative, and transparent as possible. diff --git a/markdown/blog/asyncapi-and-websocket.md b/markdown/blog/asyncapi-and-websocket.md new file mode 100644 index 000000000000..cdbbd6a31b40 --- /dev/null +++ b/markdown/blog/asyncapi-and-websocket.md @@ -0,0 +1,557 @@ +--- +title: "AsyncAPI & WebSocket: A Match Made from Heaven?" +date: 2026-02-22T06:00:00+01:00 +type: Engineering +tags: + - Specification + - EDA + - Websocket +cover: /img/posts/asyncapi-websocket.webp +authors: + - name: Azeez Elegbede + photo: /img/avatars/ace.webp + link: https://www.linkedin.com/in/acebuild/ +--- + + + +Recently, while building a collaborative drawing web application with WebSocket for one of my livestreams, I discovered just how efficient it is to document a WebSocket server using the AsyncAPI specification in a spec-first approach. But what exactly do I mean by “spec-first”? + +![API spec first diagram](/img/diagrams/spec-first.webp) + +The spec-first API development approach involves designing the API using an API specification _before_ implementing it. This method offers significant advantages, such as reducing the time needed to build the actual API, improving communication with stakeholders, and producing higher-quality APIs overall. But let’s save the deep dive into spec-first for another time and get back on track! + +## Why WebSocket and AsyncAPI Instead of OpenAPI? + +![Asyncapi-OpenAPI](/img/diagrams/asyncapi-openapi.webp) + +OpenAPI isn’t ideal for my use case because it’s specifically designed for REST APIs. WebSocket, on the other hand, differs significantly from traditional HTTP. It provides a two-way communication channel over a single Transmission Control Protocol (TCP) connection, which OpenAPI doesn’t support. + +In simpler terms, unlike REST APIs, where you must send a request to receive a response, maintaining a connection similar to a WebSocket would require repeatedly pinging the server at intervals (a process known as polling). WebSocket does the opposite. It keeps the connection open between server and client, allowing the server to send data to the client without waiting for a request. + +So, why would I use OpenAPI for that? Now you see why AsyncAPI is the better fit. Since WebSocket enables an event-driven connection between client and server, we need an API specification that supports this kind of interaction, and that’s where AsyncAPI comes in. + +Let’s explore why combining AsyncAPI with WebSocket is such a powerful approach. + +## The Intersection + +As I mentioned earlier, `WebSocket enables an event-driven connection between client and server`, meaning it operates asynchronously. AsyncAPI offers a standardized way to define these asynchronous APIs, making it a perfect match. This combination enhances real-time application development by ensuring consistent, reliable message formats and enabling instant, bidirectional data exchange between client and server. + +Now, let’s dive deeper into this powerful intersection! + +### Clear and Concise Message Format and Event Types + +Defining your WebSocket API with AsyncAPI allows you to leverage AsyncAPI's schema definitions, ensuring a structured and consistent approach to handling data exchange across WebSocket connections. This reduces misunderstandings about message formats and event types, creating a smoother, more reliable communication flow. + +Consider a real-world example from a chat application. Here's how you'd define a message schema in AsyncAPI: + +```yaml +components: + messages: + chatMessage: + name: ChatMessage + title: Chat Message + summary: A user message sent in the chat + description: Represents a message exchanged between users in a real-time chat application + payload: + type: object + properties: + messageId: + type: string + format: uuid + description: Unique identifier for this message + senderId: + type: string + description: ID of the user sending the message + senderName: + type: string + description: Display name of the sender + content: + type: string + maxLength: 1000 + description: The actual message text + timestamp: + type: string + format: date-time + description: When the message was sent + required: + - messageId + - senderId + - senderName + - content + - timestamp +``` + +Notice how each field has a clear purpose, defined type, and specific constraints. This structured approach prevents confusion about what data should be in each message and how it should be formatted, something that would be much harder to maintain without a specification. + + +### Message Schema Validation + +AsyncAPI allows your WebSocket API to validate real-time messages against predefined schemas at runtime, helping to catch errors early in the development stage. With the production-ready [AsyncAPI Validator](https://www.npmjs.com/package/asyncapi-validator/), you can automatically validate your WebSocket messages against your AsyncAPI document. + +However, there's an important detail: by default, JSON Schema (which AsyncAPI uses under the hood) allows additional properties. This means the validator would reject the `chatMessage` above if a required field is missing, but it would accept a message with extra properties not defined in your schema. + +To prevent unexpected properties from slipping through, add `additionalProperties: false` to your message payload: +```yaml +payload: + type: object + properties: + messageId: + type: string + format: uuid + # ... other properties + required: + - messageId + - senderId + - senderName + - content + - timestamp + additionalProperties: false +``` + +Now your validator enforces that only the properties you've defined are accepted, ensuring strict schema compliance across your system. + + +### Improved Architectural Planning + +Using AsyncAPI with your WebSocket API supports a spec-first approach where your AsyncAPI document becomes the single source of truth. Both your client and server implementations derive from this specification, ensuring they never drift apart. + +Rather than treating your specification as an afterthought to satisfy documentation requirements, it becomes the foundation for how you build your API. This enables faster prototyping, testing, and implementation, significantly reducing time to market. + +![AsyncAPI Ecosystem](/img/diagrams/ecosystem.webp) + +As the industry standard for defining asynchronous APIs, AsyncAPI unlocks a robust ecosystem of tools maintained by the AsyncAPI Initiative. You can generate production-ready code in multiple languages, create deployment-ready documentation automatically, and set up mock servers for development with tools like [Microcks](https://microcks.io/), all directly from your specification. + +Now that you've seen the power of this approach, let's explore the key concepts in AsyncAPI for building WebSocket APIs. + +## Key Concepts in AsyncAPI for WebSocket + +If you've used WebSocket before, you're likely familiar with **channels**, sometimes called `topics` or `paths`. Channels are specific routes within a WebSocket connection that organize how messages flow. For example, with channels named `general` and `members`, you can send and receive messages independently on each one. If you only want messages from the `members` channel, you simply listen to that channel and ignore the rest. + +### [Channels](https://www.asyncapi.com/docs/concepts/channel) + +AsyncAPI channels establish bi-directional communication between message senders and receivers. They're more than just message highways, they're composed of several elements that work together: + +- **Address**: An optional string specifying the channel's location (topic name, routing key, event type, or path) +- **Title**: A friendly, descriptive name for the channel +- **Messages**: The list of message types that can be sent and received on this channel +- **Bindings**: WebSocket-specific configuration that customizes connection details + +### [Messages](https://www.asyncapi.com/docs/concepts/message) + +In an event-driven system, **data exchange** is everything. AsyncAPI provides a structured, consistent way to define this exchange across WebSocket connections. + +A **message** is the asset by which information flows between senders and receivers via channels. Messages are flexible and can represent events, commands, requests, or responses. Basically whatever your system needs. + +Each message consists of: + +- **Name**: A descriptive identifier for the message +- **Summary**: A brief overview of the message's purpose +- **Description**: Detailed explanation of what the message contains +- **Payload**: The structured properties and required fields for the message + +### Operations + +An **operation** defines the specific actions that can occur within a channel, essentially telling you whether your application will _send_ or _receive_ messages. This clarity is crucial for understanding message flow. + +Each operation includes: + +- **Action**: Either `send` (app sends a message) or `receive` (app expects to receive a message) +- **Channel**: The specific channel where the operation happens(from the list of defined channels in your AsyncAPI specification) +- **Reply**: Specifies the expected response message in request-reply operations (optional) +- **Title**: A descriptive name for the operation +- **Summary**: A quick overview of what the operation does +- **Description**: Detailed explanation of the operation's purpose + +Together, these three concepts (Channels, Messages, Operations) give you complete control over message flow and make AsyncAPI a powerful tool for building scalable event-driven systems. + +## The Complete Breakdown + +Now that we've explored the key concepts, let's build a complete AsyncAPI document for a simple chat application step by step. + +### Step 1 - Defining Basic Information About Our WebSocket API + +First, we provide essential information about our API, including server details for client connections. +```yaml +asyncapi: "3.1.0" + +info: + title: Simple Chat API + version: 1.0.0 + description: A real-time chat API using WebSocket protocol + +servers: + development: + host: localhost:8787 + description: Development WebSocket broker + protocol: ws +``` + +### Step 2 - Defining Our WebSocket Channel + +AsyncAPI channels enable bidirectional communication. Let's define our chat channel: +```yaml +channels: + chat: + address: / + title: Chat channel +``` + +We'll define messages separately in components to keep the channel definition clean and reusable. + +### Step 3 - Creating Reusable Message Components + +Components hold reusable objects for different aspects of your AsyncAPI specification. They only take effect when explicitly referenced elsewhere. Let's define our chat message: +```yaml +components: + messages: + chat: + description: A message sent in the chat room + payload: + type: object + properties: + messageId: + type: string + format: uuid + description: Unique identifier for the message + senderId: + type: string + description: ID of the user sending the message + content: + type: string + maxLength: 1000 + description: The message content + timestamp: + type: string + format: date-time + description: Time when the message was sent + required: + - messageId + - senderId + - content + - timestamp +``` + +### Step 4 - Adding Messages to Your Channel + +Now link the component message to your channel: +```yaml +channels: + chat: + address: / + title: Chat channel + messages: + chatMessage: + $ref: '#/components/messages/chat' +``` + +### Step 5 - Defining Operations + +Operations specify what actions can happen in a channel. Let's create a `send` operation: +```yaml +operations: + sendMessage: + summary: Send a chat message + description: Allows users to send messages to the chat room + action: send + channel: + $ref: '#/channels/chat' + messages: + - $ref: '#/channels/chat/messages/chatMessage' +``` + +**Important:** The messages you reference in an operation must be available in that channel's messages. If you reference a message that doesn't exist in the channel, validation will fail. + +Now add a receive operation so clients can receive messages: +```yaml +operations: + sendMessage: + # ... send operation from above + + getMessage: + summary: Receive chat messages + description: Allows users to receive messages from the chat room + action: receive + channel: + $ref: '#/channels/chat' + messages: + - $ref: '#/channels/chat/messages/chatMessage' +``` + +### Step 6 - Reusing Messages for Multiple Operations + +Let's add user join/leave notifications. First, define a new message component: +```yaml +components: + messages: + chat: + # ... existing chat message + status: + description: User join/leave notification + payload: + type: object + properties: + userId: + type: string + description: ID of the user + type: + type: string + enum: + - join + - leave + description: Whether the user joined or left + timestamp: + type: string + format: date-time + required: + - userId + - type + - timestamp +``` + +Add this message to your channel: +```yaml +channels: + chat: + address: / + title: Chat channel + messages: + chatMessage: + $ref: '#/components/messages/chat' + userStatus: + $ref: '#/components/messages/status' +``` + +Then define operations that use the same message: +```yaml +operations: + sendMessage: + # ... existing operations + + userJoin: + summary: User join notification + description: Notifies when a user joins the chat room + action: receive + channel: + $ref: '#/channels/chat' + messages: + - $ref: '#/channels/chat/messages/userStatus' + + userLeave: + summary: User leave notification + description: Notifies when a user leaves the chat room + action: receive + channel: + $ref: '#/channels/chat' + messages: + - $ref: '#/channels/chat/messages/userStatus' +``` + +Both operations reuse the same `userStatus` message, reducing redundancy. + +### Step 7 - Securing Your API + +AsyncAPI supports various security schemes (API Key, OAuth2, HTTP authentication, etc.). Let's add API key authentication: +```yaml +components: + securitySchemes: + apiKeyHeader: + type: httpApiKey + in: header + name: X-API-Key + description: API key passed in header +``` + +Apply the security scheme to your server: +```yaml +servers: + development: + host: localhost:8787 + description: Development WebSocket broker + protocol: ws + security: + - $ref: '#/components/securitySchemes/apiKeyHeader' +``` + +The security property is an array because you can require multiple schemes, only one needs to be satisfied for authorization. + +### Step 8 - Adding Protocol-Specific Bindings + +Bindings let you add WebSocket-specific configuration. For example, if you want users to connect to multiple chat rooms with a single connection, use query parameters instead of creating separate connections for each room: +```yaml +channels: + chat: + address: / + bindings: + ws: + query: + type: object + properties: + roomIds: + type: string + description: Comma-separated list of room IDs + pattern: ^[a-zA-Z0-9,-]+$ + additionalProperties: false +``` + +Now users can connect once to `/?roomIds=room1,room2,room3` and exchange messages across all rooms on a single connection. + +> Notice `additionalProperties: false`, this ensures your system only accepts the `roomIds` query parameter and rejects any unexpected properties. + +### Step 9 - The Complete Document + +Here's your finished AsyncAPI document bringing everything together: +```yaml +asyncapi: 3.1.0 +info: + title: Simple Chat API + version: 1.0.0 + description: A real-time chat API using WebSocket protocol + +servers: + production: + host: chat.example.com + protocol: wss + description: Production server + security: + - $ref: '#/components/securitySchemes/apiKeyHeader' + +channels: + chat: + address: / + bindings: + ws: + query: + type: object + properties: + roomIds: + type: string + description: Comma-separated list of room IDs + pattern: ^[a-zA-Z0-9,-]+$ + additionalProperties: false + + messages: + chatMessage: + $ref: '#/components/messages/chat' + userStatus: + $ref: '#/components/messages/status' + +operations: + sendMessage: + action: send + channel: + $ref: '#/channels/chat' + messages: + - $ref: '#/channels/chat/messages/chatMessage' + summary: Send a chat message + description: Allows users to send messages to the chat room + + getMessage: + action: receive + channel: + $ref: '#/channels/chat' + messages: + - $ref: '#/channels/chat/messages/chatMessage' + summary: Receive chat messages + description: Allows users to receive messages from the chat room + + userJoin: + action: receive + channel: + $ref: '#/channels/chat' + messages: + - $ref: '#/channels/chat/messages/userStatus' + summary: User join notification + description: Notifies when a user joins the chat room + + userLeave: + action: receive + channel: + $ref: '#/channels/chat' + messages: + - $ref: '#/channels/chat/messages/userStatus' + summary: User leave notification + description: Notifies when a user leaves the chat room + +components: + messages: + chat: + description: A message sent in the chat room + payload: + type: object + properties: + messageId: + type: string + format: uuid + description: Unique identifier for the message + senderId: + type: string + description: ID of the user sending the message + content: + type: string + maxLength: 1000 + description: The message content + timestamp: + type: string + format: date-time + description: Time when the message was sent + required: + - messageId + - senderId + - content + - timestamp + + status: + description: User join/leave notification + payload: + type: object + properties: + userId: + type: string + description: ID of the user + type: + type: string + enum: + - join + - leave + timestamp: + type: string + format: date-time + required: + - userId + - type + - timestamp + + securitySchemes: + apiKeyHeader: + type: httpApiKey + in: header + name: X-API-Key + description: API key passed in header +``` + +### What You Can Do With This Document + +With your AsyncAPI specification complete, the spec-first approach unlocks powerful capabilities: + +- **Generate Documentation:** Tools like [AsyncAPI Studio](https://studio.asyncapi.com/) let you visualize and interact with your API definition in your browser. You can also generate and download markdown documentation or a deployable HTML website directly from your specification. + +- **Generate Code:** The [AsyncAPI CLI](https://www.asyncapi.com/tools/cli) transforms your specification into production-ready code in multiple languages. Generate client or server implementations, data models, and more, reducing development time and inconsistencies. + +- **Contract Testing:** Tools like [Microcks](https://microcks.io/) let you test and mock your API directly from your specification, ensuring your implementation matches your design before going live. + +Install the [AsyncAPI CLI](https://www.asyncapi.com/tools/cli) and try generating documentation with: ```asyncapi generate fromTemplate ./asyncapi.yaml @asyncapi/html-template@3.0.0 --use-new-generator``` + +Or preview your specification live in [AsyncAPI Studio](https://studio.asyncapi.com/?url=https://gist.githubusercontent.com/AceTheCreator/1651bd1fa1eed947441e5828d357ac4f/raw/475484a530044d734bb847ae17048fd6b20dcad2/gistfile1.txt). + +## Conclusion + +Documenting your WebSocket API with AsyncAPI brings clarity and structure to API design and management. By standardizing message formats, channels, and operations, AsyncAPI simplifies building scalable, consistent, and reliable event-driven systems. + +AsyncAPI's structured approach equips teams with a collaborative framework that enhances efficiency and reduces friction, making it essential in modern API development. + +### References + +- [Livestream](https://www.youtube.com/watch?v=22LFOLeF9Lk): Building a chat application with AsyncAPI +- [Blog post](https://www.asyncapi.com/blog/websocket-part1): WebSocket and AsyncAPI deep dive +- [AsyncAPI Slack](https://www.asyncapi.com/slack-invite/): Join the community \ No newline at end of file diff --git a/markdown/blog/asyncapi-bounty-program-2024.md b/markdown/blog/asyncapi-bounty-program-2024.md index bcfb5183d5d8..0d9666323da6 100644 --- a/markdown/blog/asyncapi-bounty-program-2024.md +++ b/markdown/blog/asyncapi-bounty-program-2024.md @@ -32,7 +32,7 @@ During one year of existence of the [AsyncAPI Bounty Program](https://github.com ### Benefits for AsyncAPI GitHub Organization Thanks to the Bounty Program Participants, AsyncAPI got: -- [Automation in Technical Steering Committee voting process](https://github.com/orgs/asyncapi/projects/36/views/4?sliceBy%5BcolumnId%5D=78904519&sliceBy%5Bvalue%5D=community%231093&filterQuery=) ([Aayush Saini](https://github.com/AayushSaini101)): New automation and the [process around voting](https://github.com/asyncapi/community/blob/master/voting.md) have been introduced, as well as [transparent summaries](https://github.com/asyncapi/community/blob/master/TSC_VOTING_OVERVIEW.md) of each voting activity. +- [Automation in Technical Steering Committee voting process](https://github.com/orgs/asyncapi/projects/36/views/4?sliceBy%5BcolumnId%5D=78904519&sliceBy%5Bvalue%5D=community%231093&filterQuery=) ([Aayush Saini](https://github.com/AayushSaini101)): New automation and the [process around voting](https://github.com/asyncapi/community/blob/master/docs/020-governance-and-policies/voting.md) have been introduced, as well as [transparent summaries](https://github.com/asyncapi/community/blob/master/docs/020-governance-and-policies/TSC_VOTING_OVERVIEW.md) of each voting activity. - New monorepo setup in [generator](https://github.com/orgs/asyncapi/projects/36/views/4?filterQuery=&sliceBy%5BcolumnId%5D=78904519&sliceBy%5Bvalue%5D=generator%231044) and [parser-js](https://github.com/orgs/asyncapi/projects/36/views/4?filterQuery=&sliceBy%5BcolumnId%5D=78904519&sliceBy%5Bvalue%5D=parser-js%23963) ([Ayush Nautiyal](https://github.com/ayushnau)): Consolidation of smaller repositories into these two larger projects helped unify the dispersed community within the organization, fostering collaboration in a single location and accelerating development. diff --git a/markdown/blog/beyond-boundaries.md b/markdown/blog/beyond-boundaries.md index 3160b7e8fd49..4d90d22edaab 100644 --- a/markdown/blog/beyond-boundaries.md +++ b/markdown/blog/beyond-boundaries.md @@ -37,7 +37,7 @@ Determined to overcome this unexpected obstacle, we regrouped and brainstormed a We knew piloting an in-house mentorship program would be challenging, so we made the initial program a way to collect feedback. We approached the program flexibly, avoiding rigid decisions or commitments. -During the project ideas phase, [we received 19 project ideas](https://github.com/asyncapi/community/blob/master/mentorship/asyncapi-mentorship/2022/project-ideas.md), and [ten of these projects made it to the final phase](https://github.com/asyncapi/community/blob/master/mentorship/asyncapi-mentorship/2022/README.md) but out of the ten selected candidates for the program only [six](https://github.com/orgs/asyncapi/discussions/577) were able to complete their project. This program addresses the real needs of the open-source community. It ensures the program leaders forge meaningful relationships with the participants to ensure their diverse voices are heard and provide them with resources, advice, and networking opportunities. +During the project ideas phase, [we received 19 project ideas](https://github.com/asyncapi/community/blob/master/docs/050-mentorship-program/asyncapi-mentorship-2022-project-ideas.md), and [ten of these projects made it to the final phase](https://github.com/asyncapi/community/blob/master/docs/050-mentorship-program/asyncapi-mentorship-2022-project-ideas.md) but out of the ten selected candidates for the program only [six](https://github.com/orgs/asyncapi/discussions/577) were able to complete their project. This program addresses the real needs of the open-source community. It ensures the program leaders forge meaningful relationships with the participants to ensure their diverse voices are heard and provide them with resources, advice, and networking opportunities. ## How We Are Approaching These Challenges For The Next Cohorts diff --git a/markdown/blog/board-nomination.md b/markdown/blog/board-nomination.md new file mode 100644 index 000000000000..2bb8557cfa6b --- /dev/null +++ b/markdown/blog/board-nomination.md @@ -0,0 +1,63 @@ +--- +title: "AsyncAPI Governance Board Nominations 2026" +date: 2026-03-30T06:00:00+01:00 +type: Communication +tags: + - Project Status +cover: /img/posts/2026-blog-banner/nominations.webp +authors: + - name: Thulisile Sibanda + photo: /img/avatars/thulieblack.webp + link: https://www.linkedin.com/in/v-thulisile-sibanda/ + byline: Community Builder and Open Source Fanatic! +excerpt: 'Call for Nominations for the AsyncAPI Governance Board 2026 seats.' +featured: true +--- + +We're excited to announce it's time to welcome new members to the Governance Board! **With three seats open**, there's a wonderful opportunity for more of you to get involved. + +## Governance Board Responsibilities + +Joining the Governance Board is a meaningful way to contribute and help shape our community's future. Board members play a critical role, and your dedication and time will have a lasting impact on everyone in our community. Some responsibilities include, but are not limited to: + +* Ensuring compliance with the charter +* Maintaining a safe and inclusive environment for all AsyncAPI participants +* Sustaining AsyncAPI’s economic viability, including sponsorship and funding strategies +* Securely managing credentials for all AsyncAPI services. +* Overseeing AsyncAPI employees, program leads, and hiring +* Managing funding streams (e.g., Open Collective, GitHub Sponsors) + +Most importantly, we’re looking for those who lead with empathy and service. Board members empower others, working within the charter, and all proposals are shaped together with the TSC. For more details, please read our [Charter](https://github.com/asyncapi/community/blob/master/docs/020-governance-and-policies/CHARTER.md) and [Governance Guide](https://github.com/asyncapi/community/blob/master/docs/020-governance-and-policies/GOVERNANCE.md). + +## Eligibility + +To become a nominee for the Governance Board, you must be a member of the Technical Steering Committee and have no past misconduct or pending issues with the Code of Conduct Committee. + +You may nominate yourself or another TSC member, but please confirm with them first that they are willing and able to serve. To submit a nomination, gather all required information and ensure the nominee is aware and committed before sending. + +## Candidate Submission Guidelines + +We encourage you to share any details you feel would help the TSC get to know nominees better. To guide the TSC in their evaluation and voting, here are a few helpful suggestions: + +* Full Name +* Photo (optional but recommended) +* Location / Time Zone +* GitHub & LinkedIn Profiles +* Personal Introduction (≤ 150 words) +* AsyncAPI Impact (≤ 150 words: role, impact, when joined) +* Motivation Statement (≤ 150 words: why you’re running) +* Contact Information for questions + +## Timeline + +Nominations are open from the **April 1st to April 26th at 12.00 PM UTC**. Simply email your name, or your nominee’s name, along with the submission details to **info@asyncapi.com**. We look forward to seeing all your wonderful nominations! + +Candidates will be announced on **April 30th**. Voting begins from **May 1st to May 31st**. + + +## In summary + +- Nominations Open: **April 1st, 2026** +- Nominations Close: **April 26th, 2026** +- Announcement: **April 30th, 2026** +- Voting: **May 1st - May 31st, 2026** diff --git a/markdown/blog/community-spotlight-hugo.md b/markdown/blog/community-spotlight-hugo.md new file mode 100644 index 000000000000..6df937cf7ca1 --- /dev/null +++ b/markdown/blog/community-spotlight-hugo.md @@ -0,0 +1,104 @@ +--- +title: "Evolving with AsyncAPI: Insights from Hugo Guerrero" +date: 2025-09-10T06:00:00+01:00 +type: Communication +tags: + - Interview + - Spotlight + - Community + - Marketing +cover: /img/posts/marketing-images/hugo-spotlight.webp +authors: + - name: Atinuke Oluwabamikemi Kayode + photo: /img/avatars/bami.webp + link: https://www.linkedin.com/in/atinuke-oluwabamikemi-kayode-5b838b1b7/ + byline: AsyncAPI Community Marketing Specialist +excerpt: "Meet Hugo Guerrero — API expert, open source contributor, and new AsyncAPI Governance Board member. In this spotlight, he shares his journey, community insights, and hopes for AsyncAPI’s future." + +--- + +In this edition of our Community Spotlight, we’re excited to feature [Hugo Guerrero](https://www.linkedin.com/in/hugoguerrero/), a seasoned software developer, open source contributor, technical marketer, and advocate for better developer experience in the world of APIs and event-driven architecture. With over two decades of industry experience, Hugo brings both depth and clarity to AsyncAPI’s growing ecosystem. Currently, he's the Head of Technical Marketing at [Kong Inc.](https://www.linkedin.com/company/konghq/) + +I had the pleasure of catching up with Hugo after the AsyncAPI track at APIDays Singapore, and we sat down for a more in-depth conversation on Hugo’s journey, his contributions, and what he sees on the horizon for AsyncAPI. + +## Meet Hugo + +**Bami: Tell us a bit about your background and how you first encountered AsyncAPI?** + +***Hugo:** "My name is Hugo Guerrero. I'm from Mexico and currently based in Massachusetts, USA. I’ve been in software development since 1996 — over 25 years in roles ranging from developer to architect to consultant."* + +Hugo's journey began with an electronic systems engineering background, but his passion for software development and architecture quickly led him into enterprise tooling, API management, and event-driven systems. His career spans both the **open source** and **enterprise software** worlds, and he’s currently focused on **Technical Marketing** and **Developer Advocacy**. + +***Hugo:** “Technical marketing is all about bridging product capabilities with real developer needs, helping unblock them and showcasing how to use new features effectively.”* + +## How Hugo Found AsyncAPI + +While working on event-driven products and tools such as Kafka and JMS, Hugo came across AsyncAPI through the work of [Fran Mendez](https://www.linkedin.com/in/fmvilas/) and the wider initiative. Around the same time, he was contributing to a CNCF project called [Microcks](https://github.com/microcks/microcks), which started to adopt AsyncAPI to better support various bindings like Kafka and JMS. + +***Hugo:** I came across AsyncAPI a few years ago when I was exploring event-driven architectures. At the time, everyone knew OpenAPI for REST APIs, but there was a gap when it came to asynchronous communication. AsyncAPI filled that gap, and did it in a developer-friendly, open way.* + +From early contributions on examples and specification discussions to supporting AsyncAPI within Micro and his enterprise tooling, Hugo's involvement has steadily deepened. + +## From Curiosity to Contribution + +**Bami: What drew you to AsyncAPI and event-driven architecture?** + +***Hugo:** While working on enterprise architecture, I realized asynchronous communication, pub/sub patterns is essential to building scalable systems. AsyncAPI offered a structured, open way to document and support those patterns. It just clicked for me. I’ve always believed that tools should make developers' lives easier, and that’s exactly what AsyncAPI aims to do. I started by advocating for it in my talks and writing tutorials, but soon realized I could contribute more directly, especially by sharing feedback from the field and helping build awareness across the industry. It wasn’t just the technology though. The community was (and is!) incredibly open, diverse, and mission-driven. That really inspired me to get involved more deeply.* + +**Bami: What’s been the most rewarding part of contributing to AsyncAPI?** + +***Hugo:** Events. Getting to talk about AsyncAPI and seeing people realize the value it brings, especially its vendor-neutral nature is incredibly fulfilling. That moment of realization, where they see the possibilities, is the best.* + +**Bami: Fantastic! Are there any AsyncAPI tools or initiatives you’re especially proud of?** + +***Hugo:** I love the specification, of course, but also the Playground, Editor, and Generators. These tools make the ecosystem practical and accessible, especially for new users trying to understand EDA.* + +**Bami: What challenges have you faced with AsyncAPI?** + +***Hugo:** The mindset shift from synchronous to asynchronous thinking can be tough. Terminology like "producer/consumer" or managing topics isn’t always intuitive. Also, support across languages and tools is still growing, and when it’s missing, you sometimes have to build your own.* + +*But that’s also a call to action: more contributions help fill those gaps.* + +## Advice to New Contributors + +**Bami: Amazing. Thank you so much. So, what advice would you give to someone just joining the AsyncAPI community as an OG in the industry?** + +***Hugo:** First, network. Get to know people. Share ideas. Be polite and open-minded. You’ll find support and honest feedback. Also, start simple. Fix a doc. Share a config that worked. Suggest an idea. Don’t worry about making a huge splash on day one, just get involved and keep going.* + +*Listen to what people are saying but don’t hesitate to contribute. Just be aware that it is an open community to share with, so it’s good to share but you will also get feedback on your ideas.* + +**Bami: Okay, Okay. So, next is how can others get started contributing to AsyncAPI?** + +***Hugo:** In open source and community work, the advice is often the same: start simple, start with what you know. If you notice issues in the documentation, fix them. If you’ve figured out how to make something work with your preferred framework or language, share that knowledge, because you're not the only one who’ll benefit. Your contributions, whether it’s configurations, specifications, or common pitfalls can help many others.* + +*And don’t underestimate the value of ideas. Share them. Some will gain traction, others might not, but putting them out there is a great way to get involved. Plus, the network you build along the way can open up even more opportunities.* + +## Fun Fact: Between Commits and Curtains + +**Bami: Amazing! Thank you so much. We are moving to the fun part now. What’s a fun or surprising fact about you that people may not know?** + +***Hugo:** Back in high school, I was into musical theatre, singing, dancing, performing on stage! I don’t do it anymore, but it was a big part of my youth. A very different kind of spotlight! Obviously I was young and agile at the time, I’m not doing that anymore but that was fun.* + +**Bami: Like “what color is the sky?”** + +**Hugo: We were singing and dancing on the stage, so you can imagine.** + +## Looking Ahead + +**Bami: I can imagine. That must have been fun. Okay, so let’s move forward, what are you looking forward to in AsyncAPI’s future?** + +***Hugo:** A robust, growing, and thriving ecosystem where the specification is at the core, but the surrounding tools, contributors, and adopters bring it to life. That’s what I expect for the future.* + +**Bami: Awesome. Well put it there. Who should we spotlight next?** + +***Hugo:** The ambassadors, the contributors, and the adopters. Their work, both behind the scenes and in the spotlight, is what keeps this community moving forward.* + +**Bami: That's right, we have a lot of folks in the community who are working behind the scene, stay tuned for more community spotlight in the coming months. It’s been a pleasure chatting with you Hugo. Thank you so much for your time and all you do for the AsyncAPI community. I look forward to talking to you soon.** + +## Conclusion + +As we draw the curtain on this interview, it’s clear that Hugo Guerrero’s passion for improving developer experience, his advocacy for knowledge sharing, and his commitment to the AsyncAPI community are deeply rooted in years of hands-on experience and open source values. His journey reminds us that meaningful contributions often start with small, familiar steps, and that ideas, no matter how simple, have the power to shape communities and technologies. + +Now serving on the AsyncAPI Governance Board, Hugo is not only influencing the future of the specification but also helping steer the community toward a more inclusive, collaborative, and developer-friendly ecosystem. We’re grateful for his continued contributions and excited to see what lies ahead with leaders like Hugo helping chart the course. + +Interested in getting involved? Check out our [contribution guide](https://github.com/asyncapi/spec/blob/master/CONTRIBUTING.md#contributing-to-asyncapi) and say hello in our [Slack community!](https://asyncapi.slack.com/ssb/redirect) \ No newline at end of file diff --git a/markdown/blog/community-spotlight-maya.md b/markdown/blog/community-spotlight-maya.md new file mode 100644 index 000000000000..b908cc8d3df4 --- /dev/null +++ b/markdown/blog/community-spotlight-maya.md @@ -0,0 +1,124 @@ +--- +title: "From Curiosity to Contribution - Maya’s Inspiring Journey into Open Source and Leading Design at AsyncAPI!" +date: 2025-09-08T06:00:00+01:00 +type: Communication +tags: + - Interview + - Spotlight + - Community + - Marketing +cover: /img/posts/marketing-images/maya-story.webp +authors: + - name: Atinuke Oluwabamikemi Kayode + photo: /img/avatars/bami.webp + link: https://www.linkedin.com/in/atinuke-oluwabamikemi-kayode-5b838b1b7/ + byline: AsyncAPI Community Marketing Specialist +excerpt: "In this AsyncAPI Community Spotlight, we chat with Aishat Muibudeen (Maya), a product designer turned Lead Design Maintainer at AsyncAPI. From her first contribution in 2022 to founding Open Nest Africa, Maya’s journey shows how showing up and staying curious can lead to leadership in open source." +--- + +In this edition of the AsyncAPI Community Spotlight, we sat down with [Aishat Muibudeen](https://www.linkedin.com/in/aishatmuibudeen/), fondly known in the community as Maya, a product designer, community builder, and the current Lead Design Maintainer at AsyncAPI. Maya shares her fascinating journey from open source newbie to core contributor and founder of [OpenNest-Africa](https://opencollective.com/open-nest-africa). This is her story. + +**Bami: Let’s start with a quick intro. Tell us about yourself, what you do and who you are.** + +***Maya:** Hi, my name is Aishat Muibudeen, but most people in the community know me as Maya. I’m a product designer and a community person at heart. I’m currently the Lead Design Maintainer at AsyncAPI and a member of the Code of Conduct Committee. Outside of AsyncAPI, I’m also the founder of [OpenNest-Africa](https://opencollective.com/open-nest-africa).* + +## Starting from Zero: Maya’s First Steps in Open Source + +**Bami: That’s awesome! Now, take us back to where it all began. How did you get into open source, and how did your AsyncAPI journey start?** + +***Maya:** Back in 2022, I barely understood how open source worked. I was curious but also confused. One thing about me, though, is when I’m interested in something, I go all in. I discovered AsyncAPI on X (formerly Twitter), where they had a call for technical writers. I didn’t have the experience, but I was eager to join a community. I reached out to the recruiter, explained I wasn’t a technical writer but was passionate about design. She referred me to the design lead, and that’s where it all began. At first, everything felt overwhelming. GitHub, for instance, looked like an alien world, very code-heavy and unfamiliar to a designer. But I kept showing up to meetings, I asked questions, and I messaged people in DMs asking how to contribute. My first contribution was designing speaker cards for the AsyncAPI Online Conference in October 2022. When my PR got merged by [Lukasz Gornicki](https://www.linkedin.com/in/lukasz-gornicki-a621914/), I was over the moon. My first official open source contribution!* + +## Leading the Design Charge at AsyncAPI + +**Bami: Incredible journey so far! Now, let’s dive into your work leading the design team and working on various initiatives. What has that experience been like?** + +***Maya:** Leading the design working group has been both challenging and rewarding. After my first few contributions, I took the initiative to design the AsyncAPI Conference on Tour website in 2023. It was my first big solo project, and there were barely any active designers in the community at the time. I had to research, brainstorm ideas, and execute everything from scratch. That project opened the door to me becoming the Lead Design Maintainer and member of the Technical Steering Committee. It wasn’t easy. I was still in school and juggling responsibilities, but I kept showing up. Slowly, more designers started joining, and we began holding regular meetings. Another major initiative I led was building the AsyncAPI Design System. For designers, a design system is like a central library of reusable components such as typography, icons, and buttons. It helps maintain visual consistency across platforms. This project was part of the AsyncAPI mentorship program, now the maintainership program.* + +## Designing the Design System: A Milestone Project + +**Bami: Let’s talk more about the maintainership project. Why did you choose to work on the design system, and what did it involve?** + +***Maya:** I chose the design system because our growing design team truly needed it. A design system isn't just about colors or components, it's a shared language. It sets the tone for who we are as a community and how we communicate visually consistently. At the time, Missy, leading the design efforts, had started a basic UI kit with some foundational colors and typography. I saw an opportunity to evolve that initial work into something more robust, something future designers could build with, rely on, and contribute to. It felt like the kind of project that could empower the entire team, not just now but for a long time.* + +**Bami: Were there any challenges you faced while working on it?** + +***Maya:** Absolutely. I had never built a design system from scratch before, I had only worked with existing ones. There were no other designers in the community to guide me at the time, so it felt like I was figuring it out alone. To navigate that, I leaned into my network. I reached out to mentors and friends outside of AsyncAPI for support. One of my mentors, Ace, really kept me grounded,he helped me stay focused and reminded me that I didn’t have to have it all figured out at once. Looking back, I realize there were people like [Fran Mendez](https://www.linkedin.com/in/fmvilas/) already in the community who could’ve supported me, but I didn’t know that then. It was a learning curve in more ways than one, not just in design, but in how I ask for help and find support within the spaces I’m part of.* + +## The Birth of Open Nest Africa + +**Bami: That’s so insightful. Now tell us about your own initiative, OpenNest-Africa. What inspired it?** + +***Maya:** OpenNest-Africa was born out of something I deeply understood, how hard it can be to find your footing in open source, especially when you’re just starting out and don’t have a technical background. My journey with AsyncAPI changed that for me. I found a space where I could contribute, lead, and grow, through design, through community, and through care. That experience opened my eyes, and I wanted to create something that could open doors for others too. In 2022, I participated in SheCodeAfrica’s HerFest, our team placed second in the GitHub project category, and that was a turning point. I realized I had the skills, clarity, and vision to help others get started in open source, too. By 2024, during the HerToberfest by She Code Africa (SCA), I took everything I had learned, from contribution models to inclusive community design, and co-founded OpenNest-Africa with three other incredible women. Though it started in Africa, OpenNest-Africa is a global initiative. We created it for beginners everywhere, whether you’re technical, non-technical, or just curious - to find guidance, support, and a community that feels safe and welcoming. We built the space we wish we had. And now we nurture it so others can find their place, too.* + +## Wrapping Up + +**Bami: Maya, your story is not just inspiring, it’s a guidebook for non-technical folks trying to break into tech and open source. Thank you so much for sharing your journey with us.** + +***Maya:** Thank you, Bami! I’m glad to be able to share my story. Open source has changed my life, and I hope others find the courage to start, even if they don’t have it all figured out. Just show up, ask questions, and never stop learning.* + +## Fun Segment: Have You Ever? + +> **Bami: I think that is all. Now the fun fact. There’s a lot of fun facts, but we can do “Have you ever?” Ten questions.** +> +> ***Maya:** Okay.* + +> **Bami: Have you ever fixed bugs? Do you fix bugs? You’re not a developer.** +> +> ***Maya:** I think I have, on my portfolio when I was doing it on VS Code.* +> +> **Bami: This has to be API-related o.** +> +> ***Maya:** Oh no, no no no.* +> +> **Bami: Have you ever created a PR you were super proud of?** +> +> ***Maya:** Yes. Yes, yes.* +> +> **Bami: Have you ever accidentally broken something important while pushing your PR?** +> +> ***Maya:** No, I thought I did break something but Lukasz told me I did not, so no, I’ve never done that.* +> +> **Bami: Okay. Have you ever helped a new contributor find their way in the community?** +> +> ***Maya:** Yeah, I mean, yeah. Several times. Yes, a lot.* +> +> **Bami: Amazing. I like the excitement.** +> +> **Bami: Have you ever had a eureka moment while doing your design work? Now “eureka” is a time where it’s just super exciting for you.** +> +> ***Maya:** Yes, yes.* +> +> **Bami: Have you ever joined a meeting in your pajamas?** +> +> ***Maya:** A lot of times I do.* +> +> **Bami: Have you ever been surprised by how fast someone reviewed your PR?** +> +> ***Maya:** No, I have not.* +> +> ***Maya:** Yes, I have. As a matter of fact, I learn something new from other contributors everyday.* +> +> **Bami: Have you ever gotten frustrated but kept going anyway?** +> +> ***Maya:** Yes, yes. We don't give up here.* +> +> **Bami: Have you ever been called out for doing way too much?** +> +> ***Maya:** No, I told you. I know myself, I know what I want. What I can and can not do. Plus the community members are cool people. So no.* +> +> **Bami: Alright. Cool. Thank you so much for your time. It was beautiful hearing your story.** +> +> ***Maya:** You’re welcome. And thank you too. It's been a pleasure being on this call* + +## Spotlight Summary + +- Name: Aishat Muibudeen (Maya) +- Role at AsyncAPI: Lead Design Maintainer, Code of Conduct Committee Member +- Key Contributions: AsyncAPI Conference on Tour Website (AACOT’23), Design System, Leading the Design Community +- Community Project: Founder, OpenNest-Africa +- Started Contributing: October 2022 + +## Final Thoughts + +Maya’s story is a reflection of how open source welcomes all kinds of contributors. With passion, persistence, and a desire to learn, anyone can contribute meaningfully. Her growth from newcomer to design leader is proof that showing up consistently and embracing the learning curve can lead to incredible opportunities. If Maya's story moved you, take that as your sign to start contributing today. +Explore opportunities at [asyncapi.com](https://www.asyncapi.com/en) and begin your own open source journey. \ No newline at end of file diff --git a/markdown/blog/first-governance-elections.md b/markdown/blog/first-governance-elections.md index 60af6ff8aea9..599e516462ea 100644 --- a/markdown/blog/first-governance-elections.md +++ b/markdown/blog/first-governance-elections.md @@ -27,7 +27,7 @@ We currently have [43 members](https://github.com/asyncapi/community/blob/master GB voting is not the typical automated voting process we use for simple "yes" or "no" decisions with emojis in GitHub issues and pull requests. These elections are a manual process. -As described in the [Governance document](https://github.com/asyncapi/community/blob/master/GOVERNANCE.md#voting), we use a **"first-past-the-post"** voting system. +As described in the [Governance document](https://github.com/asyncapi/community/blob/master/docs/020-governance-and-policies/GOVERNANCE.md#voting), we use a **"first-past-the-post"** voting system. **You should:** * Send your vote to **info@asyncapi.io** no later than two weeks after the elections begin. diff --git a/markdown/blog/google-season-of-docs-2022.md b/markdown/blog/google-season-of-docs-2022.md index 5d4d896ff968..2286ab0aa4f1 100644 --- a/markdown/blog/google-season-of-docs-2022.md +++ b/markdown/blog/google-season-of-docs-2022.md @@ -8,7 +8,7 @@ tags: cover: /img/posts/gsod-2022/SeasonofDocs_Logo.webp authors: - name: Quetzalli Writes - photo: /canela-quetzalli.webp + photo: /img/avatars/canela-quetzalli.webp link: https://www.linkedin.com/in/quetzalli-writes/ byline: Our proposal? Update Docs Information Architecture excerpt: Check out the Docs project proposal we're submitting to GSoD 2022! You won't want to miss out. diff --git a/markdown/blog/gravitee-sponsorship-2025.md b/markdown/blog/gravitee-sponsorship-2025.md new file mode 100644 index 000000000000..9bb190bf1f81 --- /dev/null +++ b/markdown/blog/gravitee-sponsorship-2025.md @@ -0,0 +1,63 @@ +--- +title: "Gravitee Returns as a Platinum Sponsor: Strengthening the AsyncAPI Ecosystem Across 2025" +date: 2025-07-28T06:00:00+01:00 +type: Communication +tags: + - Project Status + - Marketing +cover: /img/posts/marketing-images/gravitee-community.webp +authors: + - name: Atinuke Oluwabamikemi Kayode + photo: /img/avatars/bami.webp + link: https://www.linkedin.com/in/atinuke-oluwabamikemi-kayode-5b838b1b7/ + byline: AsyncAPI Community Marketing Specialist +excerpt: 'Gravitee returns as a Platinum Sponsor, strengthening the AsyncAPI community and conference across 2025.' +--- + + +We’re happy to have Gravitee return as a platinum sponsor for both the AsyncAPI community and the AsyncAPI Conferences in 2025! Their renewed partnership is not only a show of continued support but also a reflection of their belief in the power of open standards, community-driven innovation, and modern API ecosystems. +Gravitee has long been part of AsyncAPI’s journey, not just as a sponsor but as an adopter, contributor, and champion of event-driven architectures (EDAs) that are secure, discoverable, and truly developer-first. + +## A Shared Vision: Open Collaboration, Stronger Infrastructure + +AsyncAPI’s mission is to make working with event-driven systems as seamless as it is working with REST. That mission only becomes a reality when organizations across industries join forces to push it forward sharing knowledge, building tooling, contributing to the spec, and supporting our diverse global community. +Gravitee’s sponsorship is rooted in this shared vision. They understand that success in the API economy depends not only on robust tooling but on shared specifications and interoperable ecosystems. That’s why Gravitee has made AsyncAPI an essential part of its architecture, empowering teams to define, document, and govern their asynchronous APIs just as easily as their REST endpoints. + +## More Than Sponsorship: Investing in Community-Driven Growth + +Gravitee’s renewed platinum sponsorship isn’t just a logo on a banner, it’s a commitment to sustainable, community-first growth. In 2024, their support helped us organize inclusive, impactful gatherings like AsyncAPI Conf Online and the Conference on Tour series now branded as the AsyncAPI Conference. +In 2025, their contribution helps us go even bigger, with in-person conferences in Lagos, Munich, Bangalore, London, Paris, and Online each designed to bring the AsyncAPI community closer together across regions and time zones. Gravitee’s support enables: + +- Operational and travel cost for events. +- Broader outreach and visibility in growing the AsyncAPI communities around the world. +- Resources for speakers and panelists from diverse backgrounds. + +When we say Gravitee is helping us “hold nothing back,” we mean it, they’re helping build an ecosystem where everyone can contribute, learn, and grow, no matter their location or technical background. + +## Gravitee + AsyncAPI: A Real-World Use Case + +Behind Gravitee’s sponsorship is a real, practical investment in using the AsyncAPI specification to build and manage asynchronous APIs. Gravitee enables organizations to work seamlessly across protocols like [Kafka](https://kafka.apache.org/), [MQTT](https://mqtt.org/), and [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) using the AsyncAPI spec as a foundation for documentation, governance, and developer experience. This approach strengthens discoverability and observability across distributed systems, making Gravitee a natural ally in advancing AsyncAPI’s mission and ecosystem. + +By adopting AsyncAPI, Gravitee: + +- Enables better **discoverability** of event-driven APIs +- Enforces consistent **governance** across async interfaces +- Improves **observability** for systems using asynchronous messaging +- Reduces the **complexity** of managing hybrid architectures (REST + async) +This real-world usage supports AsyncAPI’s vision of making event-driven APIs easier to design, consume, and scale. + +## The Road Ahead: AsyncAPI x Gravitee in 2025 + +As AsyncAPI continues to grow, expanding its tooling, maintainership, and governance, Gravitee’s support will help us scale with intention and care. From better docs and contributor onboarding, to new design systems and international webinars, Gravitee’s sponsorship helps bring these initiatives to life. +We're especially thrilled to have them with us at the **AsyncAPI Conference 2025**, as we bring together contributors, users, and curious minds from across the globe. Gravitee's support ensures that we can keep these conferences accessible and meaningful for all. + +Thank you Gravitee for standing with us, and continuing to believe in the power of open, asynchronous systems. 💜 + +## Stay Connected + +If you’d like to learn more about Gravitee, check out their [website](https://www.gravitee.io) and their social media links below: +- [LinkedIn](https://www.linkedin.com/company/gravitee-io/posts/?feedView=all) +- [YouTube](https://www.youtube.com/c/Graviteesource) +- [Facebook](https://www.facebook.com/GraviteeSource) + +Stay tuned for more updates as we get closer to AsyncAPI Conference 2025! diff --git a/markdown/blog/july-2023.md b/markdown/blog/july-2023.md index eb632737436d..22ac6c1058fe 100644 --- a/markdown/blog/july-2023.md +++ b/markdown/blog/july-2023.md @@ -13,7 +13,7 @@ authors: excerpt: 'July Community Update' --- -Earlier this month, we officially kickstarted the AsyncAPI Mentorship Program. After receiving an overwhelming response of over 90+ applications for the program, we inducted [13 mentees into the AsyncAPI mentorship program](https://github.com/asyncapi/community/tree/master/mentorship/asyncapi-mentorship/2023). We are thrilled to welcome these talented individuals and look forward to seeing them grow and excel in their respective projects. Additionally, we are excited that our [budget of $19,500 for the AsyncAPI Mentorship Program got approved](), which means we can compensate all successful mentees of the program. We are grateful for the support and look forward to a successful program. +Earlier this month, we officially kickstarted the AsyncAPI Mentorship Program. After receiving an overwhelming response of over 90+ applications for the program, we inducted [13 mentees into the AsyncAPI mentorship program](https://github.com/asyncapi/community/blob/master/docs/050-mentorship-program/asyncapi-mentorship-2023-project-ideas.md). We are thrilled to welcome these talented individuals and look forward to seeing them grow and excel in their respective projects. Additionally, we are excited that our [budget of $19,500 for the AsyncAPI Mentorship Program got approved](https://github.com/orgs/asyncapi/discussions/689#discussioncomment-6028934), which means we can compensate all successful mentees of the program. We are grateful for the support and look forward to a successful program. ## AsyncAPI Conf on Tour 2023 (AACoT) diff --git a/markdown/blog/july-december-2021-at-asyncapi.md b/markdown/blog/july-december-2021-at-asyncapi.md index 56bf0ec87aa8..23c76c726af6 100644 --- a/markdown/blog/july-december-2021-at-asyncapi.md +++ b/markdown/blog/july-december-2021-at-asyncapi.md @@ -74,7 +74,7 @@ It was a pleasure to work with these folks and see them staying with us after GS ## Technical Steering Committee members setup -After joining the [Linux Foundation (LF)](https://www.asyncapi.com/blog/asyncapi-joins-linux-foundation) and applying the [open governance model](https://github.com/asyncapi/community/blob/master/CHARTER.md), it was time for us to start setting up a Technical Steering Committee (TSC). +After joining the [Linux Foundation (LF)](https://www.asyncapi.com/blog/asyncapi-joins-linux-foundation) and applying the [open governance model](https://github.com/asyncapi/community/blob/master/docs/020-governance-and-policies/CHARTER.md), it was time for us to start setting up a Technical Steering Committee (TSC). So here we are, 9 months after joining LF, we already have 24 members. Check out the [complete list of all the TSC members](https://www.asyncapi.com/community/tsc). Pay attention to those that are marked as **Available for hire**. Don't let folks work for free. Pay them to work on open-source. Be good humans. diff --git a/markdown/blog/march-2021-at-asyncapi.md b/markdown/blog/march-2021-at-asyncapi.md index e1f85656dba1..3fcc32dcb758 100644 --- a/markdown/blog/march-2021-at-asyncapi.md +++ b/markdown/blog/march-2021-at-asyncapi.md @@ -54,7 +54,7 @@ Let me provide more context in FAQ style: #### Is Linux Foundation taking control over AsyncAPI -No. AsyncAPI Initiative runs under [open governance model](https://github.com/asyncapi/community/blob/master/CHARTER.md) and is community-driven. LF assures the project's intellectual property (IP), and related assets do not belong to any company or individual. [Fran Mendez](https://twitter.com/fmvilas) does not retire. He only handed over rights to the project to the foundation to assure the community that it is completely safe for all to use the spec and its tooling. +No. AsyncAPI Initiative runs under [open governance model](https://github.com/asyncapi/community/blob/master/docs/020-governance-and-policies/CHARTER.md) and is community-driven. LF assures the project's intellectual property (IP), and related assets do not belong to any company or individual. [Fran Mendez](https://twitter.com/fmvilas) does not retire. He only handed over rights to the project to the foundation to assure the community that it is completely safe for all to use the spec and its tooling. It also means our [GitHub organization](https://github.com/asyncapi) is not going anywhere. Nothing changes. diff --git a/markdown/blog/new-governance-board.md b/markdown/blog/new-governance-board.md index 9fc328c84e0c..6986b6034e74 100644 --- a/markdown/blog/new-governance-board.md +++ b/markdown/blog/new-governance-board.md @@ -31,7 +31,7 @@ Our Ambassadors have delivered high-quality educational content, promotional art We will replace the single Executive Director with a three-person Governance Board this year. We will expand to five members in 2026. This change significantly improves our resilience against the [bus factor](https://en.wikipedia.org/wiki/Bus_factor). -For details, see the updated [Charter](https://github.com/asyncapi/community/blob/master/CHARTER.md) and [Governance Guide](https://github.com/asyncapi/community/blob/master/GOVERNANCE.md). +For details, see the updated [Charter](https://github.com/asyncapi/community/blob/master/docs/020-governance-and-policies/CHARTER.md) and [Governance Guide](https://github.com/asyncapi/community/blob/master/docs/020-governance-and-policies/GOVERNANCE.md). ## Election Timeline diff --git a/markdown/blog/release-notes-3.1.0.md b/markdown/blog/release-notes-3.1.0.md new file mode 100644 index 000000000000..3ddbbfaadb73 --- /dev/null +++ b/markdown/blog/release-notes-3.1.0.md @@ -0,0 +1,57 @@ +--- +title: AsyncAPI Spec 3.1.0 Release Notes +date: 2026-01-31T19:00:00+01:00 +type: Communication +tags: + - Specification + - Release Notes +cover: /img/posts/release-notes-3.1.0/cover.webp +authors: + - name: Lukasz Gornicki + photo: /img/avatars/lpgornicki.webp + link: https://www.linkedin.com/in/lukasz-gornicki-a621914/ +excerpt: 'AsyncAPI 3.1 is now released with a new ROS 2 binding.' +--- + +The new version of the AsyncAPI specification - 3.1.0 - is now available. It looks like we are out of the long break after v3 release. + +> This is a minor release, and it doesn't bring any breaking changes. You can switch to it by modifying the following value in your AsyncAPI file `asyncapi: '3.0.0'` into `asyncapi: '3.1.0'` without any issues. + + +## New protocol bindings + +The specification is now extended to support another custom protocol through the bindings feature: + +ROS 2 ([official docs](https://docs.ros.org/en/jazzy/)), thanks to [@gramss](https://github.com/gramss) and [@amparosancho](https://github.com/amparosancho). + +For more details, check out [ROS 2 binding definition](https://github.com/asyncapi/bindings/tree/master/ros2). + +## Tooling support + +The following official AsyncAPI tools are already updated to support the 3.1.0 version of the specification: +- JSON Schema that supports validation of AsyncAPI documents with ROS 2 binding is updated in [this](https://github.com/asyncapi/spec-json-schemas/releases/tag/v6.11.1) repository. Also **@asyncapi/specs** package has been updated on NPM to version 6.11.1. +- [JavaScript Parser](https://github.com/asyncapi/parser-js/releases/tag/%40asyncapi%2Fparser%403.6.0) uses latest **@asyncapi/specs** package and can be used to parse and validate 3.1.0 documents. Upgrade to the latest version. +- [JavaScript Converter](https://github.com/asyncapi/converter-js/releases/tag/v1.7.0) uses latest **@asyncapi/parser** package and can be used to convert to 3.1.0 documents. Upgrade to the latest version. This conversion is just the version change in `asyncapi` field. +- [AsyncAPI Studio](https://github.com/asyncapi/studio) is also updated so just go to https://studio.asyncapi.com/ and see you can already write 3.1.0 documents. + +## Thank you + +Huge thanks to contributors of the new addition to the spec: [Amparo Sancho Arellano](https://github.com/amparosancho) and [Florian Gramß](https://github.com/gramss). + +Huge thanks to specification maintainers that supported the process: [Fran Méndez](https://github.com/fmvilas), [Dale Lane](https://github.com/dalelane), [Vladimír Gorej](https://github.com/char0n), and [Lukasz Gornicki](https://github.com/derberg). + +Huge thanks to maintainers that helped with smooth updates of core tooling: [Maciej Urbańczyk](https://github.com/magicmatatjahu), [Ashish Padhy](https://github.com/Shurtu-gal), [Pavel Bodiachevskii](https://github.com/Pakisan), [Fran Méndez](https://github.com/fmvilas). + +And I ([Lukasz Gornicki](https://github.com/derberg)) was your release coordinator, and I just gave myself a round of applause. + +## Look ahead + +We now regularly meet to work on the AsyncAPI specification, and anyone is welcome to join. Meetings are coordinated through [this GitHub issue](https://github.com/asyncapi/spec/issues/1131). + +Next topics on the agenda: +- [Documenting channels with late or out-of-sequence events](https://github.com/asyncapi/spec/issues/1143): + For folks with experience in streaming, frameworks like Apache Flink or Apache Spark, please look into this proposal to add the possibility of specifying expected event delivery latency to AsyncAPI contracts. +- [Support AND logic for multiple security schemes](https://github.com/asyncapi/spec/issues/1129): Currently, AsyncAPI allows you to specify a list of security mechanisms where only one must be satisfied. The idea is to also allow users to specify that multiple mechanisms must be satisfied. +- [Discriminator support to be aligned with OAS3](https://github.com/asyncapi/spec/issues/1073): Right now, the discriminator field in AsyncAPI is just a string, which is too limited. People end up using it in combination with const as a workaround. We should consider aligning with the OpenAPI Discriminator Object, but we also need to address the fact that the discriminator is and would be limited to the AsyncAPI Schema. We need a solution that works for people using other schema formats, like Avro or Protobuf, for example. + +> Photo by Chinapat Saegang on Unsplash diff --git a/markdown/blog/vsasyncapi-preview-extension.md b/markdown/blog/vsasyncapi-preview-extension.md new file mode 100644 index 000000000000..049ee1fa4f18 --- /dev/null +++ b/markdown/blog/vsasyncapi-preview-extension.md @@ -0,0 +1,59 @@ +--- +title: 'AsyncAPI VS Code Preview Goes Web: Now Available in Your Browser' +date: 2025-12-07T06:00:00+01:00 +type: Community +tags: + - vscode-extension + - webview +cover: /img/posts/vs-asyncapi-preview/image.webp +authors: + - name: Ruchi Pakhle + photo: /img/avatars/ruchip16.webp + link: https://twitter.com/Ruchicodess + byline: AsyncAPI Maintainer & TSC Member +excerpt: 'AsyncAPI VS Code Preview extension is now web-compatible. Preview AsyncAPI files directly in your browser using vscode.dev or github.dev.' +--- + +For years, the AsyncAPI VS Code Preview extension has been helping developers visualize and work with AsyncAPI documents directly inside VS Code. But there was always one limitation: you needed VS Code installed on your machine. + +Not anymore! We've made the extension fully web-compatible, which means you can now open any GitHub repository in vscode.dev or github.dev and instantly preview AsyncAPI files right in your browser. No downloads, no local setup – just open and preview. + +## What Changed Under the Hood? + +Making the extension web-compatible required some technical changes: + +- **Introduced lightweight browser utilities** like `pathUtils` for cross-platform file handling +- **Updated VS Code dependencies** (`vscode` and `@types/vscode`) to ensure web extension compatibility +- **Removed Node.js-specific modules** like `fs`, `path`, and other dependencies that don't work in browsers +- **Removed EDAVisualizer integration** since it's unmaintained and incompatible with web mode + +## Why This Is a Big Deal + +This change removes a major friction point for AsyncAPI adoption. Think about it: how many times have you wanted to quickly check an AsyncAPI file in a GitHub repo but didn't want to go through the hassle of cloning it locally? + +Now contributors can review specs directly on GitHub, teams working in cloud-first environments don't need local VS Code installations, and newcomers can experiment with AsyncAPI without any setup. It's especially useful for open-source maintainers who spend a lot of time reviewing specs in pull requests. + + +## Demo + +Watch the AsyncAPI VS Code Preview extension working seamlessly in your web browser. This demonstration shows how to install the extension in VS Code web, open an AsyncAPI document, and use the preview functionality to render beautiful documentation directly in the browser without needing a local VS Code installation. + +**Demo Overview:** The video demonstrates opening a GitHub repository in vscode.dev, installing the AsyncAPI Preview extension, opening a sample AsyncAPI YAML file, and executing the preview command to generate interactive documentation in the web browser. + + + +**Accessibility Note:** This video includes visual demonstrations of the AsyncAPI extension interface. For a text-based description of the steps shown, please refer to the "Try It Out" section below. + +## Looking Forward + +This web compatibility opens up some interesting possibilities we hadn't considered before. Educators can now easily demonstrate AsyncAPI concepts without asking students to install anything. Open-source projects get more contributors because the barrier to reviewing and understanding specs is much lower. Remote teams can collaborate on AsyncAPI files without worrying about everyone having the same local setup. + +## Maintenance Mode + +A quick note: this extension is now in maintenance mode. We'll keep it working and updated, but we're not planning major new features. That said, if you run into bugs or have ideas for improvements, community contributions are always welcome! + +## Try It Out + +If you want to see this in action, head over to [vscode.dev](https://vscode.dev) and open any repo with AsyncAPI files. Install the AsyncAPI Preview extension, open a `.yaml` or `.json` file, and run "AsyncAPI: Preview Document" from the Command Palette. You'll have beautiful rendered docs in seconds. + +We'd love to hear how this works for you! Drop by the [AsyncAPI community Slack](https://www.asyncapi.com/slack-invite) and let us know if you find any issues or have suggestions for improvements. diff --git a/markdown/docs/community/000-onboarding/index.md b/markdown/docs/community/000-onboarding/index.md index 874d4a789da4..0a444840bb43 100644 --- a/markdown/docs/community/000-onboarding/index.md +++ b/markdown/docs/community/000-onboarding/index.md @@ -6,7 +6,7 @@ weight: 2 The AsyncAPI technical writer onboarding guide teaches new community members how to contribute to our documentation effectively. -> For a comprehensive understanding of the various ways you can contribute to the AsyncAPI Initiative, please consult the [AsyncAPI contributing guidelines](../../CONTRIBUTING.md). +> For a comprehensive understanding of the various ways you can contribute to the AsyncAPI Initiative, please consult the [AsyncAPI contributing guidelines](../010-contribution-guidelines) The goal is providing docs contributors with the necessary tools and knowledge to: diff --git a/markdown/docs/community/020-governance-and-policies/GOVERNANCE.md b/markdown/docs/community/020-governance-and-policies/GOVERNANCE.md index aeb93e79b479..f5795c09db0f 100644 --- a/markdown/docs/community/020-governance-and-policies/GOVERNANCE.md +++ b/markdown/docs/community/020-governance-and-policies/GOVERNANCE.md @@ -67,7 +67,7 @@ Board members will appoint a chairperson during the first board meeting followin You can determine who is a TSC member and has the right to vote from [MAINTAINERS.yaml](https://github.com/asyncapi/community/blob/master/MAINTAINERS.yaml) and [AMBASSADORS_MEMBERS.yaml](https://github.com/asyncapi/community/blob/master/AMBASSADORS_MEMBERS.yaml), `isTSCMember` properties. We also transparently list all the TSC members in [AsyncAPI Website](https://asyncapi.com/community/tsc). -Any maintainer and any ambassador can change their status by editing `isTSCMember` properties. +Any maintainer and any ambassador can change their status by editing `isTSCMember` properties. They also must provide date of the change to `true` under `tscMemberSince` property. ## Voting diff --git a/markdown/docs/community/020-governance-and-policies/TSC_MEMBERSHIP.md b/markdown/docs/community/020-governance-and-policies/TSC_MEMBERSHIP.md index af430405a181..6a4bc1ce76b2 100644 --- a/markdown/docs/community/020-governance-and-policies/TSC_MEMBERSHIP.md +++ b/markdown/docs/community/020-governance-and-policies/TSC_MEMBERSHIP.md @@ -100,7 +100,7 @@ You can become a maintainer by either: 2. Donating to an existing repository or project and continuing to maintain it. 3. Supporting and committing to existing projects and being invited by other maintainers to join them as a maintainer. For more information, refer to [Become a maintainer in an existing project](../010-contribution-guidelines/Become-maintainer-in-existing-project). -There's no invitation flow to join the TSC; it's something that you are allowed to do as a maintainer by default, as described in the [charter signed with the Linux Foundation when AsyncAPI joined the foundation](CHARTER). Instead, there is an automation flow in place that adds a new maintainer to the [`community/MAINTAINERS.yaml`](https://github.com/asyncapi/community/blob/master/MAINTAINERS.yaml) list every time the [CODEOWNERS][code-owners] file is updated in any project. And the only thing you need to do is to find your name in the `MAINTAINERS.yaml` list and change `isTscMember` from `false` to `true` along with updating other missing information like, for example, your `slack` ID. +There's no invitation flow to join the TSC; it's something that you are allowed to do as a maintainer by default, as described in the [charter signed with the Linux Foundation when AsyncAPI joined the foundation](CHARTER). Instead, there is an automation flow in place that adds a new maintainer to the [`community/MAINTAINERS.yaml`](https://github.com/asyncapi/community/blob/master/MAINTAINERS.yaml) list every time the [CODEOWNERS][code-owners] file is updated in any project. And the only thing you need to do is to find your name in the `MAINTAINERS.yaml` list and change `isTscMember` from `false` to `true` and provide date under `tscMemberSince` property along with updating other missing information like, for example, your `slack` ID. Check the current list of [TSC members](https://www.asyncapi.com/community/tsc) on the AsyncAPI website. diff --git a/markdown/docs/community/020-governance-and-policies/TSC_VOTING_OVERVIEW.md b/markdown/docs/community/020-governance-and-policies/TSC_VOTING_OVERVIEW.md index fc7c9fdbb346..56f0c68b074c 100644 --- a/markdown/docs/community/020-governance-and-policies/TSC_VOTING_OVERVIEW.md +++ b/markdown/docs/community/020-governance-and-policies/TSC_VOTING_OVERVIEW.md @@ -4,51 +4,75 @@ weight: 40 --- -| name | [chore: introduce governance board](https://github.com/asyncapi/community/issues/1634) | [Donation of `Neuroglia.AsyncAPI`](https://github.com/asyncapi/community/issues/1764) | [Budget 2025](https://github.com/asyncapi/community/issues/1681) | [2024 budget refresh and request for urgent pre-approval of some 2025 costs](https://github.com/asyncapi/community/issues/1598) | [Should AsyncAPI Initiative endorse United Nations Global Digital Compact?](https://github.com/asyncapi/community/issues/1577) | [Donate kotlin-asyncapi](https://github.com/asyncapi/community/issues/1313) | [Proposal for Admin Rights for CoC Main Committee on Slack](https://github.com/asyncapi/community/issues/1227) | [chore: add Marketing WORKING_GROUP](https://github.com/asyncapi/community/issues/1130) | [docs: add instruction how voting automation works](https://github.com/asyncapi/community/issues/1155) | lastParticipatedVoteTime | isVotedInLast3Months | lastVoteClosedTime | agreeCount | disagreeCount | abstainCount | notParticipatingCount | -| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | -| [Mayaleeeee](https://github.com/Mayaleeeee) | 👍 | 👍 | 👍 | 🔕 | 👍 | 👍 | 👍 | 👍 | 👍 | 2025-04-23 | true | 2025-04-29 | 8 | 0 | 0 | 1 | -| [aayushmau5](https://github.com/aayushmau5) | 👍 | 👍 | 👍 | 👍 | 👍 | 🔕 | 👍 | 👍 | 🔕 | 2025-04-23 | true | 2025-04-29 | 7 | 0 | 0 | 2 | -| [imabp](https://github.com/imabp) | 🔕 | 👍 | 🔕 | 🔕 | 👍 | 👍 | 👍 | 🔕 | 👍 | 2025-03-05 | false | 2025-04-29 | 5 | 0 | 0 | 4 | -| [akshatnema](https://github.com/akshatnema) | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 2025-04-24 | true | 2025-04-29 | 9 | 0 | 0 | 0 | -| [anshgoyalevil](https://github.com/anshgoyalevil) | 🔕 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 🔕 | 2025-03-05 | true | 2025-04-29 | 7 | 0 | 0 | 2 | -| [anandsunderraman](https://github.com/anandsunderraman) | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 👍 | 👍 | 🔕 | 👍 | 2024-07-23 | false | 2025-04-29 | 3 | 0 | 0 | 6 | -| [Shurtu-gal](https://github.com/Shurtu-gal) | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 2025-04-22 | true | 2025-04-29 | 9 | 0 | 0 | 0 | -| [CameronRushton](https://github.com/CameronRushton) | 🔕 | 🔕 | 🔕 | 👍 | 👍 | 🔕 | 👀 | 🔕 | 👍 | 2024-11-29 | false | 2025-04-29 | 3 | 0 | 1 | 5 | -| [dalelane](https://github.com/dalelane) | 🔕 | 👀 | 🔕 | 👀 | 👎 | 👍 | 👀 | 🔕 | 🔕 | 2025-03-11 | false | 2025-04-29 | 1 | 1 | 3 | 4 | -| [fmvilas](https://github.com/fmvilas) | 👍 | 👍 | 👍 | 👍 | 👍 | 🔕 | 👍 | 👍 | 👍 | 2025-04-22 | true | 2025-04-29 | 8 | 0 | 0 | 1 | -| [jonaslagoni](https://github.com/jonaslagoni) | 👍 | 👍 | 🔕 | 🔕 | 👍 | 👍 | 👍 | 👍 | 👍 | 2025-04-29 | true | 2025-04-29 | 7 | 0 | 0 | 2 | -| [KhudaDad414](https://github.com/KhudaDad414) | 🔕 | 🔕 | 🔕 | 🔕 | 👍 | 🔕 | 👍 | 👍 | 👍 | 2024-11-18 | false | 2025-04-29 | 4 | 0 | 0 | 5 | -| [lbroudoux](https://github.com/lbroudoux) | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 👍 | 👍 | 👍 | 🔕 | 2024-07-16 | false | 2025-04-29 | 3 | 0 | 0 | 6 | -| [M3lkior](https://github.com/M3lkior) | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 👍 | 2024-04-12 | false | 2025-04-29 | 1 | 0 | 0 | 8 | -| [derberg](https://github.com/derberg) | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 2025-04-29 | true | 2025-04-29 | 9 | 0 | 0 | 0 | -| [magicmatatjahu](https://github.com/magicmatatjahu) | 👍 | 👍 | 👍 | 🔕 | 👀 | 🔕 | 👍 | 👍 | 👍 | 2025-04-29 | true | 2025-04-29 | 6 | 0 | 1 | 2 | -| [AceTheCreator](https://github.com/AceTheCreator) | 🔕 | 👍 | 🔕 | 👍 | 🔕 | 🔕 | 👍 | 👍 | 🔕 | 2025-03-11 | false | 2025-04-29 | 4 | 0 | 0 | 5 | -| [NektariosFifes](https://github.com/NektariosFifes) | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | Member has not participated in all previous voting process. | false | 2025-04-29 | 0 | 0 | 0 | 9 | -| [Pakisan](https://github.com/Pakisan) | 👍 | 🔕 | 👍 | 👍 | 👍 | 👍 | 🔕 | 👍 | 👍 | 2025-04-28 | true | 2025-04-29 | 7 | 0 | 0 | 2 | -| [theschles](https://github.com/theschles) | 👀 | 🔕 | 🔕 | 🔕 | 👎 | 👍 | 🔕 | 🔕 | 👍 | 2025-04-23 | false | 2025-04-29 | 2 | 1 | 1 | 5 | -| [princerajpoot20](https://github.com/princerajpoot20) | 👍 | 👀 | 👍 | 🔕 | 👀 | 🔕 | 👍 | 👍 | 👍 | 2025-04-23 | true | 2025-04-29 | 5 | 0 | 2 | 2 | -| [rcoppen](https://github.com/rcoppen) | 🔕 | 👀 | 🔕 | 👀 | 👀 | 👍 | 🔕 | 🔕 | 🔕 | 2025-03-12 | false | 2025-04-29 | 1 | 0 | 3 | 5 | -| [Amzani](https://github.com/Amzani) | 🔕 | 🔕 | 🔕 | 👍 | 👍 | 🔕 | 👍 | 👍 | 🔕 | 2024-11-27 | false | 2025-04-29 | 4 | 0 | 0 | 5 | -| [smoya](https://github.com/smoya) | 🔕 | 👍 | 👍 | 👍 | 👎 | 👍 | 👍 | 👍 | 🔕 | 2025-03-05 | true | 2025-04-29 | 6 | 1 | 0 | 2 | -| [Souvikns](https://github.com/Souvikns) | 🔕 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 🔕 | 👍 | 2025-03-05 | true | 2025-04-29 | 7 | 0 | 0 | 2 | -| [quetzalliwrites](https://github.com/quetzalliwrites) | 🔕 | 🔕 | 🔕 | 👍 | 🔕 | 🔕 | 👍 | 👍 | 👍 | 2024-11-30 | false | 2025-04-29 | 4 | 0 | 0 | 5 | -| [BOLT04](https://github.com/BOLT04) | 👍 | 🔕 | 🔕 | 🔕 | 👀 | 🔕 | 👍 | 👍 | 🔕 | 2025-04-22 | false | 2025-04-29 | 3 | 0 | 1 | 5 | -| [dan-r](https://github.com/dan-r) | 👍 | 👍 | 👍 | 🔕 | 👍 | 👍 | 🔕 | 🔕 | 🔕 | 2025-04-28 | true | 2025-04-29 | 5 | 0 | 0 | 4 | -| [Tenischev](https://github.com/Tenischev) | 🔕 | 🔕 | 👍 | 👍 | 👀 | 👍 | 🔕 | 🔕 | 🔕 | 2025-02-20 | true | 2025-04-29 | 3 | 0 | 1 | 5 | -| [Samridhi-98](https://github.com/Samridhi-98) | 👍 | 🔕 | 🔕 | 👍 | 👍 | 👍 | 🔕 | 🔕 | 👍 | 2025-04-23 | false | 2025-04-29 | 5 | 0 | 0 | 4 | -| [ivangsa](https://github.com/ivangsa) | 👍 | 👀 | 🔕 | 🔕 | 👎 | 👍 | 🔕 | 🔕 | 👍 | 2025-04-23 | true | 2025-04-29 | 3 | 1 | 1 | 4 | -| [Florence-Njeri](https://github.com/Florence-Njeri) | 👍 | 👍 | 🔕 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 2025-04-23 | true | 2025-04-29 | 8 | 0 | 0 | 1 | -| [whitlockjc](https://github.com/whitlockjc) | 🔕 | 👍 | 👍 | 👍 | 👍 | 🔕 | 👍 | 🔕 | 🔕 | 2025-03-04 | true | 2025-04-29 | 5 | 0 | 0 | 4 | -| [VisualBean](https://github.com/VisualBean) | 🔕 | 👀 | 👍 | 🔕 | 👍 | 👀 | 👍 | 👍 | 👍 | 2025-03-04 | true | 2025-04-29 | 5 | 0 | 2 | 2 | -| [kennethaasan](https://github.com/kennethaasan) | 👍 | 👍 | 🔕 | 🔕 | 🔕 | 👍 | 👍 | 👍 | 👍 | 2025-04-29 | true | 2025-04-29 | 6 | 0 | 0 | 3 | -| [GreenRover](https://github.com/GreenRover) | 👍 | 👍 | 👍 | 🔕 | 👎 | 👍 | 🔕 | 🔕 | 👍 | 2025-04-29 | true | 2025-04-29 | 4 | 1 | 0 | 4 | -| [thulieblack](https://github.com/thulieblack) | 👍 | 👀 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 2025-04-23 | true | 2025-04-29 | 8 | 0 | 1 | 0 | -| [devilkiller-ag](https://github.com/devilkiller-ag) | 👍 | 👍 | 👍 | 🔕 | 🔕 | 🔕 | 👍 | 👍 | 👍 | 2025-04-23 | true | 2025-04-29 | 6 | 0 | 0 | 3 | -| [sambhavgupta0705](https://github.com/sambhavgupta0705) | 👍 | 🔕 | 👍 | 👍 | 👍 | 👍 | 🔕 | 👍 | 👍 | 2025-04-29 | true | 2025-04-29 | 7 | 0 | 0 | 2 | -| [AayushSaini101](https://github.com/AayushSaini101) | 👍 | 👍 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 2025-04-23 | true | 2025-04-29 | 2 | 0 | 0 | 0 | -| [TRohit20](https://github.com/TRohit20) | 👍 | 👍 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 2025-04-29 | true | 2025-04-29 | 2 | 0 | 0 | 0 | -| [ashmit-coder](https://github.com/ashmit-coder) | 👍 | 👍 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 2025-04-28 | true | 2025-04-29 | 2 | 0 | 0 | 0 | -| [harikrishnan83](https://github.com/harikrishnan83) | 👍 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 2025-04-23 | false | 2025-04-29 | 1 | 0 | 0 | 1 | -| [cdavernas](https://github.com/cdavernas) | 👍 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 2025-04-22 | false | 2025-04-29 | 1 | 0 | 0 | 0 | -| [jbbianchi](https://github.com/jbbianchi) | 👍 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 2025-04-23 | false | 2025-04-29 | 1 | 0 | 0 | 0 | -| [vishvamsinh28](https://github.com/vishvamsinh28) | 👍 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 🔕 | 2025-04-23 | false | 2025-04-29 | 1 | 0 | 0 | 0 | + +## How to read this table + +| Icon | Meaning | +| ---- | ------- | +| 👍 | In favor | +| 👎 | Against | +| 👀 | Abstain | +| 🔕 | Not participated — was an eligible TSC member but did not vote | +| - | Not a member yet — vote closed before this person joined the TSC | + +**`isVotedInLast3Months`** shows whether the member cast at least one vote in the three months preceding the most recent vote close date. A value of `false` does **not** automatically trigger removal. + +**Inactivity removal rule ([AsyncAPI charter](https://github.com/asyncapi/community/blob/master/docs/020-governance-and-policies/CHARTER.md)):** +A TSC member is automatically moved to emeritus only when they have missed **at least 2 consecutive votes whose close dates are 3 or more calendar months apart**. This means a member can show `isVotedInLast3Months: false` and still remain active — for example, if their recent missed votes all happened within a short window (less than 3 months between the first and last missed vote). + +## Vote index + +| # | Vote | +| --- | --- | +| #1 | [docs: add instruction how voting automation works](https://github.com/asyncapi/community/issues/1155) | +| #2 | [chore: add Marketing WORKING_GROUP](https://github.com/asyncapi/community/issues/1130) | +| #3 | [Proposal for Admin Rights for CoC Main Committee on Slack](https://github.com/asyncapi/community/issues/1227) | +| #4 | [Donate kotlin-asyncapi](https://github.com/asyncapi/community/issues/1313) | +| #5 | [Should AsyncAPI Initiative endorse United Nations Global Digital Compact?](https://github.com/asyncapi/community/issues/1577) | +| #6 | [2024 budget refresh and request for urgent pre-approval of some 2025 costs](https://github.com/asyncapi/community/issues/1598) | +| #7 | [Budget 2025](https://github.com/asyncapi/community/issues/1681) | +| #8 | [Donation of `Neuroglia.AsyncAPI`](https://github.com/asyncapi/community/issues/1764) | +| #9 | [chore: introduce governance board](https://github.com/asyncapi/community/issues/1634) | +| #10 | [AsyncAPI GitHub Organization cleanup - some repos should be archived](https://github.com/asyncapi/community/issues/1948) | +| #11 | [Voting to improve the Bounty program](https://github.com/asyncapi/community/issues/2163) | +| #12 | [Voting AsyncAPI 2026 budget](https://github.com/asyncapi/community/issues/2221) | +| #13 | [Cleanup Inactive Working Groups](https://github.com/asyncapi/community/issues/2312) | + +| GitHub handle | #1 | #2 | #3 | #4 | #5 | #6 | #7 | #8 | #9 | #10 | #11 | #12 | #13 | Last participated | Active (3 months) | Last vote closed | In favor | Against | Abstain | Not participated | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| [aayushmau5](https://github.com/aayushmau5) | 🔕 | 👍 | 👍 | 🔕 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 2026-03-25 | true | 2026-04-01 | 11 | 0 | 0 | 2 | +| [AayushSaini101](https://github.com/AayushSaini101) | - | - | - | - | - | - | 👍 | 👍 | 👍 | 🔕 | 👍 | 👍 | 👍 | 2026-03-26 | true | 2026-04-01 | 6 | 0 | 0 | 1 | +| [AceTheCreator](https://github.com/AceTheCreator) | 🔕 | 👍 | 👍 | 🔕 | 🔕 | 👍 | 🔕 | 👍 | 🔕 | 👍 | 👍 | 🔕 | 🔕 | 2025-12-03 | false | 2026-04-01 | 6 | 0 | 0 | 7 | +| [Adi-204](https://github.com/Adi-204) | - | - | - | - | - | - | - | - | - | - | 👍 | 👍 | 👍 | 2026-03-25 | true | 2026-04-01 | 3 | 0 | 0 | 0 | +| [akshatnema](https://github.com/akshatnema) | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 🔕 | 🔕 | 👍 | 🔕 | 2026-01-09 | true | 2026-04-01 | 10 | 0 | 0 | 3 | +| [Amzani](https://github.com/Amzani) | 🔕 | 👍 | 👍 | 🔕 | 👍 | 👍 | 🔕 | 🔕 | 👍 | 👍 | 👍 | 🔕 | 👍 | 2026-03-30 | true | 2026-04-01 | 8 | 0 | 0 | 5 | +| [anshgoyalevil](https://github.com/anshgoyalevil) | - | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 🔕 | 👍 | 👍 | 🔕 | 🔕 | 2025-11-29 | false | 2026-04-01 | 9 | 0 | 0 | 3 | +| [cdavernas](https://github.com/cdavernas) | - | - | - | - | - | - | - | - | 👍 | 👍 | 👍 | 👍 | 👍 | 2026-03-24 | true | 2026-04-01 | 5 | 0 | 0 | 0 | +| [dalelane](https://github.com/dalelane) | 🔕 | 🔕 | 👀 | 👍 | 👎 | 👀 | 🔕 | 👀 | 👍 | 👍 | 👀 | 👀 | 👍 | 2026-03-25 | true | 2026-04-01 | 4 | 1 | 5 | 3 | +| [danielkocot](https://github.com/danielkocot) | - | - | - | - | - | - | - | - | - | 👍 | 👍 | 👍 | 🔕 | 2026-01-12 | true | 2026-04-01 | 3 | 0 | 0 | 1 | +| [derberg](https://github.com/derberg) | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 2026-03-30 | true | 2026-04-01 | 13 | 0 | 0 | 0 | +| [Florence-Njeri](https://github.com/Florence-Njeri) | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 🔕 | 👍 | 👍 | 🔕 | 👍 | 👍 | 🔕 | 2026-01-08 | true | 2026-04-01 | 10 | 0 | 0 | 3 | +| [fmvilas](https://github.com/fmvilas) | 👍 | 👍 | 👍 | 🔕 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 2026-03-24 | true | 2026-04-01 | 12 | 0 | 0 | 1 | +| [harikrishnan83](https://github.com/harikrishnan83) | - | - | - | - | - | - | 🔕 | 🔕 | 👍 | 👍 | 👍 | 👍 | 👍 | 2026-03-26 | true | 2026-04-01 | 5 | 0 | 0 | 2 | +| [hguerrero](https://github.com/hguerrero) | - | - | - | - | - | - | - | - | - | 👍 | 👍 | 👍 | 🔕 | 2026-01-12 | true | 2026-04-01 | 3 | 0 | 0 | 1 | +| [imabp](https://github.com/imabp) | 👍 | 🔕 | 👍 | 👍 | 👍 | 🔕 | 🔕 | 👍 | 🔕 | 👍 | 👍 | 👍 | 👍 | 2026-03-26 | true | 2026-04-01 | 9 | 0 | 0 | 4 | +| [ivangsa](https://github.com/ivangsa) | 👍 | 🔕 | 🔕 | 👍 | 👎 | 🔕 | 🔕 | 👀 | 👍 | 👍 | 👀 | 👀 | 👍 | 2026-03-24 | true | 2026-04-01 | 5 | 1 | 3 | 4 | +| [jbbianchi](https://github.com/jbbianchi) | - | - | - | - | - | - | - | - | 👍 | 👀 | 👍 | 👍 | 👍 | 2026-03-25 | true | 2026-04-01 | 4 | 0 | 1 | 0 | +| [jonaslagoni](https://github.com/jonaslagoni) | 👍 | 👍 | 👍 | 👍 | 👍 | 🔕 | 🔕 | 👍 | 👍 | 👍 | 👍 | 👍 | 🔕 | 2026-01-13 | true | 2026-04-01 | 10 | 0 | 0 | 3 | +| [kennethaasan](https://github.com/kennethaasan) | 👍 | 👍 | 👍 | 👍 | 🔕 | 🔕 | 🔕 | 👍 | 👍 | 🔕 | 👍 | 👍 | 🔕 | 2026-01-08 | true | 2026-04-01 | 8 | 0 | 0 | 5 | +| [magicmatatjahu](https://github.com/magicmatatjahu) | 👍 | 👍 | 👍 | 🔕 | 👀 | 🔕 | 👍 | 👍 | 👍 | 👍 | 🔕 | 👍 | 🔕 | 2026-01-08 | true | 2026-04-01 | 8 | 0 | 1 | 4 | +| [Mayaleeeee](https://github.com/Mayaleeeee) | 👍 | 👍 | 👍 | 👍 | 👍 | 🔕 | 👍 | 👍 | 👍 | 🔕 | 👍 | 👍 | 👍 | 2026-03-31 | true | 2026-04-01 | 11 | 0 | 0 | 2 | +| [nashjain](https://github.com/nashjain) | - | - | - | - | - | - | - | - | - | 👍 | 🔕 | 👍 | 🔕 | 2026-01-07 | true | 2026-04-01 | 2 | 0 | 0 | 2 | +| [Pakisan](https://github.com/Pakisan) | 👍 | 👍 | 🔕 | 👍 | 👍 | 👍 | 👍 | 🔕 | 👍 | 👍 | 👍 | 🔕 | 👍 | 2026-03-25 | true | 2026-04-01 | 10 | 0 | 0 | 3 | +| [princerajpoot20](https://github.com/princerajpoot20) | 👍 | 👍 | 👍 | 🔕 | 👀 | 🔕 | 👍 | 👀 | 👍 | 👍 | 👍 | 👍 | 👍 | 2026-03-26 | true | 2026-04-01 | 9 | 0 | 2 | 2 | +| [rcoppen](https://github.com/rcoppen) | 🔕 | 🔕 | 🔕 | 👍 | 👀 | 👀 | 🔕 | 👀 | 👍 | 👍 | 👀 | 👀 | 👍 | 2026-03-24 | true | 2026-04-01 | 4 | 0 | 5 | 4 | +| [Samridhi-98](https://github.com/Samridhi-98) | 👍 | 🔕 | 🔕 | 👍 | 👍 | 👍 | 🔕 | 🔕 | 👍 | 👍 | 👍 | 👍 | 👍 | 2026-03-25 | true | 2026-04-01 | 9 | 0 | 0 | 4 | +| [Shurtu-gal](https://github.com/Shurtu-gal) | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 2026-03-25 | true | 2026-04-01 | 13 | 0 | 0 | 0 | +| [Souvikns](https://github.com/Souvikns) | 👍 | 🔕 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 🔕 | 🔕 | 👍 | 👍 | 2026-03-25 | true | 2026-04-01 | 10 | 0 | 0 | 3 | +| [Tenischev](https://github.com/Tenischev) | 🔕 | 🔕 | 🔕 | 👍 | 👀 | 👍 | 👍 | 🔕 | 🔕 | 🔕 | 👀 | 🔕 | 👍 | 2026-03-30 | true | 2026-04-01 | 4 | 0 | 2 | 7 | +| [TenzDelek](https://github.com/TenzDelek) | - | - | - | - | - | - | - | - | - | - | - | - | 👍 | 2026-03-25 | true | 2026-04-01 | 1 | 0 | 0 | 0 | +| [theschles](https://github.com/theschles) | 👍 | 🔕 | 🔕 | 👍 | 👎 | 🔕 | 🔕 | 🔕 | 👀 | 👀 | 🔕 | 🔕 | 👍 | 2026-03-29 | true | 2026-04-01 | 3 | 1 | 2 | 7 | +| [thulieblack](https://github.com/thulieblack) | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 👀 | 👍 | 👍 | 👍 | 👍 | 👍 | 2026-03-26 | true | 2026-04-01 | 12 | 0 | 1 | 0 | +| [TRohit20](https://github.com/TRohit20) | - | - | - | - | - | - | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 | 🔕 | 2026-01-14 | true | 2026-04-01 | 6 | 0 | 0 | 1 | +| [vishvamsinh28](https://github.com/vishvamsinh28) | - | - | - | - | - | - | - | - | 👍 | 👍 | 👍 | 👍 | 👍 | 2026-03-25 | true | 2026-04-01 | 5 | 0 | 0 | 0 | +| [whitlockjc](https://github.com/whitlockjc) | 🔕 | 🔕 | 👍 | 🔕 | 👍 | 👍 | 👍 | 👍 | 👍 | 🔕 | 👍 | 👍 | 👍 | 2026-03-25 | true | 2026-04-01 | 9 | 0 | 0 | 4 | \ No newline at end of file diff --git a/markdown/docs/community/040-guides/holopin-badge-workflow.md b/markdown/docs/community/040-guides/holopin-badge-workflow.md new file mode 100644 index 000000000000..8125b0db3fe1 --- /dev/null +++ b/markdown/docs/community/040-guides/holopin-badge-workflow.md @@ -0,0 +1,116 @@ +--- +title: Holopin Badge Workflow for Maintainers +description: Learn how to set up and use Holopin digital badges to recognize contributors in your repository. +weight: 30 +--- + +## Introduction + +**Holopin badges** (stickers) are digital rewards to recognize contributors. By following this guide, you'll learn how to: + +1. Enable Holopin badges for repositories within the AsyncAPI Github organization. +2. Issue Holopin badges to contributors. +3. Request new badges or get support. + +## Prerequisites + +Before proceeding with the guide, make sure to: + +1. Create a Holopin account. +2. Join the AsyncAPI Holopin organization to issue badges +3. Link your GitHub account. + +Find more information about each of the steps below in the section. + +### Create a Holopin Account + +1. Visit [holopin.io](https://holopin.io) and create an account +2. Complete your profile setup + +### Join the AsyncAPI Holopin Organization + +Repository maintainers must be members of the AsyncAPI Holopin organization to issue badges. + +**To get added to the organization:** + +1. Contact one of the following administrators to request membership in the AsyncAPI Holopin organization: + + - **@thulieblack** (GitHub) + - **@derberg** (GitHub) + +### Link Your GitHub Account + +If you created your Holopin account using "Sign up with GitHub", your accounts are already linked. Otherwise: + +1. Go to your [Holopin Account Settings](https://holopin.io/account) +2. Link your Holopin account to your GitHub profile +3. This enables the `@holopin-bot` to work in your repositories + +## Setting Up the Badge Workflow + +### Add the Repository Topic + +**Steps to add the topic:** + +1. Navigate to your repository on GitHub +2. Click on the gear icon next to the "About" section, or click on the topics area +3. In the topics field, add `get-global-holopin` +4. Press Enter or click outside the field to save + +The `holopin.yml` file will be automatically created in your repository's `.github` directory with all the necessary configuration replicated from the [AsyncAPI `.github` repository](https://github.com/asyncapi/.github). + +> **Note:** For more information about this automation, see the [`replicate_holopin_file` job](https://github.com/asyncapi/.github/blob/master/.github/workflows/global-replicator.yml#L271) within the global replicator workflow. + +## How to Issue a Badge + +1. Navigate to any **Issue** or **Pull Request** in your repository +2. Add a comment with the following format: + +``` +// Format +@holopin-bot @username sticker-alias + +// Example +@holopin-bot @johndoe contributor-badge +``` + +Once submitted, the `@holopin-bot` responds to the user `@johndoe` with a unique URL to claim the `contributor-badge` badge within their Holopin profile. After claiming, the badge appears on the Holopin profile and can also be [displayed in their GitHub profile](https://blog.holopin.io/posts/github-readme-tutorial). + +## Getting New Badges + +If you need new badge types created for the AsyncAPI organization: + +1. Contact **@thulieblack** or **@derberg** to request new badge designs +2. Once created, new badge id(s) will be added to the main `holopin.yml` file in the `.github` repository +3. The updated configuration will be populated to all repositories with the `get-global-holopin` topic + +## Additional Resources + +- [Holopin GitHub Integration Documentation](https://docs.holopin.io/integrations/github) +- [Holopin Issuing Rewards Guide](https://docs.holopin.io/issuing-rewards/regular-badges) +- [AsyncAPI Holopin Configuration](https://github.com/asyncapi/.github/blob/master/.github/holopin.yml) + +## Troubleshooting + +### Bot Not Responding + +- Make sure you're commenting in an Issue or Pull Request (not a discussion) +- Ensure you've added the `get-global-holopin` topic to your repository +- Verify the `holopin.yml` file exists in your `.github` directory (it should be automatically created) +- Check that your GitHub account is linked to your Holopin account +- Verify you're a member of the Holopin organization + +### Badge Not Issued + +- Verify the sticker alias exists in the `holopin.yml` file (check the [main configuration](https://github.com/asyncapi/.github/blob/master/.github/holopin.yml)) +- Check that the username is correct (starts with the `@` symbol) +- Ensure the bot has access to the repository +- Confirm the `get-global-holopin` topic is present on your repository + +### Need Help? + +If you encounter issues or need assistance: +- Open an issue in a relevant AsyncAPI repository (for example, `asyncapi/community`) and mention **@thulieblack** or **@derberg** in the description so they’re notified +- Reach out in the [AsyncAPI Slack](https://asyncapi.com/slack-invite) community +- Check the [Holopin support documentation](https://docs.holopin.io) + diff --git a/markdown/docs/community/040-guides/index.md b/markdown/docs/community/040-guides/index.md index 34fd0013e20b..18049e659cb9 100644 --- a/markdown/docs/community/040-guides/index.md +++ b/markdown/docs/community/040-guides/index.md @@ -20,4 +20,5 @@ This section contains step-by-step instructions and best practices for working o - Deployment and maintenance procedures for community resources - Integration guidelines for third-party tools and services -- Quality assurance and testing procedures \ No newline at end of file +- Quality assurance and testing procedures +- Holopin badge workflow setup and usage for recognizing contributors \ No newline at end of file diff --git a/markdown/docs/community/050-mentorship-program/summer-of-code-2026-project-ideas.md b/markdown/docs/community/050-mentorship-program/summer-of-code-2026-project-ideas.md new file mode 100644 index 000000000000..80bf2271cf5e --- /dev/null +++ b/markdown/docs/community/050-mentorship-program/summer-of-code-2026-project-ideas.md @@ -0,0 +1,84 @@ +--- +title: AsyncAPI GSoC Ideas Page 2026 +weight: 200 +--- + +> **Program Status: Application Phase** + +# AsyncAPI Ideas Page: Google Summer of Code 2026 + +Welcome to the **AsyncAPI Ideas Page** with our proposed projects for Google Summer of Code (GSoC) 2026! If you are interested in contributing, please don't hesitate to contact our mentors directly to discuss project ideas. + + + +## 1) [AsyncAPI Generator Maintainership - Hands on Open Source Experience](https://github.com/asyncapi/generator/issues/1860) +This initiative aims to guide you on a journey from contributor to maintainer of the project. You'll gain insight into the responsibilities of a maintainer, involving tasks beyond mere coding. + +- 🎯 **Outcome:** Taking responsibility for the AsyncAPI Generator's project future and continuous improvement +- 🛠️ **Skills Required:** JavaScript, Docker, Testing (Jest or similar), AsyncAPI knowledge, AsyncAPI Template Development, CI/CD, Technical Documentation +- 🧩 **Difficulty:** Hard +- 👩🏿‍🏫 **Mentor(s):** [Adi Boghawala](https://github.com/Adi-204) +- ⏳ **Length:** 350 Hours + +## 2) [AsyncAPI Conference Website Maintainership & Sustainability](https://github.com/asyncapi/conference-website/issues/919) +This project focuses on ensuring the long-term sustainability of the AsyncAPI Conference website by improving its technical foundation and onboarding a new maintainer through a hands-on GSoC experience. + +- 🎯 **Outcome:** A well-maintained, scalable AsyncAPI Conference website with a clearly onboarded long-term maintainer +- 🛠️ **Skills Required:** JavaScript/TypeScript, Next.js, Web Performance, Accessibility +- 🧩 **Difficulty:** Hard +- 👩🏿‍🏫 **Mentor(s):** [Azeez Elegbede](https://github.com/AceTheCreator) | [Tenz Delek](http://github.com/TenzDelek) +- ⏳ **Length:** 350 Hours + +## 3) [AsyncAPI Website Maintainership - From Contributor to Maintainer](https://github.com/asyncapi/website/issues/5052) +This initiative is designed to guide contributors on a hands-on journey from active contributor to maintainer of the AsyncAPI Website. The project currently requires additional maintainers to help manage its growing scale, with over 130 open issues and 100+ open pull requests. + +The goal of this project is not just to write code, but to expose contributors to the full scope of maintainership responsibilities, including decision-making, project stewardship, and long-term sustainability. + +- 🎯 **Outcome:** A contributor equipped with the skills, mindset, and experience required to help maintain and guide the AsyncAPI Website +- 🛠️ **Skills Required:** JavaScript, GitHub workflows, Code Review, Technical Documentation, Testing, Refactoring, AsyncAPI ecosystem knowledge +- 🧩 **Difficulty:** Hard +- 👩🏿‍🏫 **Mentor(s):** [Prince Rajpoot](https://github.com/princerajpoot20) | [Vishvamsinh Vaghela](https://github.com/vishvamsinh28) +- ⏳ **Length:** 350 Hours + +## 4) [Improving the AsyncAPI React Component](https://github.com/asyncapi/asyncapi-react/issues/1214) + +As the component evolves, it faces challenges around extensibility, maintainability, and long-term ownership, particularly as new features, integrations, and specification updates are introduced. This initiative aims to strengthen the component’s technical foundation while preparing a contributor for long-term maintainership. + +- 🎯 **Outcome:** A more extensible, maintainable AsyncAPI React component with a clear path to long-term ownership +- 🛠️ **Skills Required:** JavaScript/TypeScript, React, CI/CD workflows, API Specifications (AsyncAPI/OpenAPI), Technical Documentation +- 🧩 **Difficulty:** Hard +- 👩🏿‍🏫 **Mentor(s):** [Azeez Elegbede](https://github.com/AceTheCreator) +- ⏳ **Length:** 350 Hours + +## 5) [AsyncAPI CLI Maintainership - Performance, Stability & Sustainability](https://github.com/asyncapi/cli/issues/1991) +This initiative is designed to guide contributors on a hands-on journey from being an active contributor to becoming a maintainer of the AsyncAPI CLI. Participants will gain real-world experience with maintainership responsibilities that go far beyond writing code, focusing instead on long-term project health, performance, and sustainability. + +- 🎯 **Outcome:** A faster, more reliable, and maintainable AsyncAPI CLI with a contributor prepared for long-term maintainership +- 🛠️ **Skills Required:** JavaScript, TypeScript, Node.js, Performance Optimization, Testing Tooling, Dependency Management, API Design +- 🧩 **Difficulty:** Hard +- 👩🏿‍🏫 **Mentor(s):** [Aayush Saini](https://github.com/AayushSaini101) | [Ashish Padhy](https://github.com/Shurtu-gal) | [Souvik De](https://github.com/Souvikns) +- ⏳ **Length:** 350 Hours + +## Contact AsyncAPI Mentors +- Join [our Slack workspace](https://www.asyncapi.com/slack-invite). Observe our [Slack etiquette](../060-meetings-and-communication/slack-etiquette) and [AsyncAPI code of conduct](https://github.com/asyncapi/.github/blob/master/CODE_OF_CONDUCT.md). +- Join the dedicated Mentorship channel `#09_mentorships` to meet all other GSoC mentees and mentors. + +## FAQ + +1. **How active are previous GSoC contributors in AsyncAPI?** AsyncAPI participated in Google Summer of Code (GSoC) for the fourth time in 2025, a significant milestone that speaks to our commitment to nurturing the next generation of open-source contributors. Many contributors from that cohort remain actively involved in the community, while some ended up as project maintainers, including: + + - **[Adi Boghawala](https://github.com/Adi-204)**: Now a maintainer of the [AsyncAPI Generator](https://github.com/asyncapi/generator) repository + - **[Ruchi Pakhle](https://github.com/Ruchip16)**: Currently maintaining and advocating for the [AsyncAPI VsCode Extension](https://github.com/asyncapi/vs-asyncapi-preview) + - **[Tenz Delek](https://github.com/TenzDelek)**: Active contributor and triager on the [AsyncAPI Conference Website](https://github.com/asyncapi/conference-website) + + You can learn more about our GSoC 2025 participation in our official [blog post](https://www.asyncapi.com/blog/2025-gsoc-summary). + + + +2. **Is using ChatGPT for GSoC project proposals allowed?** + We advise against using ChatGPT or similar AI tools for your AsyncAPI GSoC project proposals. If you choose to use such tools, we require that you fully disclose this in your application. + +3. **Where is the AsyncAPI source code located?** + You can find all AsyncAPI source code on GitHub under our organization: [https://github.com/asyncapi](https://github.com/asyncapi). + +>If you have further questions or queries, please create an issue in this `/community` repo (with the prefix `GSoC 2026`) or start an [open AsyncAPI discussion](https://github.com/orgs/asyncapi/discussions). diff --git a/markdown/docs/community/050-mentorship-program/summerofcode-2025-asyncapi-gsoc-ideas-page.md b/markdown/docs/community/050-mentorship-program/summerofcode-2025-asyncapi-gsoc-ideas-page.md index b6591b7616ce..67320175bbe2 100644 --- a/markdown/docs/community/050-mentorship-program/summerofcode-2025-asyncapi-gsoc-ideas-page.md +++ b/markdown/docs/community/050-mentorship-program/summerofcode-2025-asyncapi-gsoc-ideas-page.md @@ -3,7 +3,7 @@ title: AsyncAPI GSoC Ideas Page 2025 weight: 190 --- -> **Program Status: In-progress** +> **Program Status: Completed** # AsyncAPI Ideas Page: Google Summer of Code 2025 diff --git a/markdown/docs/concepts/asyncapi-document/adding-messages.md b/markdown/docs/concepts/asyncapi-document/adding-messages.md index 9f81a798fdbe..ccc4551a3395 100644 --- a/markdown/docs/concepts/asyncapi-document/adding-messages.md +++ b/markdown/docs/concepts/asyncapi-document/adding-messages.md @@ -3,7 +3,7 @@ title: Adding messages weight: 140 --- -In an AsyncAPI document, adding [messages](/docs/reference/specification/v3.0.0#messageObject) mainly means setting up channels and operations. This is key for explaining how data moves between your applications. However, sometimes you might just want to use the AsyncAPI document to describe the messages themselves, without anything else. +In an AsyncAPI document, adding [messages](/docs/reference/specification/v3.1.0#messageObject) mainly means setting up channels and operations. This is key for explaining how data moves between your applications. However, sometimes you might just want to use the AsyncAPI document to describe the messages themselves, without anything else. ## Add messages @@ -72,7 +72,7 @@ components: description: Id of the comment that was liked ``` -You can reuse messages using the [Reference Object](/docs/reference/specification/v3.0.0#referenceObject). For example: +You can reuse messages using the [Reference Object](/docs/reference/specification/v3.1.0#referenceObject). For example: ```yml messages: @@ -82,7 +82,7 @@ You can reuse messages using the [Reference Object](/docs/reference/specificatio Here's the complete AsyncAPI document with channels reusing the same message: ```yml -asyncapi: 3.0.0 +asyncapi: 3.1.0 info: title: Example API version: '1.0.0' diff --git a/markdown/docs/concepts/asyncapi-document/adding-operations.md b/markdown/docs/concepts/asyncapi-document/adding-operations.md index 964e8cef18fd..023473bda659 100644 --- a/markdown/docs/concepts/asyncapi-document/adding-operations.md +++ b/markdown/docs/concepts/asyncapi-document/adding-operations.md @@ -9,7 +9,7 @@ In an AsyncAPI document, operations describe your application's behaviors and ca ## Defining operations -Operations can be defined as an independent object in the AsyncAPI document. More information about each field name that is used to define operations can be found [in the reference documentation of the specification](/docs/reference/specification/v3.0.0#operationObject). +Operations can be defined as an independent object in the AsyncAPI document. More information about each field name that is used to define operations can be found [in the reference documentation of the specification](/docs/reference/specification/v3.1.0#operationObject). The following diagram declares the field names that are frequently used to define operations in an AsyncAPI document: diff --git a/markdown/docs/concepts/asyncapi-document/dynamic-channel-address.md b/markdown/docs/concepts/asyncapi-document/dynamic-channel-address.md index 38bec737e1ae..1ede44f720e7 100644 --- a/markdown/docs/concepts/asyncapi-document/dynamic-channel-address.md +++ b/markdown/docs/concepts/asyncapi-document/dynamic-channel-address.md @@ -58,7 +58,7 @@ components: description: The ID of the streetlight. ``` -You can reuse parameters using the [Reference Object](/docs/reference/specification/v3.0.0#referenceObject) like in the following example: +You can reuse parameters using the [Reference Object](/docs/reference/specification/v3.1.0#referenceObject) like in the following example: ```yml parameters: @@ -68,7 +68,7 @@ You can reuse parameters using the [Reference Object](/docs/reference/specificat Here's the complete AsyncAPI document with the channels' parameters for the `address` field: ```yaml -asyncapi: 3.0.0 +asyncapi: 3.1.0 info: title: Example API version: '1.0.0' diff --git a/markdown/docs/concepts/asyncapi-document/extending-specification.md b/markdown/docs/concepts/asyncapi-document/extending-specification.md index b24fbf51a8cf..fb800d7e0009 100644 --- a/markdown/docs/concepts/asyncapi-document/extending-specification.md +++ b/markdown/docs/concepts/asyncapi-document/extending-specification.md @@ -16,7 +16,7 @@ Extensions can be used in any part of the AsyncAPI document. Here is an example of how to extend the AsyncAPI document with a custom property: ```yml -asyncapi: 3.0.0 +asyncapi: 3.1.0 info: title: Cool Example version: 0.1.0 diff --git a/markdown/docs/concepts/asyncapi-document/index.md b/markdown/docs/concepts/asyncapi-document/index.md index f3ea148e8e06..2954a9d46b9b 100644 --- a/markdown/docs/concepts/asyncapi-document/index.md +++ b/markdown/docs/concepts/asyncapi-document/index.md @@ -8,7 +8,7 @@ The [AsyncAPI specification](/docs/reference/specification/latest) defines field The AsyncAPI document is a communication contract between senders and receivers within an event-driven system. It specifies the payload content required for a service to send a message and provides the receiver with guidance about the message's properties. ```yaml -asyncapi: 3.0.0 +asyncapi: 3.1.0 info: title: Cool Example version: 0.1.0 diff --git a/markdown/docs/concepts/asyncapi-document/reply-info.md b/markdown/docs/concepts/asyncapi-document/reply-info.md index e3b13bca1e8b..99778eaefdf7 100644 --- a/markdown/docs/concepts/asyncapi-document/reply-info.md +++ b/markdown/docs/concepts/asyncapi-document/reply-info.md @@ -37,7 +37,7 @@ In the case where you don't know the address of the reply yet, you have the opti For instance, this pattern allows the replier to direct its response to a specific channel as defined by the requestor. This is typically achieved by including a `replyTo` property in the request header. The requestor specifies this property to indicate where it expects to receive the response, guiding the communication flow in a structured and predictable manner. ```yml -asyncapi: 3.0.0 +asyncapi: 3.1.0 info: title: Ping/pong example for a requester with a dynamic reply channel @@ -75,7 +75,7 @@ The request/reply pattern can also be implemented over multiple channels with a Here's an example of setting up both the requestor and replier over the same address: ```yml -asyncapi: 3.0.0 +asyncapi: 3.1.0 info: title: Ping/pong example with requester over the same channel @@ -110,7 +110,7 @@ In some cases, representing the [same information](#multiple-channels-with-singl Consider an example where multiple messages are transmitted over a single channel, all sharing the same address. In this setup, the `Operation` object is utilized to distinctly specify which of these messages serves as the request and which functions as the reply: ```yml -asyncapi: 3.0.0 +asyncapi: 3.1.0 info: title: Ping/pong example when a channel contains multiple messages diff --git a/markdown/docs/concepts/asyncapi-document/reusability-with-traits.md b/markdown/docs/concepts/asyncapi-document/reusability-with-traits.md index bbcd1c733f71..0e88c386261f 100644 --- a/markdown/docs/concepts/asyncapi-document/reusability-with-traits.md +++ b/markdown/docs/concepts/asyncapi-document/reusability-with-traits.md @@ -96,5 +96,5 @@ headers: ## Trait merging mechanism -In the AsyncAPI document, traits are merged into the operation or message object in the order they are defined, without overriding any properties. For detailed information on how this merging works, refer to [the specification's section on the traits merge mechanism](/docs/reference/specification/v3.0.0#traitsMergeMechanism). +In the AsyncAPI document, traits are merged into the operation or message object in the order they are defined, without overriding any properties. For detailed information on how this merging works, refer to [the specification's section on the traits merge mechanism](/docs/reference/specification/v3.1.0#traitsMergeMechanism). diff --git a/markdown/docs/concepts/asyncapi-document/reusable-parts.md b/markdown/docs/concepts/asyncapi-document/reusable-parts.md index 9effdb64ebdf..68d5f26dbaf5 100644 --- a/markdown/docs/concepts/asyncapi-document/reusable-parts.md +++ b/markdown/docs/concepts/asyncapi-document/reusable-parts.md @@ -5,7 +5,7 @@ weight: 280 Reusable parts in AsyncAPI provide flexibility, modularity, and code reusability. You can reuse the majority of document sections like messages, schema definitions, channels, operations, and more. -Reusable parts allow you to split up the AsyncAPI document into many files and reference them using the [Reference Object](/docs/reference/specification/v3.0.0#referenceObject). You can use the `$ref` keyword to reference the same document, another local file, or an external URL. The diagram below describes how to reuse parts in AsyncAPI: +Reusable parts allow you to split up the AsyncAPI document into many files and reference them using the [Reference Object](/docs/reference/specification/v3.1.0#referenceObject). You can use the `$ref` keyword to reference the same document, another local file, or an external URL. The diagram below describes how to reuse parts in AsyncAPI: ## Same document diff --git a/markdown/docs/concepts/asyncapi-document/securing-operations.md b/markdown/docs/concepts/asyncapi-document/securing-operations.md index c6619832a485..06b94f184cea 100644 --- a/markdown/docs/concepts/asyncapi-document/securing-operations.md +++ b/markdown/docs/concepts/asyncapi-document/securing-operations.md @@ -31,7 +31,7 @@ graph LR ## Operation section -Security information for an operation is defined using a [Security Scheme](/docs/reference/specification/v3.0.0#securitySchemeObject) at the operation level. You can reference a scheme from another location, such as `components.securitySchemes`, using the `$ref` keyword. +Security information for an operation is defined using a [Security Scheme](/docs/reference/specification/v3.1.0#securitySchemeObject) at the operation level. You can reference a scheme from another location, such as `components.securitySchemes`, using the `$ref` keyword. ```yaml operations: diff --git a/markdown/docs/concepts/asyncapi-document/server-security.md b/markdown/docs/concepts/asyncapi-document/server-security.md index 2463c8d8d973..a96d68e19ad4 100644 --- a/markdown/docs/concepts/asyncapi-document/server-security.md +++ b/markdown/docs/concepts/asyncapi-document/server-security.md @@ -11,7 +11,7 @@ You can describe how your server is secured with the `security` property where y Here is an example of adding security to your server, demonstrating that different servers can employ various security mechanisms: ```yml -asyncapi: 3.0.0 +asyncapi: 3.1.0 info: title: Streetlights Kafka API version: 1.0.0 diff --git a/markdown/docs/concepts/asyncapi-document/tags.md b/markdown/docs/concepts/asyncapi-document/tags.md index 5192979cdfe5..6d0b9dfcbe9f 100644 --- a/markdown/docs/concepts/asyncapi-document/tags.md +++ b/markdown/docs/concepts/asyncapi-document/tags.md @@ -40,7 +40,7 @@ graph LR Below is an example of the `tags` object inside the `info` object in an AsyncAPI document: ```yaml -asyncapi: 3.0.0 +asyncapi: 3.1.0 info: title: AsyncAPI Documentation version: 1.0.0 @@ -87,7 +87,7 @@ graph LR Below is an example of the `tags` object inside the `servers` object in an AsyncAPI document: ```yaml -asyncapi: 3.0.0 +asyncapi: 3.1.0 info: title: AsyncAPI Documentation @@ -143,7 +143,7 @@ graph LR Below is an example of the `tags` object inside the `channels` object in an AsyncAPI document: ```yaml -asyncapi: 3.0.0 +asyncapi: 3.1.0 info: title: AsyncAPI Documentation @@ -256,7 +256,7 @@ payload: Below is an example of all the tags defined in the `components` object and referenced in other components like `servers` and `channels`: ```yml -asyncapi: 3.0.0 +asyncapi: 3.1.0 components: tags: diff --git a/markdown/docs/concepts/asyncapi-document/variable-url.md b/markdown/docs/concepts/asyncapi-document/variable-url.md index 8c7c93415279..f087ace9b975 100644 --- a/markdown/docs/concepts/asyncapi-document/variable-url.md +++ b/markdown/docs/concepts/asyncapi-document/variable-url.md @@ -81,7 +81,7 @@ components: ### Define domain and port variables -Use `components.serverVariables` in your server using the [Reference Object](/docs/reference/specification/v3.0.0#referenceObject) to avoid repeating information: +Use `components.serverVariables` in your server using the [Reference Object](/docs/reference/specification/v3.1.0#referenceObject) to avoid repeating information: ```yml variables: @@ -92,7 +92,7 @@ Use `components.serverVariables` in your server using the [Reference Object](/do Here's the complete AsyncAPI document with the servers' variables for the `host` field: ```yaml -asyncapi: 3.0.0 +asyncapi: 3.1.0 info: title: Example API version: '1.0.0' diff --git a/markdown/docs/guides/message-validation.md b/markdown/docs/guides/message-validation.md index 29ea985b9478..c478dea0c484 100644 --- a/markdown/docs/guides/message-validation.md +++ b/markdown/docs/guides/message-validation.md @@ -85,7 +85,7 @@ With the Schema Registry in place, the producer first talks to the Schema Regist AsyncAPI is not directly involved in validation based on the Schema Registry. The good thing is that you do not have to duplicate schemas in your AsyncAPI document stored in Schema Registry. You can reference schemas from Schema Registry in your AsyncAPI documents. Here's an example of an AsyncAPI document where you can see both `schemaFormat` and `payload` referenced from the Schema Registry: ```yml -asyncapi: 3.0.0 +asyncapi: 3.1.0 info: title: Example with Avro version: 0.1.0 diff --git a/markdown/docs/reference/bindings/2.x.x.md b/markdown/docs/reference/bindings/2.x.x.md new file mode 100644 index 000000000000..477c5ef7d59a --- /dev/null +++ b/markdown/docs/reference/bindings/2.x.x.md @@ -0,0 +1,307 @@ +--- +title: '2.x.x' +weight: 26 +--- + +# SNS Bindings + +This document defines how to describe SNS-specific information on AsyncAPI. + + + +## Version + +Current version is `0.2.0`. + + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Channel Binding Object + +This object contains information about the channel representation in SNS. + +We represent an AsyncAPI Channel with a Topic in SNS. The bindings here allow definition of a topic within SNS. We provide properties on the binding that allow creation of a topic in infrastructure-as-code scenarios. Be aware that although the binding offers that flexibility, it may be more maintainable to specify properties such as SNS Access Control Policy outside of AsyncAPI. + +SNS supports many optional properties. To mark a channel as SNS, but use default values for the channel properties, just use an empty object {}. + +### Fields + +|Field Name | Type | Description| +|---|:---:|---| +| `name` | string | **Required.** The name of the topic. Can be different from the channel name to allow flexibility around AWS resource naming limitations.| +| `ordering` | [ordering](#ordering)| **Optional.** By default, we assume an unordered SNS topic. This field allows configuration of a FIFO SNS Topic. | +| `policy` |[policy](#policy) | **Optional.** The security policy for the SNS Topic | +| `tags` |Object | **Optional.** Key-value pairs that represent AWS tags on the topic. | +|`bindingVersion` | string | **Optional**, defaults to `latest`. The version of this binding.| + +### Schemas + +#### Ordering +|Field Name | Type | Description| +|---|:---:|---| +| `type` | string | **Required.** Defines the type of SNS Topic. Can be either `standard` or `FIFO`. | +| `contentBasedDeduplication` | boolean | **Optional.** Whether the de-duplication of messages should be turned on. Defaults to `false`| + +#### Policy +|Field Name | Type | Description| +|---|:---:|---| +| `statements` | [[Statement](#statement)] | **Required.** An array of Statement objects, each of which controls a permission for this topic | + +#### Statement +|Field Name | Type | Description| +|---|:---:|---| +| `effect` | string |**Required.** Either "Allow" or "Deny"| +| `principal` | string or AWS principal property containing a string or string array |**Required.** The AWS account(s) or resource ARN(s) that the statement applies to| +| `action` | string or array of string |**Required.** The SNS permission being allowed or denied e.g. sns:Publish| +| `resource` | string or array of string |**Optional.** The resource(s) that this policy applies to| +| `condition` | object or list of objects |**Optional.** Specific circumstances under which the policy grants permission| + +##### Examples + +Just use defaults + +```yaml +channels: + user-signedup: + description: A user has signed up to our service + bindings: + sns: {} +``` + +Minimal definition, just policy + +```yaml +channels: + user-signedup: + description: A user has signed up to our service + bindings: + sns: + policy: + statements: + - effect : Allow + principal: * + action: SNS:Publish +``` + + + +## Operation Binding Object + +This object contains information operation binding in SNS. + +We represent SNS producers via a **subscribe** Operation Object. In simple cases this may not require configuration, and can be shown as an empty SNS Binding Object i.e. {} if you need to explicitly indicate how a producer publishes to the channel. + +We represent SNS consumers via a **publish** Operation Object. These consumers need an SNS Subscription that defines how they consume from SNS i.e. the protocol that they use, and any filters applied. + +The SNS binding does not describe the receiver.If you wish to define the receiver, add a **publish** Operation Binding Object for that receiver. For example, if you send message to an SQS queue from an SNS Topic, you would add a protocol of 'sqs' and an Identifier object for the queue. That identifier could be an ARN of a queue defined outside of the scope of AsyncAPI, but if you wanted to define the receiver you would use the name of a queue defined in an SQS Binding on the **publish** Operation Binding Object. + +We support an array of consumers via the **consumers** field. This allows you to represent multiple protocols consuming an SNS Topic in one file. You may also use it for multiple consumers with the same protocol, instead of representing each consumer in a separate file. + +### Fields + +| Field Name | Type | Applies To | Description | +|---|:---:|:---:|---| +| `topic` | [identifier](#identifier) |Publish, Subscribe| **Optional.** Often we can assume that the SNS Topic is the channel name-we provide this field in case the you need to supply the ARN, or the Topic name is not the channel name in the AsyncAPI document.| +| `consumers` | [[Consumer](#consumer)] |Publish| **Required.** The protocols that listen to this topic and their endpoints.| +| `deliveryPolicy` | [deliveryPolicy](#delivery-policy) |Subscribe| **Optional.** Policy for retries to HTTP. The field is the default for HTTP receivers of the [SNS Topic](https://docs.aws.amazon.com/sns/latest/api/API_CreateTopic.html) which may be overridden by a specific consumer.| +|`bindingVersion` | string |Publish, Subscribe| **Optional**, defaults to `latest`. The version of this binding.| + +### Schemas + +#### Consumer + +| Field Name | Type | Description | +|---|:---:|---| +| `protocol` | string | **Required.** The protocol that this endpoint receives messages by. Can be `http`, `https`, `email`, `email-json`, `sms`, `sqs`, `application`, `lambda` or `firehose` | +| `endpoint` |[identifier](#identifier)| **Required.** The endpoint messages are delivered to. | +| `filterPolicy` | object | **Optional.** Only receive a subset of messages from the channel, determined by this policy. | +| `filterPolicyScope` | string | **Optional.** Determines whether the FilterPolicy applies to MessageAttributes (default) or MessageBody. | +| `rawMessageDelivery` | boolean | **Required.** If *true* AWS SNS attributes are removed from the body, and for SQS, SNS message attributes are copied to SQS message attributes. If *false* the SNS attributes are included in the body. | +| `redrivePolicy` | [redrivePolicy](#redrive-policy) | **Optional.** Prevent poison pill messages by moving un-processable messages to an SQS dead letter queue. | +| `deliveryPolicy` | [deliveryPolicy](#delivery-policy) | **Optional.** Policy for retries to HTTP. The parameter is for that [SNS Subscription](https://docs.aws.amazon.com/sns/latest/api/API_Subscribe.html) and overrides any policy on the [SNS Topic](https://docs.aws.amazon.com/sns/latest/api/API_CreateTopic.html). | +| `displayName` | string |**Optional.** The display name to use with an SMS subscription | + + +#### Delivery Policy +|Field Name | Type | Description| +|---|:---:|---| +| `minDelayTarget` | integer | **Optional.** The minimum delay for a retry in seconds | +| `maxDelayTarget` | integer | **Optional.** The maximum delay for a retry in seconds | +| `numRetries` | integer | **Optional.** The total number of retries, including immediate, pre-backoff, backoff, and post-backoff retries | +| `numNoDelayRetries` | integer | **Optional.** The number of immediate retries (with no delay) | +| `numMinDelayRetries` | integer | **Optional.** The number of immediate retries (with delay) | +| `numMaxDelayRetries` | integer | **Optional.** The number of post-backoff phase retries, with the maximum delay between retries | +| `backoffFunction` | string, one of: arithmetic, exponential, geometric or linear | **Optional.** The algorithm for backoff between retries | +| `maxReceivesPerSecond` | integer | **Optional.** The maximum number of deliveries per second, per subscription | + +#### Identifier +|Field Name | Type | Description | +|---|:---:|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +|`url` |string| **Optional.** The endpoint is a URL | +|`email` |string| **Optional.** The endpoint is an email address | +|`phone` |string| **Optional.** The endpoint is a phone number | +|`arn` |string| **Optional.** The target is an [ARN](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html). For example, for SQS, the identifier may be an ARN, which will be of the form: "[arn:aws:sqs:\{region\}:\{account-id\}:\{queueName\}](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)" | +|`name` |string| **Optional.** The endpoint is identified by a name, which corresponds to an identifying field called 'name' of a binding for that protocol on this **publish** Operation Object. For example, if the protocol is 'sqs' then the name refers to the name field **sqs** binding. We don't use $ref because we are referring, not including. | + +We provide an Identifer Object to support providing the identifier of an externally defined endpoint for this SNS *publication* to target, or an endpoint on another binding against this Operation Object (via the name field). + +#### Redrive Policy + +|Field Name | Type | Description| +|---|:---:|---| +| `deadLetterQueue` |[Identifier](#identifier)| **Required.** The SQS queue to use as a dead letter queue (DLQ). Note that you may have a Redrive Policy to put messages that cannot be delivered to an SQS queue, even if you use another protocol to consume messages from the queue, so it is defined at the level of the SNS Operation Binding Object in a Consumer Object (and is applied as part of an [SNS Subscription](https://docs.aws.amazon.com/sns/latest/dg/sns-create-subscribe-endpoint-to-topic.html)). The SQS Binding describes how to define an SQS Binding that supports defining the target SQS of the Redrive Policy. | +| `maxReceiveCount` |integer| **Optional.** The number of times a message is delivered to the source queue before being moved to the dead-letter queue. Defaults to 10. | + +### Examples + +#### SNS to SQS Pub-Sub + +[](SNS-SQS-Pub-Sub.png) + +We are producing to an SNS channel + +```yaml +channels: + user-signedup: + description: A user has signed up for our service + binding : + sns: {} # Indicates that the channel is an SNS Topic + subscribe: + operationId: sendMessage + description: send messages to the topic + bindings: + sns: + consumers: + - protocol: sqs + endpoint: + name: myQueue + rawMessageDelivery: false +``` + +We are consuming an SNS channel, using an SQS queue. A separate file specifies the producer, and has the SNS Bindings for the channel. For this reason we do not repeat the SNS binding information for the channel here, to avoid duplicated definitions diverging. Instead we just define the **publish** Operation Binding. + +In this version, the SQS queue is defined elsewhere, and we just reference via its ARN. It is worth noting that this couples the specification to the AWS *region* and *account*, which are part of the ARN, and if we moved the queue to a new region or account was this specification would need to be updated to reflect that. + + +```yaml +channels: + user-signedup: + description: A user has signed up for our service + publish: + operationId: receiveMessage + description: receive messages from the topic + bindings: + sns: + consumers: + - protocol: sqs + endpoint: + arn: arn:aws:sqs:us-west-2:123456789012:UserSignedUpQueue + rawMessageDelivery: true +``` + +We are consuming an SNS channel, using an SQS queue. A separate file specifies the producer, and has the SNS Bindings for the channel. For this reason we do not repeat the SNS binding information for the channel here, to avoid duplicated definitions diverging. Instead we just define the **publish** Operation Binding. + +In this version, the SQS queue is defined in this file, and we reference it by name. For brevity that definition is not shown here. See the SQS Binding Object for more. + +```yaml +channels: + user-signedup: + description: A user has signed up for our service + publish: + operationId: receiveMessage + description: receive messages from the topic + bindings: + sns: + consumers: + - protocol: sqs + endpoint: + name: user-signedup-queue # refers to a queue defined in this file, but not shown in this example + rawMessageDelivery: true + filterPolicy: + reason: + anything-but: password-reset + redrivePolicy: + deadLetterQueue: + name: user-signedup-queue-dlq # refers toa queue defined in this file, but not show in this example +``` + +#### SNS to HTTP Pub Sub + +[](SNS-HTTP.png) + +We are producing to an SNS channel. + +In this version, we define a default delivery policy for any HTTP based consumers + +```yaml +channels: + user-signedup: + description: A user has signed up for our service + bindings: + sns: + policy: + statements: + - effect : Allow + principal: * + action: SNS:Publish + subscribe: + operationId: sendMessage + description: send messages to the topic + bindings: + sns: + deliveryPolicy: + minDelayTarget: 1 + maxDelayTarget: 60 + numRetries: 50 + numNoDelayRetries: 3 + numMinDelayRetries: 2 + numMaxDelayRetries: 35 + backoffFunction: exponential + maxReceivesPerSecond: 10 +``` + +We are consuming an SNS channel, using an HTTP endpoint, which is defined in this AsyncAPI file. For brevity we do not show an http endpoint here. The delivery policy here is defined for the http consumer and overrides any policy set by the producer + +```yaml +channels: + user-signedup: + description: A user has signed up for our service + bindings: + sns: {} # Indicates that the channel is an SNS Topic, but assumes defined by producer + publish: + operationId: receiveMessage + description: receive messages from the topic + bindings: + sns: + - protocol: http + endpoint: + url: http://login.my.com/user/new + filterPolicy: + reason: + anything-but: password-reset + filterPolicyScope: MessageBody + deliveryPolicy: + minDelayTarget: 1 + maxDelayTarget: 120 + numRetries: 30 + numNoDelayRetries: 3 + numMinDelayRetries: 2 + numMaxDelayRetries: 25 + backoffFunction: exponential + maxReceivesPerSecond: 20 + redrivePolicy: + deadLetterQueue: + name: user-signedup-queue-dlq # refers toa queue defined in this file, but not show in this example +``` + + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. \ No newline at end of file diff --git a/markdown/docs/reference/bindings/3.0.0.md b/markdown/docs/reference/bindings/3.0.0.md new file mode 100644 index 000000000000..46b9101d4d60 --- /dev/null +++ b/markdown/docs/reference/bindings/3.0.0.md @@ -0,0 +1,332 @@ +--- +title: '3.0.0' +weight: 27 +--- + +# SNS Bindings + +This document defines how to describe SNS-specific information on AsyncAPI. + + + +## Version + +Current version is `1.0.0`. + + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Channel Binding Object + +This object contains information about the channel representation in SNS. + +We represent an AsyncAPI Channel with a Topic in SNS. The bindings here allow definition of a topic within SNS. We provide properties on the binding that allow creation of a topic in infrastructure-as-code scenarios. Be aware that although the binding offers that flexibility, it may be more maintainable to specify properties such as SNS Access Control Policy outside of AsyncAPI. + +SNS supports many optional properties. To mark a channel as SNS, but use default values for the channel properties, just use an empty object {}. + +### Fields + +|Field Name | Type | Description| +|---|:---:|---| +| `name` | string | **Required.** The name of the topic. Can be different from the channel name to allow flexibility around AWS resource naming limitations.| +| `ordering` | [ordering](#ordering)| **Optional.** By default, we assume an unordered SNS topic. This field allows configuration of a FIFO SNS Topic. | +| `policy` |[policy](#policy) | **Optional.** The security policy for the SNS Topic | +| `tags` |Object | **Optional.** Key-value pairs that represent AWS tags on the topic. | +|`bindingVersion` | string | **Optional**, defaults to `latest`. The version of this binding.| + +### Schemas + +#### Ordering +|Field Name | Type | Description| +|---|:---:|---| +| `type` | string | **Required.** Defines the type of SNS Topic. Can be either `standard` or `FIFO`. | +| `contentBasedDeduplication` | boolean | **Optional.** Whether the de-duplication of messages should be turned on. Defaults to `false`| + +#### Policy +|Field Name | Type | Description| +|---|:---:|---| +| `statements` | [[Statement](#statement)] | **Required.** An array of Statement objects, each of which controls a permission for this topic | + +#### Statement +|Field Name | Type | Description| +|---|:---:|---| +| `effect` | string |**Required.** Either "Allow" or "Deny"| +| `principal` | string or AWS principal property containing a string or string array |**Required.** The AWS account(s) or resource ARN(s) that the statement applies to| +| `action` | string or array of string |**Required.** The SNS permission being allowed or denied e.g. sns:Publish| +| `resource` | string or array of string |**Optional.** The resource(s) that this policy applies to| +| `condition` | object or list of objects |**Optional.** Specific circumstances under which the policy grants permission| + +##### Examples + +Just use defaults + +```yaml +channels: + user-signedup: + description: A user has signed up to our service + bindings: + sns: {} +``` + +Minimal definition, just policy + +```yaml +channels: + user-signedup: + description: A user has signed up to our service + bindings: + sns: + policy: + statements: + - effect : Allow + principal: * + action: SNS:Publish +``` + + + +## Operation Binding Object + +This object contains information operation binding in SNS. + +We represent SNS producers via a **subscribe** Operation Object. In simple cases this may not require configuration, and can be shown as an empty SNS Binding Object i.e. {} if you need to explicitly indicate how a producer publishes to the channel. + +SNS consumers need an SNS Subscription that defines how they consume from SNS i.e. the protocol that they use, and any filters applied. + +The SNS binding does not describe the receiver.If you wish to define the receiver, add an Operation Binding Object for that receiver. For example, if you send message to an SQS queue from an SNS Topic, you would add a protocol of 'sqs' and an Identifier object for the queue. That identifier could be an ARN of a queue defined outside of the scope of AsyncAPI, but if you wanted to define the receiver you would use the name of a queue defined in an SQS Binding in the Operation Binding Object. + +We support an array of consumers via the **consumers** field. This allows you to represent multiple protocols consuming an SNS Topic in one file. You may also use it for multiple consumers with the same protocol, instead of representing each consumer in a separate file. + +### Fields + +| Field Name | Type | Applies To | Description | +|---|:---:|:---:|---| +| `topic` | [identifier](#identifier) |send, receive| **Optional.** Often we can assume that the SNS Topic is the channel name-we provide this field in case the you need to supply the ARN, or the Topic name is not the channel name in the AsyncAPI document.| +| `consumers` | [[Consumer](#consumer)] |receive| **Required.** The protocols that listen to this topic and their endpoints.| +| `deliveryPolicy` | [deliveryPolicy](#delivery-policy) |send| **Optional.** Policy for retries to HTTP. The field is the default for HTTP receivers of the [SNS Topic](https://docs.aws.amazon.com/sns/latest/api/API_CreateTopic.html) which may be overridden by a specific consumer.| +|`bindingVersion` | string |send, receive| **Optional**, defaults to `latest`. The version of this binding.| + +### Schemas + +#### Consumer + +| Field Name | Type | Description | +|---|:---:|---| +| `protocol` | string | **Required.** The protocol that this endpoint receives messages by. Can be `http`, `https`, `email`, `email-json`, `sms`, `sqs`, `application`, `lambda` or `firehose` | +| `endpoint` |[identifier](#identifier)| **Required.** The endpoint messages are delivered to. | +| `filterPolicy` | object | **Optional.** Only receive a subset of messages from the channel, determined by this policy. | +| `filterPolicyScope` | string | **Optional.** Determines whether the FilterPolicy applies to MessageAttributes (default) or MessageBody. | +| `rawMessageDelivery` | boolean | **Required.** If *true* AWS SNS attributes are removed from the body, and for SQS, SNS message attributes are copied to SQS message attributes. If *false* the SNS attributes are included in the body. | +| `redrivePolicy` | [redrivePolicy](#redrive-policy) | **Optional.** Prevent poison pill messages by moving un-processable messages to an SQS dead letter queue. | +| `deliveryPolicy` | [deliveryPolicy](#delivery-policy) | **Optional.** Policy for retries to HTTP. The parameter is for that [SNS Subscription](https://docs.aws.amazon.com/sns/latest/api/API_Subscribe.html) and overrides any policy on the [SNS Topic](https://docs.aws.amazon.com/sns/latest/api/API_CreateTopic.html). | +| `displayName` | string |**Optional.** The display name to use with an SMS subscription | + + +#### Delivery Policy +|Field Name | Type | Description| +|---|:---:|---| +| `minDelayTarget` | integer | **Optional.** The minimum delay for a retry in seconds | +| `maxDelayTarget` | integer | **Optional.** The maximum delay for a retry in seconds | +| `numRetries` | integer | **Optional.** The total number of retries, including immediate, pre-backoff, backoff, and post-backoff retries | +| `numNoDelayRetries` | integer | **Optional.** The number of immediate retries (with no delay) | +| `numMinDelayRetries` | integer | **Optional.** The number of immediate retries (with delay) | +| `numMaxDelayRetries` | integer | **Optional.** The number of post-backoff phase retries, with the maximum delay between retries | +| `backoffFunction` | string, one of: arithmetic, exponential, geometric or linear | **Optional.** The algorithm for backoff between retries | +| `maxReceivesPerSecond` | integer | **Optional.** The maximum number of deliveries per second, per subscription | + +#### Identifier +|Field Name | Type | Description| +|---|:---:|---| +|`url` |string| **Optional.** The endpoint is a URL | +|`email` |string| **Optional.** The endpoint is an email address | +|`phone` |string| **Optional.** The endpoint is a phone number| +|`arn` |string| **Optional.** The target is an [ARN](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html). For example, for SQS, the identifier may be an ARN, which will be of the form: "[arn:aws:sqs:\{region\}:\{account-id\}:\{queueName\}](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)"| +|`name` |string| **Optional.** The endpoint is identified by a name, which corresponds to an identifying field called 'name' of a binding for that protocol on the Operation Object. For example, if the protocol is 'sqs' then the name refers to the name field **sqs** binding. We don't use $ref because we are referring, not including. | + +We provide an Identifer Object to support providing the identifier of an externally defined endpoint for this SNS *publication* to target, or an endpoint on another binding against this Operation Object (via the name field). + +#### Redrive Policy + +|Field Name | Type | Description| +|---|:---:|---| +| `deadLetterQueue` |[Identifier](#identifier)| **Required.** The SQS queue to use as a dead letter queue (DLQ). Note that you may have a Redrive Policy to put messages that cannot be delivered to an SQS queue, even if you use another protocol to consume messages from the queue, so it is defined at the level of the SNS Operation Binding Object in a Consumer Object (and is applied as part of an [SNS Subscription](https://docs.aws.amazon.com/sns/latest/dg/sns-create-subscribe-endpoint-to-topic.html)). The SQS Binding describes how to define an SQS Binding that supports defining the target SQS of the Redrive Policy. | +| `maxReceiveCount` |integer| **Optional.** The number of times a message is delivered to the source queue before being moved to the dead-letter queue. Defaults to 10. | + +### Examples + +#### SNS to SQS Pub-Sub + +[](SNS-SQS-Pub-Sub.png) + +We are producing to an SNS channel + +```yaml +channels: + userSignedUp: + description: A user has signed up for our service + binding : + sns: {} # Indicates that the channel is an SNS Topic +operations: + userSignedUp: + description: A user has signed up for our service + operationId: sendMessage + description: send messages to the topic + action: send + binding: + sns: + consumers: + - protocol: sqs + endpoint: + name: myQueue + rawMessageDelivery: false + channel: + $ref: '#/channels/userSignedUp' +``` + +We are consuming an SNS channel, using an SQS queue. A separate file specifies the producer, and has the SNS Bindings for the channel. For this reason we do not repeat the SNS binding information for the channel here, to avoid duplicated definitions diverging. Instead we just define the Operation Binding. + +In this version, the SQS queue is defined elsewhere, and we just reference via its ARN. It is worth noting that this couples the specification to the AWS *region* and *account*, which are part of the ARN, and if we moved the queue to a new region or account was this specification would need to be updated to reflect that. + + +```yaml +channels: + userSignedUp: + # ...(redacted for brevity) +operations: + userSignedUp: + description: A user has signed up for our service + operationId: receiveMessage + description: receive messages from the topic + action: receive + bindings: + sns: + consumers: + - protocol: sqs + endpoint: + arn: arn:aws:sqs:us-west-2:123456789012:UserSignedUpQueue + rawMessageDelivery: true + channel: + $ref: '#/channels/userSignedUp' +``` + +We are consuming an SNS channel, using an SQS queue. A separate file specifies the producer, and has the SNS Bindings for the channel. For this reason we do not repeat the SNS binding information for the channel here, to avoid duplicated definitions diverging. Instead we just define the Operation Binding. + +In this version, the SQS queue is defined in this file, and we reference it by name. For brevity that definition is not shown here. See the SQS Binding Object for more. + +```yaml +channels: + userSignedUp: + # ...(redacted for brevity) +operations: + userSignedUp: + description: A user has signed up for our service + operationId: receiveMessage + description: receive messages from the topic + action: receive + bindings: + sns: + consumers: + - protocol: sqs + endpoint: + name: user-signedup-queue # refers to a queue defined in this file, but not shown in this example + rawMessageDelivery: true + filterPolicy: + reason: + anything-but: password-reset + redrivePolicy: + deadLetterQueue: + name: user-signedup-queue-dlq # refers to a queue defined in this file, but not show in this example + channel: + $ref: '#/channels/userSignedUp' +``` + +#### SNS to HTTP Pub Sub + +[](SNS-HTTP.png) + +We are producing to an SNS channel. + +In this version, we define a default delivery policy for any HTTP based consumers + +```yaml +channels: + userSignedUp: + description: A user has signed up for our service + bindings: + sns: + policy: + statements: + - effect : Allow + principal: * + action: SNS:Publish +operations: + userSignedUp: + description: A user has signed up for our service + operationId: sendMessage + description: send messages to the topic + action: send + binding: + sns: + deliveryPolicy: + minDelayTarget: 1 + maxDelayTarget: 60 + numRetries: 50 + numNoDelayRetries: 3 + numMinDelayRetries: 2 + numMaxDelayRetries: 35 + backoffFunction: exponential + maxReceivesPerSecond: 10 + channel: + $ref: '#/channels/userSignedUp' +``` + +We are consuming an SNS channel, using an HTTP endpoint, which is defined in this AsyncAPI file. For brevity we do not show an http endpoint here. The delivery policy here is defined for the http consumer and overrides any policy set by the producer + +```yaml +channels: + userSignedUp: + description: A user has signed up for our service + bindings: + sns: {} # Indicates that the channel is an SNS Topic, but assumes defined by producer +operations: + userSignedUp: + description: A user has signed up for our service + operationId: receiveMessage + description: receive messages from the topic + action: receive + bindings: + sns: + - protocol: http + endpoint: + url: http://login.my.com/user/new + filterPolicy: + reason: + anything-but: password-reset + filterPolicyScope: MessageBody + deliveryPolicy: + minDelayTarget: 1 + maxDelayTarget: 120 + numRetries: 30 + numNoDelayRetries: 3 + numMinDelayRetries: 2 + numMaxDelayRetries: 25 + backoffFunction: exponential + maxReceivesPerSecond: 20 + redrivePolicy: + deadLetterQueue: + name: user-signedup-queue-dlq # refers to a queue defined in this file, but not show in this example + channel: + $ref: '#/channels/userSignedUp' +``` + + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. diff --git a/markdown/docs/reference/bindings/_section.md b/markdown/docs/reference/bindings/_section.md index 1b810dd42e3d..d2405cd9f71a 100644 --- a/markdown/docs/reference/bindings/_section.md +++ b/markdown/docs/reference/bindings/_section.md @@ -1,4 +1,4 @@ --- title: Bindings -weight: 15 ---- +weight: 11 +--- \ No newline at end of file diff --git a/markdown/docs/reference/bindings/amqp.md b/markdown/docs/reference/bindings/amqp.md new file mode 100644 index 000000000000..c6357f14942c --- /dev/null +++ b/markdown/docs/reference/bindings/amqp.md @@ -0,0 +1,159 @@ +--- +title: 'amqp' +weight: 11 +--- + +# AMQP 0-9-1 Bindings + +This document defines how to describe AMQP-specific information on AsyncAPI. + + + +## Version + +Current version is `0.3.0`. + + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + + +## Channel Binding Object + +This object contains information about the channel representation in AMQP. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +`is` | string | Defines what type of channel is it. Can be either `queue` or `routingKey` (default). +`exchange` | Map[string, any] | When `is`=`routingKey`, this object defines the exchange properties. +`exchange.name` | string | The name of the exchange. It MUST NOT exceed 255 characters long. +`exchange.type` | string | The type of the exchange. Can be either `topic`, `direct`, `fanout`, `default` or `headers`. +`exchange.durable` | boolean | Whether the exchange should survive broker restarts or not. +`exchange.autoDelete` | boolean | Whether the exchange should be deleted when the last queue is unbound from it. +`exchange.vhost` | string | The virtual host of the exchange. Defaults to `/`. +`queue` | Map[string, any] | When `is`=`queue`, this object defines the queue properties. +`queue.name` | string | The name of the queue. It MUST NOT exceed 255 characters long. +`queue.durable` | boolean | Whether the queue should survive broker restarts or not. +`queue.exclusive` | boolean | Whether the queue should be used only by one connection or not. +`queue.autoDelete` | boolean | Whether the queue should be deleted when the last consumer unsubscribes. +`queue.vhost` | string | The virtual host of the queue. Defaults to `/`. +`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. + +This object MUST contain only the properties defined above. + +##### Example + +```yaml +channels: + userSignup: + address: 'user/signup' + bindings: + amqp: + is: routingKey + exchange: + name: myExchange + type: topic + durable: true + autoDelete: false + vhost: / + bindingVersion: 0.3.0 +``` + +```yaml +channels: + userSignup: + address: 'user/signup' + bindings: + amqp: + is: queue + queue: + name: my-queue-name + durable: true + exclusive: true + autoDelete: false + vhost: / + bindingVersion: 0.3.0 +``` + + + +## Operation Binding Object + +This object contains information about the operation representation in AMQP. + +##### Fixed Fields + +Field Name | Type | Applies To Action | Description +---|:---:|:---:|--- +`expiration` | integer | `receive`, `send` | TTL (Time-To-Live) for the message. It MUST be greater than or equal to zero. +`userId` | string | `receive`, `send` | Identifies the user who has sent the message. +`cc` | [string] | `receive`, `send` | The routing keys the message should be routed to at the time of publishing. +`priority` | integer | `receive`, `send` | A priority for the message. +`deliveryMode` | integer | `receive`, `send` | Delivery mode of the message. Its value MUST be either 1 (transient) or 2 (persistent). +`mandatory` | boolean | `receive` | Whether the message is mandatory or not. +`bcc` | [string] | `receive` | Like [cc](#operationBindingObjectCC) but consumers will not receive this information. +`timestamp` | boolean | `receive`, `send` | Whether the message should include a timestamp or not. +`ack` | boolean | Subscribe | Whether the consumer should ack the message or not. +`bindingVersion` | string | `receive`, `send` | The version of this binding. If omitted, "latest" MUST be assumed. + +This object MUST contain only the properties defined above. + +##### Example + +```yaml +operations: + userSignup: + channel: + $ref: '#/channels/userSignup' + bindings: + amqp: + expiration: 100000 + userId: guest + cc: ['user.logs'] + priority: 10 + deliveryMode: 2 + mandatory: false + bcc: ['external.audit'] + timestamp: true + ack: false + bindingVersion: 0.3.0 +``` + + + + +## Message Binding Object + +This object contains information about the message representation in AMQP. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +`contentEncoding` | string | A MIME encoding for the message content. +`messageType` | string | Application-specific message type. +`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. + +This object MUST contain only the properties defined above. + +```yaml +channels: + userSignup: + address: 'user/signup' + messages: + userSignupMessage: + bindings: + amqp: + contentEncoding: gzip + messageType: 'user.signup' + bindingVersion: 0.3.0 +``` diff --git a/markdown/docs/reference/bindings/amqp1.md b/markdown/docs/reference/bindings/amqp1.md new file mode 100644 index 000000000000..1fb456b3f9ab --- /dev/null +++ b/markdown/docs/reference/bindings/amqp1.md @@ -0,0 +1,42 @@ +--- +title: 'amqp1' +weight: 12 +--- + +# AMQP 1.0 Bindings + +This document defines how to describe AMQP 1.0-specific information on AsyncAPI. + + + +## Version + +Current version is `0.1.0`. + + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + + +## Channel Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Operation Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. diff --git a/markdown/docs/reference/bindings/anypointmq.md b/markdown/docs/reference/bindings/anypointmq.md new file mode 100644 index 000000000000..2c8d3efa40a1 --- /dev/null +++ b/markdown/docs/reference/bindings/anypointmq.md @@ -0,0 +1,244 @@ +--- +title: 'anypointmq' +weight: 13 +--- + +# Anypoint MQ Bindings + +This document defines how to describe Anypoint MQ-specific information in AsyncAPI documents. + +[Anypoint MQ](https://docs.mulesoft.com/mq/) is MuleSoft's multi-tenant, cloud messaging service and is fully integrated with [Anypoint Platform](https://www.mulesoft.com/platform/enterprise-integration). + + +## Versions + +The version of this bindings specification is `0.1.0`. +This is also the `bindingVersion` for all binding objects defined by this specification. +In any given binding object, `latest` MAY alternatively be used to refer to the currently latest published version of this bindings specification. + +## Terminology + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this bindings specification are to be interpreted as described in IETF [RFC2119](https://www.ietf.org/rfc/rfc2119.txt). + +## Protocol + +These bindings use the `anypointmq` [protocol](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#definitionsProtocol) in AsyncAPI documents to denote connections to and interactions with Anypoint MQ message brokers. + +The Anypoint MQ protocol is based on invocations of the [Anypoint MQ Broker REST API](https://anypoint.mulesoft.com/exchange/portals/anypoint-platform/f1e97bc6-315a-4490-82a7-23abe036327a.anypoint-platform/anypoint-mq-broker/). + +## Server Object + +The fields of the standard [Server Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#serverObject) are constrained and interpreted as follows: + +Server Object Field Name | Values for Anypoint MQ Protocol | Description +---|:---|:--- +`protocol` | `anypointmq` | **REQUIRED**. MUST be `anypointmq` for the scope of this specification. +`host` | e.g., `https://mq-us-east-1.anypoint.mulesoft.com` | **REQUIRED**. MUST be the endpoint HOST part of the URL of the Anypoint MQ Broker REST API. Valid examples are `https://mq-us-east-1.anypoint.mulesoft.com` and `https://mq-eu-central-1.eu1.anypoint.mulesoft.com` (and _not_ `https://mq-us-east-1.anypoint.mulesoft.com/api`, or `https://.../api/v1`). +`pathname` | e.g., `/api` | **REQUIRED**. MUST be the endpoint path part of the URL of the Anypoint MQ Broker REST API _excluding_ the final major version indicator (e.g., `v1`). Valid examples are `/api` and (and _not_ `https://.../api/v1`). +`protocolVersion` | e.g., `v1` | **OPTIONAL**, defaults to `v1`. If present MUST be the major version indicator of the Anypoint MQ Broker REST API omitted from the `url`, e.g. `v1`. +`security` | suitably configured OAuth 2.0 client credentials grant type | **REQUIRED**. Authentication against the MuleSoft-hosted Anypoint MQ message brokers uses the OAuth 2.0 client credentials grant type. At runtime, the client ID and client secret values of an Anypoint MQ client app must be supplied. Also, the OAuth 2.0 scopes are currently not client-configurable. The `security` field of the server object MUST correctly match these constraints. + +Note that the choice of a particular Anypoint MQ client app (via its client ID and secret) decides the Anypoint Platform organization ID and environment (ID) to be those in which this client app is defined. See the [Anypoint MQ documentation](https://docs.mulesoft.com/mq/mq-client-apps) for details on how to configure Anypoint MQ client apps. + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + +## Channel Binding Object + +The Anypoint MQ [Channel Binding Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#channel-bindings-object) is defined by a [JSON Schema](json_schemas/channel.json), which defines these fields: + +Field Name | Type | Description +---|:---:|--- +`destination` | string | **OPTIONAL**, defaults to the channel name. The destination (queue or exchange) name for this channel. SHOULD only be specified if the channel name differs from the actual destination name, such as when the channel name is not a valid destination name in Anypoint MQ. +`destinationType` | string | **OPTIONAL**, defaults to `queue`. The type of destination, which MUST be either `exchange` or `queue` or `fifo-queue`. SHOULD be specified to document the messaging model (publish/subscribe, point-to-point, strict message ordering) supported by this channel. +`bindingVersion` | string | **OPTIONAL**, defaults to `latest`. The version of this binding. + +Note that an Anypoint MQ exchange can only be sent to, not received from. To receive messages sent to an exchange, [an intermediary queue must be defined and bound to the exchange](https://docs.mulesoft.com/mq/mq-understanding#message-exchanges). In this bindings specification, these intermediary queues are not exposed in the AsyncAPI document. Instead, it is simply assumed that whenever messages must be received from an exchange, such an intermediary queue is involved yet invisible in the AsyncAPI document. + +### Examples + +The following example shows two channels where does not apply any bindings and the second one applying `anyointmq` bindings. + +```yaml +channels: + userSignup: + address: 'user/signup' + description: | + This application receives command messages from this channel about users to sign up. + Minimal configuration, omitting a channel binding object. + messages: + #... + + userSignup: + address: 'user/signup' + description: | + This application sends events to this channel about users that have signed up. + Explicitly provides a channel binding object. + messages: + #... + bindings: + anypointmq: + destination: user-signup-exchg + destinationType: exchange + bindingVersion: '0.1.0' +``` + + +## Operation Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + +## Message Binding Object + +The Anypoint MQ [Message Binding Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#message-bindings-object) defines these fields: + +Field Name | Type | Description +---|:---:|--- +`headers` | [Schema Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject) \| [Reference Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#referenceObject) | **OPTIONAL**. A Schema object containing the definitions for Anypoint MQ-specific headers (so-called protocol headers). This schema MUST be of type `object` and have a `properties` key. Examples of Anypoint MQ protocol headers are `messageId` and `messageGroupId`. +`bindingVersion` | string | **OPTIONAL**, defaults to `latest`. The version of this binding. + +Note that application headers must be specified in the [`headers` field of the standard Message Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#messageObjectHeaders) and are transmitted in the [`properties` section of the Anypoint MQ message](https://anypoint.mulesoft.com/exchange/portals/anypoint-platform/f1e97bc6-315a-4490-82a7-23abe036327a.anypoint-platform/anypoint-mq-broker/). +In contrast, protocol headers such as `messageId` must be specified in the [`headers` field of the message binding object](#messageBindingObjectHeaders) and are transmitted in the [`headers` section of the Anypoint MQ message](https://anypoint.mulesoft.com/exchange/portals/anypoint-platform/f1e97bc6-315a-4490-82a7-23abe036327a.anypoint-platform/anypoint-mq-broker/). + +### Examples + +The following example shows a `channels` object with two channels, each having one operation (`subscribe` or `publish`) with one message. Only the message of the `subscribe` operation has a message binding object for `anypointmq`: + +```yaml +channels: + userSignup: + address: 'user/signup' + messages: + #... + userSignup: + address: 'user/signup' + messages: + userSignupMessage: + headers: + type: object + properties: + correlationId: + description: Correlation ID set by application + type: string + payload: + type: object + properties: + #... + correlationId: + description: Correlation ID is specified as a header and transmitted in the Anypoint MQ message properties section + location: $message.header#/correlationId + bindings: + anypointmq: + headers: + type: object + properties: + messageId: + type: string + bindingVersion: '0.1.0' +``` + +## Complete Example + +The following is a complete, simple AsyncAPI document illustrating the usage of all binding objects defined in this bindings specification, with all their fields. + +```yaml +asyncapi: 3.0.0 +info: + title: Example with Anypoint MQ + version: 0.0.1 +servers: + development: + host: mq-us-east-1.anypoint.mulesoft.com + pathname: /api + protocol: anypointmq + protocolVersion: v1 + description: > + Anypoint MQ broker for development, in the US East (N. Virginia) runtime + plane + + under management of the US control plane. + security: + - $ref: '#/components/securitySchemes/oauthDev' + production: + host: mq-eu-central-1.eu1.anypoint.mulesoft.com + pathname: /api + protocol: anypointmq + protocolVersion: v1 + description: > + Anypoint MQ broker for production, in the EU Central (Frankfurt) runtime + plane + + under management of the EU control plane. + security: + - $ref: '#/components/securitySchemes/oauthProd' + bindings: + anypointmq: + bindingVersion: 0.1.0 +channels: + user/signup: + address: user/signup + messages: + signUpUser.message: + contentType: application/json + headers: + type: object + properties: + correlationId: + description: Correlation ID set by application + type: string + payload: + type: object + properties: + username: + type: string + minLength: 3 + correlationId: + description: >- + Correlation ID is specified as a header and transmitted in the + Anypoint MQ message properties section + location: $message.header#/correlationId + bindings: + anypointmq: + headers: + type: object + properties: + messageId: + type: string + bindingVersion: 0.1.0 + description: > + This application receives command messages from this channel about users + to sign up. + bindings: + anypointmq: + destination: user-signup-queue + destinationType: fifo-queue + bindingVersion: 0.1.0 +operations: + signUpUser: + action: receive + channel: + $ref: '#/channels/user~1signup' + description: > + This application receives command messages via this operation about users + to sign up. + messages: + - $ref: '#/channels/user~1signup/messages/signUpUser.message' +components: + securitySchemes: + oauthDev: + type: oauth2 + flows: + clientCredentials: + tokenUrl: 'https://mq-us-east-1.anypoint.mulesoft.com/api/v1/authorize' + scopes: {} + oauthProd: + type: oauth2 + flows: + clientCredentials: + tokenUrl: 'https://mq-eu-central-1.eu1.anypoint.mulesoft.com/api/v1/authorize' + scopes: {} +``` diff --git a/markdown/docs/reference/bindings/googlepubsub.md b/markdown/docs/reference/bindings/googlepubsub.md new file mode 100644 index 000000000000..c40d92e9a0ba --- /dev/null +++ b/markdown/docs/reference/bindings/googlepubsub.md @@ -0,0 +1,179 @@ +--- +title: 'googlepubsub' +weight: 14 +--- + +# Google Cloud Pub/Sub Bindings + +This document defines how to describe Google Cloud Pub/Sub specific information with AsyncAPI. + + + +## Version + +Current version is `0.2.0`. + + + +## Channel Binding Object + +The `Channel Bindings Object` is used to describe the Google Cloud Pub/Sub specific +[Topic](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/create) details with AsyncAPI. + +Field Name | Type | Description +---|---|--- +`bindingVersion`|String|The current version is `0.2.0` +`labels`|Object|An object of key-value pairs _(These are used to categorize Cloud Resources like Cloud Pub/Sub Topics.)_ +`messageRetentionDuration`|String|Indicates the minimum duration to retain a message after it is published to the topic _(Must be a valid [Duration](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Duration).)_ +`messageStoragePolicy`|[Message Storage Policy Object](#message-storage-policy-object)|Policy constraining the set of Google Cloud Platform regions where messages published to the topic may be stored +`schemaSettings`|[Schema Settings Object](#schema-settings-object)|Settings for validating messages published against a schema + + + +### Message Storage Policy Object + +The `Message Storage Policy Object` is used to describe the Google Cloud Pub/Sub +[MessageStoragePolicy](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics#MessageStoragePolicy) +Object with AsyncAPI. + +Field Name | Type | Description +---|---|--- +`allowedPersistenceRegions`|String[]|A list of IDs of GCP regions where messages that are published to the topic may be persisted in storage + + + +### Schema Settings Object + +The `Schema Settings Object` is used to describe the Google Cloud Pub/Sub +[SchemaSettings](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics#SchemaSettings) Object with +AsyncAPI. + +Field Name | Type | Description +---|---|--- +`encoding`|String|The encoding of the message _(Must be one of the possible [Encoding](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics#encoding) values.)_ +`firstRevisionId`|String|The minimum _(inclusive)_ revision allowed for validating messages +`lastRevisionId`|String|The maximum _(inclusive)_ revision allowed for validating messages +`name`|String|The name of the schema that messages published should be validated against _(The format is `projects/{project}/schemas/{schema}`.)_ + + + +### Example + +```yaml +# ... +channels: + topic-avro-schema: + address: projects/your-project/topics/topic-avro-schema + bindings: + googlepubsub: + schemaSettings: + encoding: json + name: projects/your-project/schemas/message-avro +# ... + topic-proto-schema: + address: projects/your-project/topics/topic-proto-schema + bindings: + googlepubsub: + messageRetentionDuration: 86400s + messageStoragePolicy: + allowedPersistenceRegions: + - us-central1 + - us-central2 + - us-east1 + - us-east4 + - us-east5 + - us-east7 + - us-south1 + - us-west1 + - us-west2 + - us-west3 + - us-west4 + schemaSettings: + encoding: binary + name: projects/your-project/schemas/message-proto +# ... +``` + + + +## Message Binding Object + +The `Message Binding Object` is used to describe the Google Cloud Pub/Sub specific +[PubsubMessage](https://cloud.google.com/pubsub/docs/reference/rest/v1/PubsubMessage) details, alongside with pertintent +parts of the Google Cloud Pub/Sub +[Schema](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.schemas#Schema) +Object, with AsyncAPI. + +Field Name | Type | Description +---|---|--- +`bindingVersion`|String|The current version is `0.2.0` +`attributes`|Object|Attributes for this message _(If this field is empty, the message must contain non-empty data. This can be used to filter messages on the subscription.)_ +`orderingKey`|String|If non-empty, identifies related messages for which publish order should be respected _(For more information, see [ordering messages](https://cloud.google.com/pubsub/docs/ordering).)_ +`schema`|[Schema Definition Object](#schema-definition-object)|Describes the schema used to validate the payload of this message + + + +### Schema Definition Object + +The `Schema Definition Object` is used to describe the Google Cloud Pub/Sub +[Schema]([Schema](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.schemas#Schema)) Object with AsyncAPI. +While some of this information could be, or is, described using native AsyncAPI, for consistency it makes sense to +provide this information here at all times, especially for cases where AsyncAPI does not natively support describing +payloads using a supported Google Cloud Pub/Sub schema format like Protobuf. + +Field Name | Type | Description +---|---|--- +`name`|String|The name of the schema + + + +### Example + +```yaml +# ... +components: + messages: + messageAvro: + bindings: + googlepubsub: + schema: + name: projects/your-project/schemas/message-avro + contentType: application/json + name: MessageAvro + payload: + schema: + fields: + - name: message + type: string + name: Message + type: record + schemaFormat: application/vnd.apache.avro+yaml;version=1.9.0 + messageProto: + bindings: + googlepubsub: + schema: + name: projects/your-project/schemas/message-proto + contentType: application/octet-stream + name: MessageProto + payload: + schema: | + syntax = "proto3"; + + message Message { + required string message = 1; + } + schemaFormat: application/vnd.google.protobuf;version=3 +# ... +``` + + + +## Operation Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. diff --git a/markdown/docs/reference/bindings/http.md b/markdown/docs/reference/bindings/http.md new file mode 100644 index 000000000000..bf275a01f497 --- /dev/null +++ b/markdown/docs/reference/bindings/http.md @@ -0,0 +1,103 @@ +--- +title: 'http' +weight: 15 +--- + +# HTTP Bindings + +This document defines how to describe HTTP-specific information on AsyncAPI. + + + +## Version + +Current version is `0.3.0`. + + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Channel Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Operation Binding Object + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +`method` | string | The HTTP method for the request. Its value MUST be one of `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, `OPTIONS`, `CONNECT`, and `TRACE`. +`query` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) | A Schema object containing the definitions for each query parameter. This schema MUST be of type `object` and have a `properties` key. +`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. + +This object MUST contain only the properties defined above. + +##### Example + +```yaml +channels: + employees: + address: /employees +operations: + employees: + action: send + bindings: + http: + method: GET + query: + type: object + required: + - companyId + properties: + companyId: + type: number + minimum: 1 + description: The Id of the company. + additionalProperties: false + bindingVersion: '0.3.0' +``` + + + +## Message Binding Object + +This object contains information about the message representation in HTTP. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +`headers` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) | A Schema object containing the definitions for HTTP-specific headers. This schema MUST be of type `object` and have a `properties` key. +`statusCode` | number | The HTTP response status code according to [RFC 9110](https://httpwg.org/specs/rfc9110.html#overview.of.status.codes). `statusCode` is only relevant for messages referenced by the [Operation Reply Object](https://www.asyncapi.com/docs/reference/specification/v3.0.0#operationReplyObject), as it defines the status code for the response. In all other cases, this value can be safely ignored. +`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. + +This object MUST contain only the properties defined above. + +```yaml +channels: + test: + address: /test + messages: + testMessage: + bindings: + http: + statusCode: 200 + headers: + type: object + properties: + Content-Type: + type: string + enum: ['application/json'] + bindingVersion: '0.3.0' +``` + +[schemaObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject +[referenceObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#referenceObject diff --git a/markdown/docs/reference/bindings/ibmmq.md b/markdown/docs/reference/bindings/ibmmq.md new file mode 100644 index 000000000000..39751641f22b --- /dev/null +++ b/markdown/docs/reference/bindings/ibmmq.md @@ -0,0 +1,328 @@ +--- +title: 'ibmmq' +weight: 16 +--- + +# IBM MQ Bindings + +This document defines how to describe IBM MQ specific information with AsyncAPI. + + + +## Version + +Current version is `0.1.0`. + +## Terminology + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this bindings specification are to be interpreted as described in IETF [RFC2119](https://www.ietf.org/rfc/rfc2119.txt). + +## AsyncAPI considerations + +This specification binding requests that the AsyncAPI specification reserve the IBM MQ protocol to allow connections to queue manager endpoints to be defined within the server object. + +AsyncAPI Object Fixed Field Name | Reserved Value for IBM MQ Protocol | Description +---|:---|:--- +`server.protocol` | ibmmq | IBM MQ protocol. +`server.protocol` | ibmmq-secure | IBM MQ protocol over TLS. + +## URI scheme considerations + +For the purposes of establishing an IBM MQ binding for use within AsyncAPI, this document defines the URI scheme `ibmmq://` consisting of components and generic URI syntax as specified in [RFC3986](https://tools.ietf.org/html/rfc3986) + +### Defining an IBM MQ queue manager endpoint in the server object `url` field + +When defining an IBM MQ `url` for a queue manager endpoint, the `ibmmq://` URI scheme MUST be used. IBM MQ URIs are defined using the following components. + +URI Component | IBM MQ reference | Applicability | Description | +---|:---|:--|:-- +`scheme` | `ibmmq://` | REQUIRED | The URI scheme used to represent an IBM MQ endpoint. +`authority` | `:port` | REQUIRED | The network IP address or hostname and port of the queue manager endpoint. | +`path` | `queueManager` | OPTIONAL | The queue manager name. If no queue manager name is specified this segment is left undefined, for example `ibmmq://hostname:{port}//CHANNEL.NAME` +`path` | `mqChannelName` | REQUIRED | The `SVRCONN` channel to use for communication with an IBM MQ queue manager. When connecting to a queue manager, IBM MQ partitions this communication into logical channels. + +URI `query` or `fragment` components MUST NOT be used within the `ibmmq://` scheme. Path components that contain characters reserved by RFC2936 such as `/` MUST be percent encoded as defined in [Section 2.2 of RFC2936](https://tools.ietf.org/html/rfc3986#section-2.2). `port` MUST be specified as part of the authority component in the `ibmmq://` scheme. + + +### Defining IBM MQ queue manager endpoints with the AsyncAPI Server Object + +This section defines the convention for how IBM MQ queue manager endpoints are encoded within the AsyncAPI Server Object fields. A `groupId` field has been made available on the IBM MQ AsyncAPI server binding object to allow server objects to be defined as a related collection. This is necessary to group, or cluster, IBM MQ queue manager endpoints within the AsyncAPI specification and where a Client Channel Definition Table ([CCDT](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.con.doc/q132905_.html)) reference is not appropriate. + + +##### Example of two possible MQ servers defined using ibmmq url syntax +```yaml +servers: + production1: + url: ibmmq://qmgr1host:1414/qm1/DEV.APP.SVRCONN + protocol: ibmmq + production2: + url: ibmmq://qmgr2host:1414/qm2/DEV.APP.SVRCONN + protocol: ibmmq +``` + +##### Example of single MQ server defined using ibmmq url syntax and with no queue manager name specified +```yaml +servers: + production: + url: ibmmq://qmgr1host:1414//DEV.APP.SVRCONN + protocol: ibmmq +``` + +## Defining an IBM MQ queue manager endpoint CCDT in the `url` field +When defining a connection to IBM MQ, a CCDT connection file can be specified. The server url will specify the location of the file with additional information contained within the server binding to specify its usage. + +##### Example using an IBM MQ CCDT file url + +```yaml +servers: + production1: + url: 'http://my-ccdt-json-file' + protocol: ibmmq + production2: + url: 'file://myccdt.json' + protocol: ibmmq +``` + + + +## Server Binding Object + +This object contains server connection information about the IBM MQ server, referred to as an IBM MQ queue manager. This object contains additional connectivity information not possible to represent within the core AsyncAPI specification. + +##### Fixed Fields + + +Field Name | Type | Description | Applicability \[default\] | Constraints +---|:---:|---|:---|:--- +`groupId` | string | Defines a logical group of IBM MQ server objects. This is necessary to specify multi-endpoint configurations used in high availability deployments. If omitted, the server object is not part of a group. | OPTIONAL | MUST NOT be specified for URI Scheme `http://` or `file://` +`ccdtQueueManagerName` | string | The name of the IBM MQ queue manager to bind to in the CCDT file. | OPTIONAL [`*`] | MUST NOT be specified for URI Scheme `ibmmq://` +`cipherSpec` | string | The recommended cipher specification used to establish a TLS connection between the client and the IBM MQ queue manager. More information on SSL/TLS cipher specifications supported by IBM MQ can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.dev.doc/q113220_.html) in the IBM MQ Knowledge Center. | OPTIONAL [`ANY`] | MUST NOT be specified for protocol `ibmmq` or URI Scheme `file://` or `http://` +`multiEndpointServer` | boolean | If `multiEndpointServer` is `true` then multiple connections can be workload balanced and applications should not make assumptions as to where messages are processed. Where message ordering, or affinity to specific message resources is necessary, a single endpoint (`multiEndpointServer` = `false`) may be required. | OPTIONAL [`false`] | MUST NOT be specified for URI Scheme `file://` or `http://` +`heartBeatInterval` | integer | The recommended value (in seconds) for the heartbeat sent to the queue manager during periods of inactivity. A value of zero means that no heart beats are sent. A value of `1` means that the client will use the value defined by the queue manager. More information on heart beat interval can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q108450_.html) in the IBM MQ Knowledge Center. | OPTIONAL [`300`] | MUST be `0-999999` +`bindingVersion` | string | The version of this binding. | OPTIONAL [`latest`] | - + +This object MUST contain only the properties defined above. + +##### Example for multiple endpoints defined in the AsyncAPI configuration + +```yaml +servers: + production1: + url: ibmmq://qmgr1host:1414/qm1/DEV.APP.SVRCONN + protocol: ibmmq-secure + description: Production Instance 1 + bindings: + ibmmq: + groupId: PRODCLSTR1 + cipherSpec: ANY_TLS12_OR_HIGHER + bindingVersion: 0.1.0 + production2: + url: ibmmq://qmgr2host:1414/qm2/DEV.APP.SVRCONN + protocol: ibmmq-secure + description: Production Instance 2 + bindings: + ibmmq: + groupId: PRODCLSTR1 + bindingVersion: 0.1.0 +``` + +##### Example using combined strategy + +```yaml +servers: + production: + url: 'http://my-ccdt-json-file' + protocol: ibmmq-secure + description: Production MQ Instance + bindings: + ibmmq: + ccdtQueueManagerName: qm1 + test: + url: ibmmq://qmgrtest:1414/qm2/DEV.APP.SVRCONN + protocol: ibmmq-secure + description: Test MQ Instance + bindings: + ibmmq: + cipherSpec: ANY_TLS12_OR_HIGHER + bindingVersion: 0.1.0 +``` + + + + + +## Channel Binding Object + +This object contains information about the channel representation in IBM MQ. Each channel corresponds to a Queue or Topic within IBM MQ. + +##### Fixed Fields + +Field Name | Type | Description | Applicability [default] | Constraints +---|:---:|---|:---|:--- +`destinationType` | string | Defines the type of AsyncAPI channel. | OPTIONAL [`topic`] | MUST be either `topic` or `queue`. For type `topic`, the AsyncAPI channel name MUST be assumed for the IBM MQ topic string unless overridden. +`queue` | Map[string, any] | Defines the properties of a queue. | REQUIRED if `destinationType` = `queue` | `queue` and `topic` fields MUST NOT coexist within a channel binding +`queue.`
    `objectName` | string | Defines the name of the IBM MQ queue associated with the channel. | REQUIRED | A value MUST be specified. MUST NOT exceed 48 characters in length. MUST be a valid IBM MQ queue name +`queue.`
    `isPartitioned` | boolean | Defines if the queue is a cluster queue and therefore partitioned. If `true`, a binding option MAY be specified when accessing the queue. More information on binding options can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q101870_.html#q101870___BIND_ON_OPEN) in the IBM MQ Knowledge Center. | OPTIONAL [`false`] | If `false`, binding options SHOULD NOT be specified when accessing the queue. +`queue.`
    `exclusive` | boolean | Specifies if it is recommended to open the queue exclusively. | OPTIONAL [`false`] | - +`topic` | Map[string, any] | Defines the properties of a topic. | OPTIONAL if `destinationType` = `topic` | `queue` and `topic` fields MUST NOT coexist within a channel binding. +`topic.`
    `string` | string | The value of the IBM MQ topic string to be used. | OPTIONAL *
    Note: if specified, SHALL override AsyncAPI channel name.* | MUST NOT exceed 10240 characters in length. MAY coexist with `topic.objectName` +`topic.`
    `objectName` | string | The name of the IBM MQ topic object. | OPTIONAL *
    Note: if specified, SHALL override AsyncAPI channel name.*| MUST NOT exceed 48 characters in length. MAY coexist with `topic.string` +`topic.`
    `durablePermitted` | boolean | Defines if the subscription may be durable. | OPTIONAL [`true`] | - +`topic.`
    `lastMsgRetained` | boolean | Defines if the last message published will be made available to new subscriptions. | OPTIONAL [`false`] | - +`maxMsgLength` | integer | The maximum length of the physical message (in bytes) accepted by the Topic or Queue. Messages produced that are greater in size than this value may fail to be delivered. More information on the maximum message length can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.adm.doc/q085520_.html#q085520___maxmsgl) in the IBM MQ Knowledge Center. | OPTIONAL [negotiated on IBM MQ channel]| MUST be `0-104,857,600` bytes (100 MB). +`bindingVersion` | string | The version of this binding. | OPTIONAL [`latest`] | - + + +This object MUST contain only the properties defined above. + +##### Example for an IBM MQ Topic where topic string is defined by AsyncAPI channel + +```yaml +channels: + user/signedup: +``` + +##### Example for AsyncAPI channel mapping to an IBM MQ topic with a specified MQ Topic object + +```yaml +channels: + user/signedup: + bindings: + ibmmq: + destinationType: topic + topic: + objectName: myTopicName + bindingVersion: 0.1.0 +``` + +##### Example for AsyncAPI channel mapping to an IBM MQ Queue + +```yaml +channels: + user/signedup: + bindings: + ibmmq: + destinationType: queue + queue: + objectName: myQueueName + exclusive: true + bindingVersion: 0.1.0 +``` + + + + + +## Operation Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Message Binding Object + +This object contains information about the message representation in IBM MQ. + +##### Fixed Fields + +Field Name | Type | Description | Applicability [default] | Constraints +---|:---:|---|:---|:--- +`type` | string | The type of the message. | OPTIONAL [`string`] | MUST be either `string`, `jms` or `binary` +`headers` | string | Defines the IBM MQ message headers to include with this message. More than one header can be specified as a comma separated list. Supporting information on IBM MQ message formats can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q097520_.html) in the IBM MQ Knowledge Center. | OPTIONAL if `type` = `binary` | `headers` MUST NOT be specified if `type` = `string` or `jms` +`description` | string1 | Provides additional information for application developers: describes the message type or format. | OPTIONAL | - +`expiry` | integer | The recommended setting the client should use for the TTL (Time-To-Live) of the message. This is a period of time expressed in milliseconds and set by the application that puts the message. `expiry` values are API dependant e.g., MQI and JMS use different units of time and default values for *`unlimited`*. General information on IBM MQ message expiry can be found on this [page](https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q097490_.html) in the IBM MQ Knowledge Center. | OPTIONAL [*`unlimited`*] | `expiry` value MUST be either `zero` (*`unlimited`*) or greater than zero. +`bindingVersion` | string | The version of this binding. | OPTIONAL [`latest`] | - + +This object MUST contain only the properties defined above. + +### Rich Text Formatting + +1 The `description` field of the IBM MQ message binding object MAY include CommonMark markdown formatting. A minimum markdown syntax as described by [CommonMark 0.27](https://spec.commonmark.org/0.27/) is assumed. + +##### Example for plain text message + +```yaml +channels: + user/signup: + publish: + message: + bindings: + ibmmq: + type: string + bindingVersion: 0.1.0 +``` + +##### Example for IBM MQ message using JMS + +```yaml +channels: + user/signup: + publish: + message: + bindings: + ibmmq: + type: jms + description: JMS stream message + bindingVersion: 0.1.0 +``` + +# AsyncAPI example with IBM MQ binding + +##### Example for AsyncAPI user signup + +```yaml +asyncapi: 2.0.0 +info: + title: Account Service + version: 1.0.0 + description: This service is in charge of processing user signups +servers: + production1: + url: ibmmq://qmgr1host:1414/qm1/DEV.APP.SVRCONN + protocol: ibmmq-secure + description: Production Instance 1 + bindings: + ibmmq: + groupId: PRODCLSTR1 + cipherSpec: ANY_TLS12_OR_HIGHER + bindingVersion: 0.1.0 + production2: + url: ibmmq://qmgr2host:1414/qm2/DEV.APP.SVRCONN + protocol: ibmmq-secure + description: Production Instance 2 + bindings: + ibmmq: + groupId: PRODCLSTR1 + cipherSpec: ANY_TLS12_OR_HIGHER + bindingVersion: 0.1.0 +channels: + user/signedup: + bindings: + ibmmq: + topic: + durablePermitted: true + bindingVersion: 0.1.0 + subscribe: + message: + $ref: '#/components/messages/UserSignedUp' + bindings: + ibmmq: + type: jms + description: JMS bytes message + bindingVersion: 0.1.0 +components: + messages: + UserSignedUp: + payload: + type: object + properties: + displayName: + type: string + description: Name of the user + email: + type: string + format: email + description: Email of the user +``` \ No newline at end of file diff --git a/markdown/docs/reference/bindings/jms.md b/markdown/docs/reference/bindings/jms.md new file mode 100644 index 000000000000..77239475a0b1 --- /dev/null +++ b/markdown/docs/reference/bindings/jms.md @@ -0,0 +1,163 @@ +--- +title: 'jms' +weight: 17 +--- + +# JMS Bindings + +This document defines how to describe JMS-specific information on AsyncAPI. + + +## Versions + +The version of this bindings specification is `0.0.1`. +This is also the `bindingVersion` for all binding objects defined by this specification. +In any given binding object, `latest` MAY alternatively be used to refer to the currently latest published version of this bindings specification. + +## Terminology + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this bindings specification are to be interpreted as described in IETF [RFC2119](https://www.ietf.org/rfc/rfc2119.txt). + +## Protocol + +These bindings use the `jms` [protocol](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#definitionsProtocol) in AsyncAPI documents to denote connections to and interactions with JMS message brokers. + +JMS is not technically a protocol, rather it is an API. A JMS Provider implements the JMS API and may define a protocol for implementing JMS API operations. Regardless, for the purposes of AsyncAPI we can treat it like a "protocol" to enable AsyncAPI definitions that are somewhat portable between various JMS Providers. If necessary, the user is free to combine this binding with other bindings that implement a JMS Provider (e.g. [Apache Pulsar](https://github.com/asyncapi/bindings/tree/master/pulsar), [Amazon SQS](https://github.com/asyncapi/bindings/tree/master/sqs), [IBM MQ](https://github.com/asyncapi/bindings/tree/master/ibmmq), etc.) to detail JMS Provider specific configuration. + +**NOTE** that from protocol version 3.0, this binding is compatible with [Jakarta Messaging](https://jakarta.ee/specifications/messaging). + +## Server Object + +The fields of the standard [Server Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#serverObject) are constrained and interpreted as follows: + +Server Object Field Name | Values for JMS Protocol | Description +---|:---|:--- +`protocol` | `jms` | **REQUIRED**. MUST be `jms` for the scope of this specification. +`url` | e.g., `jms://host:port` | **REQUIRED**. MUST be a URL containing the hostname and port of a JMS Broker. +`protocolVersion` | e.g., `3.1` | **OPTIONAL**, defaults to `3.1`. If present MUST be the version indicator of the JMS API. Valid values are `1.0`, `1.0.1`, `1.0.1a`, `1.0.2`, `1.0.2a`, `1.0.2b`, `1.1`, `2.0`, `2.0a`, `2.1`, or `3.0`, `3.1.`. + + + + +## Server Binding Object + +The JMS [Server Binding Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#server-bindings-object) is defined by a [JSON Schema](json_schemas/server.json), which defines these fields: + +Field Name | Type | Description +---|:---:|--- +`jmsConnectionFactory` | string | **REQUIRED**. The classname of the [ConnectionFactory](https://docs.oracle.com/javaee/7/api/javax/jms/ConnectionFactory.html) implementation for the JMS Provider. +`properties` | [Schema Array](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaArray) | **OPTIONAL**. Additional properties to set on the JMS ConnectionFactory implementation for the JMS Provider. +`clientID` | string | **OPTIONAL**. A client identifier for applications that use this JMS connection factory. If the Client ID Policy is set to 'Restricted' (the default), then configuring a Client ID on the [ConnectionFactory](https://docs.oracle.com/javaee/7/api/javax/jms/ConnectionFactory.html) prevents more than one JMS client from using a connection from this factory. +`bindingVersion` | string | **OPTIONAL**, defaults to `latest`. The version of this binding. + +### Examples + +The following example shows a `servers` object with a server binding object for `jms` with JMS specific properties: + +```yaml +servers: + production: + url: jms://my-activemq-broker:61616 + protocol: jms + protocolVersion: '1.1' + description: The production ActiveMQ broker accessed via JMS. + bindings: + jms: + # JMS protocol specific server details + jmsConnectionFactory: org.apache.activemq.ActiveMQConnectionFactory + properties: + - name: disableTimeStampsByDefault + value: false + clientID: my-application-1 +``` + + + +## Channel Binding Object + +The JMS [Channel Binding Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#channel-bindings-object) is defined by a [JSON Schema](json_schemas/channel.json), which defines these fields: + +Field Name | Type | Description +---|:---:|--- +`destination` | string | **OPTIONAL**, defaults to the channel name. The destination (queue) name for this channel. SHOULD only be specified if the channel name differs from the actual destination name, such as when the channel name is not a valid destination name according to the JMS Provider. +`destinationType` | string | **OPTIONAL**, defaults to `queue`. The type of destination, which MUST be either `queue`, or `fifo-queue`. SHOULD be specified to document the messaging model (point-to-point, or strict message ordering) supported by this channel. +`bindingVersion` | string | **OPTIONAL**, defaults to `latest`. The version of this binding. + +### Examples + +The following example shows a `channels` object with two channels, the second having a channel binding object for `jms`: + +```yaml +channels: + user.signup: + description: This application receives command messages from this channel about users to sign up. + bindings: + jms: + destination: user-sign-up + destinationType: fifo-queue + bindingVersion: '0.0.1' + publish: + #... +``` + + + + + +## Operation Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Message Binding Object + +The JMS [Message Binding Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#message-bindings-object) is defined by a [JSON Schema](json_schemas/message.json), which defines these fields: + +Field Name | Type | Description +---|:---:|--- +`headers` | [Schema Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject) | **OPTIONAL**. A Schema object containing the definitions for JMS specific headers (so-called protocol headers). This schema MUST be of type `object` and have a `properties` key. Examples of JMS protocol headers are `JMSMessageID`, `JMSTimestamp`, and `JMSCorrelationID`. +`bindingVersion` | string | **OPTIONAL**, defaults to `latest`. The version of this binding. + +Note that application headers must be specified in the [`headers` field of the standard Message Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#messageObjectHeaders) and are set as [Message Properties](https://docs.oracle.com/javaee/7/api/javax/jms/Message.html#Message%20Properties) of the JMS Message; how they are transmitted is defined by the JMS Provider and need not be considered here. +In contrast, protocol headers such as `JMSMessageID` must be specified in the [`headers` field of the message binding object](#messageBindingObjectHeaders) and are transmitted in the [`headers` section of the JMS message](https://docs.oracle.com/javaee/7/api/javax/jms/Message.html#Message%20Headers). + +### Examples + +The following example shows a `message` object with both application specific headers, and a message binding object for `jms` with JMS specific headers: + +```yaml +message: + messageId: my-message-1 + bindings: + jms: + headers: + # JMS protocol specific message headers + required: + - JMSMessageID + properties: + JMSMessageID: + name: JMSMessageID + description: A unique message identifier. This may be set by your JMS Provider on your behalf. + type: string + JMSReplyTo: + name: JMSReplyTo + description: The queue or topic that the message sender expects replies to. + type: string + headers: + # Application specific message headers + required: + - MyToken + - MyOperationID + properties: + MyToken: + name: MyToken + description: Some sort of identificaton token for the publishing application. + type: string + MyOperationID: + name: MyOperationID + description: Some sort of unique identifier for the application operation to perform. + type: string +``` diff --git a/markdown/docs/reference/bindings/kafka.md b/markdown/docs/reference/bindings/kafka.md new file mode 100644 index 000000000000..4039eae5df44 --- /dev/null +++ b/markdown/docs/reference/bindings/kafka.md @@ -0,0 +1,207 @@ +--- +title: 'kafka' +weight: 18 +--- + +# Kafka Bindings + +This document defines how to describe Kafka-specific information on AsyncAPI. + + + +## Version + +Current version is `0.5.0`. + + + + +## Server Binding Object + +This object contains information about the server representation in Kafka. + +##### Fixed Fields + +Field Name | Type | Description | Applicability [default] | Constraints +---|:---:|:---:|:---:|--- +`schemaRegistryUrl` | string (url) | API URL for the Schema Registry used when producing Kafka messages (if a Schema Registry was used) | OPTIONAL | - +`schemaRegistryVendor` | string | The vendor of Schema Registry and Kafka serdes library that should be used (e.g. `apicurio`, `confluent`, `ibm`, or `karapace`) | OPTIONAL | MUST NOT be specified if `schemaRegistryUrl` is not specified +`bindingVersion` | string | The version of this binding. | OPTIONAL [`latest`] + +##### Example + +```yaml +servers: + production: + bindings: + kafka: + schemaRegistryUrl: 'https://my-schema-registry.com' + schemaRegistryVendor: 'confluent' + bindingVersion: '0.5.0' +``` + + + + +## Channel Binding Object + +This object contains information about the channel representation in Kafka (eg. a Kafka topic). + +##### Fixed Fields + +Field Name | Type | Description | Applicability [default] | Constraints +---|:------------------------------------------------:|:-------------------------------------------------------------------------------------------------------:|:-----------------------:|--- +`topic` | string | Kafka topic name if different from channel name. | OPTIONAL | - +`partitions` | integer | Number of partitions configured on this topic (useful to know how many parallel consumers you may run). | OPTIONAL | Must be positive +`replicas` | integer | Number of replicas configured on this topic. | OPTIONAL | MUST be positive +`topicConfiguration` | [TopicConfiguration Object](#topicConfiguration) | Topic configuration properties that are relevant for the API. | OPTIONAL | - +`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. | OPTIONAL [`latest`] | - + + +This object MUST contain only the properties defined above. + +##### Example + +```yaml +channels: + user-signedup: + bindings: + kafka: + topic: 'my-specific-topic-name' + partitions: 20 + replicas: 3 + topicConfiguration: + cleanup.policy: ["delete", "compact"] + retention.ms: 604800000 + retention.bytes: 1000000000 + delete.retention.ms: 86400000 + max.message.bytes: 1048588 + bindingVersion: '0.5.0' +``` + +## TopicConfiguration Object + +This objects contains information about the API relevant topic configuration in Kafka. + +Field Name | Type | Description | Applicability [default] | Constraints +---|:-------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-----------------------:|--- +`cleanup.policy` | array | The [`cleanup.policy`](https://kafka.apache.org/documentation/#topicconfigs_cleanup.policy) configuration option. | OPTIONAL | array may only contain `delete` and/or `compact` +`retention.ms` | long | The [`retention.ms`](https://kafka.apache.org/documentation/#topicconfigs_retention.ms) configuration option. | OPTIONAL | see kafka documentation +`retention.bytes` | long | The [`retention.bytes`](https://kafka.apache.org/documentation/#topicconfigs_retention.bytes) configuration option. | OPTIONAL | see kafka documentation +`delete.retention.ms` | long | The [`delete.retention.ms`](https://kafka.apache.org/documentation/#topicconfigs_delete.retention.ms) configuration option. | OPTIONAL | see kafka documentation +`max.message.bytes` | integer | The [`max.message.bytes`](https://kafka.apache.org/documentation/#topicconfigs_max.message.bytes) configuration option. | OPTIONAL | see kafka documentation +`confluent.key.schema.validation` | boolean | It shows whether the schema validation for the message key is enabled. Vendor specific config. | OPTIONAL | - +`confluent.key.subject.name.strategy` | string | The name of the schema lookup strategy for the message key. Vendor specific config. | OPTIONAL | Clients should default to the vendor default if not supplied. +`confluent.value.schema.validation` | boolean | It shows whether the schema validation for the message value is enabled. Vendor specific config. | OPTIONAL | - +`confluent.value.subject.name.strategy` | string | The name of the schema lookup strategy for the message value. Vendor specific config. | OPTIONAL | Clients should default to the vendor default if not supplied. + +This object MAY contain the properties defined above including optional additional properties. + +##### Example + +```yaml +topicConfiguration: + cleanup.policy: ["delete", "compact"] + retention.ms: 604800000 + retention.bytes: 1000000000 + delete.retention.ms: 86400000 + max.message.bytes: 1048588 + confluent.key.schema.validation: true + confluent.key.subject.name.strategy: "TopicNameStrategy" + confluent.value.schema.validation: true + confluent.value.subject.name.strategy: "TopicNameStrategy" +``` + + + +## Operation Binding Object + +This object contains information about the operation representation in Kafka (eg. the way to consume messages) + +##### Fixed Fields + +Field Name | Type | Description | Applicability [default] | Constraints +---|:---:|:---:|:---:|--- +`groupId` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) | Id of the consumer group. | OPTIONAL | - +`clientId` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) | Id of the consumer inside a consumer group. | OPTIONAL | - +`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. | OPTIONAL [`latest`] | - + +This object MUST contain only the properties defined above. + +##### Example + +```yaml +channels: + user-signedup: +operations: + userSignup: + action: receive + bindings: + kafka: + groupId: + type: string + enum: ['myGroupId'] + clientId: + type: string + enum: ['myClientId'] + bindingVersion: '0.5.0' +``` + + + + +## Message Binding Object + +This object contains information about the message representation in Kafka. + +##### Fixed Fields + +Field Name | Type | Description | Applicability [default] | Constraints +---|:-------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-----------------------:|--- +`key` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) \| [AVRO Schema Object](https://avro.apache.org/docs/current/spec.html) | The message key. **NOTE**: You can also use the [reference object](referenceObject) way. | OPTIONAL | - +`schemaIdLocation` | string | If a Schema Registry is used when performing this operation, tells where the id of schema is stored (e.g. `header` or `payload`). | OPTIONAL | MUST NOT be specified if `schemaRegistryUrl` is not specified at the Server level +`schemaIdPayloadEncoding` | string | Number of bytes or vendor specific values when schema id is encoded in payload (e.g `confluent`/ `apicurio-legacy` / `apicurio-new`). | OPTIONAL | MUST NOT be specified if `schemaRegistryUrl` is not specified at the Server level +`schemaLookupStrategy` | string | Freeform string for any naming strategy class to use. Clients should default to the vendor default if not supplied. | OPTIONAL | MUST NOT be specified if `schemaRegistryUrl` is not specified at the Server level +`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. | OPTIONAL [`latest`] | - + +This object MUST contain only the properties defined above. + +This example is valid for any Confluent compatible schema registry. Here we describe the implementation using the first 4 bytes in payload to store schema identifier. + +```yaml +channels: + test: + address: test-topic + messages: + testMessage: + bindings: + kafka: + key: + type: string + enum: ['myKey'] + schemaIdLocation: 'payload' + schemaIdPayloadEncoding: '4' + bindingVersion: '0.5.0' +``` + +This is another example that describes the use if Apicurio schema registry. We describe the `apicurio-new` way of serializing without details on how it's implemented. We reference a [specific lookup strategy](https://www.apicur.io/registry/docs/apicurio-registry/2.2.x/getting-started/assembly-using-kafka-client-serdes.html#registry-serdes-concepts-strategy_registry) that may be used to retrieve schema Id from registry during serialization. + +```yaml +channels: + test: + address: test-topic + messages: + testMessage: + bindings: + kafka: + key: + type: string + enum: ['myKey'] + schemaIdLocation: 'payload' + schemaIdPayloadEncoding: 'apicurio-new' + schemaLookupStrategy: 'TopicIdStrategy' + bindingVersion: '0.5.0' +``` + +[schemaObject]: https://www.asyncapi.com/docs/reference/specification/v3.0.0-next-major-spec.15#schemaObject +[referenceObject]: https://www.asyncapi.com/docs/reference/specification/v3.0.0-next-major-spec.15#referenceObject diff --git a/markdown/docs/reference/bindings/mercure.md b/markdown/docs/reference/bindings/mercure.md new file mode 100644 index 000000000000..f13432fbb291 --- /dev/null +++ b/markdown/docs/reference/bindings/mercure.md @@ -0,0 +1,48 @@ +--- +title: 'mercure' +weight: 19 +--- + +# Mercure Bindings + +This document defines how to describe Mercure-specific information on AsyncAPI. + + + +## Version + +Current version is `0.1.0`. + + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + + +## Channel Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + + +## Operation Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. diff --git a/markdown/docs/reference/bindings/mqtt.md b/markdown/docs/reference/bindings/mqtt.md new file mode 100644 index 000000000000..80441233ed0e --- /dev/null +++ b/markdown/docs/reference/bindings/mqtt.md @@ -0,0 +1,189 @@ +--- +title: 'mqtt' +weight: 20 +--- + +# MQTT Bindings + +This document defines how to describe MQTT-specific information on AsyncAPI. + +It applies to all versions of MQTT, although specific binding fields may only apply to particular versions. + + + +## Version + +Current version is `0.2.0`. + + + + +## Server Binding Object + +This object contains information about the server representation in MQTT. + +##### Fixed Fields + +Field Name | Type | MQTT Versions | Description +---|:---:|:---:|---| +`clientId` | string | 3, 5 | The client identifier. +`cleanSession` | boolean | 3, 5 | Whether to create a persistent connection or not. When `false`, the connection will be persistent. This is called **clean start** in MQTTv5. +`lastWill` | object | 3, 5 | Last Will and Testament configuration. `topic`, `qos`, `message` and `retain` are properties of this object as shown below. +`lastWill.topic` | string | 3, 5 | The topic where the Last Will and Testament message will be sent. +`lastWill.qos` | integer | 3, 5 | Defines how hard the broker/client will try to ensure that the Last Will and Testament message is received. Its value MUST be either 0, 1 or 2. +`lastWill.message` | string | 3, 5 | Last Will message. +`lastWill.retain` | boolean | 3, 5 | Whether the broker should retain the Last Will and Testament message or not. +`keepAlive` | integer | 3, 5 | Interval in seconds of the longest period of time the broker and the client can endure without sending a message. +`sessionExpiryInterval` | integer \| [Schema Object][schemaObject] \| [Reference Object][referenceObject] | 5 | Interval in seconds or a *Schema Object* containing the definition of the interval. The broker maintains a session for a disconnected client until this interval expires. +`maximumPacketSize` | integer \| [Schema Object][schemaObject] \| [Reference Object][referenceObject] | 5 | Number of bytes or a *Schema Object* representing the maximum packet size the client is willing to accept. +`bindingVersion` | string | | The version of this binding. If omitted, "latest" MUST be assumed. | + +This object MUST contain only the properties defined above. + +##### Examples + +```yaml +servers: + production: + bindings: + mqtt: + clientId: guest + cleanSession: true + lastWill: + topic: /last-wills + qos: 2 + message: Guest gone offline. + retain: false + keepAlive: 60 + sessionExpiryInterval: 600 + maximumPacketSize: 1200 + bindingVersion: 0.2.0 +``` +```yaml +servers: + production: + bindings: + mqtt: + sessionExpiryInterval: + type: integer + minimum: 30 + maximum: 1200 + maximumPacketSize: + type: integer + minimum: 256 + bindingVersion: 0.2.0 +``` + + + +## Channel Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Operation Binding Object + +This object contains information about the operation representation in MQTT. + +##### Fixed Fields + +Field Name | Type | Applies To | MQTT Versions | Description +---|:---:|:---:|:---:|--- +`qos` | integer | Publish, Subscribe | 3, 5 | Defines the Quality of Service (QoS) levels for the message flow between client and server. Its value MUST be either 0 (At most once delivery), 1 (At least once delivery), or 2 (Exactly once delivery). +`retain` | boolean | Publish | 3, 5 | Whether the broker should retain the message or not. +`messageExpiryInterval` | integer \| [Schema Object][schemaObject] \| [Reference Object][referenceObject]| Publish | 5 | Interval in seconds or a *Schema Object* containing the definition of the lifetime of the message. +`bindingVersion` | string | | | The version of this binding. If omitted, "latest" MUST be assumed. + +This object MUST contain only the properties defined above. + +##### Examples + +```yaml +channels: + user/signup: + publish: + bindings: + mqtt: + qos: 2 + retain: true + messageExpiryInterval: 60 + bindingVersion: 0.2.0 +``` +```yaml +channels: + user/signup: + publish: + bindings: + mqtt: + messageExpiryInterval: + type: integer + minimum: 30 + maximum: 300 + bindingVersion: 0.2.0 +``` +```yaml +channels: + user/signup: + subscribe: + bindings: + mqtt: + qos: 2 + bindingVersion: 0.2.0 +``` + + + +## Message Binding Object + +This object contains information about the message representation in MQTT. + +##### Fixed Fields + +Field Name | Type | MQTT Versions | Description +---|:---:|:---:|--- +`payloadFormatIndicator` | integer | 5 | Either: **0** (zero): Indicates that the payload is unspecified bytes, or **1**: Indicates that the payload is UTF-8 encoded character data. | +`correlationData` | [Schema Object][schemaObject] \| [Reference Object][referenceObject] | 5 | Correlation Data is used by the sender of the request message to identify which request the response message is for when it is received. +`contentType` | string | 5 | String describing the content type of the message payload. This should not conflict with the `contentType` field of the associated AsyncAPI Message object. +`responseTopic` | URI string \| [Schema Object][schemaObject] \| [Reference Object][referenceObject] | 5 | The topic (channel URI) for a response message. +`bindingVersion` | string | | The version of this binding. If omitted, "latest" MUST be assumed. + +This object MUST contain only the properties defined above. + +##### Examples + +```yaml +channels: + user/signup: + subscribe: + message: + bindings: + mqtt: + contentType: "application/json" + correlationData: + type: string + format: uuid + bindingVersion: 0.2.0 +``` +```yaml +channels: + userSignup: + address: user/signup + messages: + userSignup: + bindings: + mqtt: + payloadFormatIndicator: 1 + contentType: "application/json" + correlationData: + type: string + format: uuid + responseTopic: + type: string + pattern: "response/client/([a-z1-9]+)" + bindingVersion: 0.2.0 +``` + +[schemaObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject +[referenceObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#referenceObject + diff --git a/markdown/docs/reference/bindings/mqtt5.md b/markdown/docs/reference/bindings/mqtt5.md new file mode 100644 index 000000000000..4b33d45b5151 --- /dev/null +++ b/markdown/docs/reference/bindings/mqtt5.md @@ -0,0 +1,79 @@ +--- +title: 'mqtt5' +weight: 21 +--- + +# MQTT 5 Bindings + +This document defines how to describe MQTT 5-specific information on AsyncAPI. + +# **Deprecation Warning**: MQTT version 5 specific bindings are deprecated in favor of [MQTT bindings](../mqtt/README.md) that are not version specific. + + + +## Version + +Current version is `0.2.0`. + + + + +## Server Binding Object + +This object contains information about the server representation in MQTT5. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +`sessionExpiryInterval` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) \| integer | Session Expiry Interval in seconds or a Schema Object containing the definition of the interval. +`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. + +This object MUST contain only the properties defined above. + +##### Example + +```yaml +servers: + production: + bindings: + mqtt5: + sessionExpiryInterval: 60 + bindingVersion: 0.2.0 +``` +```yaml +servers: + production: + bindings: + mqtt5: + sessionExpiryInterval: + type: integer + minimum: 100 + bindingVersion: 0.2.0 +``` + + + +## Channel Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Operation Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + +[schemaObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject +[referenceObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#referenceObject diff --git a/markdown/docs/reference/bindings/nats.md b/markdown/docs/reference/bindings/nats.md new file mode 100644 index 000000000000..befeb548d1a0 --- /dev/null +++ b/markdown/docs/reference/bindings/nats.md @@ -0,0 +1,38 @@ +--- +title: 'nats' +weight: 22 +--- + +# NATS Bindings + +This document defines how to describe NATS-specific information on AsyncAPI. + + + +## Version + +Current version is `0.1.0`. + + + +## Server Binding Object +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Channel Binding Object +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Operation Binding Object + +Field Name | Type | Description +---|:---:|--- +| `queue` | string | Defines the name of the queue to use. It MUST NOT exceed 255 characters. | +| `bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. | + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. diff --git a/markdown/docs/reference/bindings/pulsar.md b/markdown/docs/reference/bindings/pulsar.md new file mode 100644 index 000000000000..99b2cc9b5352 --- /dev/null +++ b/markdown/docs/reference/bindings/pulsar.md @@ -0,0 +1,91 @@ +--- +title: 'pulsar' +weight: 23 +--- + +# Pulsar Bindings +This document defines how to describe Apache Pulsar specific information with AsyncAPI. + + + +## Version + +Current version is `0.1.0`. + + +## Server Binding Object + +This object contains information about the server representation in Pulsar. + +##### Fixed Fields + +Field Name | Type | Required | Description | Default value | +---|:---:|:---:|:---|:---| +`tenant` | String | No | The pulsar tenant. If omitted, "public" MUST be assumed. | `public` | +`bindingVersion` | String | No | The version of this binding. If omitted, "latest" MUST be assumed. | `latest` | + +##### Example + +```yaml +servers: + production: + bindings: + pulsar: + tenant: contoso + bindingVersion: '0.1.0' +``` + + +## Channel Binding Object +This object contains information about the channel representation in Pulsar + +##### Fixed Fields + +Field Name | Type | Required | Description | Default value | +---|:---:|:---:|:---|:---| +`namespace` | String | Yes | The namespace the channel is associated with. | N/A | +`persistence` | String | Yes | Persistence of the topic in Pulsar. It MUST be either `persistent` or `non-persistent`. | N/A | +`compaction`| Integer | No | Topic compaction threshold given in Megabytes. | N/A | +`geo-replication` | String[] | No | A list of clusters the topic is replicated to. | N/A | +`retention` | [Retention Definition Object](#retention-definition-object) | No | Topic retention policy. | N/A | +`ttl` | Integer | No | Message time-to-live in seconds. | N/A | +`deduplication` | Boolean | No | Message deduplication. When true, it ensures that each message produced on Pulsar topics is persisted to disk only once. | N/A | +`bindingVersion` | String | No | The version of this binding. If omitted, "latest" MUST be assumed. | `latest` | + + +### Retention Definition Object +The `Retention Definition Object` is used to describe the Pulsar [Retention](https://pulsar.apache.org/docs/cookbooks-retention-expiry/) policy. + +Field Name | Type | Required | Description | Default value | +---|:---:|:---:|:---|:---| +`time`|Integer| No | Time given in Minutes. | `0` | +`size`|Integer| No |Size given in MegaBytes. | `0` | + +##### Example + +```yaml +channels: + user-signedup: + bindings: + pulsar: + namespace: 'staging' + persistence: 'persistent' + compaction: 1000 + geo-replication: + - 'us-east1' + - 'us-west1' + retention: + time: 7 + size: 1000 + ttl: 360 + deduplication: false + bindingVersion: '0.1.0' +``` + + +## Operation binding fields +This object MUST NOT contain any properties. Its name is reserved for future use. + + +## Message binding fields +This object MUST NOT contain any properties. Its name is reserved for future use. \ No newline at end of file diff --git a/markdown/docs/reference/bindings/redis.md b/markdown/docs/reference/bindings/redis.md new file mode 100644 index 000000000000..62737ca2cdd7 --- /dev/null +++ b/markdown/docs/reference/bindings/redis.md @@ -0,0 +1,45 @@ +--- +title: 'redis' +weight: 24 +--- + +# Redis Bindings + +This document defines how to describe Redis-specific information on AsyncAPI. + + + +## Version + +Current version is `0.1.0`. + + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Channel Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Operation Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. diff --git a/markdown/docs/reference/bindings/ros2.md b/markdown/docs/reference/bindings/ros2.md new file mode 100644 index 000000000000..655cd2f15610 --- /dev/null +++ b/markdown/docs/reference/bindings/ros2.md @@ -0,0 +1,335 @@ +--- +title: 'ros2' +weight: 25 +--- + +# ROS 2 Bindings + +This document defines how to describe ROS 2-specific information in AsyncAPI. + +It applies to all [distributions of ROS 2](https://docs.ros.org/en/rolling/Releases.html). + + + +## Version + +Current version is `0.1.0`. + + + +## Server Binding Object + +This object contains information about the server representation in ROS 2. +ROS 2 can use a vast variety of [middleware implementations](https://docs.ros.org/en/rolling/Installation/RMW-Implementations.html). This document focuses on DDS and Zenoh middleware implementations. +DDS-based ROS 2 implementations are per default decentralized with no central server, so the field `host` can be set to `none`. +For more information on DDS tuning, you can visit the [DDS Tuning Guide](https://docs.ros.org/en/rolling/How-To-Guides/DDS-tuning.html). +When using Zenoh, the `host` field specifies the Zenoh Router IP address. + +###### Fixed Fields + +Field Name | Type | Description +---|:---:|---| +`rmwImplementation` | string | Specifies the ROS 2 middleware implementation to be used. Valid values include the different [ROS 2 middleware vendors (RMW)](https://docs.ros.org/en/rolling/Concepts/Intermediate/About-Different-Middleware-Vendors.html) like `rmw_fastrtps_cpp` (Fast DDS) or `rmw_zenoh_cpp` (Zenoh). This determines the underlying middleware implementation that handles communication. +`domainId` | integer | All ROS 2 nodes use domain ID 0 by default. To prevent interference between different groups of computers running ROS 2 on the same network, a group can be set with a unique domain ID. [Must be a non-negative integer less than 232](https://docs.ros.org/en/rolling/Concepts/Intermediate/About-Domain-ID.html). + +### Examples + +```yaml +servers: + ros2: + host: none + protocol: ros2 + protocolVersion: humble + bindings: + ros2: + rmwImplementation: rmw_fastrtps_cpp + domainId: 0 +``` + + + + +## Channel Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Operation Binding Object + +This object contains information about the ROS 2 node. + +###### Fixed Fields + +Field Name | Type | Description +---|:---:|---| +`role` | string | Specifies the ROS 2 type of the node for this operation. If the action is `send`, valid values for the role are: `publisher`, `action_client`, `service_client`. If the action is `receive`, valid values for the role are: `subscriber`, `action_server`, `service_server`. This defines how the node will interact with the associated topic, service or action. +`node` | string | The name of the ROS 2 node that implements this operation. +`qosPolicies` | [Quality of Service Policy Object](#QoSPolicyObject) | Quality of Service (QoS) for the topic. + + + +### Quality of Service Object +This object contains ROS 2 specific information about the Quality of Service policies. +More information here: https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Quality-of-Service-Settings.html#qos-policies + +Field Name | Type | Description +---|:---:|---| +`reliability` | string | One of `best_effort` or `reliable`. More information here: [ROS 2 QoS](https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Quality-of-Service-Settings.html#qos-policies) +`history` | string | One of `keep_last`, `keep_all` or `unknown`. More information here: [ROS 2 QoS](https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Quality-of-Service-Settings.html#qos-policies) +`durability` | string | One of `transient_local` or `volatile`. More information here: [ROS 2 QoS](https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Quality-of-Service-Settings.html#qos-policies) +`lifespan` | integer | The maximum amount of time between the publishing and the reception of a message without the message being considered stale or expired. `-1` means infinite. +`deadline` | integer | The expected maximum amount of time between subsequent messages being published to a topic. `-1` means infinite. +`liveliness` | string | One of `automatic` or `manual`. More information here: [ROS 2 QoS](https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Quality-of-Service-Settings.html#qos-policies) +`leaseDuration` | integer | The maximum period of time a publisher has to indicate that it is alive before the system considers it to have lost liveliness. `-1` means infinite. + +### Examples + +ROS 2 subscriber example: + +```yaml +receiveCmdVel: + action: receive + channel: + $ref: "#/channels/CmdVel" + bindings: + ros2: + role: subscriber + node: /turtlesim + qosPolicies: + history: unknown + reliability: reliable + durability: volatile + lifespan: -1 + deadline: -1 + liveliness: automatic + leaseDuration: -1 +``` + +ROS 2 publisher example: +```yaml + Pose: + action: receive + channel: + $ref: "#/channels/Pose" + bindings: + ros2: + role: publisher + node: /turtlesim +``` + +ROS 2 service server example: +```yaml +SetPen: + action: receive + channel: + $ref: "#/channels/SetPenRequest" + reply: + channel: + $ref: "#/channels/SetPenReply" + bindings: + ros2: + role: service_server + node: /turtlesim +``` + +ROS 2 service client example: +```yaml +SetPen: + action: send + channel: + $ref: "#/channels/SetPenRequest" + reply: + channel: + $ref: "#/channels/SetPenReply" + bindings: + ros2: + role: service_client + node: /node_client +``` + +ROS 2 action server example: +```yaml +receiveRotateAbsolute: + action: receive + channel: + $ref: "#/channels/RotateAbsoluteRequest" + reply: + channel: + $ref: "#/channels/RotateAbsoluteReply" + bindings: + ros2: + role: action_server + node: /turtlesim +``` + +ROS 2 action client example: +```yaml +RotateAbsolute: + action: send + channel: + $ref: "#/channels/RotateAbsoluteRequest" + reply: + channel: + $ref: "#/channels/RotateAbsoluteReply" + bindings: + ros2: + role: action_client + node: /teleop_turtle +``` + + + +## Message Binding Object + +While this object DOES NOT contain any ROS 2 specific properties, it is important to understand how to express the different [ROS 2 data types](https://design.ros2.org/articles/legacy_interface_definition.html#:~:text=to%20IDL%20types-,ROS%20type,string,-The%20mapping%20of) in [AsyncAPI message types and formats](https://www.asyncapi.com/docs/reference/specification/v3.0.0#dataTypeFormat:~:text=The%20formats%20defined%20by%20the%20AsyncAPI%20Specification%20are%3A). + +ROS 2 Type | AsyncAPI Type | AsyncAPI Format | +---|:---:|---| +bool | boolean | boolean +byte | string | octet +char | integer | uint8 +float32 | number | float +float64 | number | double +int8 | integer | int8 +uint8 | integer | uint8 +int16 | integer | int16 +uint16 | integer | uint16 +int32 | integer | int32 +uint32 | integer | uint32 +int64 | integer | int64 +uint64 | integer | uint64 +string | string | string +array | array | -- + +It is important to understand that the message header of the AsyncAPI specification does not map with the message header in ROS 2. +For this reason, the AsyncAPI message header will be ignored. If you want to define the header of a message in ROS 2, you should put in the payload of the message. [Example](https://docs.ros.org/en/ros2_packages/rolling/api/point_cloud_interfaces/msg/CompressedPointCloud2.html): + +```yaml +channels: + PointCloud: + address: /pointCloud + messages: + CompressedPointCloud2: + $ref: "#/components/messages/CompressedPointCloud2" +components: + CompressedPointCloud2: + tags: + - name: msg + payload: + type: object + properties: + header: + $ref: "#/components/messages/std_msgs/header/payload" + height: + $ref: "#/components/messages/uint32/payload" + width: + $ref: "#/components/messages/uint32/payload" + fields: + $ref: "#/components/messages/sensor_msgs/PointField/payload" + is_bigendian: + $ref: "#/components/messages/bool/payload" + point_step: + $ref: "#/components/messages/uint32/payload" + row_step: + $ref: "#/components/messages/uint32/payload" + compressed_data: + $ref: "#/components/messages/uint8/payload" + is_dense: + $ref: "#/components/messages/bool/payload" + format: + $ref: "#/components/messages/string/payload" +``` + +## Complete example: +From the AsyncAPI specification example it could be extracted that: +- It consist on a ROS 2 Jazzy application running with Fast DDS as RMW. +- `/turtlesim` node is a subscriber of the `/turtle1/cmd_vel` topic and its qos policies. +- The interface of the `/turtle1/cmd_vel` topic is `Twist` that has a nested type: `Vector3`. Both of them are part of the standard package `geometry_msgs`. +- `Vector3` has already the types converted to AsyncAPI types and formats (number and double), instead of using the ROS 2 types. +- There is one file (head-asyncapi.yaml) that references the different standard/custom packages. This packages contains the strucute of its messages. + + ``` + ├── interfaces + │ ├── geometry_msgs.yaml + │ ├── std_msgs.yaml + │ ├── .yaml + │ └── .... + └── head-asyncapi.yaml + ``` + +head-asyncapi.yaml + +```yaml +asyncapi: 3.0.0 +info: + title: Turtlesim example for ROS 2 + version: 1.0.0 + +servers: + ros2: + host: none + protocol: ros2 + protocolVersion: jazzy + bindings: + ros2: + rmwImplementation: rmw_fastrtps_cpp + domainId: 0 + +channels: + CmdVel: + address: /turtle1/cmd_vel + messages: + Twist: + $ref: ./interfaces/geometry_msgs.yaml#/components/messages/Twist + +operations: + CmdVel: + action: receive + channel: + $ref: "#/channels/CmdVel" + bindings: + ros2: + role: subscriber + node: /turtlesim + qosPolicies: + history: unknown + reliability: reliable + durability: volatile + lifespan: -1 + deadline: -1 + liveliness: automatic + leaseDuration: -1 +``` + +./interfaces/geometry_msgs.yaml +```yaml +asyncapi: 3.0.0 +info: + title: geometry_msgs + version: 1.0.0 +components: + messages: + Twist: + tags: + - name: msg + payload: + type: object + properties: + linear: + $ref: "#/components/messages/Vector3/payload" + angular: + $ref: "#/components/messages/Vector3/payload" + Vector3: + payload: + properties: + x: + type: number + format: double + y: + type: number + format: double + z: + type: number + format: double +``` \ No newline at end of file diff --git a/markdown/docs/reference/bindings/scripts.md b/markdown/docs/reference/bindings/scripts.md new file mode 100644 index 000000000000..4932f8b84590 --- /dev/null +++ b/markdown/docs/reference/bindings/scripts.md @@ -0,0 +1,6 @@ +--- +title: 'scripts' +weight: 10 +--- + +The entire `scripts` directory is centrally managed in [.github](https://github.com/asyncapi/.github/) repository. Any changes in this folder should be done in central repository. \ No newline at end of file diff --git a/markdown/docs/reference/bindings/solace.md b/markdown/docs/reference/bindings/solace.md new file mode 100644 index 000000000000..c114bf118783 --- /dev/null +++ b/markdown/docs/reference/bindings/solace.md @@ -0,0 +1,207 @@ +--- +title: 'solace' +weight: 28 +--- + +# Solace Bindings + +This document defines how to describe Solace-specific information with AsyncAPI. + + + +## Version + +Current version is `0.4.0`. + + + +## Server Binding Object + +| Field Name | Type | Description | +|------------------|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `bindingVersion` | String | The current version is 0.4.0 | +| `msgVpn` | String | The Virtual Private Network name on the Solace broker. | +| `clientName` | String | A unique client name to use to register to the appliance. If specified, it must be a valid Topic name, and a maximum of 160 bytes in length when encoded as UTF-8. | + + + +## Channel Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Operation Binding Object + +We need the ability to support several bindings for each operation, see the [Example](#example) section below for details. + +| Field Name | Type | Description | +|------------------|---------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `bindingVersion` | String | The current version is 0.4.0 | +| `destinations` | List of Destination Objects | Destination Objects are described next. | +| `timeToLive` | Integer \| [Schema Object][schemaObject] \| [Reference Object][referenceObject] | Interval in milliseconds or a *Schema Object* containing the definition of the lifetime of the message. | +| `priority` | Integer \| [Schema Object][schemaObject] \| [Reference Object][referenceObject] | The valid priority value range is 0-255 with 0 as the lowest priority and 255 as the highest or a *Schema Object* containing the definition of the priority. | +| `dmqEligible` | Boolean | Set the message to be eligible to be moved to a Dead Message Queue. The default value is false. | + +### Destination Object + +Each destination has the following structure: + +| Field Name | Type | Description | +|----------------------------|----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `bindingVersion` | String | The current version is 0.4.0 | +| `destinationType` | Enum | 'queue' or 'topic'. If the type is queue, then the subscriber can bind to the queue, which in turn will subscribe to the topic as represented by the channel name or to the provided topicSubscriptions. | +| `deliveryMode` | Enum | 'direct' or 'persistent'. This determines the quality of service for publishing messages as documented [here.](https://docs.solace.com/Get-Started/Core-Concepts-Message-Delivery-Modes.htm) Default is 'persistent'. | +| `queue.name` | String | The name of the queue, only applicable when destinationType is 'queue'. | +| `queue.topicSubscriptions` | List of String | A list of topics that the queue subscribes to, only applicable when destinationType is 'queue'. If none is given, the queue subscribes to the topic as represented by the channel name. | +| `queue.accessType` | Enum | 'exclusive' or 'nonexclusive'. This is documented [here.](https://docs.solace.com/Messaging/Guaranteed-Msg/Endpoints.htm#Queues) Only applicable when destinationType is 'queue'. | +| `queue.maxMsgSpoolSize` | String | The maximum amount of message spool that the given queue may use. This is documented [here.](https://docs.solace.com/Messaging/Guaranteed-Msg/Message-Spooling.htm#max-spool-usage) Only applicable when destinationType is 'queue'. | +| `queue.maxTtl` | String | The maximum TTL to apply to messages to be spooled. This is documented [here.](https://docs.solace.com/Messaging/Guaranteed-Msg/Configuring-Queues.htm) Only applicable when destinationType is 'queue'. | +| `topic.topicSubscriptions` | List of String | A list of topics that the client subscribes to, only applicable when destinationType is 'topic'. If none is given, the client subscribes to the topic as represented by the channel name. | + + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Example with two destinations ## + +Here is an example of when we could need two Solace destinations. + +Imagine a system where there is a schema called Person, and there are topics: + +`person/{personId}/created` + +and + +`person/{personId}/updated` + +and you have one application that receives both events. We also want each to be on its own queue. The AsyncAPI file could look like this: + +```yaml +components: + schemas: + Person: + type: string + messages: + PersonEvent: + payload: + $ref: '#/components/schemas/Person' + schemaFormat: application/vnd.aai.asyncapi+json;version=2.0.0 + contentType: application/json +operations: + addPerson: + action: send + channel: + $ref: '#/channels/address' + messages: + - $ref: '#/channels/address/messages/personEvent' + bindings: + solace: + bindingVersion: 0.4.0 + destinations: + - destinationType: queue + queue: + name: CreatedHREvents + topicSubscriptions: + - person/*/created + - destinationType: queue + queue: + name: UpdatedHREvents + topicSubscriptions: + - person/*/updated + timeToLive: 5000 + priority: 120 + dmqEligible: true + +channels: + person: + address: person/{personId}/{eventType} + parameters: + personId: + schema: + type: string + eventType: + schema: + type: string + messages: + personEvent: + $ref: '#/components/messages/PersonEvent' +asyncapi: 3.0.0 +info: + title: HRApp + version: 0.0.1 +``` + +The expected behavior would be that the application binds to both queues, and each queue has its own topic subscription, one to create and one to updated events. + + +## Example with a wildcard subscription ## + +This example shows how a client could receive all the topics under `person/` using a wildcard subscription: + +```yaml +components: + schemas: + Person: + type: string + messages: + PersonEvent: + payload: + schemaFormat: application/vnd.aai.asyncapi+json;version=3.0.0 + schema: + $ref: '#/components/schemas/Person' + contentType: application/json +operations: + addPerson: + action: send + channel: + $ref: '#/channels/person' + messages: + - $ref: '#/channels/person/messages/personEvent' + bindings: + solace: + bindingVersion: 0.4.0 + destinations: + - destinationType: queue + queue: + name: CreatedHREvents + topicSubscriptions: + - person/*/created + - destinationType: queue + queue: + name: UpdatedHREvents + topicSubscriptions: + - person/*/updated + timeToLive: 5000 + priority: 120 + dmqEligible: true + +channels: + person: + address: person/{personId}/{eventType} + parameters: + personId: + description: The machine readable id of the person + eventType: + enum: + - create + - delete + messages: + personEvent: + $ref: '#/components/messages/PersonEvent' +asyncapi: 3.0.0 +info: + title: HRApp + version: 0.0.1 +``` + +[schemaObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject +[referenceObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#referenceObject diff --git a/markdown/docs/reference/bindings/sqs.md b/markdown/docs/reference/bindings/sqs.md new file mode 100644 index 000000000000..46019b5fd9e5 --- /dev/null +++ b/markdown/docs/reference/bindings/sqs.md @@ -0,0 +1,249 @@ +--- +title: 'sqs' +weight: 29 +--- + +# SQS Bindings + +This document defines how to describe SQS-specific information on AsyncAPI. + +SQS can be used both stand-alone as a point-to-point and paired with SNS and as a publish-subscribe channel (where SQS is the endpoint that SNS delivers messages to). For this reason we define a Queue schema, and reference that schema from both a Channel Binding Object and a **publish** Operation Binding Object. + +For point-to-point scenarios, use the Channel Binding Object, as producers send to the queue and consumers receive from it directly. + +For publish-subscribe scenarios, use as a **publish** Operation Binding Object, as the producer sends to SNS and the consumer receives via SQS. + + + +## Version + +Current version is `0.3.0`. + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + +## Channel Binding Object + +Use the Channel Binding Operation for Point-to-Point SQS channels. + +There are three likely scenarios for use of the Channel Binding Object: + +- One file defines both publish and subscribe operations, for example if we were implementing the work queue pattern to offload work from an HTTP API endpoint to a worker process. In this case the channel would be defined on the Channel Object in that single file. +- The producer and consumer both have an AsyncAPI specification file, and the producer is raising an event, for example interop between microservices, and the producer 'owns' the channel definition and thus has the SQS Binding on its Channel Object. +- The producer and consumer both have an AsyncAPI specification file, and the consumer receives commands, for example interop between microservices, and the consumer 'owns' the channel definition and thus has the SQS Binding on its Channel Object. + +An SQS queue can set up a Dead Letter Queue as part of a Redelivery Policy. To support this requirement, the Channel Binding Object allows you to define both a Queue Object to use as the Channel or target in a *publish* Operation and a Dead Letter Queue. You can then refer to the Dead letter Queue in the Redrive Policy using the Identifier Object and setting the *name* field to match the *name* field of your Dead Letter Queue Object. (If you define the DLQ externally, the Identifier also supports an ARN). + +### Fields +|Field Name | Type | Description| +|---|:---:|---| +| `queue` | [Queue](#queue)| **Required.** A definition of the queue that will be used as the channel. | +| `deadLetterQueue` | [Queue](#queue)| **Optional.** A definition of the queue that will be used for un-processable messages. | +|`bindingVersion` | string | **Optional**, defaults to `latest`. The version of this binding.| + +### Schemas + +#### Queue +|Field Name | Type | Description| +|---|:---:|---| +| `name` | string | **Required.** The name of the queue. When an [SNS Operation Binding Object]() references an SQS queue by name, the identifier should be the one in this field.| +| `fifoQueue` | boolean | **Required.** Is this a FIFO queue? | +| `deduplicationScope` | string | **Optional.** Specifies whether message deduplication occurs at the message group or queue level. Valid values are `messageGroup` and `queue`. **This property applies only to high throughput for FIFO queues.** | +| `fifoThroughputLimit` | string | **Optional.** Specifies whether the FIFO queue throughput quota applies to the entire queue or per message group. Valid values are `perQueue` and `perMessageGroupId`. **The `perMessageGroupId` value is allowed only when the value for DeduplicationScope is `messageGroup`. Setting both these values as such will enable high throughput on a FIFO queue. As above, this property applies only to high throughput for FIFO queues.** | +| `deliveryDelay` | integer | **Optional.** The number of seconds to delay before a message sent to the queue can be received. Used to create a *delay queue*. Range is 0 to 15 minutes. Defaults to 0. | +| `visibilityTimeout` |integer| **Optional.** The length of time, in seconds, that a consumer locks a message - hiding it from reads - before it is unlocked and can be read again. Range from 0 to 12 hours (43200 seconds). Defaults to 30 seconds. | +| `receiveMessageWaitTime` |integer| **Optional.** Determines if the queue uses [short polling](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-short-and-long-polling.html) or [long polling](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-short-and-long-polling.html). Set to zero (the default) the queue reads available messages and returns immediately. Set to a non-zero integer, long polling waits the specified number of seconds for messages to arrive before returning. | +| `messageRetentionPeriod` |integer| **Optional.** How long to retain a message on the queue in seconds, unless deleted. The range is 60 (1 minute) to 1,209,600 (14 days). The default is 345,600 (4 days). | +| `redrivePolicy` | [Redrive Policy](#redrive-policy) | **Optional.** Prevent poison pill messages by moving un-processable messages to an SQS dead letter queue.| +| `policy` |[Policy](#policy) | **Optional.** The security policy for the SQS Queue | +| `tags` |Object | **Optional.** Key-value pairs that represent AWS tags on the queue. | + +#### Identifier +|Field Name | Type | Description | +|---|:---:|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +|`arn` |string| **Optional.** The target is an [ARN](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html). For example, for SQS, the identifier may be an ARN, which will be of the form: "[arn:aws:sqs:\{region\}:\{account-id\}:\{queueName\}](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)" | +|`name` |string| **Optional.** The endpoint is identified by a name, which corresponds to an identifying field called 'name' of a binding for that protocol on this **publish** Operation Object. For example, if the protocol is 'sqs' then the name refers to the name field **sqs** binding | + +#### Policy +|Field Name | Type | Description| +|---|:---:|---| +| `Statements` | [Statement](#statement) | **Required.** An array of Statement objects, each of which controls a permission for this queue. | + +#### Redrive Policy +|Field Name | Type | Description| +|---|:---:|---| +| `deadLetterQueue` |[Identifier](#identifier)| The SQS queue to use as a dead letter queue (DLQ) | +| `maxReceiveCount` |integer| **Optional.** The number of times a message is delivered to the source queue before being moved to the dead-letter queue. Default is 10. | + +#### Statement +|Field Name | Type | Description| +|---|:---:|---| +| `effect` | string |**Required.** Either "Allow" or "Deny"| +| `principal` | string or AWS principal property containing a string or string array |**Required.** The AWS account(s) or resource ARN(s) that the statement applies to| +| `action` | string or array of string |**Required.** The SNS permission being allowed or denied e.g. sns:Publish| +| `resource` | string or array of string |**Optional.** The resource(s) that this policy applies to| +| `condition` | object or list of objects |**Optional.** Specific circumstances under which the policy grants permission| + + + + +## Operation Binding Object + +### SQS Point-To-Point + +Because we have defined Queue as part of the Channel Binding Binding object, we do not require Binding information for the **publish** Operation Object of the **subscribe** Operation Object. You can use an empty Queue object ({}) to denote the Binding on the Operation Object, if you want to indicate the protocol used to send or receive for generation purposes such as Infrastructure As Code. + +### SNS to SQS Pub-Sub + +Use the Operation Binding Object when SQS is listening to an SNS Topic. In this case we need to define both an SQS Operation Binding Objects on the receiver **publish** Operation Object to represent the queue definition and we need to define an SNS Operation Binding Object to define the Subscription to SNS that makes your queue a receiver of that endpoint. + +Assuming you have separate AsyncAPI specifications for the producer and the consumer, we would assume the following bindings would appear for an SNS producer and an SQS consumer. + +Producer: SNS Channel Binding Object, SNS **subscribe** Operation Binding Object [if required] +Consumer: SNS **publish** Operation Binding Object, SQS **publish** Operation Binding Object + +- We assume that the SNS binding information only needs to be present in the producer file (although defining it in both is allowable) and any infrastructure as code dependencies can recognize this. + + +On an Operation Binding Object we support an array of Queue objects. Members of this array may be Queue Objects that define the *endpoint* field required by an [SNS Operation Object]() delivering by the SQS protocol or Queue Objects that define the Dead Letter Queue used by either the Redrive Policy of the SNS Subscription (see the SNS Binding Object) or the [Redrive Policy of the SQS Queue](#redrive-policy). The name of the Queue Object is used by an Identifier field on either the *endpoint* field of the SNS Operation Object of *deadLetterQueue* on the Redrive Policy to identify the required member of this array. + + +### Fields +|Field Name | Type | Description| +|---|:---:|---| +| `queues` | [[Queue](#queue)]| **Required.** Queue objects that are either the *endpoint* for an SNS Operation Binding Object, or the *deadLetterQueue* of the SQS Operation Binding Object | +|`bindingVersion` | string | **Optional**, defaults to `latest`. The version of this binding.| + +### Examples + +#### SQS Point-To-Point + +[](SQS-Point-To-Point.png) + +In this example, we are using SQS for a point-to-point channel. For this example, we assume that we are defining two microservices that communicate over a shared SQS channel, with the consumer receiving events over that channel and the producer owning the channel definition. + +The producer file would look like this: + +```yaml +channels: + user-signedup: + bindings: + sqs: + queue: + name: user-signedup-queue + fifoQueue: false + receiveMessageWaitTime: 4 + redrivePolicy: + deadLetterQueue: + name: user-signedup-dlq + policy: + statements: + - effect : Allow + principal: * + action: Sqs:SendMessage + - effect : Allow + principal: * + action: Sqs:ReceiveMessage + deadLetterQueue: + name: user-signedup-dlq + messageRetentionPeriod: 1209600 + fifoQueue: false + subscribe: + operationId: sendMessage + description: sends messages when a user has signed up + bindings: + sqs: {} + +``` +In this case we can minimize duplicated information by omitting the binding in our specification, and assume it is picked up from the producer file. We can use an empty object to indicate the SQS Binding on the **publish** Operation Object, if need a marker for generation, otherwise we could omit the Operation Binding Object. + +```yaml +channels: + user-signedup: + publish: + operationId: receiveMessage + description: receives a messages when a user has signed up + bindings: + sqs: {} + +``` + +#### SNS to SQS Pub-Sub + +[](SNS-SQS-Pub-Sub.png) + +In this example, we are using SNS for the channel, and SQS to receive from SNS. + + +The producer files looks like this (see the [SNS Binding]() for more). + +```yaml +channels: + user-signedup: + description: A user has signed up for our service + binding : + sns: {} # Indicates that the channel is an SNS Topic + subscribe: + operationId: sendMessage + description: send messages to the topic + bindings: + sns: + policy: + statements: + - effect : Allow + principal: * + action: SNS:Publish +``` + +And the consumer file would look like this. Note that for simplicity, we choose not to repeat the SNS Binding on the Consumer as it does not 'own' the channel. + + +```yaml +channels: + user-signedup: + description: A user has signed up for our service + publish: + operationId: receiveMessage + description: receive messages from the topic + bindings: + sns: + consumers: + - protocol: sqs + endpoint: + name: user-signedup-queue + rawMessageDelivery: true + filterPolicy: + attributes: + reason: + anything-but: password-reset + redrivePolicy: + deadLetterQueue: + name: user-signedup-queue-dlq + sqs: + queues: + - name: user-signedup-queue + fifoQueue: false + receiveMessageWaitTime: 4 + policy: + statements: + - effect : Allow + principal: * + action: Sqs:SendMessage + - effect : Allow + principal: * + action: Sqs:ReceiveMessage + - name: user-signedup-dlq + messageRetentionPeriod: 1209600 + fifoQueue: false +``` + + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. diff --git a/markdown/docs/reference/bindings/stomp.md b/markdown/docs/reference/bindings/stomp.md new file mode 100644 index 000000000000..c19ae1c4e4d1 --- /dev/null +++ b/markdown/docs/reference/bindings/stomp.md @@ -0,0 +1,45 @@ +--- +title: 'stomp' +weight: 30 +--- + +# STOMP Bindings + +This document defines how to describe STOMP-specific information on AsyncAPI. + + + +## Version + +Current version is `0.1.0`. + + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Channel Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Operation Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. diff --git a/markdown/docs/reference/bindings/websockets.md b/markdown/docs/reference/bindings/websockets.md new file mode 100644 index 000000000000..011025bef9f6 --- /dev/null +++ b/markdown/docs/reference/bindings/websockets.md @@ -0,0 +1,58 @@ +--- +title: 'websockets' +weight: 31 +--- + +# WebSockets Bindings + +This document defines how to describe WebSockets-specific information on AsyncAPI. + + + +## Version + +Current version is `0.1.0`. + + + + +## Server Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + + + +## Channel Binding Object + +When using WebSockets, the channel represents the connection. Unlike other protocols that support multiple virtual channels (topics, routing keys, etc.) per connection, WebSockets doesn't support virtual channels or, put it another way, there's only one channel and its characteristics are strongly related to the protocol used for the handshake, i.e., HTTP. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +`method` | string | The HTTP method to use when establishing the connection. Its value MUST be either `GET` or `POST`. +`query` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) | A Schema object containing the definitions for each query parameter. This schema MUST be of type `object` and have a `properties` key. +`headers` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) | A Schema object containing the definitions of the HTTP headers to use when establishing the connection. This schema MUST be of type `object` and have a `properties` key. +`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. + +This object MUST contain only the properties defined above. + + + +## Operation Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + + + +## Message Binding Object + +This object MUST NOT contain any properties. Its name is reserved for future use. + + +[schemaObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject +[referenceObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#referenceObject \ No newline at end of file diff --git a/markdown/docs/reference/specification/v3.0.0-explorer.md b/markdown/docs/reference/specification/v3.0.0-explorer.md index aae5302d6917..c98c309cca3b 100644 --- a/markdown/docs/reference/specification/v3.0.0-explorer.md +++ b/markdown/docs/reference/specification/v3.0.0-explorer.md @@ -1,6 +1,2 @@ ---- -title: "Specification Visualizer" -description: "Simplifying our specification json schema like a pro" ---- - - \ No newline at end of file + \ No newline at end of file diff --git a/markdown/docs/reference/specification/v3.1.0-explorer.md b/markdown/docs/reference/specification/v3.1.0-explorer.md new file mode 100644 index 000000000000..3f2e9e46aa1d --- /dev/null +++ b/markdown/docs/reference/specification/v3.1.0-explorer.md @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/markdown/docs/reference/specification/v3.1.0.md b/markdown/docs/reference/specification/v3.1.0.md new file mode 100644 index 000000000000..e58bda29bd70 --- /dev/null +++ b/markdown/docs/reference/specification/v3.1.0.md @@ -0,0 +1,2710 @@ +# AsyncAPI Specification + +## Attribution + +Part of this content has been taken from the great work done by the folks at the [OpenAPI Initiative](https://openapis.org). + +### Version 3.1.0 + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt). + +The AsyncAPI Specification is licensed under [The Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.html). + +## Introduction + +The AsyncAPI Specification is a project used to describe message-driven APIs in a machine-readable format. It’s protocol-agnostic, so you can use it for APIs that work over any protocol (e.g., AMQP, MQTT, WebSockets, Kafka, STOMP, HTTP, Mercure, etc). + +The AsyncAPI Specification defines a set of fields that can be used in an AsyncAPI document to describe an [application](#definitionsApplication)'s API. The document may reference other files for additional details or shared fields, but it is typically a single, primary document that encapsulates the API description. + +The AsyncAPI document SHOULD describe the operations an [application](#definitionsApplication) performs. For instance, consider the following AsyncAPI definition snippet: + +```yaml +channels: + userSignedUp: + # ...(redacted for brevity) +operations: + onUserSignedUp: + action: receive + channel: + $ref: '#/channels/userSignedUp' +``` + +It means that the [application](#definitionsApplication) will receive messages from the `userSignedUp` [channel](#definitionsChannel). + +**The AsyncAPI specification does not assume any kind of software topology, architecture or pattern.** Therefore, a server MAY be a message broker, a web server or any other kind of computer program capable of sending and/or receiving data. However, AsyncAPI offers a mechanism called "bindings" that aims to help with more specific information about the protocol. + +It's NOT RECOMMENDED to derive a [receiver](#definitionsReceiver) AsyncAPI document from a [sender](#definitionsSender) one or vice versa. There are no guarantees that the channel used by an application to receive messages will be the same channel where another application is sending them. Also, certain fields in the document like `summary`, `description`, and the id of the operation might stop making sense. For instance, given the following receiver snippet: + +```yaml +operations: + onUserSignedUp: + summary: On user signed up. + description: Event received when a user signed up on the product. + action: receive + channel: + $ref: '#/channels/userSignedUp' +``` + +We can't automatically assume that an _opposite_ application exists by simply replacing `receive` with `send`: + +```yaml +operations: + onUserSignedUp: # <-- This doesn't make sense now. Should be something like sendUserSignedUp. + summary: On user signed up. # <-- This doesn't make sense now. Should say something like "Sends a user signed up event". + description: Event received when a user signed up on the product. # <-- This doesn't make sense now. Should speak about sending an event, not receiving it. + action: send + channel: + $ref: '#/channels/userSignedUp' +``` + +Aside from the issues mentioned above, there may also be infrastructure configuration that is not represented here. For instance, a system may use a read-only channel for receiving messages, a different one for sending them, and an intermediary process that will forward messages from one channel to the other. + + +## Definitions + +### Server + +A server MAY be a message broker that is capable of sending and/or receiving between a [sender](#definitionsSender) and [receiver](#definitionsReceiver). A server MAY be a service with WebSocket API that enables message-driven communication between browser-to-server or server-to-server. + +### Application + +An application is any kind of computer program or a group of them. It MUST be a [sender](#definitionsSender), a [receiver](#definitionsReceiver), or both. An application MAY be a microservice, IoT device (sensor), mainframe process, message broker, etc. An application MAY be written in any number of different programming languages as long as they support the selected [protocol](#definitionsProtocol). An application MUST also use a protocol supported by the [server](#definitionsServer) in order to connect and exchange [messages](#definitionsMessage), or expose the protocol described in the AsyncAPI document. + +### Sender + +A sender is a type of application, that is sending [messages](#definitionsMessage) to [channels](#definitionsChannel). A sender MAY send to multiple channels depending on the [server](#definitionsServer), protocol, and use-case pattern. + +### Receiver + +A receiver is a type of application that is receiving [messages](#definitionsMessage) from [channels](#definitionsChannel). A receiver MAY receive from multiple channels depending on the [server](#definitionsServer), protocol, and the use-case pattern. A receiver MAY forward a received message further without changing it. A receiver MAY act as a consumer and react to the message. A receiver MAY act as a processor that, for example, aggregates multiple messages in one and forwards them. + +### Message + +A message is the mechanism by which information is exchanged via a channel between [servers](#definitionsServer) and applications. A message MAY contain a payload and MAY also contain headers. The headers MAY be subdivided into [protocol](#definitionsProtocol)-defined headers and header properties defined by the application which can act as supporting metadata. The payload contains the data, defined by the application, which MUST be serialized into a format (JSON, XML, Avro, binary, etc.). Since a message is a generic mechanism, it can support multiple interaction patterns such as event, command, request, or response. + +### Channel + +A channel is an addressable component, made available by the [server](#definitionsServer), for the organization of [messages](#definitionsMessage). [Sender](#definitionsSender) applications send messages to channels and [receiver](#definitionsReceiver) applications receive messages from channels. [Servers](#definitionsServer) MAY support many channel instances, allowing messages with different content to be addressed to different channels. Depending on the [server](#definitionsServer) implementation, the channel MAY be included in the message via protocol-defined headers. + +### Protocol + +A protocol is the mechanism (wireline protocol or API) by which [messages](#definitionsMessage) are exchanged between the application and the [channel](#definitionsChannel). Example protocols include, but are not limited to, AMQP, HTTP, JMS, Kafka, Anypoint MQ, MQTT, Solace, STOMP, Mercure, WebSocket, Google Pub/Sub, Pulsar, ROS 2. + +### Bindings + +A "binding" (or "protocol binding") is a mechanism to define protocol-specific information. Therefore, a protocol binding MUST define protocol-specific information only. + +## Specification + +### Format + +The files describing the message-driven API in accordance with the AsyncAPI Specification are represented as JSON objects and conform to the JSON standards. +YAML, being a superset of JSON, can be used as well to represent a A2S (AsyncAPI Specification) file. + +For example, if a field is said to have an array value, the JSON array representation will be used: + +```yaml +{ + "field" : [...] +} +``` + +While the API is described using JSON it does not impose a JSON input/output to the API itself. + +All field names in the specification are **case sensitive**. + +The schema exposes two types of fields. +Fixed fields, which have a declared name, and Patterned fields, which declare a regex pattern for the field name. +Patterned fields can have multiple occurrences as long as each has a unique name. + +In order to preserve the ability to round-trip between YAML and JSON formats, YAML version [1.2](https://www.yaml.org/spec/1.2/spec.html) is recommended along with some additional constraints: + +- Tags MUST be limited to those allowed by the [JSON Schema ruleset](https://www.yaml.org/spec/1.2/spec.html#id2803231) +- Keys used in YAML maps MUST be limited to a scalar string, as defined by the YAML Failsafe schema ruleset + +### File Structure + +An AsyncAPI document MAY be made up of a single document or be divided into multiple, +connected parts at the discretion of the author. In the latter case, [Reference Objects](#referenceObject) are used. + +It is important to note that everything that is defined in an AsyncAPI document MUST be used by the implemented [Application](#definitionsApplication), with the exception of the [Components Object](#componentsObject). Everything that is defined inside the Components Object represents a resource that MAY or MAY NOT be used by the implemented [Application](#definitionsApplication). + +By convention, the AsyncAPI Specification (A2S) file is named `asyncapi.json` or `asyncapi.yaml`. + +### Absolute URLs + +Unless specified otherwise, all properties that are absolute URLs are defined by [RFC3986, section 4.3](https://datatracker.ietf.org/doc/html/rfc3986#section-4.3). + +### Schema + +#### AsyncAPI Object + +This is the root document object for the API specification. +It combines resource listing and API declaration together into one document. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +asyncapi | [AsyncAPI Version String](#A2SVersionString) | **REQUIRED.** Specifies the AsyncAPI Specification version being used. It can be used by tooling Specifications and clients to interpret the version. The structure shall be `major`.`minor`.`patch`, where `patch` versions _must_ be compatible with the existing `major`.`minor` tooling. Typically patch versions will be introduced to address errors in the documentation, and tooling should typically be compatible with the corresponding `major`.`minor` (1.0.*). Patch versions will correspond to patches of this document. +id | [Identifier](#A2SIdString) | Identifier of the [application](#definitionsApplication) the AsyncAPI document is defining. +info | [Info Object](#infoObject) | **REQUIRED.** Provides metadata about the API. The metadata can be used by the clients if needed. +servers | [Servers Object](#serversObject) | Provides connection details of servers. +defaultContentType | [Default Content Type](#defaultContentTypeString) | Default content type to use when encoding/decoding a message's payload. +channels | [Channels Object](#channelsObject) | The channels used by this [application](#definitionsApplication). +operations | [Operations Object](#operationsObject) | The operations this [application](#definitionsApplication) MUST implement. +components | [Components Object](#componentsObject) | An element to hold various reusable objects for the specification. Everything that is defined inside this object represents a resource that MAY or MAY NOT be used in the rest of the document and MAY or MAY NOT be used by the implemented [Application](#definitionsApplication). + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +#### AsyncAPI Version String + +The version string signifies the version of the AsyncAPI Specification that the document complies to. +The format for this string _must_ be `major`.`minor`.`patch`. The `patch` _may_ be suffixed by a hyphen and extra alphanumeric characters. + +A `major`.`minor` shall be used to designate the AsyncAPI Specification version, and will be considered compatible with the AsyncAPI Specification specified by that `major`.`minor` version. +The patch version will not be considered by tooling, making no distinction between `1.0.0` and `1.0.1`. + +In subsequent versions of the AsyncAPI Specification, care will be given such that increments of the `minor` version should not interfere with operations of tooling developed to a lower minor version. Thus a hypothetical `1.1.0` specification should be usable with tooling designed for `1.0.0`. + +#### Identifier + +This field represents a unique universal identifier of the [application](#definitionsApplication) the AsyncAPI document is defining. It must conform to the URI format, according to [RFC3986](https://tools.ietf.org/html/rfc3986). + +It is RECOMMENDED to use a [URN](https://tools.ietf.org/html/rfc8141) to globally and uniquely identify the application during long periods of time, even after it becomes unavailable or ceases to exist. + +##### Examples + +```json +{ + "id": "urn:example:com:smartylighting:streetlights:server" +} +``` + +```yaml +id: 'urn:example:com:smartylighting:streetlights:server' +``` + +```json +{ + "id": "https://github.com/smartylighting/streetlights-server" +} +``` + +```yaml +id: 'https://github.com/smartylighting/streetlights-server' +``` + +#### Info Object + +The object provides metadata about the API. +The metadata can be used by the clients if needed. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +title | `string` | **REQUIRED.** The title of the application. +version | `string` | **REQUIRED** Provides the version of the application API (not to be confused with the specification version). +description | `string` | A short description of the application. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation. +termsOfService | `string` | A URL to the Terms of Service for the API. This MUST be in the form of an absolute URL. +contact | [Contact Object](#contactObject) | The contact information for the exposed API. +license | [License Object](#licenseObject) | The license information for the exposed API. +tags | [Tags Object](#tagsObject) | A list of tags for application API documentation control. Tags can be used for logical grouping of applications. +externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation of the exposed API. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +##### Info Object Example + + +```json +{ + "title": "AsyncAPI Sample App", + "version": "1.0.1", + "description": "This is a sample app.", + "termsOfService": "https://asyncapi.org/terms/", + "contact": { + "name": "API Support", + "url": "https://www.asyncapi.org/support", + "email": "support@asyncapi.org" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "externalDocs": { + "description": "Find more info here", + "url": "https://www.asyncapi.org" + }, + "tags": [ + { + "name": "e-commerce" + } + ] +} +``` + + +```yaml +title: AsyncAPI Sample App +version: 1.0.1 +description: This is a sample app. +termsOfService: https://asyncapi.org/terms/ +contact: + name: API Support + url: https://www.asyncapi.org/support + email: support@asyncapi.org +license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html +externalDocs: + description: Find more info here + url: https://www.asyncapi.org +tags: + - name: e-commerce +``` + +#### Contact Object + +Contact information for the exposed API. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +name | `string` | The identifying name of the contact person/organization. +url | `string` | The URL pointing to the contact information. This MUST be in the form of an absolute URL. +email | `string` | The email address of the contact person/organization. MUST be in the format of an email address. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +##### Contact Object Example + + +```json +{ + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" +} +``` + + +```yaml +name: API Support +url: https://www.example.com/support +email: support@example.com +``` + +#### License Object + +License information for the exposed API. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +name | `string` | **REQUIRED.** The license name used for the API. +url | `string` | A URL to the license used for the API. This MUST be in the form of an absolute URL. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +##### License Object Example + + +```json +{ + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" +} +``` + + +```yaml +name: Apache 2.0 +url: https://www.apache.org/licenses/LICENSE-2.0.html +``` + +#### Servers Object + +The Servers Object is a map of [Server Objects](#serverObject). + +##### Patterned Fields + +Field Pattern | Type | Description +---|:---:|--- +`^[A-Za-z0-9_\-]+$` | [Server Object](#serverObject) \| [Reference Object](#referenceObject) | The definition of a server this application MAY connect to. + +##### Servers Object Example + + +```json +{ + "development": { + "host": "localhost:5672", + "description": "Development AMQP broker.", + "protocol": "amqp", + "protocolVersion": "0-9-1", + "tags": [ + { + "name": "env:development", + "description": "This environment is meant for developers to run their own tests." + } + ] + }, + "staging": { + "host": "rabbitmq-staging.in.mycompany.com:5672", + "description": "RabbitMQ broker for the staging environment.", + "protocol": "amqp", + "protocolVersion": "0-9-1", + "tags": [ + { + "name": "env:staging", + "description": "This environment is a replica of the production environment." + } + ] + }, + "production": { + "host": "rabbitmq.in.mycompany.com:5672", + "description": "RabbitMQ broker for the production environment.", + "protocol": "amqp", + "protocolVersion": "0-9-1", + "tags": [ + { + "name": "env:production", + "description": "This environment is the live environment available for final users." + } + ] + } +} +``` + + +```yaml +development: + host: localhost:5672 + description: Development AMQP broker. + protocol: amqp + protocolVersion: 0-9-1 + tags: + - name: 'env:development' + description: 'This environment is meant for developers to run their own tests.' +staging: + host: rabbitmq-staging.in.mycompany.com:5672 + description: RabbitMQ broker for the staging environment. + protocol: amqp + protocolVersion: 0-9-1 + tags: + - name: 'env:staging' + description: 'This environment is a replica of the production environment.' +production: + host: rabbitmq.in.mycompany.com:5672 + description: RabbitMQ broker for the production environment. + protocol: amqp + protocolVersion: 0-9-1 + tags: + - name: 'env:production' + description: 'This environment is the live environment available for final users.' +``` + +#### Server Object + +An object representing a message broker, a server or any other kind of computer program capable of sending and/or receiving data. This object is used to capture details such as URIs, protocols and security configuration. Variable substitution can be used so that some details, for example usernames and passwords, can be injected by code generation tools. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +host | `string` | **REQUIRED**. The server host name. It MAY include the port. This field supports [Server Variables](#serverObjectVariables). Variable substitutions will be made when a variable is named in `{`braces`}`. +protocol | `string` | **REQUIRED**. The protocol this server supports for connection. +protocolVersion | `string` | The version of the protocol used for connection. For instance: AMQP `0.9.1`, HTTP `2.0`, Kafka `1.0.0`, etc. +pathname | `string` | The path to a resource in the host. This field supports [Server Variables](#serverObjectVariables). Variable substitutions will be made when a variable is named in `{`braces`}`. +description | `string` | An optional string describing the server. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. +title | `string` | A human-friendly title for the server. +summary | `string` | A short summary of the server. +variables | Map[`string`, [Server Variable Object](#serverVariableObject) \| [Reference Object](#referenceObject)]] | A map between a variable name and its value. The value is used for substitution in the server's `host` and `pathname` template. +security | [[Security Scheme Object](#securitySchemeObject) \| [Reference Object](#referenceObject)] | A declaration of which security schemes can be used with this server. The list of values includes alternative [security scheme objects](#securitySchemeObject) that can be used. Only one of the security scheme objects need to be satisfied to authorize a connection or operation. +tags | [Tags Object](#tagsObject) | A list of tags for logical grouping and categorization of servers. +externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation for this server. +bindings | [Server Bindings Object](#serverBindingsObject) \| [Reference Object](#referenceObject) | A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the server. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +##### Server Object Example + +A single server would be described as: + + +```json +{ + "host": "kafka.in.mycompany.com:9092", + "description": "Production Kafka broker.", + "protocol": "kafka", + "protocolVersion": "3.2" +} +``` + + +```yaml +host: kafka.in.mycompany.com:9092 +description: Production Kafka broker. +protocol: kafka +protocolVersion: '3.2' +``` + +An example of a server that has a `pathname`: + + +```json +{ + "host": "rabbitmq.in.mycompany.com:5672", + "pathname": "/production", + "protocol": "amqp", + "description": "Production RabbitMQ broker (uses the `production` vhost)." +} +``` + + +```yaml +host: rabbitmq.in.mycompany.com:5672 +pathname: /production +protocol: amqp +description: Production RabbitMQ broker (uses the `production` vhost). +``` + +#### Server Variable Object + +An object representing a Server Variable for server URL template substitution. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +enum | [`string`] | An enumeration of string values to be used if the substitution options are from a limited set. +default | `string` | The default value to use for substitution, and to send, if an alternate value is _not_ supplied. +description | `string` | An optional description for the server variable. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. +examples | [`string`] | An array of examples of the server variable. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +##### Server Variable Object Example + + +```json +{ + "host": "rabbitmq.in.mycompany.com:5672", + "pathname": "/{env}", + "protocol": "amqp", + "description": "RabbitMQ broker. Use the `env` variable to point to either `production` or `staging`.", + "variables": { + "env": { + "description": "Environment to connect to. It can be either `production` or `staging`.", + "enum": [ + "production", + "staging" + ] + } + } +} +``` + + +```yaml +host: 'rabbitmq.in.mycompany.com:5672' +pathname: '/{env}' +protocol: amqp +description: RabbitMQ broker. Use the `env` variable to point to either `production` or `staging`. +variables: + env: + description: Environment to connect to. It can be either `production` or `staging`. + enum: + - production + - staging +``` + +#### Default Content Type + +A string representing the default content type to use when encoding/decoding a message's payload. The value MUST be a specific media type (e.g. `application/json`). This value MUST be used by schema parsers when the [contentType](#messageObjectContentType) property is omitted. + +In case a message can't be encoded/decoded using this value, schema parsers MUST use their default content type. + +##### Default Content Type Example + + +```json +{ + "defaultContentType": "application/json" +} +``` + + +```yaml +defaultContentType: application/json +``` + +#### Channels Object + +An object containing all the [Channel Object](#channelObject) definitions the [Application](#definitionsApplication) MUST use during runtime. + +##### Patterned Fields + +Field Pattern | Type | Description +---|:---:|--- +\{channelId} | [Channel Object](#channelObject) \| [Reference Object](#referenceObject) | An identifier for the described channel. The `channelId` value is **case-sensitive**. Tools and libraries MAY use the `channelId` to uniquely identify a channel, therefore, it is RECOMMENDED to follow common programming naming conventions. + +##### Channels Object Example + + +```json +{ + "userSignedUp": { + "address": "user.signedup", + "messages": { + "userSignedUp": { + "$ref": "#/components/messages/userSignedUp" + } + } + } +} +``` + + +```yaml +userSignedUp: + address: 'user.signedup' + messages: + userSignedUp: + $ref: '#/components/messages/userSignedUp' +``` + +#### Channel Object + +Describes a shared communication channel. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +address | `string` \| `null` | An optional string representation of this channel's address. The address is typically the "topic name", "routing key", "event type", or "path". When `null` or absent, it MUST be interpreted as unknown. This is useful when the address is generated dynamically at runtime or can't be known upfront. It MAY contain [Channel Address Expressions](#channelAddressExpressions). Query parameters and fragments SHALL NOT be used, instead use [bindings](#channelBindingsObject) to define them. +messages | [Messages Object](#messagesObject) | A map of the messages that will be sent to this channel by any application at any time. **Every message sent to this channel MUST be valid against one, and only one, of the [message objects](#messageObject) defined in this map.** +title | `string` | A human-friendly title for the channel. +summary | `string` | A short summary of the channel. +description | `string` | An optional description of this channel. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation. +servers | [[Reference Object](#referenceObject)] | An array of `$ref` pointers to the definition of the servers in which this channel is available. If the channel is located in the [root Channels Object](#channelsObject), it MUST point to a subset of server definitions located in the [root Servers Object](#serversObject), and MUST NOT point to a subset of server definitions located in the [Components Object](#componentsObject) or anywhere else. If the channel is located in the [Components Object](#componentsObject), it MAY point to a [Server Objects](#serverObject) in any location. If `servers` is absent or empty, this channel MUST be available on all the servers defined in the [Servers Object](#serversObject). Please note the `servers` property value MUST be an array of [Reference Objects](#referenceObject) and, therefore, MUST NOT contain an array of [Server Objects](#serverObject). However, it is RECOMMENDED that parsers (or other software) dereference this property for a better development experience. +parameters | [Parameters Object](#parametersObject) | A map of the parameters included in the channel address. It MUST be present only when the address contains [Channel Address Expressions](#channelAddressExpressions). +tags | [Tags Object](#tagsObject) | A list of tags for logical grouping of channels. +externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation for this channel. +bindings | [Channel Bindings Object](#channelBindingsObject) \| [Reference Object](#referenceObject) | A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the channel. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +##### Channel Object Example + + +```json +{ + "address": "users.{userId}", + "title": "Users channel", + "description": "This channel is used to exchange messages about user events.", + "messages": { + "userSignedUp": { + "$ref": "#/components/messages/userSignedUp" + }, + "userCompletedOrder": { + "$ref": "#/components/messages/userCompletedOrder" + } + }, + "parameters": { + "userId": { + "$ref": "#/components/parameters/userId" + } + }, + "servers": [ + { "$ref": "#/servers/rabbitmqInProd" }, + { "$ref": "#/servers/rabbitmqInStaging" } + ], + "bindings": { + "amqp": { + "is": "queue", + "queue": { + "exclusive": true + } + } + }, + "tags": [{ + "name": "user", + "description": "User-related messages" + }], + "externalDocs": { + "description": "Find more info here", + "url": "https://example.com" + } +} +``` + + +```yaml +address: 'users.{userId}' +title: Users channel +description: This channel is used to exchange messages about user events. +messages: + userSignedUp: + $ref: '#/components/messages/userSignedUp' + userCompletedOrder: + $ref: '#/components/messages/userCompletedOrder' +parameters: + userId: + $ref: '#/components/parameters/userId' +servers: + - $ref: '#/servers/rabbitmqInProd' + - $ref: '#/servers/rabbitmqInStaging' +bindings: + amqp: + is: queue + queue: + exclusive: true +tags: + - name: user + description: User-related messages +externalDocs: + description: 'Find more info here' + url: 'https://example.com' +``` + +#### Channel Address Expressions + +Channel addresses MAY contain expressions that can be used to define dynamic values. + +Expressions MUST be composed by a name enclosed in curly braces (`{` and `}`). E.g., `{userId}`. + +#### Messages Object + +Describes a map of messages included in a channel. + +##### Patterned Fields + +Field Pattern | Type | Description +---|:---:|--- +`{messageId}` | [Message Object](#messageObject) \| [Reference Object](#referenceObject) | The key represents the message identifier. The `messageId` value is **case-sensitive**. Tools and libraries MAY use the `messageId` value to uniquely identify a message, therefore, it is RECOMMENDED to follow common programming naming conventions. + +##### Messages Object Example + + +```json +{ + "userSignedUp": { + "$ref": "#/components/messages/userSignedUp" + }, + "userCompletedOrder": { + "$ref": "#/components/messages/userCompletedOrder" + } +} +``` + + +```yaml +userSignedUp: + $ref: '#/components/messages/userSignedUp' +userCompletedOrder: + $ref: '#/components/messages/userCompletedOrder' +``` + +#### Operations Object + +Holds a dictionary with all the [operations](#operationObject) this application MUST implement. + +> If you're looking for a place to define operations that MAY or MAY NOT be implemented by the application, consider defining them in [`components/operations`](#componentsOperations). + +##### Patterned Fields + +Field Pattern | Type | Description +---|:---:|--- +\{operationId} | [Operation Object](#operationObject) \| [Reference Object](#referenceObject) | The operation this application MUST implement. The field name (`operationId`) MUST be a string used to identify the operation in the document where it is defined, and its value is **case-sensitive**. Tools and libraries MAY use the `operationId` to uniquely identify an operation, therefore, it is RECOMMENDED to follow common programming naming conventions. + +##### Operations Object Example + + +```json +{ + "onUserSignUp": { + "title": "User sign up", + "summary": "Action to sign a user up.", + "description": "A longer description", + "channel": { + "$ref": "#/channels/userSignup" + }, + "action": "send", + "tags": [ + { "name": "user" }, + { "name": "signup" }, + { "name": "register" } + ], + "bindings": { + "amqp": { + "ack": false + } + }, + "traits": [ + { "$ref": "#/components/operationTraits/kafka" } + ] + } +} +``` + + +```yaml +onUserSignUp: + title: User sign up + summary: Action to sign a user up. + description: A longer description + channel: + $ref: '#/channels/userSignup' + action: send + tags: + - name: user + - name: signup + - name: register + bindings: + amqp: + ack: false + traits: + - $ref: '#/components/operationTraits/kafka' +``` + +#### Operation Object + +Describes a specific operation. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +action | `"send"` | `"receive"` | **Required**. Use `send` when it's expected that the application will send a message to the given [`channel`](#operationObjectChannel), and `receive` when the application should expect receiving messages from the given [`channel`](#operationObjectChannel). +channel | [Reference Object](#referenceObject) | **Required**. A `$ref` pointer to the definition of the channel in which this operation is performed. If the operation is located in the [root Operations Object](#operationsObject), it MUST point to a channel definition located in the [root Channels Object](#channelsObject), and MUST NOT point to a channel definition located in the [Components Object](#componentsObject) or anywhere else. If the operation is located in the [Components Object](#componentsObject), it MAY point to a [Channel Object](#channelObject) in any location. Please note the `channel` property value MUST be a [Reference Object](#referenceObject) and, therefore, MUST NOT contain a [Channel Object](#channelObject). However, it is RECOMMENDED that parsers (or other software) dereference this property for a better development experience. +title | `string` | A human-friendly title for the operation. +summary | `string` | A short summary of what the operation is about. +description | `string` | A verbose explanation of the operation. [CommonMark syntax](http://spec.commonmark.org/) can be used for rich text representation. +security | [[Security Scheme Object](#securitySchemeObject) \| [Reference Object](#referenceObject)]| A declaration of which security schemes are associated with this operation. Only one of the [security scheme objects](#securitySchemeObject) MUST be satisfied to authorize an operation. In cases where [Server Security](#serverObjectSecurity) also applies, it MUST also be satisfied. +tags | [Tags Object](#tagsObject) | A list of tags for logical grouping and categorization of operations. +externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation for this operation. +bindings | [Operation Bindings Object](#operationBindingsObject) \| [Reference Object](#referenceObject) | A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the operation. +traits | [[Operation Trait Object](#operationTraitObject) | [Reference Object](#referenceObject) ] | A list of traits to apply to the operation object. Traits MUST be merged using [traits merge mechanism](#traits-merge-mechanism). The resulting object MUST be a valid [Operation Object](#operationObject). +messages | [[Reference Object](#referenceObject)] | A list of `$ref` pointers pointing to the supported [Message Objects](#messageObject) that can be processed by this operation. It MUST contain a subset of the messages defined in the [channel referenced in this operation](#operationObjectChannel), and MUST NOT point to a subset of message definitions located in the [Messages Object](#componentsMessages) in the [Components Object](#componentsObject) or anywhere else. **Every message processed by this operation MUST be valid against one, and only one, of the [message objects](#messageObject) referenced in this list.** Please note the `messages` property value MUST be a list of [Reference Objects](#referenceObject) and, therefore, MUST NOT contain [Message Objects](#messageObject). However, it is RECOMMENDED that parsers (or other software) dereference this property for a better development experience.

    **Note**: excluding this property from the Operation implies that all messages from the channel will be included. Explicitly set the `messages` property to `[]` if this operation should contain no messages.

    +reply | [Operation Reply Object](#operationReplyObject) | [Reference Object](#referenceObject) | The definition of the reply in a request-reply operation. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +##### Operation Object Example + + +```json +{ + "title": "User sign up", + "summary": "Action to sign a user up.", + "description": "A longer description", + "channel": { + "$ref": "#/channels/userSignup" + }, + "action": "send", + "security": [ + { + "type": "oauth2", + "description": "The oauth security descriptions", + "flows": { + "clientCredentials": { + "tokenUrl": "https://example.com/api/oauth/dialog", + "availableScopes": { + "subscribe:auth_revocations": "Scope required for authorization revocation topic" + } + } + }, + "scopes": [ + "subscribe:auth_revocations" + ], + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ], + "tags": [ + { "name": "user" }, + { "name": "signup" }, + { "name": "register" } + ], + "bindings": { + "amqp": { + "ack": false + } + }, + "traits": [ + { "$ref": "#/components/operationTraits/kafka" } + ], + "messages": [ + { "$ref": "#/channels/userSignup/messages/userSignedUp" } + ], + "reply": { + "address": { + "location": "$message.header#/replyTo" + }, + "channel": { + "$ref": "#/channels/userSignupReply" + }, + "messages": [ + { "$ref": "#/channels/userSignupReply/messages/userSignedUpReply" } + ] + } +} +``` + + +```yaml +title: User sign up +summary: Action to sign a user up. +description: A longer description +channel: + $ref: '#/channels/userSignup' +action: send +security: + - type: oauth2 + description: The oauth security descriptions + flows: + clientCredentials: + tokenUrl: 'https://example.com/api/oauth/dialog' + availableScopes: + 'subscribe:auth_revocations': Scope required for authorization revocation topic + scopes: + - 'subscribe:auth_revocations' + petstore_auth: + - 'write:pets' + - 'read:pets' +tags: + - name: user + - name: signup + - name: register +bindings: + amqp: + ack: false +traits: + - $ref: '#/components/operationTraits/kafka' +messages: + - $ref: '#/channels/userSignup/messages/userSignedUp' +reply: + address: + location: '$message.header#/replyTo' + channel: + $ref: '#/channels/userSignupReply' + messages: + - $ref: '#/channels/userSignupReply/messages/userSignedUpReply' +``` + +#### Operation Trait Object + +Describes a trait that MAY be applied to an [Operation Object](#operationObject). This object MAY contain any property from the [Operation Object](#operationObject), except the `action`, `channel`, `messages` and `traits` ones. + +If you're looking to apply traits to a message, see the [Message Trait Object](#messageTraitObject). + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +title | `string` | A human-friendly title for the operation. +summary | `string` | A short summary of what the operation is about. +description | `string` | A verbose explanation of the operation. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation. +security | [[Security Scheme Object](#securitySchemeObject) \| [Reference Object](#referenceObject)]| A declaration of which security schemes are associated with this operation. Only one of the [security scheme objects](#securitySchemeObject) MUST be satisfied to authorize an operation. In cases where [Server Security](#serverObjectSecurity) also applies, it MUST also be satisfied. +tags | [Tags Object](#tagsObject) | A list of tags for logical grouping and categorization of operations. +externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation for this operation. +bindings | [Operation Bindings Object](#operationBindingsObject) \| [Reference Object](#referenceObject) | A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the operation. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +##### Operation Trait Object Example + + +```json +{ + "bindings": { + "amqp": { + "ack": false + } + } +} +``` + + +```yaml +bindings: + amqp: + ack: false +``` + +#### Operation Reply Object + +Describes the reply part that MAY be applied to an Operation Object. If an operation implements the request/reply pattern, the reply object represents the response message. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +address | [Operation Reply Address Object](#operationReplyAddressObject) | [Reference Object](#referenceObject) | Definition of the address that implementations MUST use for the reply. +channel | [Reference Object](#referenceObject) | A `$ref` pointer to the definition of the channel in which this operation is performed. When [address](#operationReplyAddressObject) is specified, the [`address` property](#channelObjectAddress) of the channel referenced by this property MUST be either `null` or not defined. If the operation reply is located inside a [root Operation Object](#operationObject), it MUST point to a channel definition located in the [root Channels Object](#channelsObject), and MUST NOT point to a channel definition located in the [Components Object](#componentsObject) or anywhere else. If the operation reply is located inside an [Operation Object] in the [Components Object](#componentsObject) or in the [Replies Object](#componentsReplies) in the [Components Object](#componentsObject), it MAY point to a [Channel Object](#channelObject) in any location. Please note the `channel` property value MUST be a [Reference Object](#referenceObject) and, therefore, MUST NOT contain a [Channel Object](#channelObject). However, it is RECOMMENDED that parsers (or other software) dereference this property for a better development experience. +messages | [[Reference Object](#referenceObject)] | A list of `$ref` pointers pointing to the supported [Message Objects](#messageObject) that can be processed by this operation as reply. It MUST contain a subset of the messages defined in the [channel referenced in this operation reply](#operationObjectChannel), and MUST NOT point to a subset of message definitions located in the [Components Object](#componentsObject) or anywhere else. **Every message processed by this operation MUST be valid against one, and only one, of the [message objects](#messageObject) referenced in this list.** Please note the `messages` property value MUST be a list of [Reference Objects](#referenceObject) and, therefore, MUST NOT contain [Message Objects](#messageObject). However, it is RECOMMENDED that parsers (or other software) dereference this property for a better development experience. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +#### Operation Reply Address Object + +An object that specifies where an operation has to send the reply. + +For specifying and computing the location of a reply address, a [runtime expression](#runtimeExpression) is used. + +##### Fixed Fields + +Field Name | Type | Description +---|:---|--- +description | `string` | An optional description of the address. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation. +location | `string` | **REQUIRED.** A [runtime expression](#runtimeExpression) that specifies the location of the reply address. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +##### Examples + + +```json +{ + "description": "Consumer inbox", + "location": "$message.header#/replyTo" +} +``` + + +```yaml +description: Consumer Inbox +location: $message.header#/replyTo +``` + +#### Parameters Object + +Describes a map of parameters included in a channel address. + +This map MUST contain all the parameters used in the parent channel address. + +##### Patterned Fields + +Field Pattern | Type | Description +---|:---:|--- +`^[A-Za-z0-9_\-]+$` | [Parameter Object](#parameterObject) | [Reference Object](#referenceObject) | The key represents the name of the parameter. It MUST match the parameter name used in the parent channel address. + +##### Parameters Object Example + + +```json +{ + "address": "user/{userId}/signedup", + "parameters": { + "userId": { + "description": "Id of the user." + } + } +} +``` + + +```yaml +address: user/{userId}/signedup +parameters: + userId: + description: Id of the user. +``` + +#### Parameter Object + +Describes a parameter included in a channel address. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +enum | [`string`] | An enumeration of string values to be used if the substitution options are from a limited set. +default | `string` | The default value to use for substitution, and to send, if an alternate value is _not_ supplied. +description | `string` | An optional description for the parameter. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. +examples | [`string`] | An array of examples of the parameter value. +location | `string` | A [runtime expression](#runtimeExpression) that specifies the location of the parameter value. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +##### Parameter Object Example + + +```json +{ + "address": "user/{userId}/signedup", + "parameters": { + "userId": { + "description": "Id of the user.", + "location": "$message.payload#/user/id" + } + } +} +``` + + +```yaml +address: user/{userId}/signedup +parameters: + userId: + description: Id of the user. + location: $message.payload#/user/id +``` + +#### Server Bindings Object + +Map describing protocol-specific definitions for a server. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +`http` | [HTTP Server Binding](https://github.com/asyncapi/bindings/blob/master/http#server) | Protocol-specific information for an HTTP server. +`ws` | [WebSockets Server Binding](https://github.com/asyncapi/bindings/blob/master/websockets#server) | Protocol-specific information for a WebSockets server. +`kafka` | [Kafka Server Binding](https://github.com/asyncapi/bindings/blob/master/kafka#server) | Protocol-specific information for a Kafka server. +`anypointmq` | [Anypoint MQ Server Binding](https://github.com/asyncapi/bindings/blob/master/anypointmq#server) | Protocol-specific information for an Anypoint MQ server. +`amqp` | [AMQP Server Binding](https://github.com/asyncapi/bindings/blob/master/amqp#server) | Protocol-specific information for an AMQP 0-9-1 server. +`amqp1` | [AMQP 1.0 Server Binding](https://github.com/asyncapi/bindings/blob/master/amqp1#server) | Protocol-specific information for an AMQP 1.0 server. +`mqtt` | [MQTT Server Binding](https://github.com/asyncapi/bindings/blob/master/mqtt#server) | Protocol-specific information for an MQTT server. +`mqtt5` | [MQTT 5 Server Binding](https://github.com/asyncapi/bindings/blob/master/mqtt5#server) | Protocol-specific information for an MQTT 5 server. +`nats` | [NATS Server Binding](https://github.com/asyncapi/bindings/blob/master/nats#server) | Protocol-specific information for a NATS server. +`jms` | [JMS Server Binding](https://github.com/asyncapi/bindings/blob/master/jms#server) | Protocol-specific information for a JMS server. +`sns` | [SNS Server Binding](https://github.com/asyncapi/bindings/blob/master/sns#server) | Protocol-specific information for an SNS server. +`solace` | [Solace Server Binding](https://github.com/asyncapi/bindings/blob/master/solace#server) | Protocol-specific information for a Solace server. +`sqs` | [SQS Server Binding](https://github.com/asyncapi/bindings/blob/master/sqs#server) | Protocol-specific information for an SQS server. +`stomp` | [STOMP Server Binding](https://github.com/asyncapi/bindings/blob/master/stomp#server) | Protocol-specific information for a STOMP server. +`redis` | [Redis Server Binding](https://github.com/asyncapi/bindings/blob/master/redis#server) | Protocol-specific information for a Redis server. +`mercure` | [Mercure Server Binding](https://github.com/asyncapi/bindings/blob/master/mercure#server) | Protocol-specific information for a Mercure server. +`ibmmq` | [IBM MQ Server Binding](https://github.com/asyncapi/bindings/blob/master/ibmmq#server-binding-object) | Protocol-specific information for an IBM MQ server. +`googlepubsub` | [Google Cloud Pub/Sub Server Binding](https://github.com/asyncapi/bindings/blob/master/googlepubsub#server) | Protocol-specific information for a Google Cloud Pub/Sub server. +`pulsar` | [Pulsar Server Binding](https://github.com/asyncapi/bindings/tree/master/pulsar#server-binding-object) | Protocol-specific information for a Pulsar server. +`ros2` | [ROS 2 Server Binding](https://github.com/asyncapi/bindings/tree/master/ros2#server-binding-object) | Protocol-specific information for a ROS 2 server. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +#### Channel Bindings Object + +Map describing protocol-specific definitions for a channel. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +`http` | [HTTP Channel Binding](https://github.com/asyncapi/bindings/blob/master/http/README.md#channel) | Protocol-specific information for an HTTP channel. +`ws` | [WebSockets Channel Binding](https://github.com/asyncapi/bindings/blob/master/websockets/README.md#channel) | Protocol-specific information for a WebSockets channel. +`kafka` | [Kafka Channel Binding](https://github.com/asyncapi/bindings/blob/master/kafka/README.md#channel) | Protocol-specific information for a Kafka channel. +`anypointmq` | [Anypoint MQ Channel Binding](https://github.com/asyncapi/bindings/blob/master/anypointmq/README.md#channel) | Protocol-specific information for an Anypoint MQ channel. +`amqp` | [AMQP Channel Binding](https://github.com/asyncapi/bindings/blob/master/amqp/README.md#channel) | Protocol-specific information for an AMQP 0-9-1 channel. +`amqp1` | [AMQP 1.0 Channel Binding](https://github.com/asyncapi/bindings/blob/master/amqp1/README.md#channel) | Protocol-specific information for an AMQP 1.0 channel. +`mqtt` | [MQTT Channel Binding](https://github.com/asyncapi/bindings/blob/master/mqtt/README.md#channel) | Protocol-specific information for an MQTT channel. +`mqtt5` | [MQTT 5 Channel Binding](https://github.com/asyncapi/bindings/blob/master/mqtt5#channel) | Protocol-specific information for an MQTT 5 channel. +`nats` | [NATS Channel Binding](https://github.com/asyncapi/bindings/blob/master/nats/README.md#channel) | Protocol-specific information for a NATS channel. +`jms` | [JMS Channel Binding](https://github.com/asyncapi/bindings/blob/master/jms/README.md#channel) | Protocol-specific information for a JMS channel. +`sns` | [SNS Channel Binding](https://github.com/asyncapi/bindings/blob/master/sns/README.md#channel) | Protocol-specific information for an SNS channel. +`solace` | [Solace Channel Binding](https://github.com/asyncapi/bindings/blob/master/solace#channel) | Protocol-specific information for a Solace channel. +`sqs` | [SQS Channel Binding](https://github.com/asyncapi/bindings/blob/master/sqs/README.md#channel) | Protocol-specific information for an SQS channel. +`stomp` | [STOMP Channel Binding](https://github.com/asyncapi/bindings/blob/master/stomp/README.md#channel) | Protocol-specific information for a STOMP channel. +`redis` | [Redis Channel Binding](https://github.com/asyncapi/bindings/blob/master/redis#channel) | Protocol-specific information for a Redis channel. +`mercure` | [Mercure Channel Binding](https://github.com/asyncapi/bindings/blob/master/mercure#channel) | Protocol-specific information for a Mercure channel. +`ibmmq` | [IBM MQ Channel Binding](https://github.com/asyncapi/bindings/tree/master/ibmmq#channel-binding-object) | Protocol-specific information for an IBM MQ channel. +`googlepubsub` | [Google Cloud Pub/Sub Channel Binding](https://github.com/asyncapi/bindings/tree/master/googlepubsub#channel) | Protocol-specific information for a Google Cloud Pub/Sub channel. +`pulsar` | [Pulsar Channel Binding](https://github.com/asyncapi/bindings/tree/master/pulsar#channel-binding-object) | Protocol-specific information for a Pulsar channel. +`ros2` | [ROS 2 Channel Binding](https://github.com/asyncapi/bindings/tree/master/ros2#channel-binding-object) | Protocol-specific information for a ROS 2 channel. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +#### Operation Bindings Object + +Map describing protocol-specific definitions for an operation. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +`http` | [HTTP Operation Binding](https://github.com/asyncapi/bindings/blob/master/http/README.md#operation) | Protocol-specific information for an HTTP operation. +`ws` | [WebSockets Operation Binding](https://github.com/asyncapi/bindings/blob/master/websockets/README.md#operation) | Protocol-specific information for a WebSockets operation. +`kafka` | [Kafka Operation Binding](https://github.com/asyncapi/bindings/blob/master/kafka/README.md#operation) | Protocol-specific information for a Kafka operation. +`anypointmq` | [Anypoint MQ Operation Binding](https://github.com/asyncapi/bindings/blob/master/anypointmq/README.md#operation) | Protocol-specific information for an Anypoint MQ operation. +`amqp` | [AMQP Operation Binding](https://github.com/asyncapi/bindings/blob/master/amqp/README.md#operation) | Protocol-specific information for an AMQP 0-9-1 operation. +`amqp1` | [AMQP 1.0 Operation Binding](https://github.com/asyncapi/bindings/blob/master/amqp1/README.md#operation) | Protocol-specific information for an AMQP 1.0 operation. +`mqtt` | [MQTT Operation Binding](https://github.com/asyncapi/bindings/blob/master/mqtt/README.md#operation) | Protocol-specific information for an MQTT operation. +`mqtt5` | [MQTT 5 Operation Binding](https://github.com/asyncapi/bindings/blob/master/mqtt5/README.md#operation) | Protocol-specific information for an MQTT 5 operation. +`nats` | [NATS Operation Binding](https://github.com/asyncapi/bindings/blob/master/nats/README.md#operation) | Protocol-specific information for a NATS operation. +`jms` | [JMS Operation Binding](https://github.com/asyncapi/bindings/blob/master/jms/README.md#operation) | Protocol-specific information for a JMS operation. +`sns` | [SNS Operation Binding](https://github.com/asyncapi/bindings/blob/master/sns/README.md#operation) | Protocol-specific information for an SNS operation. +`solace` | [Solace Operation Binding](https://github.com/asyncapi/bindings/blob/master/solace#operation) | Protocol-specific information for a Solace operation. +`sqs` | [SQS Operation Binding](https://github.com/asyncapi/bindings/blob/master/sqs/README.md#operation) | Protocol-specific information for an SQS operation. +`stomp` | [STOMP Operation Binding](https://github.com/asyncapi/bindings/blob/master/stomp/README.md#operation) | Protocol-specific information for a STOMP operation. +`redis` | [Redis Operation Binding](https://github.com/asyncapi/bindings/blob/master/redis#operation) | Protocol-specific information for a Redis operation. +`mercure` | [Mercure Operation Binding](https://github.com/asyncapi/bindings/blob/master/mercure#operation) | Protocol-specific information for a Mercure operation. +`googlepubsub` | [Google Cloud Pub/Sub Operation Binding](https://github.com/asyncapi/bindings/blob/master/googlepubsub#operation) | Protocol-specific information for a Google Cloud Pub/Sub operation. +`ibmmq` | [IBM MQ Operation Binding](https://github.com/asyncapi/bindings/blob/master/ibmmq#operation-binding-object) | Protocol-specific information for an IBM MQ operation. +`pulsar` | [Pulsar Operation Binding](https://github.com/asyncapi/bindings/tree/master/pulsar#operation-binding-fields) | Protocol-specific information for a Pulsar operation. +`ros2` | [ROS 2 Operation Binding](https://github.com/asyncapi/bindings/tree/master/ros2#operation-binding-fields) | Protocol-specific information for a ROS 2 operation. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +#### Message Bindings Object + +Map describing protocol-specific definitions for a message. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +`http` | [HTTP Message Binding](https://github.com/asyncapi/bindings/blob/master/http/README.md#message) | Protocol-specific information for an HTTP message, i.e., a request or a response. +`ws` | [WebSockets Message Binding](https://github.com/asyncapi/bindings/blob/master/websockets/README.md#message) | Protocol-specific information for a WebSockets message. +`kafka` | [Kafka Message Binding](https://github.com/asyncapi/bindings/blob/master/kafka/README.md#message) | Protocol-specific information for a Kafka message. +`anypointmq` | [Anypoint MQ Message Binding](https://github.com/asyncapi/bindings/blob/master/anypointmq/README.md#message) | Protocol-specific information for an Anypoint MQ message. +`amqp` | [AMQP Message Binding](https://github.com/asyncapi/bindings/blob/master/amqp/README.md#message) | Protocol-specific information for an AMQP 0-9-1 message. +`amqp1` | [AMQP 1.0 Message Binding](https://github.com/asyncapi/bindings/blob/master/amqp1/README.md#message) | Protocol-specific information for an AMQP 1.0 message. +`mqtt` | [MQTT Message Binding](https://github.com/asyncapi/bindings/blob/master/mqtt/README.md#message) | Protocol-specific information for an MQTT message. +`mqtt5` | [MQTT 5 Message Binding](https://github.com/asyncapi/bindings/blob/master/mqtt5/README.md#message) | Protocol-specific information for an MQTT 5 message. +`nats` | [NATS Message Binding](https://github.com/asyncapi/bindings/blob/master/nats/README.md#message) | Protocol-specific information for a NATS message. +`jms` | [JMS Message Binding](https://github.com/asyncapi/bindings/blob/master/jms/README.md#message) | Protocol-specific information for a JMS message. +`sns` | [SNS Message Binding](https://github.com/asyncapi/bindings/blob/master/sns/README.md#message) | Protocol-specific information for an SNS message. +`solace` | [Solace Server Binding](https://github.com/asyncapi/bindings/blob/master/solace#message) | Protocol-specific information for a Solace message. +`sqs` | [SQS Message Binding](https://github.com/asyncapi/bindings/blob/master/sqs/README.md#message) | Protocol-specific information for an SQS message. +`stomp` | [STOMP Message Binding](https://github.com/asyncapi/bindings/blob/master/stomp/README.md#message) | Protocol-specific information for a STOMP message. +`redis` | [Redis Message Binding](https://github.com/asyncapi/bindings/blob/master/redis#message) | Protocol-specific information for a Redis message. +`mercure` | [Mercure Message Binding](https://github.com/asyncapi/bindings/blob/master/mercure#message) | Protocol-specific information for a Mercure message. +`ibmmq` | [IBM MQ Message Binding](https://github.com/asyncapi/bindings/tree/master/ibmmq#message-binding-object) | Protocol-specific information for an IBM MQ message. +`googlepubsub` | [Google Cloud Pub/Sub Message Binding](https://github.com/asyncapi/bindings/tree/master/googlepubsub#message) | Protocol-specific information for a Google Cloud Pub/Sub message. +`pulsar` | [Pulsar Message Binding](https://github.com/asyncapi/bindings/tree/master/pulsar#message-binding-fields) | Protocol-specific information for a Pulsar message. +`ros2` | [ROS 2 Message Binding](https://github.com/asyncapi/bindings/tree/master/ros2#message-binding-fields) | Protocol-specific information for a ROS 2 message. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +#### Message Object + +Describes a message received on a given channel and operation. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +headers | [Multi Format Schema Object](#multiFormatSchemaObject) | [Schema Object](#schemaObject) | [Reference Object](#referenceObject) | Schema definition of the application headers. Schema MUST be a map of key-value pairs. It **MUST NOT** define the protocol headers. If this is a [Schema Object](#schemaObject), then the `schemaFormat` will be assumed to be "application/vnd.aai.asyncapi+json;version=`asyncapi`" where the version is equal to the [AsyncAPI Version String](#A2SVersionString). +payload | [Multi Format Schema Object](#multiFormatSchemaObject) | [Schema Object](#schemaObject) | [Reference Object](#referenceObject) | Definition of the message payload. If this is a [Schema Object](#schemaObject), then the `schemaFormat` will be assumed to be "application/vnd.aai.asyncapi+json;version=`asyncapi`" where the version is equal to the [AsyncAPI Version String](#A2SVersionString). +correlationId | [Correlation ID Object](#correlationIdObject) | [Reference Object](#referenceObject) | Definition of the correlation ID used for message tracing or matching. +contentType | `string` | The content type to use when encoding/decoding a message's payload. The value MUST be a specific media type (e.g. `application/json`). When omitted, the value MUST be the one specified on the [defaultContentType](#defaultContentTypeString) field. +name | `string` | A machine-friendly name for the message. +title | `string` | A human-friendly title for the message. +summary | `string` | A short summary of what the message is about. +description | `string` | A verbose explanation of the message. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation. +tags | [Tags Object](#tagsObject) | A list of tags for logical grouping and categorization of messages. +externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation for this message. +bindings | [Message Bindings Object](#messageBindingsObject) \| [Reference Object](#referenceObject) | A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the message. +examples | [[Message Example Object](#messageExampleObject)] | List of examples. +traits | [[Message Trait Object](#messageTraitObject) | [Reference Object](#referenceObject)] | A list of traits to apply to the message object. Traits MUST be merged using [traits merge mechanism](#traits-merge-mechanism). The resulting object MUST be a valid [Message Object](#messageObject). + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +##### Message Object Example + + +```json +{ + "name": "UserSignup", + "title": "User signup", + "summary": "Action to sign a user up.", + "description": "A longer description", + "contentType": "application/json", + "tags": [ + { "name": "user" }, + { "name": "signup" }, + { "name": "register" } + ], + "headers": { + "type": "object", + "properties": { + "correlationId": { + "description": "Correlation ID set by application", + "type": "string" + }, + "applicationInstanceId": { + "description": "Unique identifier for a given instance of the publishing application", + "type": "string" + } + } + }, + "payload": { + "type": "object", + "properties": { + "user": { + "$ref": "#/components/schemas/userCreate" + }, + "signup": { + "$ref": "#/components/schemas/signup" + } + } + }, + "correlationId": { + "description": "Default Correlation ID", + "location": "$message.header#/correlationId" + }, + "traits": [ + { "$ref": "#/components/messageTraits/commonHeaders" } + ], + "examples": [ + { + "name": "SimpleSignup", + "summary": "A simple UserSignup example message", + "headers": { + "correlationId": "my-correlation-id", + "applicationInstanceId": "myInstanceId" + }, + "payload": { + "user": { + "someUserKey": "someUserValue" + }, + "signup": { + "someSignupKey": "someSignupValue" + } + } + } + ] +} +``` + + +```yaml +name: UserSignup +title: User signup +summary: Action to sign a user up. +description: A longer description +contentType: application/json +tags: + - name: user + - name: signup + - name: register +headers: + type: object + properties: + correlationId: + description: Correlation ID set by application + type: string + applicationInstanceId: + description: Unique identifier for a given instance of the publishing application + type: string +payload: + type: object + properties: + user: + $ref: '#/components/schemas/userCreate' + signup: + $ref: '#/components/schemas/signup' +correlationId: + description: Default Correlation ID + location: $message.header#/correlationId +traits: + - $ref: '#/components/messageTraits/commonHeaders' +examples: + - name: SimpleSignup + summary: A simple UserSignup example message + headers: + correlationId: my-correlation-id + applicationInstanceId: myInstanceId + payload: + user: + someUserKey: someUserValue + signup: + someSignupKey: someSignupValue +``` + +Example using Avro to define the payload: + + +```json +{ + "name": "UserSignup", + "title": "User signup", + "summary": "Action to sign a user up.", + "description": "A longer description", + "tags": [ + { "name": "user" }, + { "name": "signup" }, + { "name": "register" } + ], + "payload": { + "schemaFormat": "application/vnd.apache.avro+json;version=1.9.0", + "schema": { + "$ref": "./user-create.avsc" + } + } +} +``` + + +```yaml +name: UserSignup +title: User signup +summary: Action to sign a user up. +description: A longer description +tags: + - name: user + - name: signup + - name: register +payload: + schemaFormat: 'application/vnd.apache.avro+yaml;version=1.9.0' + schema: + $ref: './user-create.avsc' +``` + +#### Message Trait Object + +Describes a trait that MAY be applied to a [Message Object](#messageObject). This object MAY contain any property from the [Message Object](#messageObject), except `payload` and `traits`. + +If you're looking to apply traits to an operation, see the [Operation Trait Object](#operationTraitObject). + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +headers | [Multi Format Schema Object](#multiFormatSchemaObject) | [Schema Object](#schemaObject) | [Reference Object](#referenceObject) | Schema definition of the application headers. Schema MUST be a map of key-value pairs. It **MUST NOT** define the protocol headers. If this is a [Schema Object](#schemaObject), then the `schemaFormat` will be assumed to be "application/vnd.aai.asyncapi+json;version=`asyncapi`" where the version is equal to the [AsyncAPI Version String](#A2SVersionString). +correlationId | [Correlation ID Object](#correlationIdObject) | [Reference Object](#referenceObject) | Definition of the correlation ID used for message tracing or matching. +contentType | `string` | The content type to use when encoding/decoding a message's payload. The value MUST be a specific media type (e.g. `application/json`). When omitted, the value MUST be the one specified on the [defaultContentType](#defaultContentTypeString) field. +name | `string` | A machine-friendly name for the message. +title | `string` | A human-friendly title for the message. +summary | `string` | A short summary of what the message is about. +description | `string` | A verbose explanation of the message. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation. +tags | [Tags Object](#tagsObject) | A list of tags for logical grouping and categorization of messages. +externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation for this message. +bindings | [Message Bindings Object](#messageBindingsObject) \| [Reference Object](#referenceObject) | A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the message. +examples | [[Message Example Object](#messageExampleObject)] | List of examples. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +##### Message Trait Object Example + + +```json +{ + "contentType": "application/json" +} +``` + + +```yaml +contentType: application/json +``` + +#### Message Example Object + +Message Example Object represents an example of a [Message Object](#messageObject) and MUST contain either **headers** and/or **payload** fields. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +headers | `Map[string, any]` | The value of this field MUST validate against the [Message Object's headers](#messageObjectHeaders) field. +payload | `any` | The value of this field MUST validate against the [Message Object's payload](#messageObjectPayload) field. +name | `string` | A machine-friendly name. +summary | `string` | A short summary of what the example is about. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +##### Message Example Object Example + + +```json +{ + "name": "SimpleSignup", + "summary": "A simple UserSignup example message", + "headers": { + "correlationId": "my-correlation-id", + "applicationInstanceId": "myInstanceId" + }, + "payload": { + "user": { + "someUserKey": "someUserValue" + }, + "signup": { + "someSignupKey": "someSignupValue" + } + } +} +``` + + +```yaml +name: SimpleSignup +summary: A simple UserSignup example message +headers: + correlationId: my-correlation-id + applicationInstanceId: myInstanceId +payload: + user: + someUserKey: someUserValue + signup: + someSignupKey: someSignupValue +``` + +#### Tags Object + +A Tags object is a list of [Tag Objects](#tagObject). An [Tag Object](#tagObject) in a list can be referenced by [Reference Object](#referenceObject). + +#### Tag Object + +Allows adding meta data to a single tag. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +name | `string` | **REQUIRED.** The name of the tag. +description | `string` | A short description for the tag. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation. +externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation for this tag. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +##### Tag Object Example + + +```json +{ + "name": "user", + "description": "User-related messages" +} +``` + + +```yaml +name: user +description: User-related messages +``` + +#### External Documentation Object + +Allows referencing an external resource for extended documentation. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +description | `string` | A short description of the target documentation. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation. +url | `string` | **REQUIRED.** The URL for the target documentation. This MUST be in the form of an absolute URL. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +##### External Documentation Object Example + + +```json +{ + "description": "Find more info here", + "url": "https://example.com" +} +``` + + +```yaml +description: Find more info here +url: https://example.com +``` + +#### Reference Object + +A simple object to allow referencing other components in the specification, internally and externally. + +The Reference Object is defined by [JSON Reference](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03) and follows the same structure, behavior and rules. A JSON Reference SHALL only be used to refer to a schema that is formatted in either JSON or YAML. In the case of a YAML-formatted Schema, the JSON Reference SHALL be applied to the JSON representation of that schema. The JSON representation SHALL be made by applying the conversion described [here](#format). + +For this specification, reference resolution is done as defined by the JSON Reference specification and not by the JSON Schema specification. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +$ref | `string` | **REQUIRED.** The reference string. + +This object cannot be extended with additional properties and any properties added SHALL be ignored. + +##### Reference Object Example + + +```json +{ + "$ref": "#/components/schemas/Pet" +} +``` + + +```yaml + $ref: '#/components/schemas/Pet' +``` + +#### Components Object + +Holds a set of reusable objects for different aspects of the AsyncAPI specification. +All objects defined within the components object will have no effect on the API unless they are explicitly referenced from properties outside the components object. + +##### Fixed Fields + +Field Name | Type | Description +---|:---|--- + schemas | Map[`string`, [Multi Format Schema Object](#multiFormatSchemaObject) \| [Schema Object](#schemaObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Schema Object](#schemaObject). If this is a [Schema Object](#schemaObject), then the `schemaFormat` will be assumed to be "application/vnd.aai.asyncapi+json;version=`asyncapi`" where the version is equal to the [AsyncAPI Version String](#A2SVersionString). + servers | Map[`string`, [Server Object](#serverObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Server Objects](#serverObject). + channels | Map[`string`, [Channel Object](#channelObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Channel Objects](#channelObject). + operations | Map[`string`, [Operation Object](#operationObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Operation Objects](#operationObject). + messages | Map[`string`, [Message Object](#messageObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Message Objects](#messageObject). + securitySchemes| Map[`string`, [Security Scheme Object](#securitySchemeObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Security Scheme Objects](#securitySchemeObject). + serverVariables | Map[`string`, [Server Variable Object](#serverVariableObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Server Variable Objects](#serverVariableObject). + parameters | Map[`string`, [Parameter Object](#parameterObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Parameter Objects](#parameterObject). + correlationIds | Map[`string`, [Correlation ID Object](#correlationIdObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Correlation ID Objects](#correlationIdObject). +replies | Map[`string`, [Operation Reply Object](#operationReplyObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Operation Reply Objects](#operationReplyObject). + replyAddresses | Map[`string`, [Operation Reply Address Object](#operationReplyAddressObject) | [Reference Object](#referenceObject)] | An object to hold reusable [Operation Reply Address Objects](#operationReplyAddressObject). + externalDocs | Map[`string`, [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [External Documentation Objects](#externalDocumentationObject). + tags | Map[`string`, [Tag Object](#tagObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Tag Objects](#tagObject). + operationTraits | Map[`string`, [Operation Trait Object](#operationTraitObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Operation Trait Objects](#operationTraitObject). + messageTraits | Map[`string`, [Message Trait Object](#messageTraitObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Message Trait Objects](#messageTraitObject). + serverBindings | Map[`string`, [Server Bindings Object](#serverBindingsObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Server Bindings Objects](#serverBindingsObject). + channelBindings | Map[`string`, [Channel Bindings Object](#channelBindingsObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Channel Bindings Objects](#channelBindingsObject). + operationBindings | Map[`string`, [Operation Bindings Object](#operationBindingsObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Operation Bindings Objects](#operationBindingsObject). + messageBindings | Map[`string`, [Message Bindings Object](#messageBindingsObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Message Bindings Objects](#messageBindingsObject). + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +All the fixed fields declared above are objects that MUST use keys that match the regular expression: `^[a-zA-Z0-9\.\-_]+$`. + +Field Name Examples: + +```text +User +User_1 +User_Name +user-name +my.org.User +``` + +##### Components Object Example + + +```json +{ + "components": { + "schemas": { + "Category": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + } + }, + "Tag": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + } + }, + "AvroExample": { + "schemaFormat": "application/vnd.apache.avro+json;version=1.9.0", + "schema": { + "$ref": "./user-create.avsc" + } + } + }, + "servers": { + "development": { + "host": "{stage}.in.mycompany.com:{port}", + "description": "RabbitMQ broker", + "protocol": "amqp", + "protocolVersion": "0-9-1", + "variables": { + "stage": { + "$ref": "#/components/serverVariables/stage" + }, + "port": { + "$ref": "#/components/serverVariables/port" + } + } + } + }, + "serverVariables": { + "stage": { + "default": "demo", + "description": "This value is assigned by the service provider, in this example `mycompany.com`" + }, + "port": { + "enum": ["5671", "5672"], + "default": "5672" + } + }, + "channels": { + "user/signedup": { + "subscribe": { + "message": { + "$ref": "#/components/messages/userSignUp" + } + } + } + }, + "messages": { + "userSignUp": { + "summary": "Action to sign a user up.", + "description": "Multiline description of what this action does.\nHere you have another line.\n", + "tags": [ + { + "name": "user" + }, + { + "name": "signup" + } + ], + "headers": { + "type": "object", + "properties": { + "applicationInstanceId": { + "description": "Unique identifier for a given instance of the publishing application", + "type": "string" + } + } + }, + "payload": { + "type": "object", + "properties": { + "user": { + "$ref": "#/components/schemas/userCreate" + }, + "signup": { + "$ref": "#/components/schemas/signup" + } + } + } + } + }, + "parameters": { + "userId": { + "description": "Id of the user." + } + }, + "correlationIds": { + "default": { + "description": "Default Correlation ID", + "location": "$message.header#/correlationId" + } + }, + "messageTraits": { + "commonHeaders": { + "headers": { + "type": "object", + "properties": { + "my-app-header": { + "type": "integer", + "minimum": 0, + "maximum": 100 + } + } + } + } + } + } +} +``` + + +```yaml +components: + schemas: + Category: + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + Tag: + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + AvroExample: + schemaFormat: 'application/vnd.apache.avro+json;version=1.9.0' + schema: + $ref: './user-create.avsc' + servers: + development: + host: '{stage}.in.mycompany.com:{port}' + description: RabbitMQ broker + protocol: amqp + protocolVersion: 0-9-1 + variables: + stage: + $ref: '#/components/serverVariables/stage' + port: + $ref: '#/components/serverVariables/port' + serverVariables: + stage: + default: demo + description: | + This value is assigned by the service provider, in this example + `mycompany.com` + port: + enum: + - '5671' + - '5672' + default: '5672' + channels: + user/signedup: + subscribe: + message: + $ref: '#/components/messages/userSignUp' + messages: + userSignUp: + summary: Action to sign a user up. + description: | + Multiline description of what this action does. + Here you have another line. + tags: + - name: user + - name: signup + headers: + type: object + properties: + applicationInstanceId: + description: | + Unique identifier for a given instance of the publishing + application + type: string + payload: + type: object + properties: + user: + $ref: '#/components/schemas/userCreate' + signup: + $ref: '#/components/schemas/signup' + parameters: + userId: + description: Id of the user. + correlationIds: + default: + description: Default Correlation ID + location: '$message.header#/correlationId' + messageTraits: + commonHeaders: + headers: + type: object + properties: + my-app-header: + type: integer + minimum: 0 + maximum: 100 +``` + +#### Multi Format Schema Object + +The Multi Format Schema Object represents a schema definition. It differs from the [Schema Object](#schemaObject) in that it supports multiple schema formats or languages (e.g., JSON Schema, Avro, etc.). + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +schemaFormat | `string` | **Required**. A string containing the name of the schema format that is used to define the information. If `schemaFormat` is missing, it MUST default to `application/vnd.aai.asyncapi+json;version={{asyncapi}}` where `{{asyncapi}}` matches the [AsyncAPI Version String](#A2SVersionString). In such a case, this would make the Multi Format Schema Object equivalent to the [Schema Object](#schemaObject). When using [Reference Object](#referenceObject) within the schema, the `schemaFormat` of the resource being referenced MUST match the `schemaFormat` of the schema that contains the initial reference. For example, if you reference Avro `schema`, then `schemaFormat` of referencing resource and the resource being reference MUST match.

    Check out the [supported schema formats table](#multiFormatSchemaFormatTable) for more information. Custom values are allowed but their implementation is OPTIONAL. A custom value MUST NOT refer to one of the schema formats listed in the [table](#multiFormatSchemaFormatTable).

    When using [Reference Objects](#referenceObject) within the schema, the `schemaFormat` of the referenced resource MUST match the `schemaFormat` of the schema containing the reference. +schema | `any` | **Required**. Definition of the message payload. It can be of any type but defaults to [Schema Object](#schemaObject). It MUST match the schema format defined in [`schemaFormat`](#multiFormatSchemaObjectSchemaFormat), including the encoding type. E.g., Avro should be inlined as either a YAML or JSON object instead of as a string to be parsed as YAML or JSON. Non-JSON-based schemas (e.g., Protobuf or XSD) MUST be inlined as a string. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +##### Schema formats table + +The following table contains a set of values that every implementation MUST support. + +Name | Allowed values | Notes +---|:---:|--- +[AsyncAPI 3.1.0 Schema Object](#schemaObject) | `application/vnd.aai.asyncapi;version=3.1.0`, `application/vnd.aai.asyncapi+json;version=3.1.0`, `application/vnd.aai.asyncapi+yaml;version=3.1.0` | This is the default when a `schemaFormat` is not provided. +[JSON Schema Draft 07](https://json-schema.org/specification-links.html#draft-7) | `application/schema+json;version=draft-07`, `application/schema+yaml;version=draft-07` | + +The following table contains a set of values that every implementation is RECOMMENDED to support. + +Name | Allowed values | Notes +---|:---:|--- +[Avro 1.9.0 schema](https://avro.apache.org/docs/1.9.0/spec.html#schemas) | `application/vnd.apache.avro;version=1.9.0`, `application/vnd.apache.avro+json;version=1.9.0`, `application/vnd.apache.avro+yaml;version=1.9.0` | +[OpenAPI 3.0.0 Schema Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject) | `application/vnd.oai.openapi;version=3.0.0`, `application/vnd.oai.openapi+json;version=3.0.0`, `application/vnd.oai.openapi+yaml;version=3.0.0` | +[RAML 1.0 data type](https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md/) | `application/raml+yaml;version=1.0` | +[Protocol Buffers](https://protobuf.dev/) | `application/vnd.google.protobuf;version=2`, `application/vnd.google.protobuf;version=3` | + +##### Multi Format Schema Object Examples + +###### Multi Format Schema Object Example with Avro + + +```yaml +channels: + example: + messages: + myMessage: + payload: + schemaFormat: 'application/vnd.apache.avro;version=1.9.0' + schema: + type: record + name: User + namespace: com.company + doc: User information + fields: + - name: displayName + type: string + - name: age + type: int +``` + +#### Schema Object + +The Schema Object allows the definition of input and output data types. +These types can be objects, but also primitives and arrays. This object is a superset of the [JSON Schema Specification Draft 07](https://json-schema.org/). The empty schema (which allows any instance to validate) MAY be represented by the `boolean` value `true` and a schema which allows no instance to validate MAY be represented by the `boolean` value `false`. + +Further information about the properties can be found in [JSON Schema Core](https://tools.ietf.org/html/draft-handrews-json-schema-01) and [JSON Schema Validation](https://tools.ietf.org/html/draft-handrews-json-schema-validation-01). +Unless stated otherwise, the property definitions follow the JSON Schema specification as referenced here. For other formats (e.g., Avro, RAML, etc) see [Multi Format Schema Object](#multiFormatSchemaObject). + +##### Properties + +The AsyncAPI Schema Object is a JSON Schema vocabulary which extends JSON Schema Core and Validation vocabularies. As such, any keyword available for those vocabularies is by definition available in AsyncAPI, and will work the exact same way, including but not limited to: + +- title +- type +- required +- multipleOf +- maximum +- exclusiveMaximum +- minimum +- exclusiveMinimum +- maxLength +- minLength +- pattern (This string SHOULD be a valid regular expression, according to the [ECMA 262 regular expression](https://www.ecma-international.org/ecma-262/5.1/#sec-7.8.5) dialect) +- maxItems +- minItems +- uniqueItems +- maxProperties +- minProperties +- enum +- const +- examples +- if / then / else +- readOnly +- writeOnly +- properties +- patternProperties +- additionalProperties +- additionalItems +- items +- propertyNames +- contains +- allOf +- oneOf +- anyOf +- not + +The following properties are taken from the JSON Schema definition but their definitions were adjusted to the AsyncAPI Specification. + +- description - [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation. +- format - See [Data Type Formats](#dataTypeFormat) for further details. While relying on JSON Schema's defined formats, the AsyncAPI Specification offers a few additional predefined formats. +- default - Use it to specify that property has a predefined value if no other value is present. Unlike JSON Schema, the value MUST conform to the defined type for the Schema Object defined at the same level. For example, of `type` is `string`, then `default` can be `"foo"` but cannot be `1`. + +Alternatively, any time a Schema Object can be used, a [Reference Object](#referenceObject) can be used in its place. This allows referencing definitions in place of defining them inline. It is appropriate to clarify that the `$ref` keyword MUST follow the behavior described by [Reference Object](#referenceObject) instead of the one in [JSON Schema definition](https://json-schema.org/understanding-json-schema/structuring.html#ref). + +In addition to the JSON Schema fields, the following AsyncAPI vocabulary fields MAY be used for further schema documentation: + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +discriminator | `string` | Adds support for polymorphism. The discriminator is the schema property name that is used to differentiate between other schema that inherit this schema. The property name used MUST be defined at this schema and it MUST be in the `required` property list. When used, the value MUST be the name of this schema or any schema that inherits it. See [Composition and Inheritance](#schemaComposition) for more details. +externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation for this schema. + deprecated | `boolean` | Specifies that a schema is deprecated and SHOULD be transitioned out of usage. Default value is `false`. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +###### Composition and Inheritance (Polymorphism) + +The AsyncAPI Specification allows combining and extending model definitions using the `allOf` property of JSON Schema, in effect offering model composition. +`allOf` takes in an array of object definitions that are validated _independently_ but together compose a single object. + +While composition offers model extensibility, it does not imply a hierarchy between the models. +To support polymorphism, AsyncAPI Specification adds the support of the `discriminator` field. +When used, the `discriminator` will be the name of the property used to decide which schema definition is used to validate the structure of the model. +As such, the `discriminator` field MUST be a required field. +There are two ways to define the value of a discriminator for an inheriting instance. + +- Use the schema's name. +- Override the schema's name by overriding the property with a new value. If exists, this takes precedence over the schema's name. + +As such, inline schema definitions, which do not have a given id, _cannot_ be used in polymorphism. + +##### Schema Object Examples + +###### Primitive Sample + + +```json +{ + "type": "string", + "format": "email" +} +``` + + +```yaml +type: string +format: email +``` + +###### Simple Model + + +```json +{ + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "address": { + "$ref": "#/components/schemas/Address" + }, + "age": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } +} +``` + + +```yaml +type: object +required: +- name +properties: + name: + type: string + address: + $ref: '#/components/schemas/Address' + age: + type: integer + format: int32 + minimum: 0 +``` + +###### Model with Map/Dictionary Properties + +For a simple string to string mapping: + + +```json +{ + "type": "object", + "additionalProperties": { + "type": "string" + } +} +``` + + +```yaml +type: object +additionalProperties: + type: string +``` + +For a string to model mapping: + + +```json +{ + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/ComplexModel" + } +} +``` + + +```yaml +type: object +additionalProperties: + $ref: '#/components/schemas/ComplexModel' +``` + +###### Model with Example + + +```json +{ + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "required": [ + "name" + ], + "examples": [ + { + "name": "Puma", + "id": 1 + } + ] +} +``` + + +```yaml +type: object +properties: + id: + type: integer + format: int64 + name: + type: string +required: +- name +examples: +- name: Puma + id: 1 +``` + +###### Model with Boolean Schemas + + +```json +{ + "type": "object", + "required": [ + "anySchema" + ], + "properties": { + "anySchema": true, + "cannotBeDefined": false + } +} +``` + + +```yaml +type: object +required: +- anySchema +properties: + anySchema: true + cannotBeDefined: false +``` + +###### Models with Composition + + +```json +{ + "schemas": { + "ErrorModel": { + "type": "object", + "required": [ + "message", + "code" + ], + "properties": { + "message": { + "type": "string" + }, + "code": { + "type": "integer", + "minimum": 100, + "maximum": 600 + } + } + }, + "ExtendedErrorModel": { + "allOf": [ + { + "$ref": "#/components/schemas/ErrorModel" + }, + { + "type": "object", + "required": [ + "rootCause" + ], + "properties": { + "rootCause": { + "type": "string" + } + } + } + ] + } + } +} +``` + + +```yaml +schemas: + ErrorModel: + type: object + required: + - message + - code + properties: + message: + type: string + code: + type: integer + minimum: 100 + maximum: 600 + ExtendedErrorModel: + allOf: + - $ref: '#/components/schemas/ErrorModel' + - type: object + required: + - rootCause + properties: + rootCause: + type: string +``` + +###### Models with Polymorphism Support + + +```json +{ + "schemas": { + "Pet": { + "type": "object", + "discriminator": "petType", + "properties": { + "name": { + "type": "string" + }, + "petType": { + "type": "string" + } + }, + "required": [ + "name", + "petType" + ] + }, + "Cat": { + "description": "A representation of a cat. Note that `Cat` will be used as the discriminator value.", + "allOf": [ + { + "$ref": "#/components/schemas/Pet" + }, + { + "type": "object", + "properties": { + "huntingSkill": { + "type": "string", + "description": "The measured skill for hunting", + "enum": [ + "clueless", + "lazy", + "adventurous", + "aggressive" + ] + } + }, + "required": [ + "huntingSkill" + ] + } + ] + }, + "Dog": { + "description": "A representation of a dog. Note that `Dog` will be used as the discriminator value.", + "allOf": [ + { + "$ref": "#/components/schemas/Pet" + }, + { + "type": "object", + "properties": { + "packSize": { + "type": "integer", + "format": "int32", + "description": "the size of the pack the dog is from", + "minimum": 0 + } + }, + "required": [ + "packSize" + ] + } + ] + }, + "StickInsect": { + "description": "A representation of an Australian walking stick. Note that `StickBug` will be used as the discriminator value.", + "allOf": [ + { + "$ref": "#/components/schemas/Pet" + }, + { + "type": "object", + "properties": { + "petType": { + "const": "StickBug" + }, + "color": { + "type": "string" + } + }, + "required": [ + "color" + ] + } + ] + } + } +} +``` + + +```yaml +schemas: + Pet: + type: object + discriminator: petType + properties: + name: + type: string + petType: + type: string + required: + - name + - petType + ## applies to instances with `petType: "Cat"` + ## because that is the schema name + Cat: + description: A representation of a cat + allOf: + - $ref: '#/components/schemas/Pet' + - type: object + properties: + huntingSkill: + type: string + description: The measured skill for hunting + enum: + - clueless + - lazy + - adventurous + - aggressive + required: + - huntingSkill + ## applies to instances with `petType: "Dog"` + ## because that is the schema name + Dog: + description: A representation of a dog + allOf: + - $ref: '#/components/schemas/Pet' + - type: object + properties: + packSize: + type: integer + format: int32 + description: the size of the pack the dog is from + minimum: 0 + required: + - packSize + ## applies to instances with `petType: "StickBug"` + ## because that is the required value of the discriminator field, + ## overriding the schema name + StickInsect: + description: A representation of an Australian walking stick + allOf: + - $ref: '#/components/schemas/Pet' + - type: object + properties: + petType: + const: StickBug + color: + type: string + required: + - color +``` + +#### Security Scheme Object + +Defines a security scheme that can be used by the operations. Supported schemes are: + +- User/Password. +- API key (either as user or as password). +- X.509 certificate. +- End-to-end encryption (either symmetric or asymmetric). +- HTTP authentication. +- HTTP API key. +- OAuth2's common flows (Implicit, Resource Owner Protected Credentials, Client Credentials and Authorization Code) as defined in [RFC6749](https://tools.ietf.org/html/rfc6749). +- [OpenID Connect Discovery](https://tools.ietf.org/html/draft-ietf-oauth-discovery-06). +- SASL (Simple Authentication and Security Layer) as defined in [RFC4422](https://tools.ietf.org/html/rfc4422). + +##### Fixed Fields + +Field Name | Type | Applies To | Description +---|:---:|---|--- +type | `string` | Any | **REQUIRED**. The type of the security scheme. Valid values are `"userPassword"`, `"apiKey"`, `"X509"`, `"symmetricEncryption"`, `"asymmetricEncryption"`, `"httpApiKey"`, `"http"`, `"oauth2"`, `"openIdConnect"`, `"plain"`, `"scramSha256"`, `"scramSha512"`, and `"gssapi"`. +description | `string` | Any | A short description for security scheme. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. +name | `string` | `httpApiKey` | **REQUIRED**. The name of the header, query or cookie parameter to be used. +in | `string` | `apiKey` \| `httpApiKey` | **REQUIRED**. The location of the API key. Valid values are `"user"` and `"password"` for `apiKey` and `"query"`, `"header"` or `"cookie"` for `httpApiKey`. +scheme | `string` | `http` | **REQUIRED**. The name of the HTTP Authorization scheme to be used in the [Authorization header as defined in RFC7235](https://tools.ietf.org/html/rfc7235#section-5.1). +bearerFormat | `string` | `http` (`"bearer"`) | A hint to the client to identify how the bearer token is formatted. Bearer tokens are usually generated by an authorization server, so this information is primarily for documentation purposes. +flows | [OAuth Flows Object](#oauthFlowsObject) | `oauth2` | **REQUIRED**. An object containing configuration information for the flow types supported. +openIdConnectUrl | `string` | `openIdConnect` | **REQUIRED**. OpenId Connect URL to discover OAuth2 configuration values. This MUST be in the form of an absolute URL. +scopes | [`string`] | `oauth2` \| `openIdConnect` | List of the needed scope names. An empty array means no scopes are needed. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +##### Security Scheme Object Example + +###### User/Password Authentication Sample + + +```json +{ + "type": "userPassword" +} +``` + + +```yaml +type: userPassword +``` + +###### API Key Authentication Sample + + +```json +{ + "type": "apiKey", + "in": "user" +} +``` + + +```yaml +type: apiKey +in: user +``` + +###### X.509 Authentication Sample + + +```json +{ + "type": "X509" +} +``` + + +```yaml +type: X509 +``` + +###### End-to-end Encryption Authentication Sample + + +```json +{ + "type": "symmetricEncryption" +} +``` + + +```yaml +type: symmetricEncryption +``` + +###### Basic Authentication Sample + + +```json +{ + "type": "http", + "scheme": "basic" +} +``` + + +```yaml +type: http +scheme: basic +``` + +###### API Key Sample + + +```json +{ + "type": "httpApiKey", + "name": "api_key", + "in": "header" +} +``` + + +```yaml +type: httpApiKey +name: api_key +in: header +``` + +###### JWT Bearer Sample + + +```json +{ + "type": "http", + "scheme": "bearer", + "bearerFormat": "JWT" +} +``` + + +```yaml +type: http +scheme: bearer +bearerFormat: JWT +``` + +###### Implicit OAuth2 Sample + + +```json +{ + "type": "oauth2", + "flows": { + "implicit": { + "authorizationUrl": "https://example.com/api/oauth/dialog", + "availableScopes": { + "write:pets": "modify pets in your account", + "read:pets": "read your pets" + } + } + }, + "scopes": [ + "write:pets" + ] +} +``` + + +```yaml +type: oauth2 +flows: + implicit: + authorizationUrl: https://example.com/api/oauth/dialog + availableScopes: + write:pets: modify pets in your account + read:pets: read your pets +scopes: + - 'write:pets' +``` + +###### SASL Sample + + +```json +{ + "type": "scramSha512" +} +``` + + +```yaml +type: scramSha512 +``` + +#### OAuth Flows Object + +Allows configuration of the supported OAuth Flows. + +##### Fixed Fields + +Field Name | Type | Description +---|:---:|--- +implicit| [OAuth Flow Object](#oauthFlowObject) | Configuration for the OAuth Implicit flow. +password| [OAuth Flow Object](#oauthFlowObject) | Configuration for the OAuth Resource Owner Protected Credentials flow. +clientCredentials| [OAuth Flow Object](#oauthFlowObject) | Configuration for the OAuth Client Credentials flow. +authorizationCode| [OAuth Flow Object](#oauthFlowObject) | Configuration for the OAuth Authorization Code flow. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +#### OAuth Flow Object + +Configuration details for a supported OAuth Flow + +##### Fixed Fields + +Field Name | Type | Applies To | Description +---|:---:|---|--- +authorizationUrl | `string` | `oauth2` (`"implicit"`, `"authorizationCode"`) | **REQUIRED**. The authorization URL to be used for this flow. This MUST be in the form of an absolute URL. +tokenUrl | `string` | `oauth2` (`"password"`, `"clientCredentials"`, `"authorizationCode"`) | **REQUIRED**. The token URL to be used for this flow. This MUST be in the form of an absolute URL. +refreshUrl | `string` | `oauth2` | The URL to be used for obtaining refresh tokens. This MUST be in the form of an absolute URL. +availableScopes | Map[`string`, `string`] | `oauth2` | **REQUIRED**. The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +##### OAuth Flow Object Examples + +###### clientCredentials Oauth Flow Object Example + + +```json +{ + "tokenUrl": "https://example.com/api/oauth/token", + "availableScopes": { + "write:pets": "modify pets in your account", + "read:pets": "read your pets" + } +} +``` + +```yaml +tokenUrl: https://example.com/api/oauth/token +availableScopes: + write:pets: modify pets in your account + read:pets: read your pets +``` + +### Correlation ID Object + +An object that specifies an identifier at design time that can used for message tracing and correlation. + +For specifying and computing the location of a Correlation ID, a [runtime expression](#runtimeExpression) is used. + +#### Fixed Fields + +Field Name | Type | Description +---|:---|--- +description | `string` | An optional description of the identifier. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation. +location | `string` | **REQUIRED.** A [runtime expression](#runtimeExpression) that specifies the location of the correlation ID. + +This object MAY be extended with [Specification Extensions](#specificationExtensions). + +##### Examples + + +```json +{ + "description": "Default Correlation ID", + "location": "$message.header#/correlationId" +} +``` + + +```yaml +description: Default Correlation ID +location: $message.header#/correlationId +``` + +### Runtime Expression + +A runtime expression allows values to be defined based on information that will be available within the message. +This mechanism is used by [Correlation ID Object](#correlationIdObject) and [Operation Reply Address Object](#operationReplyAddressObject). + +The runtime expression is defined by the following [ABNF](https://tools.ietf.org/html/rfc5234) syntax: + +```text + expression = ( "$message" "." source ) + source = ( header-reference | payload-reference ) + header-reference = "header" ["#" fragment] + payload-reference = "payload" ["#" fragment] + fragment = a JSON Pointer [RFC 6901](https://tools.ietf.org/html/rfc6901) +``` + +The table below provides examples of runtime expressions and examples of their use in a value: + +#### Examples + +Source Location | Example expression | Notes +---|:---|:---| +Message Header Property | `$message.header#/MQMD/CorrelId` | Correlation ID is set using the `CorrelId` value from the `MQMD` header. +Message Payload Property | `$message.payload#/messageId` | Correlation ID is set using the `messageId` value from the message payload. + +Runtime expressions preserve the type of the referenced value. + +### Traits Merge Mechanism + +Traits MUST be merged with the target object using the [JSON Merge Patch](https://tools.ietf.org/html/rfc7386) algorithm in the same order they are defined. A property on a trait MUST NOT override the same property on the target object. + +#### Example + +An object like the following: + +```yaml +description: A longer description. +traits: + - name: UserSignup + description: Description from trait. + - tags: + - name: user +``` + +Would look like the following after applying traits: + +```yaml +name: UserSignup +description: A longer description. +tags: + - name: user +``` + +### Specification Extensions + +While the AsyncAPI Specification tries to accommodate most use cases, additional data can be added to extend the specification at certain points. + +The extensions properties are implemented as patterned fields that are always prefixed by `"x-"`. + +Field Pattern | Type | Description +---|:---:|--- +`^x-[\w\d\.\x2d_]+$` | Any | Allows extensions to the AsyncAPI Schema. The field name MUST begin with `x-`, for example, `x-internal-id`. The value can be `null`, a primitive, an array or an object. Can have any valid JSON format value. + +The extensions may or may not be supported by the available tooling, but those may be extended as well to add requested support (if tools are internal or open-sourced). + +### Data Type Formats + +Primitives have an optional modifier property: `format`. +The AsyncAPI specification uses several known formats to more finely define the data type being used. +However, the `format` property is an open `string`-valued property, and can have any value to support documentation needs. +Formats such as `"email"`, `"uuid"`, etc., can be used even though they are not defined by this specification. +Types that are not accompanied by a `format` property follow their definition from the JSON Schema. +Tools that do not recognize a specific `format` MAY default back to the `type` alone, as if the `format` was not specified. + +The formats defined by the AsyncAPI Specification are: + +Common Name | `type` | [`format`](#dataTypeFormat) | Comments +----------- | ------ | -------- | -------- +integer | `integer` | `int32` | signed 32 bits +long | `integer` | `int64` | signed 64 bits +float | `number` | `float` | | +double | `number` | `double` | | +string | `string` | | | +byte | `string` | `byte` | base64 encoded characters +binary | `string` | `binary` | any sequence of octets +boolean | `boolean` | | | +date | `string` | `date` | As defined by `full-date` - [RFC3339](https://www.rfc-editor.org/rfc/rfc3339.html#section-5.6) +dateTime | `string` | `date-time` | As defined by `date-time` - [RFC3339](https://www.rfc-editor.org/rfc/rfc3339.html#section-5.6) +password | `string` | `password` | Used to hint UIs the input needs to be obscured. diff --git a/markdown/docs/tools/cli/architecture.md b/markdown/docs/tools/cli/architecture.md index 053a51ae0d5e..362a5928c248 100644 --- a/markdown/docs/tools/cli/architecture.md +++ b/markdown/docs/tools/cli/architecture.md @@ -3,95 +3,150 @@ title: 'CLI Architecture' weight: 40 --- -The AsyncAPI CLI uses oclif (Open CLI Framework) as its core framework, which enables developers to build powerful and scalable command-line applications. +# CLI Architecture -**Structure of the AsyncAPI CLI**: The CLI is primarily divided into two components: commands and the core part. +## Overview -1. **Command Component**: The commands include all the necessary functionalities that help developers interact with features like creating new AsyncAPI projects, validating AsyncAPI files, formatting AsyncAPI files, and more. -2. **Core Component**: The core part of the CLI contains various utilities that facilitate the efficient creation of new commands. +The AsyncAPI CLI is built with [oclif](https://oclif.io/) and provides both command-line operations and a REST API server for working with AsyncAPI specifications. --- -### Detailed Explanation of Key Directories in the CLI - -#### `src/commands/` -- **Purpose:** Implements the CLI commands available to the user. -- **Subdirectories:** - - `config/`: Stores configuration-related files for commands. - - `generate/`: Generates typed models or other artifacts like clients, applications, or documentation using AsyncAPI Generator templates. - - **Files:** - - `fromTemplate.ts`: Contains logic for generating files using templates. - - `models.ts`: Defines the models used during generation. - - `new/`: Create a new AsyncAPI project, specification files, or templates for clients and applications. - - **Files:** - - `file.ts`: Handles file creation logic. - - `template.ts`: Manages templates for new projects. - - `start/`: Implements starting functionalities like launching a local server or studio. - - **Files:** - - `studio.ts`: Integrates with the AsyncAPI Studio. - -- **Standalone Files:** - - `bundle.ts`: Bundles one or multiple AsyncAPI documents and their references together. - - `convert.ts`: Converts AsyncAPI documents from older to newer versions or transforms OpenAPI/Postman-collection documents into AsyncAPI. - - `diff.ts`: Compares two AsyncAPI documents. - - `format.ts`: Converts AsyncAPI documents from any format to YAML, YML, or JSON. - - `optimize.ts`: Optimizes AsyncAPI documents for performance. - - `pretty.ts`: Beautifies the AsyncAPI spec file (indentation, styling) in place or outputs the formatted spec to a new file. - - `validate.ts`: Validates AsyncAPI documents for correctness. +## Architecture Diagram + +``` +┌─────────────────────────────────────────────────┐ +│ Entry Points │ +│ ┌──────────┐ ┌──────────┐ │ +│ │ CLI │ │ API │ │ +│ │ (oclif) │ │ (Express)│ │ +│ └────┬─────┘ └────┬─────┘ │ +└───────┼─────────────────────────┼───────────────┘ + └───────────┬─────────────┘ + ▼ + ┌───────────────────────┐ + │ Domain Services │ + │ Validation, Generator│ + │ Convert, Config │ + └───────────┬───────────┘ + ▼ + ┌───────────────────────┐ + │ Domain Models │ + │ Specification,Context│ + └───────────┬───────────┘ + ▼ + ┌───────────────────────┐ + │ Utilities │ + │ Logger, Helpers │ + └───────────────────────┘ +``` --- -#### `src/core/` -- **Purpose:** Provides foundational components and utilities for the CLI. -- **Subdirectories:** - - `errors/`: Centralized error definitions. - - `flags/`: Defines CLI flags and their behavior. - - `hooks/`: Event hooks used for customization. - - `models/`: Core data models used across the application. - - `utils/`: Utility functions for common operations. - -- **Standalone Files:** - - `base.ts`: Base class or logic for CLI commands. - - `global.d.ts`: Global TypeScript definitions. - - `globals.ts`: Stores global variables and configurations. - - `parser.ts`: Parses AsyncAPI documents. +## Directory Structure + +``` +src/ +├── apps/ +│ ├── cli/ # CLI commands & internals +│ └── api/ # REST API (Express) +├── domains/ +│ ├── models/ # Specification, Context +│ └── services/ # Business logic +├── errors/ # Custom errors +├── interfaces/ # TypeScript types +└── utils/ # Utilities +``` --- -#### `test/` -- **Purpose:** Implements the test suite for the CLI. -- **Subdirectories:** - - `fixtures/`: Contains mock data or files for testing. - - `hooks/`: Tests related to hooks. - - `integration/`: Integration tests to verify end-to-end functionality. - - `system/`: System-level tests. - - `unit/`: Unit tests for individual modules or functions. +## Core Components + +### CLI Application + +| Component | Description | +|-----------|-------------| +| **Entry Points** | `bin/run` (dev), `bin/run_bin` (prod) | +| **Base Command** | Metrics, parser integration, error handling | + +**Commands:** +- **Core:** `validate`, `convert`, `format`, `optimize`, `diff`, `bundle` +- **Generation:** `generate client`, `generate models`, `generate fromTemplate` +- **Config:** `config context`, `config analytics`, `config versions` +- **Utility:** `new file`, `new template`, `start api|studio|preview`, `pretty` + +### API Server + +**Endpoints:** `/v1/validate`, `/v1/parse`, `/v1/generate`, `/v1/convert`, `/v1/bundle`, `/v1/diff`, `/v1/docs`, `/v1/help`, `/v1/version` + +**Features:** Express with Helmet security, CORS, compression, RFC 7807 error responses + +### Domain Services + +All services extend `BaseService` and return `ServiceResult`: + +| Service | Purpose | +|---------|---------| +| `ValidationService` | Validates specs with Spectral, calculates scores | +| `GeneratorService` | Generates code/models | +| `ConvertService` | Converts between AsyncAPI/OpenAPI formats | +| `ConfigService` | Manages CLI config and contexts | +| `ArchiverService` | Creates ZIP archives | + +### Domain Models + +| Model | Purpose | +|-------|---------| +| **Specification** | Loads from file, URL, or context; auto-detects `asyncapi.json\|yml\|yaml` | +| **Context** | Manages multiple AsyncAPI contexts; stored in `~/.asyncapi/` | + +### Error Classes + +`ContextError`, `SpecificationFileError`, `ValidationError`, `GeneratorError`, `DiffError` --- -### Use Cases +## Execution Flow -1. **Generate AsyncAPI Artifacts:** - - Use the `generate` command to create client/server code, documentation, or other artifacts based on AsyncAPI templates. +**CLI Command:** +``` +User Command → oclif → Base Command → Domain Service → ServiceResult +``` -2. **Create New Projects:** - - The `new` command helps users scaffold new AsyncAPI projects with predefined templates. +**API Request:** +``` +HTTP Request → Express → Controller → Domain Service → HTTP Response +``` -3. **Validate AsyncAPI Documents:** - - The `validate` command ensures AsyncAPI documents conform to the specification. +--- -4. **Optimize and Format Documents:** - - The `optimize` and `pretty` commands provide tools for improving document readability and performance. +## Extension Points -5. **Compare Documents:** - - The `diff` command enables comparison between two AsyncAPI documents to track changes. +| Add | Steps | +|-----|-------| +| **New Command** | Create in `src/apps/cli/commands/`, extend `Command`, implement `run()` | +| **New API Endpoint** | Create controller in `src/apps/api/controllers/`, register in `index.ts` | +| **New Service** | Create in `src/domains/services/`, extend `BaseService`, return `ServiceResult` | -6. **Integration with AsyncAPI Studio:** - - The `start` command integrates with the AsyncAPI Studio for editing and visualizing documents. +--- + +## Configuration -7. **Convert Between Formats:** - - The `convert` command supports converting AsyncAPI documents between formats like YAML and JSON. +| Config | Location | +|--------|----------| +| CLI Context | `~/.asyncapi/contexts.json`, `~/.asyncapi/.current` | +| Analytics | `~/.asyncapi-analytics` | + +**Environment Variables:** +- `NODE_ENV` — `development` | `production` | `test` +- `PORT` — API server port (default: 3000) +- `ASYNCAPI_METRICS_*` — Metrics configuration --- -This structure ensures the CLI is modular, scalable, and easy to maintain. Let me know if you need further clarification or additional details! \ No newline at end of file +## Technology Stack + +| Category | Technologies | +|----------|--------------| +| **Core** | oclif, TypeScript, Express | +| **AsyncAPI** | @asyncapi/parser, generator, converter, bundler, diff, optimizer | +| **Supporting** | winston, ajv, chalk, @clack/prompts | diff --git a/markdown/docs/tools/cli/contributing-prs.md b/markdown/docs/tools/cli/contributing-prs.md new file mode 100644 index 000000000000..0ff8b0e8a14c --- /dev/null +++ b/markdown/docs/tools/cli/contributing-prs.md @@ -0,0 +1,114 @@ +--- +title: 'Contributing via Pull Requests' +weight: 50 +--- + +# Contributing via Pull Requests + +## Getting Started + +1. **Open an issue first** (unless it's a trivial fix) +2. **Set up environment** — Follow [DEVELOPMENT.md](../DEVELOPMENT.md) +3. **Create a branch** — Use prefixes: `feat/`, `fix/`, `docs/`, `refactor/`, `test/`, `chore/` + +--- + +## PR Title Format + +Follow [Conventional Commits](https://www.conventionalcommits.org/): + +| Type | Description | Release | +|------|-------------|---------| +| `feat:` | New feature | MINOR | +| `fix:` | Bug fix | PATCH | +| `docs:` | Documentation | None | +| `chore:` | Maintenance | None | +| `test:` | Tests only | None | +| `refactor:` | Code refactoring | None | + +**Breaking changes:** Add `!` → `feat!:`, `fix!:` + +**Examples:** +- ✅ `feat: add AsyncAPI 3.0 validation support` +- ✅ `fix: resolve context loading with special characters` +- ❌ `Added new feature` +- ❌ `fix bug` + +--- + +## PR Checklist + +**Before submitting:** +- [ ] Branch synced with `main` +- [ ] `npm run build` passes +- [ ] `npm run cli:test` passes +- [ ] `npm run lint` passes (max 5 warnings) +- [ ] Documentation updated (if needed) + +**Code quality:** +- [ ] Follows existing code patterns +- [ ] TypeScript types used (avoid `any`) +- [ ] Error handling implemented +- [ ] Tests added for new functionality +- [ ] No `console.log` or commented code + +--- + +## Code Standards + +| Area | Guideline | +|------|-----------| +| **TypeScript** | Explicit types, interfaces for objects, prefer `const` | +| **Organization** | Follow existing structure, use path aliases (`@/`, `@cli/`, `@domains/`) | +| **Errors** | Use custom errors from `src/errors/`, return `ServiceResult` from services | +| **Commands** | Extend base `Command`, use domain services for business logic | + +--- + +## Testing + +**Add tests for:** +- New commands or API endpoints +- Bug fixes (regression tests) +- New domain services +- Complex business logic + +```bash +npm run cli:test # All tests +npm run unit:test # Unit tests only +``` + +--- + +## Best Practices + +| ❌ Avoid | ✅ Do | +|----------|-------| +| Large PRs (>500 lines) | Small, focused PRs | +| Multiple concerns in one PR | One issue per PR | +| Skipping tests | Comprehensive tests | +| Hardcoded values | Externalize configuration | +| Force push to main | Rebase instead of merge | + +--- + +## Review Process + +1. CI runs automated checks +2. Maintainers review code +3. Address feedback promptly +4. PR merged when approved + +--- + +## Quick Reference + +```bash +# Setup +npm install && npx lefthook install + +# Before PR +npm run build && npm run lint && npm run cli:test +``` + +**Quality over speed** — Write good code, tests, and documentation. diff --git a/markdown/docs/tools/cli/debugging-testing.md b/markdown/docs/tools/cli/debugging-testing.md new file mode 100644 index 000000000000..23f7f3d07c5c --- /dev/null +++ b/markdown/docs/tools/cli/debugging-testing.md @@ -0,0 +1,635 @@ +--- +title: 'Debugging & Testing Guide' +weight: 60 +--- + +# Debugging & Testing Guide + +This guide provides step-by-step instructions for debugging and testing the AsyncAPI CLI. Whether you're fixing a bug, adding a new feature, or understanding existing code, this document will help you navigate the debugging process effectively. + +## Table of Contents + +- [Project Structure Overview](#project-structure-overview) +- [Setting Up Your Environment](#setting-up-your-environment) +- [Debugging CLI Commands](#debugging-cli-commands) +- [Debugging the API Server](#debugging-the-api-server) +- [Debugging Services](#debugging-services) +- [Writing Tests](#writing-tests) +- [Running Tests](#running-tests) +- [Common Issues & Solutions](#common-issues--solutions) +- [Debugging Tools & Tips](#debugging-tools--tips) + +--- + +## Project Structure Overview + +Understanding the codebase structure is essential for effective debugging: + +``` +src/ +├── apps/ +│ ├── api/ # REST API server (Express.js) +│ │ ├── controllers/ # API endpoint handlers +│ │ ├── middlewares/ # Request/response middleware +│ │ └── exceptions/ # API error types +│ └── cli/ # CLI application (oclif) +│ ├── commands/ # CLI command implementations +│ └── internal/ # Shared CLI utilities, flags, base classes +├── domains/ +│ ├── models/ # Domain models (SpecificationFile, Context, etc.) +│ └── services/ # Business logic services +├── errors/ # Custom error classes +├── utils/ # Utility functions +└── interfaces/ # TypeScript interfaces + +test/ +├── fixtures/ # Test data files (AsyncAPI specs, etc.) +├── helpers/ # Test utilities +├── integration/ # Integration tests for CLI commands +└── unit/ # Unit tests for services and controllers + ├── controllers/ # API controller tests + ├── services/ # Service layer tests + └── utils/ # Utility function tests +``` + +--- + +## Setting Up Your Environment + +### 1. Install Dependencies + +```bash +npm install +``` + +### 2. Build the Project + +```bash +npm run build +``` + +### 3. Set Up Environment Variables for Debugging + +Create a `.env` file or export variables: + +```bash +# Enable development mode (verbose logging) +export NODE_ENV=development + +# Disable analytics during testing +export TEST=1 + +# Set custom context file for testing +export CUSTOM_CONTEXT_FILENAME="test.asyncapi-cli" +export CUSTOM_CONTEXT_FILE_LOCATION="" +``` + +--- + +## Debugging CLI Commands + +### Method 1: Using `bin/run` (Development Mode) + +The `bin/run` script runs the CLI in development mode with TypeScript directly: + +```bash +# Run any command with debugging +./bin/run validate ./path/to/asyncapi.yml + +# With verbose output +DEBUG=* ./bin/run validate ./path/to/asyncapi.yml +``` + +### Method 2: Using Node.js Inspector + +```bash +# Start with Node inspector +node --inspect-brk ./bin/run validate ./path/to/asyncapi.yml + +# Then open Chrome DevTools at: chrome://inspect +``` + +### Method 3: VS Code Debugging + +Create `.vscode/launch.json`: + +```json +{ + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Debug CLI Command", + "program": "${workspaceFolder}/bin/run", + "args": ["validate", "./test/fixtures/specification.yml"], + "env": { + "NODE_ENV": "development", + "TEST": "1" + }, + "sourceMaps": true, + "outFiles": ["${workspaceFolder}/lib/**/*.js"] + }, + { + "type": "node", + "request": "launch", + "name": "Debug Current Test File", + "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", + "args": [ + "--require", "ts-node/register", + "--require", "tsconfig-paths/register", + "--timeout", "100000", + "${file}" + ], + "env": { + "NODE_ENV": "development", + "TEST": "1", + "CUSTOM_CONTEXT_FILENAME": "test.asyncapi-cli" + }, + "sourceMaps": true + } + ] +} +``` + +### Method 4: Adding Console Logs + +For quick debugging, add logs in command files: + +```typescript +// In src/apps/cli/commands/validate.ts +async run() { + const { args, flags } = await this.parse(Validate); + + // Debug: Log parsed arguments + console.log('DEBUG - Args:', JSON.stringify(args, null, 2)); + console.log('DEBUG - Flags:', JSON.stringify(flags, null, 2)); + + // ... rest of the command +} +``` + +--- + +## Debugging the API Server + +### Starting the API in Development Mode + +```bash +# Start with hot-reload +npm run api:dev + +# Or manually with debugging +NODE_ENV=development DEBUG=* node ./lib/apps/api/server.js +``` + +### Testing API Endpoints + +```bash +# Validate endpoint +curl -X POST http://localhost:3000/v1/validate \ + -H "Content-Type: application/json" \ + -d '{"asyncapi": "asyncapi: 3.1.0\ninfo:\n title: Test\n version: 1.0.0\nchannels: {}"}' + +# Parse endpoint +curl -X POST http://localhost:3000/v1/parse \ + -H "Content-Type: application/json" \ + -d '{"asyncapi": "..."}' +``` + +### Debugging API Controllers + +Add middleware logging: + +```typescript +// In src/apps/api/middlewares/logger.middleware.ts +// Logs are automatically enabled in development mode +``` + +--- + +## Debugging Services + +### ValidationService + +The `ValidationService` handles document validation. To debug: + +```typescript +// Test the service directly +import { ValidationService } from '@services/validation.service'; +import { load } from '@models/SpecificationFile'; + +async function debugValidation() { + const service = new ValidationService(); + const specFile = await load('./path/to/spec.yml'); + + const result = await service.validateDocument(specFile, { + 'fail-severity': 'error', + 'log-diagnostics': true, + }); + + console.log('Validation Result:', JSON.stringify(result, null, 2)); +} +``` + +### ConversionService + +```typescript +import { ConversionService } from '@services/convert.service'; +import { load } from '@models/SpecificationFile'; + +async function debugConversion() { + const service = new ConversionService(); + const specFile = await load('./path/to/spec.yml'); + + const result = await service.convertDocument(specFile, { + format: 'asyncapi', + 'target-version': '3.0.0', + perspective: 'server', + }); + + console.log('Conversion Result:', JSON.stringify(result, null, 2)); +} +``` + +### GeneratorService + +```typescript +import { GeneratorService } from '@services/generator.service'; + +async function debugGenerator() { + const service = new GeneratorService(); + // Add your debugging logic +} +``` + +--- + +## Writing Tests + +### Test File Naming Convention + +- Unit tests: `test/unit//.test.ts` +- Integration tests: `test/integration/.test.ts` + +### Unit Test Structure + +```typescript +// test/unit/services/my-service.test.ts +import { expect } from 'chai'; +import { MyService } from '../../../src/domains/services/my.service'; + +describe('MyService', () => { + let service: MyService; + + beforeEach(() => { + service = new MyService(); + }); + + describe('methodName', () => { + it('should do something when given valid input', async () => { + // Arrange + const input = { /* test data */ }; + + // Act + const result = await service.methodName(input); + + // Assert + expect(result.success).to.be.true; + expect(result.data).to.exist; + }); + + it('should handle errors gracefully', async () => { + // Arrange + const invalidInput = null; + + // Act + const result = await service.methodName(invalidInput); + + // Assert + expect(result.success).to.be.false; + expect(result.error).to.include('error message'); + }); + }); +}); +``` + +### Integration Test Structure (CLI Commands) + +```typescript +// test/integration/mycommand.test.ts +import { expect, test } from '@oclif/test'; +import path from 'path'; + +const validSpec = path.resolve(__dirname, '../fixtures/specification.yml'); +const invalidSpec = path.resolve(__dirname, '../fixtures/specification-invalid.yml'); + +describe('mycommand', () => { + describe('with valid input', () => { + test + .stdout() + .command(['mycommand', validSpec]) + .it('should succeed with valid specification', (ctx) => { + expect(ctx.stdout).to.contain('Success'); + }); + }); + + describe('with invalid input', () => { + test + .stderr() + .command(['mycommand', invalidSpec]) + .exit(1) + .it('should fail with invalid specification', (ctx) => { + expect(ctx.stderr).to.contain('Error'); + }); + }); + + describe('with flags', () => { + test + .stdout() + .command(['mycommand', validSpec, '--output', 'result.json']) + .it('should handle output flag', (ctx) => { + expect(ctx.stdout).to.contain('saved'); + }); + }); +}); +``` + +### API Controller Test Structure + +```typescript +// test/unit/controllers/my.controller.test.ts +import request from 'supertest'; +import { App } from '../../../src/apps/api/app'; +import { MyController } from '../../../src/apps/api/controllers/my.controller'; + +describe('MyController', () => { + let app: App; + + beforeEach(async () => { + app = new App([new MyController()]); + await app.init(); + }); + + describe('[POST] /v1/myendpoint', () => { + it('should return 200 with valid input', async () => { + return request(app.getServer()) + .post('/v1/myendpoint') + .send({ data: 'valid' }) + .expect(200) + .then((response) => { + expect(response.body).to.have.property('result'); + }); + }); + + it('should return 422 with invalid input', async () => { + return request(app.getServer()) + .post('/v1/myendpoint') + .send({}) + .expect(422); + }); + }); +}); +``` + +### Using Test Fixtures + +```typescript +import path from 'path'; +import { load } from '@models/SpecificationFile'; + +// Load test fixtures +const fixturesPath = path.resolve(__dirname, '../../fixtures'); + +async function loadTestSpec(filename: string) { + return load(path.join(fixturesPath, filename)); +} + +// Usage in tests +describe('MyTest', () => { + it('should handle v3 spec', async () => { + const spec = await loadTestSpec('specification-v3.yml'); + // ... test logic + }); +}); +``` + +--- + +## Running Tests + +### Run All Tests + +```bash +npm test +``` + +### Run Only CLI Tests + +```bash +npm run cli:test +``` + +### Run Only Unit Tests + +```bash +npm run unit:test +``` + +### Run a Single Test File + +```bash +npm run test:one -- test/integration/validate.test.ts +``` + +### Run Tests with Coverage + +```bash +npm run cli:test +# Coverage report is generated in ./coverage/ +``` + +### Run Tests in Watch Mode (Development) + +```bash +# Using nodemon for file watching +npm run dev + +# Then run tests manually when needed +npm run unit:test +``` + +--- + +## Common Issues & Solutions + +### Issue 1: "Cannot find module '@utils/proxy'" + +**Cause:** TypeScript path aliases not resolved. + +**Solution:** +```bash +# Rebuild the project +npm run build +``` + +### Issue 2: Permission Denied Errors + +**Cause:** Files created by root or different user. + +**Solution:** +```bash +# Fix permissions +sudo chown -R $(whoami) ./lib ./node_modules ./.nyc_output +``` + +### Issue 3: Test Context File Conflicts + +**Cause:** Tests using the same context file as development. + +**Solution:** +```bash +# Set test-specific context file +export CUSTOM_CONTEXT_FILENAME="test.asyncapi-cli" +export CUSTOM_CONTEXT_FILE_LOCATION="" +``` + +### Issue 4: "ECONNREFUSED" in API Tests + +**Cause:** API server not started or wrong port. + +**Solution:** +```bash +# Ensure the app is initialized in tests +const app = new App([new MyController()]); +await app.init(); // Don't forget this! +``` + +### Issue 5: Async Test Timeouts + +**Cause:** Default timeout too short for async operations. + +**Solution:** +```typescript +// Increase timeout for specific tests +it('should handle slow operation', async function() { + this.timeout(30000); // 30 seconds + // ... test logic +}); +``` + +### Issue 6: ESLint Errors in Tests + +**Cause:** Using testing patterns that trigger lint rules. + +**Solution:** +```typescript +// Add eslint disable for specific patterns +/* eslint-disable @typescript-eslint/no-unused-expressions */ +expect(result).to.be.true; // Chai assertions +``` + +--- + +## Debugging Tools & Tips + +### 1. Enable Verbose Logging + +```bash +DEBUG=* ./bin/run validate spec.yml +``` + +### 2. Use Node.js Inspector + +```bash +node --inspect-brk ./bin/run validate spec.yml +# Open chrome://inspect in Chrome +``` + +### 3. Print Stack Traces + +```typescript +try { + // risky operation +} catch (error) { + console.error('Stack trace:', error.stack); + throw error; +} +``` + +### 4. Use TypeScript Source Maps + +Ensure `tsconfig.json` has: +```json +{ + "compilerOptions": { + "sourceMap": true + } +} +``` + +### 5. Debug Parser Output + +```typescript +import { Parser } from '@asyncapi/parser'; + +const parser = new Parser(); +const { document, diagnostics } = await parser.parse(specContent); + +console.log('Parsed document:', JSON.stringify(document?.json(), null, 2)); +console.log('Diagnostics:', JSON.stringify(diagnostics, null, 2)); +``` + +### 6. Inspect Service Results + +All services return a `ServiceResult` type: +```typescript +interface ServiceResult { + success: boolean; + data?: T; + error?: string; +} + +// Always check both success and data +if (result.success && result.data) { + console.log('Success:', result.data); +} else { + console.log('Error:', result.error); +} +``` + +### 7. Test Commands Interactively + +```bash +# Build and run immediately +npm run build && ./bin/run validate ./test/fixtures/specification.yml +``` + +--- + +## Quick Reference + +| Task | Command | +|------|---------| +| Build project | `npm run build` | +| Run all tests | `npm test` | +| Run CLI tests | `npm run cli:test` | +| Run unit tests | `npm run unit:test` | +| Run single test | `npm run test:one -- ` | +| Lint code | `npm run lint` | +| Fix lint issues | `npm run lint:fix` | +| Start API dev server | `npm run api:dev` | +| Debug CLI command | `./bin/run ` | +| Debug with inspector | `node --inspect-brk ./bin/run ` | + +--- + +## Getting Help + +If you're still stuck: + +1. Check existing tests for similar functionality +2. Look at the error messages and stack traces +3. Search for similar issues in the [GitHub Issues](https://github.com/asyncapi/cli/issues) +4. Ask in the [AsyncAPI Slack](https://asyncapi.com/slack-invite) `#tooling` channel + diff --git a/markdown/docs/tools/cli/usage.md b/markdown/docs/tools/cli/usage.md index e587bffef577..ecfa68d17d15 100644 --- a/markdown/docs/tools/cli/usage.md +++ b/markdown/docs/tools/cli/usage.md @@ -27,7 +27,7 @@ $ npm install -g @asyncapi/cli $ asyncapi COMMAND running command... $ asyncapi (--version|--v) -@asyncapi/cli/3.2.0 linux-x64 node-v18.20.8 +@asyncapi/cli/5.0.7 darwin-arm64 node-v24.7.0 $ asyncapi --help [COMMAND] USAGE $ asyncapi COMMAND @@ -56,15 +56,16 @@ USAGE * [`asyncapi diff OLD NEW`](#asyncapi-diff-old-new) * [`asyncapi format [SPEC-FILE]`](#asyncapi-format-spec-file) * [`asyncapi generate`](#asyncapi-generate) +* [`asyncapi generate client LANGUAGE [ASYNCAPI]`](#asyncapi-generate-client-language-asyncapi) * [`asyncapi generate fromTemplate [ASYNCAPI] [TEMPLATE]`](#asyncapi-generate-fromtemplate-asyncapi-template) * [`asyncapi generate models LANGUAGE FILE`](#asyncapi-generate-models-language-file) * [`asyncapi new`](#asyncapi-new) * [`asyncapi new file`](#asyncapi-new-file) -* [`asyncapi new glee`](#asyncapi-new-glee) * [`asyncapi new template`](#asyncapi-new-template) * [`asyncapi optimize [SPEC-FILE]`](#asyncapi-optimize-spec-file) * [`asyncapi pretty SPEC-FILE`](#asyncapi-pretty-spec-file) * [`asyncapi start`](#asyncapi-start) +* [`asyncapi start api`](#asyncapi-start-api) * [`asyncapi start preview SPEC-FILE`](#asyncapi-start-preview-spec-file) * [`asyncapi start studio [SPEC-FILE]`](#asyncapi-start-studio-spec-file) * [`asyncapi validate [SPEC-FILE]`](#asyncapi-validate-spec-file) @@ -78,7 +79,7 @@ USAGE $ asyncapi autocomplete [SHELL] [-r] ARGUMENTS - SHELL (zsh|bash|powershell) Shell type + [SHELL] (zsh|bash|powershell) Shell type FLAGS -r, --refresh-cache Refresh cache (ignores displaying instructions) @@ -98,7 +99,7 @@ EXAMPLES $ asyncapi autocomplete --refresh-cache ``` -_See code: [@oclif/plugin-autocomplete](https://github.com/oclif/plugin-autocomplete/blob/v3.2.26/src/commands/autocomplete/index.ts)_ +_See code: [@oclif/plugin-autocomplete](https://github.com/oclif/plugin-autocomplete/blob/v3.2.40/src/commands/autocomplete/index.ts)_ ## `asyncapi bundle` @@ -135,7 +136,7 @@ EXAMPLES $ asyncapi bundle ./asyncapi.yaml -o final-asyncapi.yaml --base ../public-api/main.yaml --baseDir ./social-media/comments-service ``` -_See code: [src/commands/bundle.ts](https://github.com/asyncapi/cli/blob/v3.2.0/src/commands/bundle.ts)_ +_See code: [src/commands/bundle.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/bundle.ts)_ ## `asyncapi config` @@ -149,7 +150,7 @@ DESCRIPTION CLI config settings ``` -_See code: [src/commands/config/index.ts](https://github.com/asyncapi/cli/blob/v3.2.0/src/commands/config/index.ts)_ +_See code: [src/commands/config/index.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/index.ts)_ ## `asyncapi config analytics` @@ -169,7 +170,7 @@ DESCRIPTION Enable or disable analytics for metrics collection ``` -_See code: [src/commands/config/analytics.ts](https://github.com/asyncapi/cli/blob/v3.2.0/src/commands/config/analytics.ts)_ +_See code: [src/commands/config/analytics.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/analytics.ts)_ ## `asyncapi config auth add PATTERN TOKEN` @@ -185,22 +186,13 @@ ARGUMENTS FLAGS -a, --auth-type= Authentication type (default is "Bearer") - -h, --header=... Additional headers in key=value format + -h, --header=... Additional header in key=value format; can be used multiple times DESCRIPTION Add an authentication config for resolving $ref files requiring HTTP Authorization. - -EXAMPLES - $ asyncapi config auth add "https://github.com/org/repo/**/*" "ghp_XuYi7ZWQWjmrJpY2Kz3ET" - - $ asyncapi config auth add "https://api.github.com/repos/org/repo/**/*" "$GITHUB_TOKEN" - - $ asyncapi config auth add "https://private-registry.com/**/*" "my-token" --auth-type="Token" - - $ asyncapi config auth add "https://api.example.com/**/*" "token123" --header="X-API-Key=abc123" --header="User-Agent=MyApp/1.0" ``` -_See code: [src/commands/config/auth/add.ts](https://github.com/asyncapi/cli/blob/v3.2.0/src/commands/config/auth/add.ts)_ +_See code: [src/commands/config/auth/add.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/auth/add.ts)_ ## `asyncapi config context` @@ -214,7 +206,7 @@ DESCRIPTION Manage short aliases for full paths to AsyncAPI documents ``` -_See code: [src/commands/config/context/index.ts](https://github.com/asyncapi/cli/blob/v3.2.0/src/commands/config/context/index.ts)_ +_See code: [src/commands/config/context/index.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/context/index.ts)_ ## `asyncapi config context add CONTEXT-NAME SPEC-FILE-PATH` @@ -236,7 +228,7 @@ DESCRIPTION Add a context to the store ``` -_See code: [src/commands/config/context/add.ts](https://github.com/asyncapi/cli/blob/v3.2.0/src/commands/config/context/add.ts)_ +_See code: [src/commands/config/context/add.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/context/add.ts)_ ## `asyncapi config context current` @@ -253,7 +245,7 @@ DESCRIPTION Shows the current context that is being used ``` -_See code: [src/commands/config/context/current.ts](https://github.com/asyncapi/cli/blob/v3.2.0/src/commands/config/context/current.ts)_ +_See code: [src/commands/config/context/current.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/context/current.ts)_ ## `asyncapi config context edit CONTEXT-NAME NEW-SPEC-FILE-PATH` @@ -274,7 +266,7 @@ DESCRIPTION Edit a context in the store ``` -_See code: [src/commands/config/context/edit.ts](https://github.com/asyncapi/cli/blob/v3.2.0/src/commands/config/context/edit.ts)_ +_See code: [src/commands/config/context/edit.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/context/edit.ts)_ ## `asyncapi config context init [CONTEXT-FILE-PATH]` @@ -285,10 +277,10 @@ USAGE $ asyncapi config context init [CONTEXT-FILE-PATH] [-h] ARGUMENTS - CONTEXT-FILE-PATH Specify directory in which context file should be created: - - current directory : asyncapi config context init .(default) - - root of current repository : asyncapi config context init ./ - - user's home directory : asyncapi config context init ~` + [CONTEXT-FILE-PATH] Specify directory in which context file should be created: + - current directory : asyncapi config context init .(default) + - root of current repository : asyncapi config context init ./ + - user's home directory : asyncapi config context init ~` FLAGS -h, --help Show CLI help. @@ -297,7 +289,7 @@ DESCRIPTION Initialize context ``` -_See code: [src/commands/config/context/init.ts](https://github.com/asyncapi/cli/blob/v3.2.0/src/commands/config/context/init.ts)_ +_See code: [src/commands/config/context/init.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/context/init.ts)_ ## `asyncapi config context list` @@ -314,7 +306,7 @@ DESCRIPTION List all the stored contexts in the store ``` -_See code: [src/commands/config/context/list.ts](https://github.com/asyncapi/cli/blob/v3.2.0/src/commands/config/context/list.ts)_ +_See code: [src/commands/config/context/list.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/context/list.ts)_ ## `asyncapi config context remove CONTEXT-NAME` @@ -334,7 +326,7 @@ DESCRIPTION Delete a context from the store ``` -_See code: [src/commands/config/context/remove.ts](https://github.com/asyncapi/cli/blob/v3.2.0/src/commands/config/context/remove.ts)_ +_See code: [src/commands/config/context/remove.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/context/remove.ts)_ ## `asyncapi config context use CONTEXT-NAME` @@ -354,7 +346,7 @@ DESCRIPTION Set a context as current ``` -_See code: [src/commands/config/context/use.ts](https://github.com/asyncapi/cli/blob/v3.2.0/src/commands/config/context/use.ts)_ +_See code: [src/commands/config/context/use.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/context/use.ts)_ ## `asyncapi config versions` @@ -371,37 +363,37 @@ DESCRIPTION Show versions of AsyncAPI tools used ``` -_See code: [src/commands/config/versions.ts](https://github.com/asyncapi/cli/blob/v3.2.0/src/commands/config/versions.ts)_ +_See code: [src/commands/config/versions.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/versions.ts)_ ## `asyncapi convert [SPEC-FILE]` -Convert asyncapi documents older to newer versions or OpenAPI/postman-collection documents to AsyncAPI +Convert asyncapi documents older to newer versions or OpenAPI documents to AsyncAPI ``` USAGE - $ asyncapi convert [SPEC-FILE] -f openapi|asyncapi|postman-collection [-h] [-o ] [-t ] [-p - client|server] [--proxyHost ] [--proxyPort ] + $ asyncapi convert [SPEC-FILE] -f openapi|asyncapi [-h] [-o ] [-t ] [-p client|server] + [--proxyHost ] [--proxyPort ] ARGUMENTS - SPEC-FILE spec path, url, or context-name + [SPEC-FILE] spec path, url, or context-name FLAGS -f, --format=