diff --git a/components/TOC.tsx b/components/TOC.tsx
index 43819f0257ed..f51acadc0fef 100644
--- a/components/TOC.tsx
+++ b/components/TOC.tsx
@@ -47,7 +47,7 @@ export default function TOC({ className, cssBreakingPoint = 'xl', toc, contentSe
return (
setOpen(!open)}
>
+
+[Please join the discussion and share your thoughts on the progress made on the brand refresh mascot issue](https://github.com/asyncapi/brand/issues/12).
+
+## AsyncAPI Conference Hall of Fame
+I want to extend a heartfelt thank you to the incredible volunteers who generously dedicated their skills and time to ensure the success of the Online Conference. From developers and designers to those working both on-stage and off-stage, their efforts made the planning and execution of the event seamless.
+
+
+
+## Coming in November
+- **AsyncAPI Community Updates Newsletter** - The November Edition issue will arrive in your inbox on the 8th. [Ensure you subscribe to the AsyncAPI Newsletter](https://www.asyncapi.com/newsletter); you don't want to miss out.
diff --git a/markdown/blog/2024-september-summary-and-london.md b/markdown/blog/2024-september-summary-and-london.md
index cbac4f5563ed..0e965cefe356 100644
--- a/markdown/blog/2024-september-summary-and-london.md
+++ b/markdown/blog/2024-september-summary-and-london.md
@@ -11,7 +11,6 @@ authors:
link: https://www.linkedin.com/in/v-thulisile-sibanda/
byline: AsyncAPI Community Manager
excerpt: 'September Community Update and London Conference Highlights'
-featured: true
---
In September, we had our second in-person AsyncAPI conference after Helsinki; read all about it in the [AsyncAPI Helsinki Conference update](https://www.asyncapi.com/blog/helsinki-and-community).
diff --git a/markdown/blog/asyncapi-bounty-program-2024.md b/markdown/blog/asyncapi-bounty-program-2024.md
index bc409d285814..bcfb5183d5d8 100644
--- a/markdown/blog/asyncapi-bounty-program-2024.md
+++ b/markdown/blog/asyncapi-bounty-program-2024.md
@@ -11,7 +11,6 @@ authors:
link: https://github.com/aeworxet
byline: Bounty Program Coordinator
excerpt: 'Annual update on the quarterly published set of tasks that are currently in demand among AsyncAPI Maintainers, targeted at engineers of Middle and Senior professional levels.'
-featured: true
---
## AsyncAPI Bounty Program
diff --git a/markdown/blog/helsinki-and-community.md b/markdown/blog/helsinki-and-community.md
index ffb47a8f82a7..5f1dae232259 100644
--- a/markdown/blog/helsinki-and-community.md
+++ b/markdown/blog/helsinki-and-community.md
@@ -11,7 +11,6 @@ authors:
link: https://twitter.com/derberq
byline: AsyncAPI Executive Director
excerpt: 'Conferences are great. They bring communities together and give people a platform to share their experiences. But is that enough?'
-featured: true
---
## How It All Started
diff --git a/markdown/docs/concepts/application.md b/markdown/docs/concepts/application.md
index 1d9c4634a944..63bc5d75757e 100644
--- a/markdown/docs/concepts/application.md
+++ b/markdown/docs/concepts/application.md
@@ -5,12 +5,12 @@ weight: 23
## What is an application?
-An application is any computer program or a group of them.
+An _application_ is a computer program or a group of them.
-An application could also be a micro-service, IoT device (sensor), mainframe process, etc. Users may even write applications in different programming languages if they support one of the selected protocols.
+An application can be a micro-service, IoT (Internet of things) device (for example, a sensor), mainframe process, and more. Users can create applications using various programming languages that support the chosen protocols.
## Why do we need applications?
-In Event-Driven Architecture (EDA), an application must be a `producer`, a `consumer`, or both. Applications must also use the protocols the server supports if they wish to connect and exchange messages.
+In Event-Driven Architecture (EDA), an application can either be a producer, a consumer, or both. Additionally, if an application wants to connect and exchange messages with the server, it must adhere to the protocols supported by the server.
### Applications: producers and consumers
```mermaid
@@ -20,4 +20,5 @@ flowchart TD
C --> D[message]
D --> F[CONSUMER application]
```
-The above diagram describes a message communication traveling through a channel between a **PRODUCER application** and a **CONSUMER application**.
+
+The diagram above illustrates a message transmission between a Producer application and a Consumer application through a channel.
\ No newline at end of file
diff --git a/markdown/docs/concepts/asyncapi-document/index.md b/markdown/docs/concepts/asyncapi-document/index.md
index 032e8a0a9e2b..9419ff90ff83 100644
--- a/markdown/docs/concepts/asyncapi-document/index.md
+++ b/markdown/docs/concepts/asyncapi-document/index.md
@@ -3,11 +3,11 @@ title: 'Introduction'
weight: 50
---
-The AsyncAPI Specification defines a set of fields that can be used in an AsyncAPI document to describe an application'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 Specification defines a set of fields that can be used in an AsyncAPI document to describe an application’s API. While the document may reference other files for additional details or shared fields, it usually serves as a single, primary document that encapsulates the API description.
-Furthermore, the AsyncAPI document acts as a communication contract between `receivers` and `senders` within an event-driven system. It specifies the payload content required when a service sends a message and offers clear guidance to the receiver regarding the message's properties.
+Furthermore, the AsyncAPI document acts as a communication contract between receivers and senders within an event-driven system. It specifies the payload content necessary for a service to send a message and provides clear guidance to the receiver about the message's properties.
-```YAML
+```yaml
asyncapi: 3.0.0
info:
title: Cool Example
@@ -37,7 +37,5 @@ operations:
```
-You might have additional fields depending on the implemented protocol (i.e., MQTT, AMQP, Kafka, etc.).
-
-For example, your AsyncAPI document could have additional fields for configuring Kafka bindings.
+Depending on the implemented protocol (such as MQTT, AMQP, Kafka, etc.), you may have additional fields in your AsyncAPI document. For example, for configuring Kafka bindings.
diff --git a/markdown/docs/concepts/channel.md b/markdown/docs/concepts/channel.md
index 96fefe067f71..d44759b8a2cf 100644
--- a/markdown/docs/concepts/channel.md
+++ b/markdown/docs/concepts/channel.md
@@ -4,12 +4,10 @@ weight: 20
---
# What is a channel?
-A `channel` is a mechanism created by the server for the organization and transmission of messages. Users can define channels as a _topic, queue, routing key, path,_ or _subject_ depending on the protocol used.
+A _channel_ is a mechanism created by the server that facilitates the organization and transmission of messages. Depending on the used protocol, users can define channels as a _topic_, _queue_, _routing key_, _path_, or _subject_.
# Why do we need channels?
-Channels play a crucial role in communication between `producers` and `consumers`. A producer can send a message through the channel, and the consumer receives messages from a particular channel. A channel's sole purpose is to ensure the right messages route to the right consumers.
-
-
+Channels are pivotal for establishing communication between producers and consumers. They enable producers to send messages, while consumers receive messages from specific channels. The primary function of a channel is to ensure that the intended messages reach the appropriate consumers.
```mermaid
graph LR
@@ -19,4 +17,6 @@ graph LR
C --> E[Consumer]
C --> F[Consumer]
```
-The diagram above shows the communication between a `producer` and `consumer`, with the producer sending a `message` through the `channel`. The channel then queues the message to the specific consumer.
+
+The diagram above illustrates the communication process between a producer and a consumer. The producer sends a message through the channel, which then queues the message for delivery to the specific consumer.
+The diagram above illustrates the communication process between a producer and multiple consumers. The producer sends a message through the channel, which then queues the message for delivery to the appropriate consumers.
\ No newline at end of file
diff --git a/markdown/docs/concepts/consumer.md b/markdown/docs/concepts/consumer.md
index 512970e11d4b..a115505419fd 100644
--- a/markdown/docs/concepts/consumer.md
+++ b/markdown/docs/concepts/consumer.md
@@ -4,12 +4,12 @@ weight: 4
---
## What is a consumer?
-In an Event Driven Architecture (EDA), a consumer is an application that listens for a particular event from a broker and reacts to it.
+A _consumer_ is an application that subscribes to a specific event from a broker and responds accordingly.
## Why do we need consumers?
-Unlike traditional REST APIs, in EDA, event consumers are not expected to respond immediately on the same connection. In this architecture, a consumer is unaware of the producer or other consumers; all they know is that when a broker sends them an event, it is because they subscribed to it.
+Unlike traditional REST APIs, in Event-Driven Architecture (EDA), event consumers are asynchronous, which means they are not required to respond immediately on the same connection. In this architecture, consumers are unaware of the producers or other consumers. All they know is that when a broker sends them an event, it is because they have subscribed to it.
-When you want events processed asynchronously in your application, the consumer plays an important role in completing that event data flow in the event channel.
+When you want your application to process events asynchronously, the consumer plays a crucial role in completing the event data flow through the event channel.
```mermaid
flowchart LR
@@ -26,7 +26,8 @@ flowchart LR
end
```
-The above diagram depicts a sample flow of events from `producer` to `broker` to `consumer`. In this instance, the `producer` publishes two events _(A and B)_ and sends them to the `broker`. Then each `consumer` subscribes to receive those events.
+The diagram above illustrates a sample flow of events from the `producer` to the `broker` to the `consumers`. In this scenario, the `producer` publishes two events _(A and B)_ and sends them to the `broker`. Subsequently, each `consumer` subscribes to receive those events.
+
Subscribers can also be producers.
diff --git a/markdown/docs/concepts/index.md b/markdown/docs/concepts/index.md
index 34e581fea077..63dd3b9573e3 100644
--- a/markdown/docs/concepts/index.md
+++ b/markdown/docs/concepts/index.md
@@ -5,9 +5,9 @@ weight: 1
import ContributionNotes from '@/assets/docs/fragments/contribution-notes.md';
-## Concepts: Define AsyncAPI features and capabilities
+## Concepts
-Welcome to AsyncAPI **Concepts**! Our Concepts section will define the concepts of AsyncAPI features and capabilities.
+Welcome to AsyncAPI **Concepts**! This section defines AsyncAPI features and capabilities.
diff --git a/markdown/docs/concepts/message.md b/markdown/docs/concepts/message.md
index e5e65e91fb0a..497bfa30a089 100644
--- a/markdown/docs/concepts/message.md
+++ b/markdown/docs/concepts/message.md
@@ -4,8 +4,9 @@ weight: 30
---
## What is a message?
-A `message` is a communication asset used to transmit or exchange information from a sender to the receiver through `channels`. A single `message` can be consumed by multiple independent receivers and can also be defined as an _event_ or _command_. The sender includes a payload of data (that has been serialized into an appropriate format, e.g., JSON, XML, binary, etc.) that needs to be processed by the receiver. It may also include metadata; information that describes the message itself. This metadata is often known as _headers_ or _properties_.
+A _message_ is a communication asset that transmits or exchanges information from a sender to the receiver through channels.
+One message can also be defined as an event or command and can be consumed by multiple independent receivers. The sender encodes a payload of data (serialized into a suitable format, such as JSON, XML, binary, or others) that requires processing by the receiver. Additionally, the message may include _metadata_, which is information that describes the message itself. This metadata is commonly referred to as _headers_ or _properties_.
``` mermaid
graph LR
@@ -17,11 +18,10 @@ A{{sender application}} --> b --> C{{receiver application}}
```
-In the diagram above, the sender application transmits a `message` to the receiver application.
+The diagram above illustrates how a sender application transmits a message through a channel to a receiver application, demonstrating the basic flow of message-based communication.
## Messages vs Events
-A `message` carries information from one application to the other, while an `event` is a message that provides details of something that has already occurred. One important aspect to note is that depending on the type of information a `message` contains, it can fall under an _event_, _query_, or _command_.
-*See the diagram below.*
+A **message** conveys information between applications, while an **event** is a message that provides details of something that has already occurred. A crucial aspect to note is that depending on the type of information a message carries, it can either be an event, query, or command. Check the diagram below.
``` mermaid
graph TD
@@ -32,4 +32,4 @@ graph TD
C --> E(Command)
```
-Overall, `events` are `messages` but not all `messages` are `events`.
+Summing up, events are messages, but not all messages are events.
diff --git a/markdown/docs/concepts/producer.md b/markdown/docs/concepts/producer.md
index ce17b9e31042..c2614d9c5b81 100644
--- a/markdown/docs/concepts/producer.md
+++ b/markdown/docs/concepts/producer.md
@@ -4,24 +4,26 @@ weight: 3
---
## What is a Producer?
-A producer is an application that senses state changes (events) and publishes those events as messages. An event indicates a state change or update triggered by a user's/device's action.
+A _producer_ is an application that detects state changes (_events_) and publishes these events as messages. An event signifies a state change or update triggered by a user’s or device’s action.
The following are sample events:
-* Placing an item in a shopping cart on an e-commerce website.
+* Adding an item to a shopping cart on an e-commerce website.
* Clicking the subscribe button on a YouTube channel.
-* A temperature change in a sensor.
+* Detecting a temperature change using a sensor.
+
## Why do we need Producers?
-One of the core concepts of event-driven architecture is the publish/subscribe communication model. Producers are publishers in this model; they're the first logical layer responsible for distributing messages to the broker so that others can subscribe to receive messages.
+The publish/subscribe communication model is one of the core concepts of event-driven architecture. In this model, producers are publishers, acting as the first logical layer responsible for distributing messages to the broker, enabling others to subscribe and receive these messages.
```mermaid
flowchart TD
a[Producer]-- Message 1 --->d[(Broker)]
d -- Message 1 --->g[Consumer]
```
-The diagram above depicts the communication between a **producer** publishing events to a specific channel in a **broker** and a **consumer** subscribed to the same channel.
-In some cases, an entity can be both a producer publishing messages to a specific channel in the broker and a consumer subscribing to messages from a different channel in the broker.
+The diagram above illustrates the communication flow between a producer who publishes events to a specific channel in a broker and a consumer who subscribes to the same channel.
+
+In some cases, an entity can simultaneously function as both a producer, publishing messages to a specific channel in the broker, and a consumer, subscribing to messages from a different channel in the broker.
```mermaid
flowchart LR
@@ -31,4 +33,4 @@ flowchart LR
c -- Message 2 ---> d[Consumer]
```
-In the diagram above, we see a producer publishing messages to a specific channel and a consumer subscribing to messages from that channel. We also have a second producer who publishes to one channel, but subscribes to messages from another.
+In the diagram above, there is a producer publishing messages to a specific channel and a consumer subscribing to messages from that channel. Also, there is a second producer publishing to one channel and subscribing to messages from another channel.
diff --git a/markdown/docs/concepts/protocol.md b/markdown/docs/concepts/protocol.md
index 61a454744844..8fb93541f008 100644
--- a/markdown/docs/concepts/protocol.md
+++ b/markdown/docs/concepts/protocol.md
@@ -5,7 +5,7 @@ weight: 25
## What is a protocol?
-A protocol is a set of rules that specifies how information is exchanged between applications and/or servers.
+A _protocol_ is a set of rules that governs the exchange of information between applications and/or servers.
Protocol examples:
* [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
@@ -14,7 +14,7 @@ Protocol examples:
* [MQTT](https://mqtt.org/)
## Why do we need protocols?
-Whenever a producer detects a state change (events) and publishes those events as messages, a protocol carries those messages to the channel and then to a consumer. Protocol plays a vital role in message transmission.
+Protocols play a crucial role in message transmission. Whenever a producer detects a state change (events) and publishes those events as messages, a protocol carries those messages to the channel and then to the consumer.
```mermaid
sequenceDiagram
@@ -23,8 +23,8 @@ sequenceDiagram
Publisher->>+Publisher: Delete(Msg)
```
-The diagram above depicts the message exchange flow from `producer` to `broker` to `consumer` using the MQTT protocol with QoS0 (quality of service 0). This means that information exchanged from `producer` to `broker` to `consumer` is delivered at most once.
+The diagram above illustrates the message exchange flow from `producer` to `broker` to `consumer` using the MQTT protocol with QoS0 (quality of service 0). In other words, the information transferred from the producer to broker to consumer is delivered at most once.
-The quality of service information rule is specified on a protocol level. Broker implementations and other involved actors must act accordingly.
+The quality of service information rule is defined at the protocol level. Broker implementations and other involved parties must adhere to this rule.
-In AsyncAPI documents, all protocol-specific details that the application follows can be described using [bindings](/docs/reference/specification/v2.5.0#definitionsBindings).
+In AsyncAPI documents, all protocol-specific details that the application follows can be described using [bindings](https://www.asyncapi.com/docs/reference/specification/latest#definitionsBindings).
diff --git a/markdown/docs/concepts/server.md b/markdown/docs/concepts/server.md
index 7d3a6441bb3e..d6f461076132 100644
--- a/markdown/docs/concepts/server.md
+++ b/markdown/docs/concepts/server.md
@@ -5,10 +5,10 @@ weight: 2
## What is a server?
-A server represents a messaging broker system where connections and communication between a producer and a consumer are established. Unlike traditional API servers which are dependent on request/response, message broker interactions occur back and forth over different channels.
+A _server_ acts as a _messaging broker_ system, establishing connections and facilitating communication between [_producers_](producer) and [_consumers_](consumer). Unlike traditional API servers that rely on request-response interactions, message broker interactions occur bidirectionally across various channels.
## What is the purpose of servers?
-Servers play an important role in maintaining a relationship between producers and consumers. When designing and setting up an event-driven application, servers are in charge of delivering asynchronous messages from the producer to the consumers through the use of channels. By integrating different messaging protocols, servers can transmit and exchange messages between clients.
+Servers play a crucial role in establishing a connection between producers and consumers. In the context of designing and setting up an event-driven application, servers are responsible for delivering asynchronous messages from the producer to the consumers through the use of [_channels_](channel). Additionally, servers can integrate various messaging [_protocols_](protocol) to facilitate the transmission and exchange of messages between _clients_.
### Clients and Server
```mermaid
@@ -18,7 +18,7 @@ flowchart TD
c[Client Mobile] --> b[(server)]
b --> c
```
-The diagram above describes a bi-directional communication between several **clients** and one **server**. In this case, in your AsyncAPI file, you describe the `server`, and therefore the [`Server Object`](https://www.asyncapi.com/docs/reference/specification/latest#serverObject) holds information about the actual server, including its physical location.
+The diagram above illustrates a bidirectional communication between one server and several clients. In this case, in your AsyncAPI file, you describe the `server`, so the [`Server Object`](https://www.asyncapi.com/docs/reference/specification/latest#serverObject) holds information about the actual server, including its physical location.
### Broker Centric
@@ -35,4 +35,4 @@ flowchart TD
a2 --> C[consumer2]
```
-The diagram above shows the *Broker Centric Architecture*. In this case, we created three AsyncAPI files for the `producer`, `consumer1`, and `consumer2`. In these AsyncAPI files, the [`Server Object`](https://www.asyncapi.com/docs/reference/specification/latest#serverObject) provides information about the `broker`, so that API users know where to connect to start receiving or sending messages.
+The diagram above illustrates the Broker-centric Architecture. In this case, there are three AsyncAPI files for the `producer`, `consumer1`, and `consumer2`. In these AsyncAPI files, the [`Server Object`](https://www.asyncapi.com/docs/reference/specification/latest#serverObject) provides information about the `broker`, so that API users know where to connect to start receiving or sending messages.
diff --git a/markdown/docs/tools/cli/usage.md b/markdown/docs/tools/cli/usage.md
index 98ccd5e79dd0..d10e249f1909 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)
-@asyncapi/cli/2.7.4 linux-x64 node-v18.20.4
+@asyncapi/cli/2.8.0 linux-x64 node-v18.20.4
$ asyncapi --help [COMMAND]
USAGE
$ asyncapi COMMAND
@@ -99,7 +99,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/v2.7.4/src/commands/bundle.ts)_
+_See code: [src/commands/bundle.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/bundle.ts)_
## `asyncapi config`
@@ -113,7 +113,7 @@ DESCRIPTION
CLI config settings
```
-_See code: [src/commands/config/index.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/config/index.ts)_
+_See code: [src/commands/config/index.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/config/index.ts)_
## `asyncapi config analytics`
@@ -133,7 +133,7 @@ DESCRIPTION
Enable or disable analytics for metrics collection
```
-_See code: [src/commands/config/analytics.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/config/analytics.ts)_
+_See code: [src/commands/config/analytics.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/config/analytics.ts)_
## `asyncapi config context`
@@ -147,7 +147,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/v2.7.4/src/commands/config/context/index.ts)_
+_See code: [src/commands/config/context/index.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/config/context/index.ts)_
## `asyncapi config context add CONTEXT-NAME SPEC-FILE-PATH`
@@ -169,7 +169,7 @@ DESCRIPTION
Add a context to the store
```
-_See code: [src/commands/config/context/add.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/config/context/add.ts)_
+_See code: [src/commands/config/context/add.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/config/context/add.ts)_
## `asyncapi config context current`
@@ -186,7 +186,7 @@ DESCRIPTION
Shows the current context that is being used
```
-_See code: [src/commands/config/context/current.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/config/context/current.ts)_
+_See code: [src/commands/config/context/current.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/config/context/current.ts)_
## `asyncapi config context edit CONTEXT-NAME NEW-SPEC-FILE-PATH`
@@ -207,7 +207,7 @@ DESCRIPTION
Edit a context in the store
```
-_See code: [src/commands/config/context/edit.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/config/context/edit.ts)_
+_See code: [src/commands/config/context/edit.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/config/context/edit.ts)_
## `asyncapi config context init [CONTEXT-FILE-PATH]`
@@ -230,7 +230,7 @@ DESCRIPTION
Initialize context
```
-_See code: [src/commands/config/context/init.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/config/context/init.ts)_
+_See code: [src/commands/config/context/init.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/config/context/init.ts)_
## `asyncapi config context list`
@@ -247,7 +247,7 @@ DESCRIPTION
List all the stored contexts in the store
```
-_See code: [src/commands/config/context/list.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/config/context/list.ts)_
+_See code: [src/commands/config/context/list.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/config/context/list.ts)_
## `asyncapi config context remove CONTEXT-NAME`
@@ -267,7 +267,7 @@ DESCRIPTION
Delete a context from the store
```
-_See code: [src/commands/config/context/remove.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/config/context/remove.ts)_
+_See code: [src/commands/config/context/remove.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/config/context/remove.ts)_
## `asyncapi config context use CONTEXT-NAME`
@@ -287,7 +287,7 @@ DESCRIPTION
Set a context as current
```
-_See code: [src/commands/config/context/use.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/config/context/use.ts)_
+_See code: [src/commands/config/context/use.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/config/context/use.ts)_
## `asyncapi config versions`
@@ -304,7 +304,7 @@ DESCRIPTION
Show versions of AsyncAPI tools used
```
-_See code: [src/commands/config/versions.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/config/versions.ts)_
+_See code: [src/commands/config/versions.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/config/versions.ts)_
## `asyncapi convert [SPEC-FILE]`
@@ -332,7 +332,7 @@ DESCRIPTION
Convert asyncapi documents older to newer versions or OpenAPI/postman-collection documents to AsyncAPI
```
-_See code: [src/commands/convert.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/convert.ts)_
+_See code: [src/commands/convert.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/convert.ts)_
## `asyncapi diff OLD NEW`
@@ -372,7 +372,7 @@ DESCRIPTION
Find diff between two asyncapi files
```
-_See code: [src/commands/diff.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/diff.ts)_
+_See code: [src/commands/diff.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/diff.ts)_
## `asyncapi generate`
@@ -386,7 +386,7 @@ DESCRIPTION
Generate typed models or other things like clients, applications or docs using AsyncAPI Generator templates.
```
-_See code: [src/commands/generate/index.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/generate/index.ts)_
+_See code: [src/commands/generate/index.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/generate/index.ts)_
## `asyncapi generate fromTemplate ASYNCAPI TEMPLATE`
@@ -431,7 +431,7 @@ EXAMPLES
$ asyncapi generate fromTemplate asyncapi.yaml @asyncapi/html-template --param version=1.0.0 singleFile=true --output ./docs --force-write
```
-_See code: [src/commands/generate/fromTemplate.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/generate/fromTemplate.ts)_
+_See code: [src/commands/generate/fromTemplate.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/generate/fromTemplate.ts)_
## `asyncapi generate models LANGUAGE FILE`
@@ -502,7 +502,7 @@ DESCRIPTION
Generates typed models
```
-_See code: [src/commands/generate/models.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/generate/models.ts)_
+_See code: [src/commands/generate/models.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/generate/models.ts)_
## `asyncapi new`
@@ -560,7 +560,7 @@ EXAMPLES
$ asyncapi new --file-name=my-asyncapi.yml --example=default-example.yml --no-tty - create a new file with a specific name, using one of the examples and without interactive mode
```
-_See code: [src/commands/new/index.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/new/index.ts)_
+_See code: [src/commands/new/index.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/new/index.ts)_
## `asyncapi new file`
@@ -618,7 +618,7 @@ EXAMPLES
$ asyncapi new --file-name=my-asyncapi.yml --example=default-example.yml --no-tty - create a new file with a specific name, using one of the examples and without interactive mode
```
-_See code: [src/commands/new/file.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/new/file.ts)_
+_See code: [src/commands/new/file.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/new/file.ts)_
## `asyncapi new glee`
@@ -640,7 +640,7 @@ DESCRIPTION
Creates a new Glee project
```
-_See code: [src/commands/new/glee.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/new/glee.ts)_
+_See code: [src/commands/new/glee.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/new/glee.ts)_
## `asyncapi new template`
@@ -664,7 +664,7 @@ DESCRIPTION
Creates a new template
```
-_See code: [src/commands/new/template.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/new/template.ts)_
+_See code: [src/commands/new/template.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/new/template.ts)_
## `asyncapi optimize [SPEC-FILE]`
@@ -706,7 +706,7 @@ EXAMPLES
$ asyncapi optimize ./asyncapi.yaml --ignore=schema
```
-_See code: [src/commands/optimize.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/optimize.ts)_
+_See code: [src/commands/optimize.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/optimize.ts)_
## `asyncapi start`
@@ -720,7 +720,7 @@ DESCRIPTION
Starts AsyncAPI-related services. Currently, it supports launching the AsyncAPI Studio
```
-_See code: [src/commands/start/index.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/start/index.ts)_
+_See code: [src/commands/start/index.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/start/index.ts)_
## `asyncapi start studio`
@@ -739,7 +739,7 @@ DESCRIPTION
starts a new local instance of Studio
```
-_See code: [src/commands/start/studio.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/start/studio.ts)_
+_See code: [src/commands/start/studio.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/start/studio.ts)_
## `asyncapi validate [SPEC-FILE]`
@@ -769,5 +769,5 @@ DESCRIPTION
validate asyncapi file
```
-_See code: [src/commands/validate.ts](https://github.com/asyncapi/cli/blob/v2.7.4/src/commands/validate.ts)_
+_See code: [src/commands/validate.ts](https://github.com/asyncapi/cli/blob/v2.8.0/src/commands/validate.ts)_
diff --git a/public/img/posts/2024-blog-banner/blog-banner-october.webp b/public/img/posts/2024-blog-banner/blog-banner-october.webp
new file mode 100644
index 000000000000..6fa9652162b8
Binary files /dev/null and b/public/img/posts/2024-blog-banner/blog-banner-october.webp differ
diff --git a/public/img/posts/2024-blog-banner/mascots.webp b/public/img/posts/2024-blog-banner/mascots.webp
new file mode 100644
index 000000000000..2205f5072cb1
Binary files /dev/null and b/public/img/posts/2024-blog-banner/mascots.webp differ
diff --git a/scripts/dashboard/build-dashboard.js b/scripts/dashboard/build-dashboard.js
index 5b0a34bee17b..c20be204e87b 100644
--- a/scripts/dashboard/build-dashboard.js
+++ b/scripts/dashboard/build-dashboard.js
@@ -1,4 +1,4 @@
-const { writeFileSync } = require('fs');
+const { writeFile } = require('fs-extra');
const { resolve } = require('path');
const { graphql } = require('@octokit/graphql');
const { Queries } = require('./issue-queries');
@@ -44,10 +44,10 @@ async function getDiscussions(query, pageSize, endCursor = null) {
return result.search.nodes.concat(await getDiscussions(query, pageSize, result.search.pageInfo.endCursor));
} catch (e) {
console.error(e);
-
return Promise.reject(e);
}
}
+
async function getDiscussionByID(isPR, id) {
try {
const result = await graphql(isPR ? Queries.pullRequestById : Queries.issueById, {
@@ -60,7 +60,6 @@ async function getDiscussionByID(isPR, id) {
return result;
} catch (e) {
console.error(e);
-
return Promise.reject(e);
}
}
@@ -69,7 +68,6 @@ async function processHotDiscussions(batch) {
return Promise.all(
batch.map(async (discussion) => {
try {
- // eslint-disable-next-line no-underscore-dangle
const isPR = discussion.__typename === 'PullRequest';
if (discussion.comments.pageInfo.hasNextPage) {
const fetchedDiscussion = await getDiscussionByID(isPR, discussion.id);
@@ -83,9 +81,10 @@ async function processHotDiscussions(batch) {
const finalInteractionsCount = isPR
? interactionsCount +
- discussion.reviews.totalCount +
- discussion.reviews.nodes.reduce((acc, curr) => acc + curr.comments.totalCount, 0)
+ discussion.reviews.totalCount +
+ discussion.reviews.nodes.reduce((acc, curr) => acc + curr.comments.totalCount, 0)
: interactionsCount;
+
return {
id: discussion.id,
isPR,
@@ -98,7 +97,7 @@ async function processHotDiscussions(batch) {
score: finalInteractionsCount / (monthsSince(discussion.timelineItems.updatedAt) + 2) ** 1.8
};
} catch (e) {
- console.error(`there was some issues while parsing this item: ${JSON.stringify(discussion)}`);
+ console.error(`there were some issues while parsing this item: ${JSON.stringify(discussion)}`);
throw e;
}
})
@@ -111,21 +110,28 @@ async function getHotDiscussions(discussions) {
for (let i = 0; i < discussions.length; i += batchSize) {
const batch = discussions.slice(i, i + batchSize);
- // eslint-disable-next-line no-await-in-loop
const batchResults = await processHotDiscussions(batch);
-
- // eslint-disable-next-line no-await-in-loop
await pause(1000);
-
result.push(...batchResults);
}
+
result.sort((ElemA, ElemB) => ElemB.score - ElemA.score);
const filteredResult = result.filter((issue) => issue.author !== 'asyncapi-bot');
return filteredResult.slice(0, 12);
}
-async function writeToFile(content) {
- writeFileSync(resolve(__dirname, '..', '..', 'dashboard.json'), JSON.stringify(content, null, ' '));
+
+async function writeToFile(content, writePath) {
+ try {
+ await writeFile(writePath, JSON.stringify(content, null, ' '));
+ } catch (error) {
+ console.error('Failed to write dashboard data:', {
+ error: error.message,
+ writePath
+ });
+ throw error;
+ }
}
+
async function mapGoodFirstIssues(issues) {
return issues.map((issue) => ({
id: issue.id,
@@ -153,7 +159,7 @@ function monthsSince(date) {
return Math.floor(months);
}
-async function start() {
+async function start(writePath) {
try {
const issues = await getDiscussions(Queries.hotDiscussionsIssues, 20);
const PRs = await getDiscussions(Queries.hotDiscussionsPullRequests, 20);
@@ -163,12 +169,16 @@ async function start() {
getHotDiscussions(discussions),
mapGoodFirstIssues(rawGoodFirstIssues)
]);
- writeToFile({ hotDiscussions, goodFirstIssues });
+ return await writeToFile({ hotDiscussions, goodFirstIssues }, writePath);
} catch (e) {
console.log('There were some issues parsing data from github.');
console.log(e);
}
}
-start();
-module.exports = { getLabel, monthsSince, mapGoodFirstIssues, getHotDiscussions, getDiscussionByID };
+/* istanbul ignore next */
+if (require.main === module) {
+ start(resolve(__dirname, '..', '..', 'dashboard.json'));
+}
+
+module.exports = { getLabel, monthsSince, mapGoodFirstIssues, getHotDiscussions, getDiscussionByID, getDiscussions, writeToFile, start, processHotDiscussions };
diff --git a/styles/globals.css b/styles/globals.css
index fa419b645142..ecbca2ff0cbf 100644
--- a/styles/globals.css
+++ b/styles/globals.css
@@ -351,3 +351,7 @@ abbr[title] {
.explorer-menu-wrapper > div > div > div > button {
margin-top: 0px;
}
+
+select {
+ cursor:pointer;
+}
\ No newline at end of file
diff --git a/tests/dashboard/build-dashboard.test.js b/tests/dashboard/build-dashboard.test.js
new file mode 100644
index 000000000000..e7861c36dc65
--- /dev/null
+++ b/tests/dashboard/build-dashboard.test.js
@@ -0,0 +1,198 @@
+const { graphql } = require('@octokit/graphql');
+const { promises: fs, mkdirSync, rmSync } = require('fs-extra');
+const { resolve } = require('path');
+const os = require('os');
+const {
+ getLabel,
+ monthsSince,
+ mapGoodFirstIssues,
+ getHotDiscussions,
+ getDiscussionByID,
+ writeToFile,
+ getDiscussions,
+ start
+} = require('../../scripts/dashboard/build-dashboard');
+
+const {
+ issues,
+ mockDiscussion,
+ discussionWithMoreComments,
+ fullDiscussionDetails,
+ mockRateLimitResponse
+} = require("../fixtures/dashboardData")
+
+jest.mock('@octokit/graphql');
+
+describe('GitHub Discussions Processing', () => {
+ let tempDir;
+ let consoleErrorSpy;
+ let consoleLogSpy;
+
+ beforeAll(() => {
+ tempDir = resolve(os.tmpdir(), 'test-config');
+ mkdirSync(tempDir);
+ });
+
+ afterAll(() => {
+ rmSync(tempDir, { recursive: true, force: true });
+ });
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => { });
+ consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(() => { });
+ });
+
+ afterEach(() => {
+ consoleErrorSpy.mockRestore();
+ consoleLogSpy.mockRestore();
+ });
+
+ it('should fetch additional discussion details when comments have next page', async () => {
+ graphql.mockResolvedValueOnce(fullDiscussionDetails);
+
+ const result = await getHotDiscussions([discussionWithMoreComments]);
+
+ expect(graphql).toHaveBeenCalledWith(
+ expect.any(String),
+ expect.objectContaining({
+ id: 'paginated-discussion',
+ headers: expect.any(Object)
+ })
+ );
+
+ expect(result[0]).toMatchObject({
+ id: 'paginated-discussion',
+ isPR: false,
+ title: 'Test with Pagination'
+ });
+
+ const firstResult = result[0];
+ expect(firstResult.score).toBeGreaterThan(0);
+ });
+
+ it('should handle rate limit warnings', async () => {
+ graphql.mockResolvedValueOnce(mockRateLimitResponse);
+
+ await getDiscussions('test-query', 10);
+
+ expect(consoleLogSpy).toHaveBeenCalledWith(
+ '[WARNING] GitHub GraphQL rateLimit',
+ 'cost = 1',
+ 'limit = 5000',
+ 'remaining = 50',
+ expect.any(String)
+ );
+ });
+
+ it('should handle pagination', async () => {
+ const mockFirstResponse = {
+ search: {
+ nodes: [mockDiscussion],
+ pageInfo: { hasNextPage: true, endCursor: 'cursor1' }
+ },
+ rateLimit: { remaining: 1000 }
+ };
+
+ const mockSecondResponse = {
+ search: {
+ nodes: [{ ...mockDiscussion, id: 'test-id-2' }],
+ pageInfo: { hasNextPage: false }
+ },
+ rateLimit: { remaining: 1000 }
+ };
+
+ graphql
+ .mockResolvedValueOnce(mockFirstResponse)
+ .mockResolvedValueOnce(mockSecondResponse);
+
+ const result = await getDiscussions('test-query', 10);
+ expect(result).toHaveLength(2);
+ });
+
+ it('should handle complete failure', async () => {
+ graphql.mockRejectedValue(new Error('Complete API failure'));
+
+ const filePath = resolve(tempDir, 'error-output.json');
+ await start(filePath);
+
+ expect(consoleLogSpy).toHaveBeenCalledWith('There were some issues parsing data from github.');
+ });
+
+ it('should successfully process and write data', async () => {
+ graphql.mockResolvedValue(mockRateLimitResponse);
+
+ const filePath = resolve(tempDir, 'success-output.json');
+ await start(filePath);
+
+ const content = JSON.parse(await fs.readFile(filePath, 'utf-8'));
+ expect(content).toHaveProperty('hotDiscussions');
+ expect(content).toHaveProperty('goodFirstIssues');
+ });
+
+ it('should get labels correctly', () => {
+ const issue = {
+ labels: { nodes: [{ name: 'area/bug' }, { name: 'good first issue' }] }
+ };
+ expect(getLabel(issue, 'area/')).toBe('bug');
+ expect(getLabel(issue, 'nonexistent/')).toBeUndefined();
+ });
+
+ it('should calculate months since date', () => {
+ const date = new Date();
+ date.setMonth(date.getMonth() - 2);
+ expect(monthsSince(date)).toBe(2);
+ });
+
+ it('should map good first issues', async () => {
+
+ const result = await mapGoodFirstIssues(issues);
+ expect(result[0]).toMatchObject({
+ id: '1',
+ area: 'docs'
+ });
+ });
+
+ it('should handle discussion retrieval', async () => {
+ graphql.mockResolvedValueOnce({ node: mockDiscussion });
+ const result = await getDiscussionByID(false, 'test-id');
+ expect(result.node).toBeDefined();
+
+ graphql.mockRejectedValueOnce(new Error('API error'));
+ await expect(getDiscussionByID(true, 'test-id')).rejects.toThrow();
+ });
+
+ it('should process hot discussions', async () => {
+ const prDiscussion = {
+ ...mockDiscussion,
+ __typename: 'PullRequest',
+ reviews: {
+ totalCount: 1,
+ nodes: [{ comments: { totalCount: 1 } }]
+ }
+ };
+
+ const result = await getHotDiscussions([mockDiscussion, prDiscussion]);
+ expect(result.length).toBeLessThanOrEqual(12);
+ });
+
+ it('should write to file', async () => {
+ const filePath = resolve(tempDir, 'test.json');
+ await writeToFile({ test: true }, filePath);
+ const content = JSON.parse(await fs.readFile(filePath, 'utf-8'));
+ expect(content).toEqual({ test: true });
+ });
+
+ it('should handle parsing errors in processHotDiscussions', async () => {
+ const localConsoleErrorSpy = jest.spyOn(console, 'error');
+
+ await expect(getHotDiscussions([undefined])).rejects.toThrow();
+
+ expect(consoleErrorSpy).toHaveBeenCalledWith(
+ 'there were some issues while parsing this item: undefined'
+ );
+
+ localConsoleErrorSpy.mockRestore();
+ });
+
+});
diff --git a/tests/fixtures/dashboardData.js b/tests/fixtures/dashboardData.js
new file mode 100644
index 000000000000..fa0618c299a9
--- /dev/null
+++ b/tests/fixtures/dashboardData.js
@@ -0,0 +1,81 @@
+const mockDiscussion = {
+ id: 'test-id',
+ __typename: 'Issue',
+ title: 'Test',
+ author: { login: 'author' },
+ resourcePath: '/path',
+ repository: { name: 'repo' },
+ assignees: { totalCount: 0 },
+ reactions: { totalCount: 5 },
+ comments: {
+ totalCount: 2,
+ nodes: [{ reactions: { totalCount: 1 } }],
+ pageInfo: { hasNextPage: false }
+ },
+ labels: { nodes: [] },
+ timelineItems: { updatedAt: new Date().toISOString() }
+};
+
+const discussionWithMoreComments = {
+ id: 'paginated-discussion',
+ __typename: 'Issue',
+ title: 'Test with Pagination',
+ author: { login: 'author' },
+ resourcePath: '/path',
+ repository: { name: 'repo' },
+ assignees: { totalCount: 0 },
+ reactions: { totalCount: 5 },
+ comments: {
+ totalCount: 5,
+ nodes: [{ reactions: { totalCount: 1 } }],
+ pageInfo: { hasNextPage: true }
+ },
+ labels: { nodes: [] },
+ timelineItems: { updatedAt: new Date().toISOString() }
+};
+
+const fullDiscussionDetails = {
+ node: {
+ ...discussionWithMoreComments,
+ comments: {
+ totalCount: 5,
+ nodes: [
+ { reactions: { totalCount: 1 } },
+ { reactions: { totalCount: 2 } },
+ { reactions: { totalCount: 3 } }
+ ],
+ pageInfo: { hasNextPage: false }
+ }
+ }
+};
+
+const mockRateLimitResponse = {
+ search: {
+ nodes: [mockDiscussion],
+ pageInfo: { hasNextPage: false }
+ },
+ rateLimit: {
+ cost: 1,
+ limit: 5000,
+ remaining: 50,
+ resetAt: new Date().toISOString()
+ }
+};
+
+const issues = [{
+ id: '1',
+ title: 'Test',
+ assignees: { totalCount: 1 },
+ resourcePath: '/path',
+ repository: { name: 'repo' },
+ author: { login: 'author' },
+ labels: { nodes: [{ name: 'area/docs' }] }
+}];
+
+module.exports = {
+ issues,
+ mockDiscussion,
+ discussionWithMoreComments,
+ fullDiscussionDetails,
+ mockRateLimitResponse
+};