From f151fb32aafd6a1425d391da510a0d5177862a71 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Wed, 13 Nov 2024 14:17:14 +0200 Subject: [PATCH] docs: add emit events + types documentation (#10026) * docs: add emit events + types documentation * vale fixes --- .../emit-event/page.mdx | 159 +++++++++++++++++- www/apps/book/generated/edit-dates.mjs | 2 +- www/apps/book/sidebar.mjs | 3 +- 3 files changed, 155 insertions(+), 9 deletions(-) diff --git a/www/apps/book/app/learn/advanced-development/events-and-subscribers/emit-event/page.mdx b/www/apps/book/app/learn/advanced-development/events-and-subscribers/emit-event/page.mdx index 7f768aa385a34..70635f5b12157 100644 --- a/www/apps/book/app/learn/advanced-development/events-and-subscribers/emit-event/page.mdx +++ b/www/apps/book/app/learn/advanced-development/events-and-subscribers/emit-event/page.mdx @@ -1,22 +1,50 @@ +import { CodeTabs, CodeTab } from "docs-ui" + export const metadata = { - title: `${pageNumber} Emit an Event`, + title: `${pageNumber} Emit Workflow and Service Events`, } # {metadata.title} -In this chapter, you'll learn how to emit an event in a workflow. +In this chapter, you'll learn about event types and how to emit an event in a service or workflow. + +## Event Types + +In your customization, you can emit an event, then listen to it in a subscriber and perform an asynchronus action, such as send a notification or data to a third-party system. + +There are two types of events in Medusa: + +1. Worflow event: an event that's emitted in a workflow after a commerce feature is performed. For example, Medusa emits the `order.placed` event after a cart is completed. +2. Service event: an event that's emitted to track, trace, or debug processes under the hood. For example, you can emit an event with an audit trail. + +### Which Event Type to Use? + +**Workflow events** are the most common event type in development, as most custom features and customizations are built around workflows. + +Some examples of workflow events: -## Emit Event Step +1. When a user creates a blog post and you're emitting an event to send a newsletter email. +2. When you finish syncing products to a third-party system and you want to notify the admin user of new products added. +3. When a customer purchases a digital product and you want to generate and send it to them. -Medusa provides an `emitEventStep` helper step in the `@medusajs/medusa/core-flows` package that emits an event. +You should only go for a **service event** if you're emitting an event for processes under the hood that don't directly affect front-facing features. -When you emit an event, you specify the event's name and data payload to pass with the event. +Some examples of service events: + +1. When you're tracing data manipulation and changes, and you want to track every time some custom data is changed. +2. When you're syncing data with a search engine. + +--- + +## Emit Event in a Workflow + +To emit a workflow event, use the `emitEventStep` helper step provided in the `@medusajs/medusa/core-flows` package. For example: export const highlights = [ ["13", "emitEventStep", "Emit an event."], - ["14", `"custom.created"`, "The name of the event to emit."], + ["14", `eventName`, "The name of the event to emit."], ["15", "data", "The data payload to pass with the event."] ] @@ -37,12 +65,129 @@ const helloWorldWorkflow = createWorkflow( eventName: "custom.created", data: { id: "123", + // other data payload }, }) } ) ``` +The `emitEventStep` accepts an object having the following properties: + +- `eventName`: The event's name. +- `data`: The data payload as an object. You can pass any properties in the object, and subscribers listening to the event will receive this data in the event's payload. + In this example, you emit the event `custom.created` and pass in the data payload an ID property. -If you execute the workflow, the emit is emitted and any subscribers listening to the event are executed. +### Test it Out + +If you execute the workflow, the event is emitted and you can see it in your application's logs. + +Any subscribers listening to the event are executed. + +--- + +## Emit Event in a Service + +To emit a service event: + +1. Resolve `event_bus` from the module's container in your service's constructor: + + + + +```ts title="src/modules/hello/service.ts" highlights={["9"]} +import { IEventBusService } from "@medusajs/framework/types" +import { MedusaService } from "@medusajs/framework/utils" + +class HelloModuleService extends MedusaService({ + MyCustom, +}){ + protected eventBusService_: AbstractEventBusModuleService + + constructor({ event_bus }) { + super(...arguments) + this.eventBusService_ = event_bus + } +} +``` + + + + +```ts title="src/modules/hello/service.ts" highlights={["6"]} +import { IEventBusService } from "@medusajs/framework/types" + +class HelloModuleService { + protected eventBusService_: AbstractEventBusModuleService + + constructor({ event_bus }) { + this.eventBusService_ = event_bus + } +} +``` + + + + +2. Use the event bus service's `emit` method in the service's methods to emit an event: + +export const serviceHighlights = [ + ["6", "emit", "Emit an event."], + ["7", "name", "The name of the event to emit."], + ["8", "data", "The data payload to pass with the event."] +] + +```ts title="src/modules/hello/service.ts" highlights={serviceHighlights} +class HelloModuleService { + // ... + performAction() { + // TODO perform action + + this.eventBusService_.emit({ + name: "custom.event", + data: { + id: "123", + // other data payload + } + }) + } +} +``` + +The method accepts an object having the following properties: + +- `name`: The event's name. +- `data`: The data payload as an object. You can pass any properties in the object, and subscribers listening to the event will receive this data in the event's payload. + +3. By default, the Event Module's service isn't injected into your module's container. To add it to the container, pass it in the module's registration object in `medusa-config.ts` in the `dependencies` property: + +export const depsHighlight = [ + ["8", "dependencies", "An array of module registration names to inject into the Module's container."], +] + +```ts title="medusa-config.ts" highlights={depsHighlight} +import { Modules } from '@medusajs/framework/utils' + +module.exports = defineConfig({ + // ... + modules: [ + { + resolve: "./src/modules/hello", + dependencies: [ + Modules.EVENT_BUS + ] + } + ] +}) +``` + +The `dependencies` property accepts an array of module registration keys. The specified modules' main services are injected into the module's container. + +That's how you can resolve it in your module's main service's constructor. + +### Test it Out + +If you execute the `performAction` method of your service, the event is emitted and you can see it in your application's logs. + +Any subscribers listening to the event are also executed. diff --git a/www/apps/book/generated/edit-dates.mjs b/www/apps/book/generated/edit-dates.mjs index 27eef72c0741e..981cb6c1eec75 100644 --- a/www/apps/book/generated/edit-dates.mjs +++ b/www/apps/book/generated/edit-dates.mjs @@ -35,7 +35,7 @@ export const generatedEditDates = { "app/learn/advanced-development/events-and-subscribers/data-payload/page.mdx": "2024-07-16T17:12:05+01:00", "app/learn/advanced-development/data-models/default-properties/page.mdx": "2024-09-19T07:32:06.118Z", "app/learn/advanced-development/workflows/advanced-example/page.mdx": "2024-09-11T10:46:59.975Z", - "app/learn/advanced-development/events-and-subscribers/emit-event/page.mdx": "2024-09-30T08:43:53.125Z", + "app/learn/advanced-development/events-and-subscribers/emit-event/page.mdx": "2024-11-11T15:17:58.045Z", "app/learn/advanced-development/workflows/conditions/page.mdx": "2024-09-30T08:43:53.128Z", "app/learn/advanced-development/modules/module-link-directions/page.mdx": "2024-07-24T09:16:01+02:00", "app/learn/advanced-development/admin/page.mdx": "2024-10-07T12:39:13.178Z", diff --git a/www/apps/book/sidebar.mjs b/www/apps/book/sidebar.mjs index c779323590a1c..39dc85e17dbcc 100644 --- a/www/apps/book/sidebar.mjs +++ b/www/apps/book/sidebar.mjs @@ -392,8 +392,9 @@ export const sidebar = numberSidebarItems( title: "Events Data Payload", }, { + type: "link", path: "/learn/advanced-development/events-and-subscribers/emit-event", - title: "Emit an Event", + title: "Emit Event", }, ], },