3.7.7. Expose a Workflow Hook
In this chapter, you'll learn how to expose a hook in your workflow.
When to Expose a Hook?#
Medusa exposes hooks in many of its workflows to allow you to inject custom functionality.
You can also expose your own hooks in your workflows to allow other developers to consume them. This is useful when you're creating a workflow in a plugin and you want plugin users to extend the workflow's functionality.
For example, you are creating a blog plugin and you want to allow developers to perform custom validation before a blog post is created. You can expose a hook in your workflow that developers can consume to perform their custom validation.
If your workflow is not in a plugin, you probably don't need to expose a hook as you can perform the necessary actions directly in the workflow.
How to Expose a Hook in a Workflow?#
To expose a hook in your workflow, use createHook
from the Workflows SDK.
For example:
1import {2 createStep,3 createHook,4 createWorkflow,5 WorkflowResponse,6} from "@medusajs/framework/workflows-sdk"7import { createPostStep } from "./steps/create-post"8 9export const createBlogPostWorkflow = createWorkflow(10 "create-blog-post", 11 function (input) {12 const validate = createHook(13 "validate", 14 { post: input }15 )16 const post = createPostStep(input)17 18 return new WorkflowResponse(post, {19 hooks: [validate],20 })21 }22)
The createHook
function accepts two parameters:
- The first is a string indicating the hook's name. Developers consuming the hook will use this name to access the hook.
- The second is the input to pass to the hook handler. Developers consuming the hook will receive this input in the hook handler.
You must also return the hook in the workflow's response by passing a hooks
property to the WorkflowResponse
's second parameter object. Its value is an array of the workflow's hooks.
How to Consume the Hook?#
To consume the hook of the workflow, create the file src/workflows/hooks/create-blog-post.ts
with the following content:
1import { MedusaError } from "@medusajs/framework/utils"2import { createBlogPostWorkflow } from "../create-blog-post"3 4createBlogPostWorkflow.hooks.validate(5 async ({ post }, { container }) => {6 // TODO perform an action7 if (!post.additional_data.custom_title) {8 throw new MedusaError(9 MedusaError.Types.INVALID_DATA,10 "Custom title is required"11 )12 }13 }14)
The hook is available on the workflow's hooks
property using its name validate
.
You invoke the hook, passing a step function (the hook handler) as a parameter.
The hook handler is essentially a step function. You can perform in it any actions you perform in a step. For example, you can throw an error, which would stop the workflow execution.
You can also access the Medusa container in the hook handler to perform actions like using Query or module services.
For example:
1import { createBlogPostWorkflow } from "../create-blog-post"2 3createBlogPostWorkflow.hooks.validate(4 async ({ post }, { container }) => {5 const query = container.resolve("query")6 7 const { data: existingPosts } = await query.graph({8 entity: "post",9 fields: ["*"],10 })11 12 // TODO do something with existing posts...13 }14)
Learn more about the hook handler in the Workflow Hooks chapter.