From 705ea0ad33ae7b5a64928ddf358f59e05dd90d4e Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Tue, 13 Aug 2024 09:55:37 +0300 Subject: [PATCH] docs: improve the workflow hooks guide (#8538) * initial * docs: improve workflow hook guides --- .../workflows/add-workflow-hook/page.mdx | 53 +------- .../workflows/workflow-hooks/page.mdx | 116 ++++++++++++++++++ www/apps/book/sidebar.mjs | 6 +- 3 files changed, 127 insertions(+), 48 deletions(-) create mode 100644 www/apps/book/app/advanced-development/workflows/workflow-hooks/page.mdx diff --git a/www/apps/book/app/advanced-development/workflows/add-workflow-hook/page.mdx b/www/apps/book/app/advanced-development/workflows/add-workflow-hook/page.mdx index f7901c9cf1..b00396d61a 100644 --- a/www/apps/book/app/advanced-development/workflows/add-workflow-hook/page.mdx +++ b/www/apps/book/app/advanced-development/workflows/add-workflow-hook/page.mdx @@ -1,31 +1,23 @@ export const metadata = { - title: `${pageNumber} Workflow Hooks`, + title: `${pageNumber} Expose a Workflow Hook`, } # {metadata.title} -In this chapter, you'll learn what a workflow hook is, how to expose it in your workflow, and how to consume the hook with a handler. +In this chapter, you'll learn how to expose a hook in your workflow. -## What is a Workflow Hook? - -A workflow hook is a point in a workflow where you can inject custom functionality as a step function, called a hook handler. - -Hook handlers receive input from the workflow to perform custom actions during the workflow's execution. - - + - Your workflow is reusable in other applications, and you allow performing an external action at some point in your workflow. - + - Your workflow isn't reusable by other applications. Use a step that performs what a hook handler would instead. ---- - ## How to Expose a Hook in a Workflow? To expose a hook in your workflow, use the `createHook` function imported from `@medusajs/workflows-sdk`. @@ -71,15 +63,9 @@ The `createHook` function accepts two parameters: The workflow must also pass an object having a `hooks` property as a second parameter to the `WorkflowResponse` constructor. Its value is an array of the workflow's hooks. ---- +### How to Consume the Hook? -## How to Consume a Hook? - -You consume a hook by registering a hook handler on the workflow. A hook handler is registered in a TypeScript or JavaScript file created in the `src/workflows/hooks` directory. - -You'll find a workflow's exposed hooks in its `hooks` property. - -For example, to consume the hook of the workflow in the previous example, create the file `src/workflows/hooks/my-workflow.ts` with the following content: +To consume the hook of the workflow, create the file `src/workflows/hooks/my-workflow.ts` with the following content: export const handlerHighlights = [ ["3", "productCreated", "Invoke the hook, passing it a step function as a parameter."], @@ -95,31 +81,4 @@ myWorkflow.hooks.productCreated( ) ``` - - -A hook can have only one handler. - - - The hook is available on the workflow's `hooks` property using its name `productCreated`. You invoke the hook, passing the handler as a parameter, which is a step function. - -Similar to a step, the handler receives the hook's input as a first parameter, and the container in the object as a second parameter. - -### Hook Handler Compensation - -You can also pass a compensation function as a second parameter: - -```ts -import { myWorkflow } from "../my-workflow" - -myWorkflow.hooks.productCreated( - async ({ productId }, { container }) => { - // TODO perform an action - }, - async () => { - // undo the performed action - } -) -``` - -The compensation function is executed if an error occurs in the workflow to undo the actions performed by the hook handler. diff --git a/www/apps/book/app/advanced-development/workflows/workflow-hooks/page.mdx b/www/apps/book/app/advanced-development/workflows/workflow-hooks/page.mdx new file mode 100644 index 0000000000..feb19d283e --- /dev/null +++ b/www/apps/book/app/advanced-development/workflows/workflow-hooks/page.mdx @@ -0,0 +1,116 @@ +export const metadata = { + title: `${pageNumber} Workflow Hooks`, +} + +# {metadata.title} + +In this chapter, you'll learn what a workflow hook is, and an example of how to consume a workflow hook defined in Medusa. + +## What is a Workflow Hook? + +A workflow hook is a point in a workflow where you can inject custom functionality as a step function, called a hook handler. + +Medusa exposes hooks in many of its workflows that are used in its API routes. You can consume those hooks to add your custom logic. + + + +- You want to perform a custom action during a workflow's execution, such as when a product is created. + + + +--- + +## How to Consume a Hook? + +You consume a hook by registering a hook handler on the workflow. A hook handler is registered in a TypeScript or JavaScript file created in the `src/workflows/hooks` directory. + +You'll find a workflow's exposed hooks in its `hooks` property. + +For example, to consume the `productsCreated` hook of Medusa's `createProductsWorkflow`, create the file `src/workflows/hooks/my-workflow.ts` with the following content: + +export const handlerHighlights = [ + ["3", "productsCreated", "Invoke the hook, passing it a step function as a parameter."], +] + +```ts title="src/workflows/hooks/my-workflow.ts" highlights={handlerHighlights} +import { createProductsWorkflow } from "@medusajs/core-flows" + +createProductsWorkflow.hooks.productsCreated( + async ({ products }, { container }) => { + // TODO perform an action + } +) +``` + +The hook is available on the workflow's `hooks` property using its name `productsCreated`. You invoke the hook, passing the handler as a parameter, which is a step function. + +Now, when a product is created using the Create Product API route, your hooks handler is executed. + + + +A hook can have only one handler. + + + +Similar to a step, the handler receives the hook's input as a first parameter, and the container in the object as a second parameter. + +### Hook Handler Compensation + +You can also pass a compensation function as a second parameter: + +```ts +import { myWorkflow } from "../my-workflow" + +myWorkflow.hooks.productCreated( + async ({ productId }, { container }) => { + // TODO perform an action + }, + async () => { + // undo the performed action + } +) +``` + +The compensation function is executed if an error occurs in the workflow to undo the actions performed by the hook handler. + +### Additional Data + +Medusa's workflow hooks pass to their handlers in the first parameter object an `additional_data` property: + +```ts highlights={[["4", "additional_data"]]} +import { createProductsWorkflow } from "@medusajs/core-flows" + +createProductsWorkflow.hooks.productsCreated( + async ({ products, additional_data }, { container }) => { + // TODO perform an action + } +) +``` + +This property is an object that holds additional data passed to the workflow. + +{/* TODO change to talk about validators once we can document them. */} + +To pass that additional data when executing the workflow, pass it as a parameter to the `.run` method of the workflow: + +```ts highlights={[["10", "additional_data"]]} +import type { MedusaRequest, MedusaResponse } from "@medusajs/medusa"; +import { createProductsWorkflow } from "@medusajs/core-flows" + +export async function POST(req: MedusaRequest, res: MedusaResponse) { + await createProductsWorkflow(req.scope).run({ + input: { + products: [ + // ... + ], + additional_data: { + custom_field: "test" + } + }, + }) +} +``` + +Your hook handler then receives that passed data in the `additional_data` object. + +{/* TODO add a link to the workflows reference once available */} \ No newline at end of file diff --git a/www/apps/book/sidebar.mjs b/www/apps/book/sidebar.mjs index 7e34c349d5..291fdf9216 100644 --- a/www/apps/book/sidebar.mjs +++ b/www/apps/book/sidebar.mjs @@ -212,9 +212,13 @@ export const sidebar = sidebarAttachHrefCommonOptions( title: "Compensation Function", }, { - path: "/advanced-development/workflows/add-workflow-hook", + path: "/advanced-development/workflows/workflow-hooks", title: "Workflow Hooks", }, + { + path: "/advanced-development/workflows/add-workflow-hook", + title: "Expose a Hook", + }, { path: "/advanced-development/workflows/access-workflow-errors", title: "Access Workflow Errors",