How to Create a Notification Provider Module

In this document, you’ll learn how to create a notification provider module and the methods you must implement in it.


1. Create Module Directory#

Start by creating a new directory for your module. For example, src/modules/my-notification.


2. Create the Notification Provider Service#

Create the file src/modules/my-notification/service.ts that holds the implementation of the notification service.

The Notification Provider Module's main service must extend the AbstractNotificationProviderService class imported from @medusajs/framework/utils:

src/modules/my-notification/service.ts
1import { 2  AbstractNotificationProviderService3} from "@medusajs/framework/utils"4
5class MyNotificationProviderService extends AbstractNotificationProviderService {6  // TODO add methods7}8
9export default MyNotificationProviderService

constructor#

The constructor allows you to access resources from the module's container using the first parameter, and the module's options using the second parameter.

If you're creating a client or establishing a connection with a third-party service, do it in the constructor.

Example

Code
1import { AbstractNotificationProviderService } from "@medusajs/framework/utils"2import { Logger } from "@medusajs/framework/types"3
4type InjectedDependencies = {5  logger: Logger6}7
8type Options = {9  apiKey: string10}11
12class MyNotificationProviderService extends AbstractNotificationProviderService {13  protected logger_: Logger14  protected options_: Options15  // assuming you're initializing a client16  protected client17
18  constructor (19    { logger }: InjectedDependencies,20    options: Options21  ) {22    super()23
24    this.logger_ = logger25    this.options_ = options26
27    // assuming you're initializing a client28    this.client = new Client(options)29  }30}31
32export default MyNotificationProviderService

constructor#

validateOptions#

This method validates the options of the provider set in medusa-config.ts. Implementing this method is optional. It's useful if your provider requires custom validation.

If the options aren't valid, throw an error.

Example

Code
1class MyNotificationProviderService extends AbstractNotificationProviderService {2  static validateOptions(options: Record<any, any>) {3    if (!options.apiKey) {4      throw new MedusaError(5        MedusaError.Types.INVALID_DATA,6        "API key is required in the provider's options."7      )8    }9  }10}

Parameters

Loading...

Returns

Loading...

send#

This method is used to send a notification using the third-party provider or your custom logic.

Example

Code
1// other imports...2import {3  ProviderSendNotificationDTO,4  ProviderSendNotificationResultsDTO5} from "@medusajs/framework/types"6
7class MyNotificationProviderService extends AbstractNotificationProviderService {8  // ...9  async send(10    notification: ProviderSendNotificationDTO11  ): Promise<ProviderSendNotificationResultsDTO> {12    // TODO send the notification using a third-party13    // provider or custom logic.14    // for example:15    return this.client.send({16      email: notification.to,17      template: notification.template,18      template_data: notification.data19    })20  }21}

Parameters

Loading...

Returns

Loading...

3. Create Module Definition File#

Create the file src/modules/my-notification/index.ts with the following content:

src/modules/my-notification/index.ts
1import MyNotificationProviderService from "./service"2import { 3  ModuleProvider, 4  Modules5} from "@medusajs/framework/utils"6
7export default ModuleProvider(Modules.NOTIFICATION, {8  services: [MyNotificationProviderService],9})

This exports the module's definition, indicating that the MyNotificationProviderService is the module's service.


4. Use Module#

To use your Notification Module Provider, add it to the providers array of the Notification Module in medusa-config.ts:

NoteThe Notification Module accepts one provider per channel.
medusa-config.ts
1import { Modules } from "@medusajs/framework/utils"2
3// ...4
5module.exports = defineConfig({6  // ...7  modules: [8    {9      resolve: "@medusajs/medusa/notification",10      options: {11        providers: [12          {13            resolve: "./src/modules/my-notification",14            id: "my-notification",15            options: {16              channels: ["email"],17              // provider options...18            },19          },20        ],21      },22    },23  ]24})

Make sure to specify the correct channels for your provider in the channels option.


5. Test it Out#

Create Subscriber#

To test out the provider, create a subscriber at src/subscribers/user-created.ts with the following content:

src/subscribers/user-created.ts
1import { Modules } from "@medusajs/framework/utils"2import {3  SubscriberArgs,4  type SubscriberConfig,5} from "@medusajs/medusa"6
7export default async function userCreatedHandler({8  event: { data },9  container,10}: SubscriberArgs<{ id: string }>) {11  const notificationModuleService = container.resolve(12    Modules.NOTIFICATION13  )14  const userModule = container.resolve(15    Modules.USER16  )17
18  const user = await userModule.retrieveUser(data.id)19
20  await notificationModuleService.createNotifications({21    to: user.email,22    channel: "email",23    template: "new-user"24  })25}26
27export const config: SubscriberConfig = {28  event: "user.created",29}

In the subscriber, you resolve the Notification and User modules. Then, you use the User Module's main service to retrieve the user's details.

Finally, you use the Notification Module's main service to send a notification to the user's email through the email channel (assuming that's your provider's channel).

Make sure to replace the value of template to the ID of the template in your provider.

Create User#

Use the following command to create a user:

Terminal
npx medusa user -e admin@test.com -p supersecret

After the user is created, the subscriber is executed, sending the notification using your provider.

Was this page helpful?