From c5d52240aab196a5d1ba021ad5059d309e2d5fc7 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Wed, 8 Jun 2022 18:55:01 +0300 Subject: [PATCH 1/4] added notification overview --- docs/content/add-plugins/sendgrid.mdx | 2 +- .../advanced/backend/notification/overview.md | 92 ++++++++++++++++ .../backend/subscribers/events-list.md | 2 +- docs/content/how-to/notification-api.md | 103 ------------------ www/docs/sidebars.js | 11 +- 5 files changed, 103 insertions(+), 107 deletions(-) create mode 100644 docs/content/advanced/backend/notification/overview.md delete mode 100644 docs/content/how-to/notification-api.md diff --git a/docs/content/add-plugins/sendgrid.mdx b/docs/content/add-plugins/sendgrid.mdx index 9f602f1601..4fcc04f60c 100644 --- a/docs/content/add-plugins/sendgrid.mdx +++ b/docs/content/add-plugins/sendgrid.mdx @@ -3963,5 +3963,5 @@ You can also track analytics related to emails sent from the SendGrid dashboard. ## What’s Next 🚀 -- Learn more about how [Notifications work in Medusa](../how-to/notification-api.md). +- Learn more about how [Notifications work in Medusa](../advanced/backend/notification/overview.md). - Install the [Medusa admin](https://github.com/medusajs/admin#-setting-up-admin) for functionalities like Gift Cards creation, swaps, claims, order return requests, and more. \ No newline at end of file diff --git a/docs/content/advanced/backend/notification/overview.md b/docs/content/advanced/backend/notification/overview.md new file mode 100644 index 0000000000..68426e450e --- /dev/null +++ b/docs/content/advanced/backend/notification/overview.md @@ -0,0 +1,92 @@ +# Architecture Overview + +This document gives an overview of the notification architecture and how it works. + +## Introduction + +Medusa provides a Notification API to mainly handle sending and resending notifications when an event occurs. For example, sending an email to the customer when they place an order. + +The Notification architecture is made up of 2 main components: the Notification Provider and the Notification. Simply put, the Notification Provider handles the sending and resending of a Notification. + +## Notification Provider + +### Overview + +A Notification Provider is a provider that handles sending and resending of notifications. You can either create and integrate your own provider or install a Notification Provider through a third-party plugin. + +An example of a notification provider is SendGrid. When an order is placed, the SendGrid plugin sends an email to the customer. + +### How it is Created + +A Notification Provider is essentially a Medusa [Service](../services/create-service.md) with a unique identifier, and it extends the [`NotificationService`](../../../references/services/classes/NotificationService.md) provided by the `medusa-interfaces` package. It can be created as part of a [Plugin](../../../guides/plugins.md), or it can be created just as a service file in your Medusa server. + +As a developer, you mainly work with the Notification Provider when integrating a third-party service that handles notifications in Medusa. + +When you run your Medusa server, the Notification Provider is registered on your server if it isn’t already. This means that it will be inserted into the `notification_provider` table in your database. + +### Entity Overview + +The `NotificationProvider` entity only has 2 attributes: `id` and `is_installed`. + +`id` is the value of the static property `identifier` defined inside the notification service class. + +`is_installed` indicates whether the Notification Provider is installed or not. When you install a Notification Provider, the value of this attribute is `true`. + +If you installed a Notification provider and then removed the service files or plugin that registered the Notification Provider, the Notification Provider remains in your database, but the value of the `is_installed` field changes to `false`. + +## Notification + +### Overview + +A notification is a form of an alert sent to the customers or users to inform them of an action that has occurred. For example, if an order is placed, the notification, in this case, can be an email that confirms their order and lists the order details. + +Notifications can take on other forms such as an SMS or a Slack message. + +### How it is Created + +Notifications are created in the `NotificationService` class in Medusa’s core after the Notification has been handled by the Notification Provider. + +The data and additional details that the Notification Provider returns to the `NotificationService` is used to fill some of the attributes of the Notification in the database. + +A Notification also represents a resent notification. So, when a notification is resent, a new one is created that references the original Notification as a parent. This Notification is also created by the `NotificationService` class. + +### Entity Overview + +The 2 most important properties in the `Notification` entity are the `to` and `data` properties. + +The `to` property is a string that represents the receiver of the Notification. For example, if the Notification was sent to an email address, the `to` property holds the email address the Notification was sent to. + +The `to` property can alternatively be a phone number or a chat username. It depends on the Notification Provider and how it sends the Notification. + +The `data` property is an object that holds all the data necessary to send the Notification. For example, in the case of an order confirmation Notification, it can hold data related to the order. + +The `data` property is useful when a notification is resent later. The same `data` can be used to resend the notification. + +In the case of resent notifications, the resent notification has a `parent_id` set to the ID of the original Notification. The value of the `parent_id` property in the original Notification is `null`. + +The `Notification` entity has some properties that determine the context of this Notification. This includes the `event_name` property which is the event that triggered the sending of this notification. + +Additionally, the `resource_type` property is used to determine what resource this event is associated with. For example, if the `event_name` is `order.placed`, the `resource_type` is `order`. + +You can also access the specific resource using the `resource_id` property, which is the ID of the resource. So, in case of the `order.placed` event, the `resource_id` is the ID of the order that was created. + +The `Notification` entity also includes properties related to the receiver of the Notification. In case the receiver is a customer, the `customer_id` property is used to identify which customer. + +## Automating Flows with Notifications + +With Medusa you can create notifications as a reaction to a wide spectrum of events, allowing you to automate communication and processes. + +An example of a flow that can be implemented using Medusa's Notification API is automated return flows: + +- A customer requests a return by sending a `POST` request to the `/store/returns` endpoint. +- The Notification Provider listens to the `order.return_requested` event and sends an email to the customer with a return invoice and return label generated by the Fulfillment Provider. +- The customer returns the items triggering the `return.recieved` event. +- The Notification Provider listens to the `return.received` event and sends an email to the customer with confirmation that their items have been received and that a refund has been issued. + +## What’s Next 🚀 + +- Learn how to create your own Notification Provider. +- [Check out the list of events in Medusa.](../subscribers/events-list.md) +- [Check the `NotificationService` API reference for more details on how it works.](../../../references/services/classes/NotificationService.md) +- [Check out the SendGrid Notification plugin.](../../../add-plugins/sendgrid.mdx) +- Learn more about [Subscribers](../subscribers/create-subscriber.md) and [Services](../services/create-service.md) in Medusa. diff --git a/docs/content/advanced/backend/subscribers/events-list.md b/docs/content/advanced/backend/subscribers/events-list.md index 1f76d6fa2d..21b917d10f 100644 --- a/docs/content/advanced/backend/subscribers/events-list.md +++ b/docs/content/advanced/backend/subscribers/events-list.md @@ -1862,4 +1862,4 @@ Object of the following format: ## What’s Next 🚀 - Learn how you can [use services in subscribers](create-subscriber.md#using-services-in-subscribers). -- Learn how to [create notifications](../../../how-to/notification-api.md) in Medusa. +- Learn how to [create notifications](../notification/overview.md) in Medusa. diff --git a/docs/content/how-to/notification-api.md b/docs/content/how-to/notification-api.md deleted file mode 100644 index 2e39c2523a..0000000000 --- a/docs/content/how-to/notification-api.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: Notifications and automated flows ---- - -# Notification API and how to structure email flows - -### Introduction - -Plugins offer a way to extend and integrate the core functionality of Medusa. For a walkthrough of the implementation details behind these, please see [Plugins in Medusa](https://docs.medusajs.com/guides/plugins). - -Medusa makes it possible for plugins to implement the Notification API. The API allows for different types of implementations of notifications (emails, text messages, Slack messages, etc), that are sent as a reaction to events in Medusa. All Notifications are stored in the database with information about the receiver of the notification and what plugin was in charge of sending it. This allows merchants to resend notifications, but also gives an overview of what communication has been sent to customers. - -### How it works - -The Notification API works by subscribing to all events that are emitted to the Event Bus and channeling them through to notification plugins that listen to the events. In a plugin you can subscribe to a notification event by exporting a subscriber class that calls `notificationService.subscribe`: - -```jsx -// src/subscribers/my-notification.js - -class MyNotification { - constructor({ notificationService }) { - // Subscribe to order.placed events - notificationService.subscribe("order.placed", "my-service"); - } -} - -export default MyNotification; -``` - -The above code tells the notification service to send `order.placed` events to the `my-service` notification service implemented in your plugin. - -For a plugin to work with the Notification API you must implement 2 methods `sendNotification` and `resendNotification`; - -```jsx -// src/services/my-notification.js - -class MyService extends NotificationService { - static identifier = "my-service"; - - constructor({ orderService }, options) { - super(); - - this.options_ = options; - this.orderService_ = orderService; - } - - async sendNotification(eventName, eventData, attachmentGenerator) { - let sendData; - switch (eventName) { - case "order.placed": - sendData = await this.orderService_.retrieve(eventData.id); - break; - default: - // If the return value is undefined no notification will be stored - return; - } - - await CoolEmailSender.send({ - email: sendData.email, - templateData: sendData, - }); - - return { to: sendData.email, data: sendData }; - } - - async resendNotification(notification, config, attachmentGenerator) { - const recipient = config.to || notification.to; - - await CoolEmailSender.send({ - email: recipient, - templateData: notification.data, - }); - - return { to: sendOptions.to, data: notification.data }; - } -} - -export default MyService; -``` - -:::note - - A notification service must have a static property called `identifier` this is used to determine which classes are called when subscribing to different events. In this case the service identifier is `my-service` so to subscribe to notifications you must use: - `notificationService.subscribe([eventname], "my-service")` - -::: - -The above class is an example implementation of a NotificationService. It uses a fictional email service called `CoolEmailSender` to send emails to a customer whenever an order is placed. The `sendNotification` implementation gets the event name and fetches relevant data based on what event is being processed; in this case it retrieves an order, which is later used when requesting `CoolEmailSender` to dispatch an email. The address to send the email to is likewise fetched from the order. - -The return type of `sendNotification` and `resendNotification` is an object with `to` and `data`. The `to` prop should identify the receiver of the notification, in this case an email, but it could also be a phone number, an ID, a channel name or something similar depending on the type of notification provider. The `data` prop contains the data as it was gathered when the notification was sent; the same data will be provided if the notification is resent at a later point. - -When `resendNotification` is called the original Notification is provided along with a config object. The config object may contain a `to` property that can be used to overwrite the original `to`. - -## Creating automated notification flows - -When running an ecommerce store you typically want to send communication to your customers when different events occur, these include messages like order confirmations and shipping updates. With Medusa you can create transactional notifications as a reaction to a wide spectrum of events, allowing you to automate communication and processes. An example of a flow that can be implemented using Medusa's Notification API is automated return flows. Below is an outline of how an automated return flow might work. - -- Customer requests a return with `POST /store/returns` -- Notification Service listens for `order.return_requested` and sends email to the customer with a return invoice and return label generated by fulfillment provider -- Customer returns items triggering `return.recieved` -- Notification Service listens for `return.received` and sends email to the customer with confirmation that their items have been received and that a refund has been issued. - -Check out `medusa-plugin-sendgrid` for an Notification API implementation that works with Sendgrid. diff --git a/www/docs/sidebars.js b/www/docs/sidebars.js index 6a6988e54a..f2208b538d 100644 --- a/www/docs/sidebars.js +++ b/www/docs/sidebars.js @@ -186,8 +186,15 @@ module.exports = { ] }, { - type: "doc", - id: "how-to/notification-api", + type: "category", + label: "Notification", + collapsed: true, + items: [ + { + type: "doc", + id: "advanced/backend/notification/overview" + } + ] }, { type: "doc", From 2ac07400a6f5136c2e4b87fb194b5a1b07327b57 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Thu, 9 Jun 2022 16:35:06 +0300 Subject: [PATCH 2/4] added how to create notification provider --- .../how-to-create-notification-provider.md | 272 ++++++++++++++++++ .../advanced/backend/notification/overview.md | 26 +- www/docs/sidebars.js | 5 + 3 files changed, 288 insertions(+), 15 deletions(-) create mode 100644 docs/content/advanced/backend/notification/how-to-create-notification-provider.md diff --git a/docs/content/advanced/backend/notification/how-to-create-notification-provider.md b/docs/content/advanced/backend/notification/how-to-create-notification-provider.md new file mode 100644 index 0000000000..73ec0e949c --- /dev/null +++ b/docs/content/advanced/backend/notification/how-to-create-notification-provider.md @@ -0,0 +1,272 @@ +# How to Create a Notification Provider + +In this document, you’ll learn how to add a Notification Provider to your Medusa server. If you’re unfamiliar with the Notification architecture in Medusa, it is recommended to check out the [architecture overview](overview.md) first. + +## Overview + +A Notification Provider is the custom or third-party service used to handle sending alerts to customers or users when an event occurs. + +For example, you can use SendGrid to send a confirmation email to a customer after they place an order. SendGrid in this example is a Notification Provider. + +:::tip + +If you’re interested in using SendGrid to send Notifications, you can use the [SendGrid](../../../add-plugins/sendgrid.mdx) plugin instead of using your own. + +::: + +Adding a Notification Provider is as simple as creating a [Service](../services/create-service.md) file in `src/services`. A Notification Provider is essentially a Service that extends the `NotificationService` from `medusa-interfaces`. + +:::info + +Notification Providers are loaded and installed at the server startup. + +::: + +After creating the Notification Provider Service, you must create a [Subscriber](../subscribers/create-subscriber.md) that subscribes the Notification Provider to specific events. + +## Prerequisites + +Before you start creating a Notification Provider, you need to install a [Medusa server](../../../quickstart/quick-start.md). + +You also need to install and configure Redis. You can check out the documentation “[Set Up Your Development Environment](../../../tutorial/0-set-up-your-development-environment.mdx)” for help. + +## Create a Notification Provider + +The first step to creating a Notification Provider is to create a file in `src/services` with the following content: + +```jsx +import { NotificationService } from "medusa-interfaces"; + +class EmailSenderService extends NotificationService { + +} + +export default EmailSenderService; +``` + +Where `EmailSenderService` is the name of your Notification Provider Service. + +Notification Providers must extend `NotificationService` from `medusa-interfaces`. + +:::info + +Following the naming convention of Services, the name of the file should be the slug name of the Notification Provider, and the name of the class should be the camel case name of the Notification Provider suffixed with “Service”. In the example above, the name of the file should be `email-sender.js`. You can learn more in the [service documentation](../services/create-service.md). + +::: + +### identifier + +Notification Provider Services must have a static property `identifier`. + +The `NotificationProvider` entity has 2 properties: `identifier` and `is_installed`. The value of the `identifier` property in the Service class is used when the Notification Provider is created in the database. + +The value of this property is also used later when you want to subscribe the Notification Provider to events in a Subscriber. + +For example, in the class you created in the previous code snippet you can add the following property: + +```jsx +static identifier = "email-sender"; +``` + +### constructor + +You can use the `constructor` of your Notification Provider to have access to different Services in Medusa through dependency injection. + +You can also use the constructor to initialize your integration with the third-party provider. For example, if you use a client to connect to the third-party provider’s APIs, you can initialize it in the constructor and use it in other methods in the Service. + +Additionally, if you’re creating your Notification Provider as an external plugin to be installed on any Medusa server and you want to access the options added for the plugin, you can access it in the constructor. The options are passed as a second parameter. + +:::info + +You can learn more about plugins and how to create them in the [Plugins](../../../guides/plugins.md) documentation. + +::: + +Continuing on with the previous example, if you want to use the [`OrderService`](../../../references/services/classes/OrderService.md) later when sending notifications, you can inject it into the constructor: + +```jsx +constructor({ orderService }, options) { + //you can access options here in case you're + //using a plugin + super(); + + this.orderService = orderService; +} +``` + +### sendNotification + +When an event is triggered that your Notification Provider is registered as a handler for, the [`NotificationService`](../../../references/services/classes/NotificationService.md) in Medusa’s core will execute the `sendNotification` method of your Notification Provider. + +In this method, you can perform the necessary operation to send the Notification. Following the example above, you can send an email to the customer when they place an order. + +This method receives 3 parameters: + +1. `eventName`: This is the name of the event that was triggered. For example, `order.placed`. +2. `eventData`: This is the data payload of the event that was triggered. For example, if the `order.placed` event is triggered, the `eventData` object contains the property `id` which is the ID of the order that was placed. +3. `attachmentGenerator`: If you’ve previously attached a generator to the `NotificationService` using the [`registerAttachmentGenerator`](../../../references/services/classes/NotificationService.md#registerattachmentgenerator) method, you have access to it here. You can use the `attachmentGenerator` to generate on-demand invoices or other documents. The default value of this parameter is null. + +:::info + +You can learn more about what events are triggered in Medusa and their data payload in the [Events List](../subscribers/events-list.md) documentation. + +::: + +This method must return an object containing two properties: + +1. `to`: a string that represents the receiver of the Notification. For example, if you sent an email to the customer then `to` is the email address of the customer. In other cases, it might be a phone number or a username. +2. `data`: an object that contains the data used to send the Notification. For example, if you sent an order confirmation email to the customer, then the `data` object might include the order items or the subject of the email. This `data` is necessary if the notification is resent later as you can use the same data. + +Continuing with the previous example you can have the following implementation of the `sendNotification` method: + +```jsx +async sendNotification(eventName, eventData, attachmentGenerator) { + if (eventName === 'order.placed') { + //retrieve order + const order = await this.orderService.retrieve(eventData.id); + //TODO send email + + console.log('Notification sent'); + return { + to: order.email, + data: { + //any data necessary to send the email + //for example: + subject: 'You placed a new order!', + items: order.items + } + }; + } +} +``` + +In this code snippet, you check first if the event is `order.placed`. This can be helpful if you’re handling multiple events using the same Notification Provider. + +You then retrieve the order using the ID and send the email. Here, the logic related to sending the email is not implemented as it is generally specific to your Notification Provider. + +Finally, you return an object with the `to` property set to the customer email and the `data` property is an object that contains data necessary to send the email such as a `subject` or `items`. + +:::note + +The `to` and `data` properties are used in the `NotificationService` in Medusa’s core to create a new `Notification` record in the database. You can learn more about the `Notification` entity in the [Architecture Overview](overview.md#notification-entity-overview) documentation. + +::: + +### resendNotification + +Using the [Resend Notification endpoint](https://docs.medusajs.com/api/admin/notification/resend-notification), an admin user can resend a Notification to the customer. The [`NotificationService`](../../../references/services/classes/NotificationService.md) in Medusa’s core then executes the `resendNotification` method in your Notification Provider. + +This method receives 3 parameters: + +1. `notification`: This is the original Notification record that was created after you sent the notification with `sendNotification`. You can get an overview of the entity and its attributes in the [architecture overview](overview.md#notification-entity-overview), but most notably it includes the `to` and `data` attributes which are populated originally using the `to` and `data` properties of the object you return in `sendNotification`. +2. `config`: In the Resend Notification endpoint you may specify an alternative receiver of the notification using the `to` request body parameter. For example, you may want to resend the order confirmation email to a different email. If that’s the case, you have access to it in the `config` parameter object. Otherwise, `config` will be an empty object. +3. `attachmentGenerator`: If you’ve previously attached a generator to the Notification Service using the [`registerAttachmentGenerator`](../../../references/services/classes/NotificationService.md#registerattachmentgenerator) method, you have access to it here. You can use the `attachmentGenerator` to generate on-demand invoices or other documents. The default value of this parameter is null. + +Similarly to the `sendNotification` method, this method must return an object containing two properties: + +1. `to`: a string that represents the receiver of the Notification. You can either return the same `to` available in the `notification` parameter or the updated one in the `config` parameter. +2. `data`: an object that contains the data used to send the Notification. You can either return the same `data` in the `notification` parameter or make any necessary updates to it. + +Continuing with the previous example you can have the following implementation of the `resendNotification` method: + +```jsx +resendNotification(notification, config, attachmentGenerator) { + //check if the receiver of the notification should be changed + const to = config.to ? config.to : notification.to; + + //TODO resend the notification using the same data that is saved under notification.data + + console.log('Notification resent'); + return { + to, + data: notification.data //you can also make changes to the data + } +} +``` + +In the above snippet, you check if the `to` should be changed by checking if the `config` parameter has a `to` property. Otherwise, you keep the same `to` address stored in the `notification` parameter. + +You then resend the email. Here, the logic related to sending the email is not implemented as it is generally specific to your Notification Provider. + +Finally, you return an object with the `to` property set to the email (either new or old) and the `data` property is the same data used before to send the original notification. you can alternatively make any changes to the data. + +:::note + +The `to` and `data` properties are used in the `NotificationService` in Medusa’s core to create a new `Notification` record in the database. No changes are made to the original `Notification` record created after the `sendNotification` method. This new record is associated with the original `Notification` record using the `parent_id` attribute in the entity. You can learn more about the `Notification` entity in the [Architecture Overview](overview.md#notification-entity-overview) documentation. + +::: + +## Create a Subscriber + +After creating your Notification Provider Service, you must create a Subscriber that registers this Service as a notification handler of events. + +:::note + +This section will not cover the basics of Subscribers. You can read the [Subscribers](../subscribers/create-subscriber.md) documentation to learn more about them and how to create them. + +::: + +Following the previous example, to make sure the `email-sender` Notification Provider handles the `order.placed` event, create the file `src/subscribers/notification.js` with the following content: + +```jsx +class NotificationSubscriber { + constructor({ notificationService }) { + notificationService.subscribe('order.placed', 'email-sender'); + } +} + +export default NotificationSubscriber; +``` + +This subscriber accesses the `notificationService` using dependency injection. The `notificationService` contains a `subscribe` method that accepts 2 parameters. The first one is the name of the event to subscribe to, and the second is the identifier of the Notification Provider that is subscribing to that event. + +:::tip + +Notice that the value of the `identifier` static property defined in the `EmailSenderService` is used to register the Notification Provider to handle the `order.placed` event. + +::: + +## Test Sending Notifications with your Notification Provider + +Make sure you've configured Redis with your Medusa server as explained in the Prerequisites section and that the Redis service is running. + +Then, start by running your Medusa server: + +```bash +npm run start +``` + +Then, place an order either using the [REST APIs](https://docs.medusajs.com/api/store/auth) or using the storefront. + +:::tip + +If you don’t have a storefront installed you can get started with either our [Next.js](../../../starters/nextjs-medusa-starter.md) or [Gatsby](../../../starters/gatsby-medusa-starter.md) starter storefronts in minutes. + +::: + +After placing an order, you can see in your console the message “Notification Sent”. If you added your own notification sending logic, you should receive an email or alternatively the type of notification you’ve set up. + +## Test Resending Notifications with your Notification Provider + +To test resending a notification, first, retrieve the ID of the notification you just sent using the [List Notifications admin endpoint](https://docs.medusajs.com/api/admin/notification/list-notifications). You can pass as a body parameter the `to` or `event_name` parameters to filter out the notification you just sent. + +:::tip + +You must be authenticated as an admin user before sending this request. You can use the [Authenticate a User](https://docs.medusajs.com/api/admin/auth/) endpoint to get authenticated. + +::: + +![List Notifications Request](https://i.imgur.com/iF1rZX1.png) + +Then, send a request to the [Resend Notification](https://docs.medusajs.com/api/admin/notification/resend-notification) endpoint using the ID retrieved from the previous request. You can pass the `to` parameter in the body to change the receiver of the notification. You should see the message “Notification Resent” in your console and if you implemented your own logic for resending the notification it will be resent. + +![Resend Notifications Request](https://i.imgur.com/0zFfPed.png) + +This request returns the same notification object as the List Notifications endpoint, but it now has a new object in the `resends` array. This is the resent notification. If you supplied a `to` parameter in the request body, you should see its value in the `to` property of the resent notification object. + +## What’s Next 🚀 + +- Check out the [list of events](../subscribers/events-list.md) you can listen to. +- Check out the [SendGrid](../../../add-plugins/sendgrid.mdx) plugin for easy integration of email notifications. +- Learn how to [create your own plugin](../../../guides/plugins.md). +- Learn more about [Subscribers](../subscribers/create-subscriber.md) and [Services](../services/create-service.md). diff --git a/docs/content/advanced/backend/notification/overview.md b/docs/content/advanced/backend/notification/overview.md index 68426e450e..b2ed328272 100644 --- a/docs/content/advanced/backend/notification/overview.md +++ b/docs/content/advanced/backend/notification/overview.md @@ -10,39 +10,35 @@ The Notification architecture is made up of 2 main components: the Notification ## Notification Provider -### Overview - A Notification Provider is a provider that handles sending and resending of notifications. You can either create and integrate your own provider or install a Notification Provider through a third-party plugin. An example of a notification provider is SendGrid. When an order is placed, the SendGrid plugin sends an email to the customer. -### How it is Created +### How Notification Provider is Created -A Notification Provider is essentially a Medusa [Service](../services/create-service.md) with a unique identifier, and it extends the [`NotificationService`](../../../references/services/classes/NotificationService.md) provided by the `medusa-interfaces` package. It can be created as part of a [Plugin](../../../guides/plugins.md), or it can be created just as a service file in your Medusa server. +A Notification Provider is essentially a Medusa [Service](../services/create-service.md) with a unique identifier, and it extends the [`NotificationService`](../../../references/services/classes/NotificationService.md) provided by the `medusa-interfaces` package. It can be created as part of a [Plugin](../../../guides/plugins.md), or it can be created just as a Service file in your Medusa server. As a developer, you mainly work with the Notification Provider when integrating a third-party service that handles notifications in Medusa. When you run your Medusa server, the Notification Provider is registered on your server if it isn’t already. This means that it will be inserted into the `notification_provider` table in your database. -### Entity Overview +### NotificationProvider Entity Overview The `NotificationProvider` entity only has 2 attributes: `id` and `is_installed`. -`id` is the value of the static property `identifier` defined inside the notification service class. +`id` is the value of the static property `identifier` defined inside the notification Service class. `is_installed` indicates whether the Notification Provider is installed or not. When you install a Notification Provider, the value of this attribute is `true`. -If you installed a Notification provider and then removed the service files or plugin that registered the Notification Provider, the Notification Provider remains in your database, but the value of the `is_installed` field changes to `false`. +If you installed a Notification provider and then removed the Service files or plugin that registered the Notification Provider, the Notification Provider remains in your database, but the value of the `is_installed` field changes to `false`. ## Notification -### Overview - A notification is a form of an alert sent to the customers or users to inform them of an action that has occurred. For example, if an order is placed, the notification, in this case, can be an email that confirms their order and lists the order details. Notifications can take on other forms such as an SMS or a Slack message. -### How it is Created +### How Notification is Created Notifications are created in the `NotificationService` class in Medusa’s core after the Notification has been handled by the Notification Provider. @@ -50,11 +46,11 @@ The data and additional details that the Notification Provider returns to the `N A Notification also represents a resent notification. So, when a notification is resent, a new one is created that references the original Notification as a parent. This Notification is also created by the `NotificationService` class. -### Entity Overview +### Notification Entity Overview The 2 most important properties in the `Notification` entity are the `to` and `data` properties. -The `to` property is a string that represents the receiver of the Notification. For example, if the Notification was sent to an email address, the `to` property holds the email address the Notification was sent to. +The `to` property is a string that represents the receiver of the Notification. For example, if the Notification was sent to an email address, the `to` property holds the email address the Notification was sent to. The `to` property can alternatively be a phone number or a chat username. It depends on the Notification Provider and how it sends the Notification. @@ -86,7 +82,7 @@ An example of a flow that can be implemented using Medusa's Notification API is ## What’s Next 🚀 - Learn how to create your own Notification Provider. -- [Check out the list of events in Medusa.](../subscribers/events-list.md) -- [Check the `NotificationService` API reference for more details on how it works.](../../../references/services/classes/NotificationService.md) -- [Check out the SendGrid Notification plugin.](../../../add-plugins/sendgrid.mdx) +- Check out the [list of events](../subscribers/events-list.md) in Medusa. +- Check the [`NotificationService`](../../../references/services/classes/NotificationService.md) API reference for more details on how it works. +- Check out the [SendGrid](../../../add-plugins/sendgrid.mdx) Notification plugin. - Learn more about [Subscribers](../subscribers/create-subscriber.md) and [Services](../services/create-service.md) in Medusa. diff --git a/www/docs/sidebars.js b/www/docs/sidebars.js index f2208b538d..0e9fc6de61 100644 --- a/www/docs/sidebars.js +++ b/www/docs/sidebars.js @@ -193,6 +193,11 @@ module.exports = { { type: "doc", id: "advanced/backend/notification/overview" + }, + { + type: "doc", + id: "advanced/backend/notification/how-to-create-notification-provider", + label: "Create a Notification Provider" } ] }, From 444ef1ea3f7f1f05b778a88c631661103e4798ec Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Wed, 8 Jun 2022 18:55:01 +0300 Subject: [PATCH 3/4] added notification overview --- docs/content/add-plugins/sendgrid.mdx | 2 +- .../advanced/backend/notification/overview.md | 92 ++++++++++++++++ .../backend/subscribers/events-list.md | 2 +- docs/content/how-to/notification-api.md | 103 ------------------ www/docs/sidebars.js | 11 +- 5 files changed, 103 insertions(+), 107 deletions(-) create mode 100644 docs/content/advanced/backend/notification/overview.md delete mode 100644 docs/content/how-to/notification-api.md diff --git a/docs/content/add-plugins/sendgrid.mdx b/docs/content/add-plugins/sendgrid.mdx index 9f602f1601..4fcc04f60c 100644 --- a/docs/content/add-plugins/sendgrid.mdx +++ b/docs/content/add-plugins/sendgrid.mdx @@ -3963,5 +3963,5 @@ You can also track analytics related to emails sent from the SendGrid dashboard. ## What’s Next 🚀 -- Learn more about how [Notifications work in Medusa](../how-to/notification-api.md). +- Learn more about how [Notifications work in Medusa](../advanced/backend/notification/overview.md). - Install the [Medusa admin](https://github.com/medusajs/admin#-setting-up-admin) for functionalities like Gift Cards creation, swaps, claims, order return requests, and more. \ No newline at end of file diff --git a/docs/content/advanced/backend/notification/overview.md b/docs/content/advanced/backend/notification/overview.md new file mode 100644 index 0000000000..68426e450e --- /dev/null +++ b/docs/content/advanced/backend/notification/overview.md @@ -0,0 +1,92 @@ +# Architecture Overview + +This document gives an overview of the notification architecture and how it works. + +## Introduction + +Medusa provides a Notification API to mainly handle sending and resending notifications when an event occurs. For example, sending an email to the customer when they place an order. + +The Notification architecture is made up of 2 main components: the Notification Provider and the Notification. Simply put, the Notification Provider handles the sending and resending of a Notification. + +## Notification Provider + +### Overview + +A Notification Provider is a provider that handles sending and resending of notifications. You can either create and integrate your own provider or install a Notification Provider through a third-party plugin. + +An example of a notification provider is SendGrid. When an order is placed, the SendGrid plugin sends an email to the customer. + +### How it is Created + +A Notification Provider is essentially a Medusa [Service](../services/create-service.md) with a unique identifier, and it extends the [`NotificationService`](../../../references/services/classes/NotificationService.md) provided by the `medusa-interfaces` package. It can be created as part of a [Plugin](../../../guides/plugins.md), or it can be created just as a service file in your Medusa server. + +As a developer, you mainly work with the Notification Provider when integrating a third-party service that handles notifications in Medusa. + +When you run your Medusa server, the Notification Provider is registered on your server if it isn’t already. This means that it will be inserted into the `notification_provider` table in your database. + +### Entity Overview + +The `NotificationProvider` entity only has 2 attributes: `id` and `is_installed`. + +`id` is the value of the static property `identifier` defined inside the notification service class. + +`is_installed` indicates whether the Notification Provider is installed or not. When you install a Notification Provider, the value of this attribute is `true`. + +If you installed a Notification provider and then removed the service files or plugin that registered the Notification Provider, the Notification Provider remains in your database, but the value of the `is_installed` field changes to `false`. + +## Notification + +### Overview + +A notification is a form of an alert sent to the customers or users to inform them of an action that has occurred. For example, if an order is placed, the notification, in this case, can be an email that confirms their order and lists the order details. + +Notifications can take on other forms such as an SMS or a Slack message. + +### How it is Created + +Notifications are created in the `NotificationService` class in Medusa’s core after the Notification has been handled by the Notification Provider. + +The data and additional details that the Notification Provider returns to the `NotificationService` is used to fill some of the attributes of the Notification in the database. + +A Notification also represents a resent notification. So, when a notification is resent, a new one is created that references the original Notification as a parent. This Notification is also created by the `NotificationService` class. + +### Entity Overview + +The 2 most important properties in the `Notification` entity are the `to` and `data` properties. + +The `to` property is a string that represents the receiver of the Notification. For example, if the Notification was sent to an email address, the `to` property holds the email address the Notification was sent to. + +The `to` property can alternatively be a phone number or a chat username. It depends on the Notification Provider and how it sends the Notification. + +The `data` property is an object that holds all the data necessary to send the Notification. For example, in the case of an order confirmation Notification, it can hold data related to the order. + +The `data` property is useful when a notification is resent later. The same `data` can be used to resend the notification. + +In the case of resent notifications, the resent notification has a `parent_id` set to the ID of the original Notification. The value of the `parent_id` property in the original Notification is `null`. + +The `Notification` entity has some properties that determine the context of this Notification. This includes the `event_name` property which is the event that triggered the sending of this notification. + +Additionally, the `resource_type` property is used to determine what resource this event is associated with. For example, if the `event_name` is `order.placed`, the `resource_type` is `order`. + +You can also access the specific resource using the `resource_id` property, which is the ID of the resource. So, in case of the `order.placed` event, the `resource_id` is the ID of the order that was created. + +The `Notification` entity also includes properties related to the receiver of the Notification. In case the receiver is a customer, the `customer_id` property is used to identify which customer. + +## Automating Flows with Notifications + +With Medusa you can create notifications as a reaction to a wide spectrum of events, allowing you to automate communication and processes. + +An example of a flow that can be implemented using Medusa's Notification API is automated return flows: + +- A customer requests a return by sending a `POST` request to the `/store/returns` endpoint. +- The Notification Provider listens to the `order.return_requested` event and sends an email to the customer with a return invoice and return label generated by the Fulfillment Provider. +- The customer returns the items triggering the `return.recieved` event. +- The Notification Provider listens to the `return.received` event and sends an email to the customer with confirmation that their items have been received and that a refund has been issued. + +## What’s Next 🚀 + +- Learn how to create your own Notification Provider. +- [Check out the list of events in Medusa.](../subscribers/events-list.md) +- [Check the `NotificationService` API reference for more details on how it works.](../../../references/services/classes/NotificationService.md) +- [Check out the SendGrid Notification plugin.](../../../add-plugins/sendgrid.mdx) +- Learn more about [Subscribers](../subscribers/create-subscriber.md) and [Services](../services/create-service.md) in Medusa. diff --git a/docs/content/advanced/backend/subscribers/events-list.md b/docs/content/advanced/backend/subscribers/events-list.md index 1f76d6fa2d..21b917d10f 100644 --- a/docs/content/advanced/backend/subscribers/events-list.md +++ b/docs/content/advanced/backend/subscribers/events-list.md @@ -1862,4 +1862,4 @@ Object of the following format: ## What’s Next 🚀 - Learn how you can [use services in subscribers](create-subscriber.md#using-services-in-subscribers). -- Learn how to [create notifications](../../../how-to/notification-api.md) in Medusa. +- Learn how to [create notifications](../notification/overview.md) in Medusa. diff --git a/docs/content/how-to/notification-api.md b/docs/content/how-to/notification-api.md deleted file mode 100644 index 2e39c2523a..0000000000 --- a/docs/content/how-to/notification-api.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: Notifications and automated flows ---- - -# Notification API and how to structure email flows - -### Introduction - -Plugins offer a way to extend and integrate the core functionality of Medusa. For a walkthrough of the implementation details behind these, please see [Plugins in Medusa](https://docs.medusajs.com/guides/plugins). - -Medusa makes it possible for plugins to implement the Notification API. The API allows for different types of implementations of notifications (emails, text messages, Slack messages, etc), that are sent as a reaction to events in Medusa. All Notifications are stored in the database with information about the receiver of the notification and what plugin was in charge of sending it. This allows merchants to resend notifications, but also gives an overview of what communication has been sent to customers. - -### How it works - -The Notification API works by subscribing to all events that are emitted to the Event Bus and channeling them through to notification plugins that listen to the events. In a plugin you can subscribe to a notification event by exporting a subscriber class that calls `notificationService.subscribe`: - -```jsx -// src/subscribers/my-notification.js - -class MyNotification { - constructor({ notificationService }) { - // Subscribe to order.placed events - notificationService.subscribe("order.placed", "my-service"); - } -} - -export default MyNotification; -``` - -The above code tells the notification service to send `order.placed` events to the `my-service` notification service implemented in your plugin. - -For a plugin to work with the Notification API you must implement 2 methods `sendNotification` and `resendNotification`; - -```jsx -// src/services/my-notification.js - -class MyService extends NotificationService { - static identifier = "my-service"; - - constructor({ orderService }, options) { - super(); - - this.options_ = options; - this.orderService_ = orderService; - } - - async sendNotification(eventName, eventData, attachmentGenerator) { - let sendData; - switch (eventName) { - case "order.placed": - sendData = await this.orderService_.retrieve(eventData.id); - break; - default: - // If the return value is undefined no notification will be stored - return; - } - - await CoolEmailSender.send({ - email: sendData.email, - templateData: sendData, - }); - - return { to: sendData.email, data: sendData }; - } - - async resendNotification(notification, config, attachmentGenerator) { - const recipient = config.to || notification.to; - - await CoolEmailSender.send({ - email: recipient, - templateData: notification.data, - }); - - return { to: sendOptions.to, data: notification.data }; - } -} - -export default MyService; -``` - -:::note - - A notification service must have a static property called `identifier` this is used to determine which classes are called when subscribing to different events. In this case the service identifier is `my-service` so to subscribe to notifications you must use: - `notificationService.subscribe([eventname], "my-service")` - -::: - -The above class is an example implementation of a NotificationService. It uses a fictional email service called `CoolEmailSender` to send emails to a customer whenever an order is placed. The `sendNotification` implementation gets the event name and fetches relevant data based on what event is being processed; in this case it retrieves an order, which is later used when requesting `CoolEmailSender` to dispatch an email. The address to send the email to is likewise fetched from the order. - -The return type of `sendNotification` and `resendNotification` is an object with `to` and `data`. The `to` prop should identify the receiver of the notification, in this case an email, but it could also be a phone number, an ID, a channel name or something similar depending on the type of notification provider. The `data` prop contains the data as it was gathered when the notification was sent; the same data will be provided if the notification is resent at a later point. - -When `resendNotification` is called the original Notification is provided along with a config object. The config object may contain a `to` property that can be used to overwrite the original `to`. - -## Creating automated notification flows - -When running an ecommerce store you typically want to send communication to your customers when different events occur, these include messages like order confirmations and shipping updates. With Medusa you can create transactional notifications as a reaction to a wide spectrum of events, allowing you to automate communication and processes. An example of a flow that can be implemented using Medusa's Notification API is automated return flows. Below is an outline of how an automated return flow might work. - -- Customer requests a return with `POST /store/returns` -- Notification Service listens for `order.return_requested` and sends email to the customer with a return invoice and return label generated by fulfillment provider -- Customer returns items triggering `return.recieved` -- Notification Service listens for `return.received` and sends email to the customer with confirmation that their items have been received and that a refund has been issued. - -Check out `medusa-plugin-sendgrid` for an Notification API implementation that works with Sendgrid. diff --git a/www/docs/sidebars.js b/www/docs/sidebars.js index a0a6e20f6d..52742fcbac 100644 --- a/www/docs/sidebars.js +++ b/www/docs/sidebars.js @@ -182,8 +182,15 @@ module.exports = { ] }, { - type: "doc", - id: "how-to/notification-api", + type: "category", + label: "Notification", + collapsed: true, + items: [ + { + type: "doc", + id: "advanced/backend/notification/overview" + } + ] }, { type: "doc", From 1af7a9d1ebd3ef0b9918a042e2f71b43f43b2aed Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Thu, 9 Jun 2022 16:35:06 +0300 Subject: [PATCH 4/4] added how to create notification provider --- .../how-to-create-notification-provider.md | 272 ++++++++++++++++++ .../advanced/backend/notification/overview.md | 26 +- www/docs/sidebars.js | 5 + 3 files changed, 288 insertions(+), 15 deletions(-) create mode 100644 docs/content/advanced/backend/notification/how-to-create-notification-provider.md diff --git a/docs/content/advanced/backend/notification/how-to-create-notification-provider.md b/docs/content/advanced/backend/notification/how-to-create-notification-provider.md new file mode 100644 index 0000000000..73ec0e949c --- /dev/null +++ b/docs/content/advanced/backend/notification/how-to-create-notification-provider.md @@ -0,0 +1,272 @@ +# How to Create a Notification Provider + +In this document, you’ll learn how to add a Notification Provider to your Medusa server. If you’re unfamiliar with the Notification architecture in Medusa, it is recommended to check out the [architecture overview](overview.md) first. + +## Overview + +A Notification Provider is the custom or third-party service used to handle sending alerts to customers or users when an event occurs. + +For example, you can use SendGrid to send a confirmation email to a customer after they place an order. SendGrid in this example is a Notification Provider. + +:::tip + +If you’re interested in using SendGrid to send Notifications, you can use the [SendGrid](../../../add-plugins/sendgrid.mdx) plugin instead of using your own. + +::: + +Adding a Notification Provider is as simple as creating a [Service](../services/create-service.md) file in `src/services`. A Notification Provider is essentially a Service that extends the `NotificationService` from `medusa-interfaces`. + +:::info + +Notification Providers are loaded and installed at the server startup. + +::: + +After creating the Notification Provider Service, you must create a [Subscriber](../subscribers/create-subscriber.md) that subscribes the Notification Provider to specific events. + +## Prerequisites + +Before you start creating a Notification Provider, you need to install a [Medusa server](../../../quickstart/quick-start.md). + +You also need to install and configure Redis. You can check out the documentation “[Set Up Your Development Environment](../../../tutorial/0-set-up-your-development-environment.mdx)” for help. + +## Create a Notification Provider + +The first step to creating a Notification Provider is to create a file in `src/services` with the following content: + +```jsx +import { NotificationService } from "medusa-interfaces"; + +class EmailSenderService extends NotificationService { + +} + +export default EmailSenderService; +``` + +Where `EmailSenderService` is the name of your Notification Provider Service. + +Notification Providers must extend `NotificationService` from `medusa-interfaces`. + +:::info + +Following the naming convention of Services, the name of the file should be the slug name of the Notification Provider, and the name of the class should be the camel case name of the Notification Provider suffixed with “Service”. In the example above, the name of the file should be `email-sender.js`. You can learn more in the [service documentation](../services/create-service.md). + +::: + +### identifier + +Notification Provider Services must have a static property `identifier`. + +The `NotificationProvider` entity has 2 properties: `identifier` and `is_installed`. The value of the `identifier` property in the Service class is used when the Notification Provider is created in the database. + +The value of this property is also used later when you want to subscribe the Notification Provider to events in a Subscriber. + +For example, in the class you created in the previous code snippet you can add the following property: + +```jsx +static identifier = "email-sender"; +``` + +### constructor + +You can use the `constructor` of your Notification Provider to have access to different Services in Medusa through dependency injection. + +You can also use the constructor to initialize your integration with the third-party provider. For example, if you use a client to connect to the third-party provider’s APIs, you can initialize it in the constructor and use it in other methods in the Service. + +Additionally, if you’re creating your Notification Provider as an external plugin to be installed on any Medusa server and you want to access the options added for the plugin, you can access it in the constructor. The options are passed as a second parameter. + +:::info + +You can learn more about plugins and how to create them in the [Plugins](../../../guides/plugins.md) documentation. + +::: + +Continuing on with the previous example, if you want to use the [`OrderService`](../../../references/services/classes/OrderService.md) later when sending notifications, you can inject it into the constructor: + +```jsx +constructor({ orderService }, options) { + //you can access options here in case you're + //using a plugin + super(); + + this.orderService = orderService; +} +``` + +### sendNotification + +When an event is triggered that your Notification Provider is registered as a handler for, the [`NotificationService`](../../../references/services/classes/NotificationService.md) in Medusa’s core will execute the `sendNotification` method of your Notification Provider. + +In this method, you can perform the necessary operation to send the Notification. Following the example above, you can send an email to the customer when they place an order. + +This method receives 3 parameters: + +1. `eventName`: This is the name of the event that was triggered. For example, `order.placed`. +2. `eventData`: This is the data payload of the event that was triggered. For example, if the `order.placed` event is triggered, the `eventData` object contains the property `id` which is the ID of the order that was placed. +3. `attachmentGenerator`: If you’ve previously attached a generator to the `NotificationService` using the [`registerAttachmentGenerator`](../../../references/services/classes/NotificationService.md#registerattachmentgenerator) method, you have access to it here. You can use the `attachmentGenerator` to generate on-demand invoices or other documents. The default value of this parameter is null. + +:::info + +You can learn more about what events are triggered in Medusa and their data payload in the [Events List](../subscribers/events-list.md) documentation. + +::: + +This method must return an object containing two properties: + +1. `to`: a string that represents the receiver of the Notification. For example, if you sent an email to the customer then `to` is the email address of the customer. In other cases, it might be a phone number or a username. +2. `data`: an object that contains the data used to send the Notification. For example, if you sent an order confirmation email to the customer, then the `data` object might include the order items or the subject of the email. This `data` is necessary if the notification is resent later as you can use the same data. + +Continuing with the previous example you can have the following implementation of the `sendNotification` method: + +```jsx +async sendNotification(eventName, eventData, attachmentGenerator) { + if (eventName === 'order.placed') { + //retrieve order + const order = await this.orderService.retrieve(eventData.id); + //TODO send email + + console.log('Notification sent'); + return { + to: order.email, + data: { + //any data necessary to send the email + //for example: + subject: 'You placed a new order!', + items: order.items + } + }; + } +} +``` + +In this code snippet, you check first if the event is `order.placed`. This can be helpful if you’re handling multiple events using the same Notification Provider. + +You then retrieve the order using the ID and send the email. Here, the logic related to sending the email is not implemented as it is generally specific to your Notification Provider. + +Finally, you return an object with the `to` property set to the customer email and the `data` property is an object that contains data necessary to send the email such as a `subject` or `items`. + +:::note + +The `to` and `data` properties are used in the `NotificationService` in Medusa’s core to create a new `Notification` record in the database. You can learn more about the `Notification` entity in the [Architecture Overview](overview.md#notification-entity-overview) documentation. + +::: + +### resendNotification + +Using the [Resend Notification endpoint](https://docs.medusajs.com/api/admin/notification/resend-notification), an admin user can resend a Notification to the customer. The [`NotificationService`](../../../references/services/classes/NotificationService.md) in Medusa’s core then executes the `resendNotification` method in your Notification Provider. + +This method receives 3 parameters: + +1. `notification`: This is the original Notification record that was created after you sent the notification with `sendNotification`. You can get an overview of the entity and its attributes in the [architecture overview](overview.md#notification-entity-overview), but most notably it includes the `to` and `data` attributes which are populated originally using the `to` and `data` properties of the object you return in `sendNotification`. +2. `config`: In the Resend Notification endpoint you may specify an alternative receiver of the notification using the `to` request body parameter. For example, you may want to resend the order confirmation email to a different email. If that’s the case, you have access to it in the `config` parameter object. Otherwise, `config` will be an empty object. +3. `attachmentGenerator`: If you’ve previously attached a generator to the Notification Service using the [`registerAttachmentGenerator`](../../../references/services/classes/NotificationService.md#registerattachmentgenerator) method, you have access to it here. You can use the `attachmentGenerator` to generate on-demand invoices or other documents. The default value of this parameter is null. + +Similarly to the `sendNotification` method, this method must return an object containing two properties: + +1. `to`: a string that represents the receiver of the Notification. You can either return the same `to` available in the `notification` parameter or the updated one in the `config` parameter. +2. `data`: an object that contains the data used to send the Notification. You can either return the same `data` in the `notification` parameter or make any necessary updates to it. + +Continuing with the previous example you can have the following implementation of the `resendNotification` method: + +```jsx +resendNotification(notification, config, attachmentGenerator) { + //check if the receiver of the notification should be changed + const to = config.to ? config.to : notification.to; + + //TODO resend the notification using the same data that is saved under notification.data + + console.log('Notification resent'); + return { + to, + data: notification.data //you can also make changes to the data + } +} +``` + +In the above snippet, you check if the `to` should be changed by checking if the `config` parameter has a `to` property. Otherwise, you keep the same `to` address stored in the `notification` parameter. + +You then resend the email. Here, the logic related to sending the email is not implemented as it is generally specific to your Notification Provider. + +Finally, you return an object with the `to` property set to the email (either new or old) and the `data` property is the same data used before to send the original notification. you can alternatively make any changes to the data. + +:::note + +The `to` and `data` properties are used in the `NotificationService` in Medusa’s core to create a new `Notification` record in the database. No changes are made to the original `Notification` record created after the `sendNotification` method. This new record is associated with the original `Notification` record using the `parent_id` attribute in the entity. You can learn more about the `Notification` entity in the [Architecture Overview](overview.md#notification-entity-overview) documentation. + +::: + +## Create a Subscriber + +After creating your Notification Provider Service, you must create a Subscriber that registers this Service as a notification handler of events. + +:::note + +This section will not cover the basics of Subscribers. You can read the [Subscribers](../subscribers/create-subscriber.md) documentation to learn more about them and how to create them. + +::: + +Following the previous example, to make sure the `email-sender` Notification Provider handles the `order.placed` event, create the file `src/subscribers/notification.js` with the following content: + +```jsx +class NotificationSubscriber { + constructor({ notificationService }) { + notificationService.subscribe('order.placed', 'email-sender'); + } +} + +export default NotificationSubscriber; +``` + +This subscriber accesses the `notificationService` using dependency injection. The `notificationService` contains a `subscribe` method that accepts 2 parameters. The first one is the name of the event to subscribe to, and the second is the identifier of the Notification Provider that is subscribing to that event. + +:::tip + +Notice that the value of the `identifier` static property defined in the `EmailSenderService` is used to register the Notification Provider to handle the `order.placed` event. + +::: + +## Test Sending Notifications with your Notification Provider + +Make sure you've configured Redis with your Medusa server as explained in the Prerequisites section and that the Redis service is running. + +Then, start by running your Medusa server: + +```bash +npm run start +``` + +Then, place an order either using the [REST APIs](https://docs.medusajs.com/api/store/auth) or using the storefront. + +:::tip + +If you don’t have a storefront installed you can get started with either our [Next.js](../../../starters/nextjs-medusa-starter.md) or [Gatsby](../../../starters/gatsby-medusa-starter.md) starter storefronts in minutes. + +::: + +After placing an order, you can see in your console the message “Notification Sent”. If you added your own notification sending logic, you should receive an email or alternatively the type of notification you’ve set up. + +## Test Resending Notifications with your Notification Provider + +To test resending a notification, first, retrieve the ID of the notification you just sent using the [List Notifications admin endpoint](https://docs.medusajs.com/api/admin/notification/list-notifications). You can pass as a body parameter the `to` or `event_name` parameters to filter out the notification you just sent. + +:::tip + +You must be authenticated as an admin user before sending this request. You can use the [Authenticate a User](https://docs.medusajs.com/api/admin/auth/) endpoint to get authenticated. + +::: + +![List Notifications Request](https://i.imgur.com/iF1rZX1.png) + +Then, send a request to the [Resend Notification](https://docs.medusajs.com/api/admin/notification/resend-notification) endpoint using the ID retrieved from the previous request. You can pass the `to` parameter in the body to change the receiver of the notification. You should see the message “Notification Resent” in your console and if you implemented your own logic for resending the notification it will be resent. + +![Resend Notifications Request](https://i.imgur.com/0zFfPed.png) + +This request returns the same notification object as the List Notifications endpoint, but it now has a new object in the `resends` array. This is the resent notification. If you supplied a `to` parameter in the request body, you should see its value in the `to` property of the resent notification object. + +## What’s Next 🚀 + +- Check out the [list of events](../subscribers/events-list.md) you can listen to. +- Check out the [SendGrid](../../../add-plugins/sendgrid.mdx) plugin for easy integration of email notifications. +- Learn how to [create your own plugin](../../../guides/plugins.md). +- Learn more about [Subscribers](../subscribers/create-subscriber.md) and [Services](../services/create-service.md). diff --git a/docs/content/advanced/backend/notification/overview.md b/docs/content/advanced/backend/notification/overview.md index 68426e450e..b2ed328272 100644 --- a/docs/content/advanced/backend/notification/overview.md +++ b/docs/content/advanced/backend/notification/overview.md @@ -10,39 +10,35 @@ The Notification architecture is made up of 2 main components: the Notification ## Notification Provider -### Overview - A Notification Provider is a provider that handles sending and resending of notifications. You can either create and integrate your own provider or install a Notification Provider through a third-party plugin. An example of a notification provider is SendGrid. When an order is placed, the SendGrid plugin sends an email to the customer. -### How it is Created +### How Notification Provider is Created -A Notification Provider is essentially a Medusa [Service](../services/create-service.md) with a unique identifier, and it extends the [`NotificationService`](../../../references/services/classes/NotificationService.md) provided by the `medusa-interfaces` package. It can be created as part of a [Plugin](../../../guides/plugins.md), or it can be created just as a service file in your Medusa server. +A Notification Provider is essentially a Medusa [Service](../services/create-service.md) with a unique identifier, and it extends the [`NotificationService`](../../../references/services/classes/NotificationService.md) provided by the `medusa-interfaces` package. It can be created as part of a [Plugin](../../../guides/plugins.md), or it can be created just as a Service file in your Medusa server. As a developer, you mainly work with the Notification Provider when integrating a third-party service that handles notifications in Medusa. When you run your Medusa server, the Notification Provider is registered on your server if it isn’t already. This means that it will be inserted into the `notification_provider` table in your database. -### Entity Overview +### NotificationProvider Entity Overview The `NotificationProvider` entity only has 2 attributes: `id` and `is_installed`. -`id` is the value of the static property `identifier` defined inside the notification service class. +`id` is the value of the static property `identifier` defined inside the notification Service class. `is_installed` indicates whether the Notification Provider is installed or not. When you install a Notification Provider, the value of this attribute is `true`. -If you installed a Notification provider and then removed the service files or plugin that registered the Notification Provider, the Notification Provider remains in your database, but the value of the `is_installed` field changes to `false`. +If you installed a Notification provider and then removed the Service files or plugin that registered the Notification Provider, the Notification Provider remains in your database, but the value of the `is_installed` field changes to `false`. ## Notification -### Overview - A notification is a form of an alert sent to the customers or users to inform them of an action that has occurred. For example, if an order is placed, the notification, in this case, can be an email that confirms their order and lists the order details. Notifications can take on other forms such as an SMS or a Slack message. -### How it is Created +### How Notification is Created Notifications are created in the `NotificationService` class in Medusa’s core after the Notification has been handled by the Notification Provider. @@ -50,11 +46,11 @@ The data and additional details that the Notification Provider returns to the `N A Notification also represents a resent notification. So, when a notification is resent, a new one is created that references the original Notification as a parent. This Notification is also created by the `NotificationService` class. -### Entity Overview +### Notification Entity Overview The 2 most important properties in the `Notification` entity are the `to` and `data` properties. -The `to` property is a string that represents the receiver of the Notification. For example, if the Notification was sent to an email address, the `to` property holds the email address the Notification was sent to. +The `to` property is a string that represents the receiver of the Notification. For example, if the Notification was sent to an email address, the `to` property holds the email address the Notification was sent to. The `to` property can alternatively be a phone number or a chat username. It depends on the Notification Provider and how it sends the Notification. @@ -86,7 +82,7 @@ An example of a flow that can be implemented using Medusa's Notification API is ## What’s Next 🚀 - Learn how to create your own Notification Provider. -- [Check out the list of events in Medusa.](../subscribers/events-list.md) -- [Check the `NotificationService` API reference for more details on how it works.](../../../references/services/classes/NotificationService.md) -- [Check out the SendGrid Notification plugin.](../../../add-plugins/sendgrid.mdx) +- Check out the [list of events](../subscribers/events-list.md) in Medusa. +- Check the [`NotificationService`](../../../references/services/classes/NotificationService.md) API reference for more details on how it works. +- Check out the [SendGrid](../../../add-plugins/sendgrid.mdx) Notification plugin. - Learn more about [Subscribers](../subscribers/create-subscriber.md) and [Services](../services/create-service.md) in Medusa. diff --git a/www/docs/sidebars.js b/www/docs/sidebars.js index 52742fcbac..84ca07f9f0 100644 --- a/www/docs/sidebars.js +++ b/www/docs/sidebars.js @@ -189,6 +189,11 @@ module.exports = { { type: "doc", id: "advanced/backend/notification/overview" + }, + { + type: "doc", + id: "advanced/backend/notification/how-to-create-notification-provider", + label: "Create a Notification Provider" } ] },