docs: documentation for v1.18 (#5652)
* docs: documentation for v.17.5 * fix links * updated version number
This commit is contained in:
@@ -62,9 +62,9 @@ In the class you must implement the `emit` method. You can optionally implement
|
||||
|
||||
### Note About the eventToSubscribersMap Property
|
||||
|
||||
The `AbstractEventBusModuleService` implements two methods for handling subscription: `subscribe` and `unsubscribe`. In these methods, the subscribed handler methods are managed within a class property `eventToSubscribersMap`, which is a JavaScript Map. The map's keys are the event names, whereas the value of each key is an array of subscribed handler methods.
|
||||
The `AbstractEventBusModuleService` implements two methods for handling subscription: `subscribe` and `unsubscribe`. In these methods, the subscribed handler functions are managed within a class property `eventToSubscribersMap`, which is a JavaScript Map. The map's keys are the event names, whereas the value of each key is an array of subscribed handler functions.
|
||||
|
||||
In your custom implementation, you can use this property to manage the subscribed handler methods. For example, you can get the subscribers of a method using the `get` method of the map:
|
||||
In your custom implementation, you can use this property to manage the subscribed handler functions. For example, you can get the subscribers of a method using the `get` method of the map:
|
||||
|
||||
```ts
|
||||
const eventSubscribers =
|
||||
@@ -144,13 +144,13 @@ class CustomEventBus extends AbstractEventBusModuleService {
|
||||
|
||||
As mentioned earlier, this method is already implemented in the `AbstractEventBusModuleService` class. This section explains how you can implement your custom subscribe logic if necessary.
|
||||
|
||||
The `subscribe` method attaches a handler method to the specified event, which is run when the event is triggered. It is typically used inside a subscriber class.
|
||||
The `subscribe` method attaches a handler function to the specified event, which is run when the event is triggered. It is typically used inside a subscriber class.
|
||||
|
||||
The `subscribe` method accepts three parameters:
|
||||
|
||||
1. The first parameter `eventName` is a required string. It indicates which event the handler method is subscribing to.
|
||||
1. The first parameter `eventName` is a required string. It indicates which event the handler function is subscribing to.
|
||||
2. The second parameter `subscriber` is a required function that performs an action when the event is triggered.
|
||||
3. The third parameter `context` is an optional object that has the property `subscriberId`. Subscriber IDs are useful to differentiate between handler methods when retrying a failed method. It’s also useful for unsubscribing an event handler. Note that if you must implement the mechanism around assigning IDs to subscribers when you override the `subscribe` method.
|
||||
3. The third parameter `context` is an optional object that has the property `subscriberId`. Subscriber IDs are useful to differentiate between handler functions when retrying a failed method. It’s also useful for unsubscribing an event handler. Note that if you must implement the mechanism around assigning IDs to subscribers when you override the `subscribe` method.
|
||||
|
||||
The implementation of this method depends on the service you’re using for the event bus:
|
||||
|
||||
@@ -170,11 +170,11 @@ class CustomEventBus extends AbstractEventBusModuleService {
|
||||
|
||||
As mentioned earlier, this method is already implemented in the `AbstractEventBusModuleService` class. This section explains how you can implement your custom unsubscribe logic if necessary.
|
||||
|
||||
The `unsubscribe` method is used to unsubscribe a handler method from an event.
|
||||
The `unsubscribe` method is used to unsubscribe a handler function from an event.
|
||||
|
||||
The `unsubscribe` method accepts three parameters:
|
||||
|
||||
1. The first parameter `eventName` is a required string. It indicates which event the handler method is unsubscribing from.
|
||||
1. The first parameter `eventName` is a required string. It indicates which event the handler function is unsubscribing from.
|
||||
2. The second parameter `subscriber` is a required function that was initially subscribed to the event.
|
||||
3. The third parameter `context` is an optional object that has the property `subscriberId`. It can be used to specify the ID of the subscriber to unsubscribe.
|
||||
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
---
|
||||
description: 'Learn how to create a subscriber in Medusa. You can use subscribers to implement functionalities like sending an order confirmation email.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# (Deprecated) How to Create a Subscriber
|
||||
|
||||
In this document, you’ll learn how to create a [Subscriber](./subscribers.mdx) in Medusa that listens to events to perform an action.
|
||||
|
||||
:::note
|
||||
|
||||
Following v1.18 of `@medusajs/medusa`, the approach in this guide is deprecated. It's recommended to follow [this guide](./create-subscriber.md) instead.
|
||||
|
||||
:::
|
||||
|
||||
## Implementation
|
||||
|
||||
A subscriber is a TypeScript or JavaScript file that is created under `src/subscribers`. Its file name, by convention, should be the class name of the subscriber without the word `Subscriber`. For example, if the subscriber is `HelloSubscriber`, the file name should be `hello.ts`.
|
||||
|
||||
After creating the file under `src/subscribers`, in the constructor of your subscriber, listen to events using `eventBusService.subscribe` , where `eventBusService` is a service injected into your subscriber’s constructor.
|
||||
|
||||
The `eventBusService.subscribe` method receives the name of the event as a first parameter and as a second parameter a method in your subscriber that will handle this event.
|
||||
|
||||
For example, here is the `OrderNotifierSubscriber` class created in `src/subscribers/order-notifier.ts`:
|
||||
|
||||
```ts title=src/subscribers/order-notifier.ts
|
||||
class OrderNotifierSubscriber {
|
||||
constructor({ eventBusService }) {
|
||||
eventBusService.subscribe("order.placed", this.handleOrder)
|
||||
}
|
||||
|
||||
handleOrder = async (data) => {
|
||||
console.log("New Order: " + data.id)
|
||||
}
|
||||
}
|
||||
|
||||
export default OrderNotifierSubscriber
|
||||
```
|
||||
|
||||
This subscriber registers the method `handleOrder` as one of the handlers of the `order.placed` event. The method `handleOrder` will be executed every time an order is placed. It receives the order ID in the `data` parameter. You can then use the order’s details to perform any kind of task you need.
|
||||
|
||||
:::tip
|
||||
|
||||
For the `order.placed` event, the `data` object won't contain other order data. Only the ID of the order. You can retrieve the order information using the `orderService`.
|
||||
|
||||
:::
|
||||
|
||||
### Subscriber ID
|
||||
|
||||
The `subscribe` method of the `eventBusService` accepts a third optional parameter which is a context object. This object has a property `subscriberId` with its value being a string. This ID is useful when there is more than one handler method attached to a single event or if you have multiple Medusa backends running. This allows the events bus service to differentiate between handler methods when retrying a failed one.
|
||||
If a subscriber ID is not passed on subscription, all handler methods are run again. This can lead to data inconsistencies or general unwanted behavior in your system. On the other hand, if you want all handler methods to run again when one of them fails, you can omit passing a subscriber ID.
|
||||
|
||||
An example of using the subscribe method with the third parameter:
|
||||
|
||||
```ts
|
||||
eventBusService.subscribe("order.placed", this.handleOrder, {
|
||||
subscriberId: "my-unique-subscriber",
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Retrieve Medusa Configurations
|
||||
|
||||
Within your subscriber, you may need to access the Medusa configuration exported from `medusa-config.js`. To do that, you can access `configModule` using dependency injection.
|
||||
|
||||
For example:
|
||||
|
||||
```ts
|
||||
import { ConfigModule, EventBusService } from "@medusajs/medusa"
|
||||
|
||||
type InjectedDependencies = {
|
||||
eventBusService: EventBusService
|
||||
configModule: ConfigModule
|
||||
}
|
||||
|
||||
class OrderNotifierSubscriber {
|
||||
protected readonly configModule_: ConfigModule
|
||||
|
||||
constructor({
|
||||
eventBusService,
|
||||
configModule,
|
||||
}: InjectedDependencies) {
|
||||
this.configModule_ = configModule
|
||||
eventBusService.subscribe("order.placed", this.handleOrder)
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
export default OrderNotifierSubscriber
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Using Services in Subscribers
|
||||
|
||||
You can access any service through the dependencies injected to your subscriber’s constructor.
|
||||
|
||||
For example:
|
||||
|
||||
```ts title=src/subscribers/order-notifier.ts
|
||||
class OrderNotifierSubscriber {
|
||||
constructor({ productService, eventBusService }) {
|
||||
this.productService = productService
|
||||
|
||||
eventBusService.subscribe(
|
||||
"order.placed",
|
||||
this.handleOrder
|
||||
)
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
You can then use `this.productService` anywhere in your subscriber’s methods. For example:
|
||||
|
||||
```ts title=src/subscribers/order-notifier.ts
|
||||
class OrderNotifierSubscriber {
|
||||
// ...
|
||||
handleOrder = async (data) => {
|
||||
// ...
|
||||
const product = this.productService.list()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::note
|
||||
|
||||
When using attributes defined in the subscriber, such as the `productService` in the example above, you must use an arrow function to declare the method. Otherwise, the attribute will be undefined when used.
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [Example: send order confirmation email](../../modules/orders/backend/send-order-confirmation.md)
|
||||
- [Example: send registration confirmation email](../../modules/customers/backend/send-confirmation.md)
|
||||
- [Create a Plugin](../plugins/create.mdx)
|
||||
@@ -7,51 +7,98 @@ addHowToData: true
|
||||
|
||||
In this document, you’ll learn how to create a [Subscriber](./subscribers.mdx) in Medusa that listens to events to perform an action.
|
||||
|
||||
## Implementation
|
||||
|
||||
A subscriber is a TypeScript or JavaScript file that is created under `src/subscribers`. Its file name, by convention, should be the class name of the subscriber without the word `Subscriber`. For example, if the subscriber is `HelloSubscriber`, the file name should be `hello.ts`.
|
||||
|
||||
After creating the file under `src/subscribers`, in the constructor of your subscriber, listen to events using `eventBusService.subscribe` , where `eventBusService` is a service injected into your subscriber’s constructor.
|
||||
|
||||
The `eventBusService.subscribe` method receives the name of the event as a first parameter and as a second parameter a method in your subscriber that will handle this event.
|
||||
|
||||
For example, here is the `OrderNotifierSubscriber` class created in `src/subscribers/order-notifier.ts`:
|
||||
|
||||
```ts title=src/subscribers/order-notifier.ts
|
||||
class OrderNotifierSubscriber {
|
||||
constructor({ eventBusService }) {
|
||||
eventBusService.subscribe("order.placed", this.handleOrder)
|
||||
}
|
||||
|
||||
handleOrder = async (data) => {
|
||||
console.log("New Order: " + data.id)
|
||||
}
|
||||
}
|
||||
|
||||
export default OrderNotifierSubscriber
|
||||
```
|
||||
|
||||
This subscriber registers the method `handleOrder` as one of the handlers of the `order.placed` event. The method `handleOrder` will be executed every time an order is placed. It receives the order ID in the `data` parameter. You can then use the order’s details to perform any kind of task you need.
|
||||
|
||||
:::tip
|
||||
|
||||
For the `order.placed` event, the `data` object won't contain other order data. Only the ID of the order. You can retrieve the order information using the `orderService`.
|
||||
v1.18 of `@medusajs/medusa` introduced a new approach to create a subscriber. If you're looking for the old guide, you can find it [here](./create-subscriber-deprecated.md). However, it's highly recommended you follow this new approach, as the old one is deprecated.
|
||||
|
||||
:::
|
||||
|
||||
### Subscriber ID
|
||||
## Implementation
|
||||
|
||||
The `subscribe` method of the `eventBusService` accepts a third optional parameter which is a context object. This object has a property `subscriberId` with its value being a string. This ID is useful when there is more than one handler method attached to a single event or if you have multiple Medusa backends running. This allows the events bus service to differentiate between handler methods when retrying a failed one.
|
||||
If a subscriber ID is not passed on subscription, all handler methods are run again. This can lead to data inconsistencies or general unwanted behavior in your system. On the other hand, if you want all handler methods to run again when one of them fails, you can omit passing a subscriber ID.
|
||||
A subscriber is a TypeScript or JavaScript file that is created under `src/subscribers`. It can be created under subdirectories of `src/subscribers` as well. For example, you can place all subscribers to product events under the `src/subscribers/products` directory.
|
||||
|
||||
An example of using the subscribe method with the third parameter:
|
||||
The subscriber file exports a default handler function, and the subscriber's configurations.
|
||||
|
||||
```ts
|
||||
eventBusService.subscribe("order.placed", this.handleOrder, {
|
||||
subscriberId: "my-unique-subscriber",
|
||||
})
|
||||
For example:
|
||||
|
||||
```ts title=src/subscribers/product-update-handler.ts
|
||||
import {
|
||||
ProductService,
|
||||
type SubscriberConfig,
|
||||
type SubscriberArgs,
|
||||
} from "@medusajs/medusa"
|
||||
|
||||
export default async function productUpdateHandler({
|
||||
data, eventName, container, pluginOptions,
|
||||
}: SubscriberArgs<Record<string, any>>) {
|
||||
const productService: ProductService = container.resolve(
|
||||
"productService"
|
||||
)
|
||||
|
||||
const { id } = data
|
||||
|
||||
const product = await productService.retrieve(id)
|
||||
|
||||
// do something with the product...
|
||||
}
|
||||
|
||||
export const config: SubscriberConfig = {
|
||||
event: ProductService.Events.UPDATED,
|
||||
context: {
|
||||
subscriberId: "product-update-handler",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Subscriber Configuration
|
||||
|
||||
The exported configuration object of type `SubscriberConfig` must include the following properties:
|
||||
|
||||
- `event`: A string or an array of strings, each being the name of the event that the subscriber handler function listens to.
|
||||
- `context`: An object that defines the context of the subscriber. It can accept any properties along with the `subscriberId` property. Learn more about the subscriber ID and the context object in [this section](#context-with-subscriber-id).
|
||||
|
||||
### Subscriber Handler Function
|
||||
|
||||
The default-export of the subscriber file is a handler function that is executed when the events specified in the exported configuration is triggerd.
|
||||
|
||||
The function accepts a parameter of type `SubscriberArgs`, which has the following properties:
|
||||
|
||||
- `data`: The data payload of the emitted event. Its type is different for each event. So, make sure to check the [events reference](./events-list.md) for the expected payload of the events your subscriber listens to. You can then pass the expected payload type as a type parameter to `SubscriberArgs`, for example, `Record<string, string>`.
|
||||
- `eventName`: A string indicating the name of the event. This is useful if your subscriber listens to more than one event and you want to differentiate between them.
|
||||
- `container`: The [dependency container](../fundamentals/dependency-injection.md) that allows you to resolve Medusa resources, such as services.
|
||||
- `pluginOptions`: When the subscriber is created within a plugin, this object holds the plugin's options defined in the [Medusa configurations](../backend/configurations.md).
|
||||
|
||||
---
|
||||
|
||||
## Context with Subscriber ID
|
||||
|
||||
The `context` property of the subscriber configuration object is passed to the `eventBusService`. You can pass the `subscriberId` and any custom data in it.
|
||||
|
||||
:::note
|
||||
|
||||
The subscriber ID is useful when there is more than one handler function attached to a single event or if you have multiple Medusa backends running. This allows the events bus service to differentiate between handler functions when retrying a failed one, avoiding retrying all subscribers which can lead to data inconsistencies or general unwanted behavior in your system.
|
||||
|
||||
:::
|
||||
|
||||
### Inferred Subscriber ID
|
||||
|
||||
If you don't pass a subscriber ID to the subscriber configurations, the name of the subscriber function is used as the subscriber ID. If the subscriber function is an anonymous function, the name of the subscriber file is used instead.
|
||||
|
||||
---
|
||||
|
||||
## Caveats for Local Event Bus
|
||||
|
||||
If you use the `event-bus-local` as your event bus sevice, note the following:
|
||||
|
||||
- The `subscriberId` passed in the context is overwritten to a random ID when using `event-bus-local`. So, setting the subscriber ID in the context won't have any effect in this case.
|
||||
- The `eventName` passed to the handler function will be `undefined` when using `event-bus-local` as it doesn't pass the event name properly.
|
||||
|
||||
:::note
|
||||
|
||||
While the local event bus is a good option for development, it's highly recommended to use the [Redis Event Module](./modules/redis.md) in production.
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Retrieve Medusa Configurations
|
||||
@@ -60,71 +107,32 @@ Within your subscriber, you may need to access the Medusa configuration exported
|
||||
|
||||
For example:
|
||||
|
||||
```ts
|
||||
import { ConfigModule, EventBusService } from "@medusajs/medusa"
|
||||
```ts title=src/subscribers/product-update-handler.ts
|
||||
import {
|
||||
ProductService,
|
||||
type SubscriberConfig,
|
||||
type SubscriberArgs,
|
||||
type ConfigModule,
|
||||
} from "@medusajs/medusa"
|
||||
|
||||
type InjectedDependencies = {
|
||||
eventBusService: EventBusService
|
||||
configModule: ConfigModule
|
||||
}
|
||||
|
||||
class OrderNotifierSubscriber {
|
||||
protected readonly configModule_: ConfigModule
|
||||
export default async function productUpdateHandler({
|
||||
data, eventName, container, pluginOptions,
|
||||
}: SubscriberArgs) {
|
||||
const configModule: ConfigModule = container.resolve(
|
||||
"configModule"
|
||||
)
|
||||
|
||||
constructor({
|
||||
eventBusService,
|
||||
configModule,
|
||||
}: InjectedDependencies) {
|
||||
this.configModule_ = configModule
|
||||
eventBusService.subscribe("order.placed", this.handleOrder)
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
export default OrderNotifierSubscriber
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Using Services in Subscribers
|
||||
|
||||
You can access any service through the dependencies injected to your subscriber’s constructor.
|
||||
|
||||
For example:
|
||||
|
||||
```ts title=src/subscribers/order-notifier.ts
|
||||
class OrderNotifierSubscriber {
|
||||
constructor({ productService, eventBusService }) {
|
||||
this.productService = productService
|
||||
|
||||
eventBusService.subscribe(
|
||||
"order.placed",
|
||||
this.handleOrder
|
||||
)
|
||||
}
|
||||
// ...
|
||||
export const config: SubscriberConfig = {
|
||||
event: ProductService.Events.UPDATED,
|
||||
context: {
|
||||
subscriberId: "product-update-handler",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
You can then use `this.productService` anywhere in your subscriber’s methods. For example:
|
||||
|
||||
```ts title=src/subscribers/order-notifier.ts
|
||||
class OrderNotifierSubscriber {
|
||||
// ...
|
||||
handleOrder = async (data) => {
|
||||
// ...
|
||||
const product = this.productService.list()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::note
|
||||
|
||||
When using attributes defined in the subscriber, such as the `productService` in the example above, you must use an arrow function to declare the method. Otherwise, the attribute will be undefined when used.
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
@@ -4,7 +4,7 @@ description: 'Learn about the available events and their data payloads in Medusa
|
||||
|
||||
# Events Reference
|
||||
|
||||
This document details all events in Medusa, when they are triggered, and what data your handler method will receive when the event is triggered.
|
||||
This document details all events in Medusa, when they are triggered, and what data your handler function will receive when the event is triggered.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
||||
@@ -15,9 +15,9 @@ Subscribers register handlers for an events and allows you to perform an action
|
||||
|
||||
Natively in Medusa there are subscribers to handle different events. However, you can also create your own custom subscribers.
|
||||
|
||||
Custom subscribers are TypeScript or JavaScript files in your project's `src/subscribers` directory. Files here should export classes, which will be treated as subscribers by Medusa. By convention, the class name should end with `Subscriber` and the file name should be the camel-case version of the class name without `Subscriber`. For example, the `WelcomeSubscriber` class is in the file `src/subscribers/welcome.ts`.
|
||||
Custom subscribers are TypeScript or JavaScript files in your project's `src/subscribers` directory. Subscriber files must default export a handler function and export a configuration object.
|
||||
|
||||
Whenever an event is emitted, the subscriber’s registered handler method is executed. The handler method receives as a parameter an object that holds data related to the event. For example, if an order is placed the `order.placed` event will be emitted and all the handlers will receive the order id in the parameter object.
|
||||
Whenever an event is emitted, the subscriber’s handler function is executed. The handler function receives as a parameter an object that includes the data payload, among other parameters. For example, if an order is placed, the `order.placed` event is emitted and all the handlers receive the order ID in the `data` object.
|
||||
|
||||
### Example Use Cases
|
||||
|
||||
|
||||
Reference in New Issue
Block a user