diff --git a/www/apps/book/app/learn/customization/custom-features/module/page.mdx b/www/apps/book/app/learn/customization/custom-features/module/page.mdx
index 8d02aee745..1828510dce 100644
--- a/www/apps/book/app/learn/customization/custom-features/module/page.mdx
+++ b/www/apps/book/app/learn/customization/custom-features/module/page.mdx
@@ -179,4 +179,4 @@ The `db:generate` command accepts as an argument the name of the module to gener
The Brand Module now creates a `brand` table in the database and provides a class to manage its records.
-In the next step, you'll implement the functionality to create a brand in a workflow. You'll then use that workflow in a later chapter to expose an endpoint that allows admin users to create a brand.
+In the next chapter, you'll implement the functionality to create a brand in a workflow. You'll then use that workflow in a later chapter to expose an endpoint that allows admin users to create a brand.
diff --git a/www/apps/book/app/learn/customization/custom-features/workflow/page.mdx b/www/apps/book/app/learn/customization/custom-features/workflow/page.mdx
index ab66d555f3..79f0d68a3b 100644
--- a/www/apps/book/app/learn/customization/custom-features/workflow/page.mdx
+++ b/www/apps/book/app/learn/customization/custom-features/workflow/page.mdx
@@ -1,35 +1,23 @@
import { Prerequisites } from "docs-ui"
export const metadata = {
- title: `${pageNumber} Define Workflow to Create a Brand`,
+ title: `${pageNumber} Guide: Create Brand Workflow`,
}
# {metadata.title}
-
+This chapter is a follow-up to the [previous one](../module/page.mdx) where you created a Brand Module. In this chapter, you'll create a workflow that creates a brand.
-This chapter covers how to define a workflow that creates a brand as part of the ["Build Custom Features" chapter](../page.mdx).
+You implement commerce features within workflows. A workflow is a series of queries and actions, called steps, that complete a task. You construct a workflow similar to a regular function, but it's a special function that allows you to define roll-back logic, retry configurations, and more advanced features.
-
-
-## Workflows vs Services: Why use Workflows?
-
-When manipulating data, use workflows instead of invoking a service's methods directly in your API route or other customizations.
-
-Workflows eliminate data inconsistency in your application with its compensation mechanism that undoes changes if an error occurs. For example, if a workflow's step creates a brand, it also defines a compensation mechanism to remove the brand if an error occurs.
+The workflow you'll create in this chapter will use the Brand Module's service to implement the feature of creating a brand. In the [next chapter](../api-route/page.mdx), you'll expose an API route that allows admin users to create a brand, and you'll use this workflow in the route's implementation.
-Learn more about workflows [in this guide](../../../basics/workflows/page.mdx).
+Learn more about workflows in [this chapter](../../../basics/workflows/page.mdx).
-This is even more useful when you create workflows with many steps, or integrate third-party systems.
-
----
-
-## Create createBrandWorkflow
-
-Create the file `src/workflows/create-brand/index.ts` with the following content:
-
-```ts
-import {
- createWorkflow,
- WorkflowResponse,
-} from "@medusajs/framework/workflows-sdk"
-
-export type CreateBrandInput = {
- name: string
-}
-
-export const createBrandWorkflow = createWorkflow(
- "create-brand",
- (input: CreateBrandInput) => {
- // TODO
- }
-)
-```
-
-For now, this workflow only defines its input. You'll create its step and use it in the workflow.
-
---
-## Create createBrandStep
+## 1. Create createBrandStep
-Create the file `src/workflows/create-brand/steps/create-brand.ts` with the following content:
+A workflow consists of a series of steps, each step created in a TypeScript or JavaScript file under the `src/workflows` directory. A step is defined using the `createStep` utility function imported from `@medusajs/framework/workflows-sdk`.
-```ts title="src/workflows/create-brand/steps/create-brand.ts" collapsibleLines="1-8" expandButtonLabel="Show Imports"
+The workflow you're creating in this guide has one step to create the brand. So, create the file `src/workflows/create-brand/steps/create-brand.ts` with the following content:
+
+```ts title="src/workflows/create-brand/steps/create-brand.ts"
import {
createStep,
StepResponse,
} from "@medusajs/framework/workflows-sdk"
-import { CreateBrandInput } from ".."
import { BRAND_MODULE } from "../../../modules/brand"
import BrandModuleService from "../../../modules/brand/service"
+export type CreateBrandStepInput = {
+ name: string
+}
+
export const createBrandStep = createStep(
"create-brand-step",
- async (input: CreateBrandInput, { container }) => {
+ async (input: CreateBrandStepInput, { container }) => {
const brandModuleService: BrandModuleService = container.resolve(
BRAND_MODULE
)
@@ -90,17 +61,33 @@ export const createBrandStep = createStep(
)
```
-This defines a `createBrandStep`. In the step, you resolve the Brand Module's main service and use its generated `createBrands` method, which accepts one or more objects of brands to create.
+You create a `createBrandStep` using the `createStep` function. It accepts the step's unique name as a first parameter, and the step's function as a second parameter.
-The step returns the created brand in the first parameter of the `StepResponse`'s constructor.
+The step function receives two parameters: input passed to the step when it's invoked, and an object of general context and configurations. This object has a `container` property, which is the Medusa container.
+
+The [Medusa container](../../../basics/medusa-container/page.mdx) is a registry of framework and commerce tools accessible in your customizations, such as a workflow's step. The Medusa application registers the services of core and custom modules in the container, allowing you to resolve and use them.
+
+So, In the step function, you use the Medusa container to resolve the Brand Module's service and use its generated `createBrands` method, which accepts an object of brands to create.
+
+
+
+Learn more about the generated `create` method's usage in [this reference](!resources!/service-factory-reference/methods/create).
+
+
+
+A step must return an instance of `StepResponse`. Its first parameter is the data returned by the step, and the second is the data passed to the compensation function, which you'll learn about next.
### Add Compensation Function to Step
-A compensation function rolls back changes made by the step if an error occurs in the workflow.
+You define for each step a compensation function that's executed when an error occurs in the workflow. The compensation function defines the logic to roll-back the changes made by the step. This ensures your data remains consistent if an error occurs, which is especially useful when you integrate third-party services.
-The second parameter of the `StepResponse`'s constructor is passed to the compensation function.
+
-To add the compensation function, pass a third parameter to `createStep`:
+Learn more about the compensation function in [this chapter](../../../advanced-development/workflows/compensation-function/page.mdx).
+
+
+
+To add a compensation function to the `createBrandStep`, pass it as a third parameter to `createStep`:
```ts title="src/workflows/create-brand/steps/create-brand.ts"
export const createBrandStep = createStep(
@@ -115,38 +102,57 @@ export const createBrandStep = createStep(
)
```
-You resolve the Brand Module's main service and use its generated `deleteBrands` method to delete the brand created by the step.
+The compensation function's first parameter is the brand's ID which you passed as a second parameter to the step function's returned `StepResponse`. It also accepts a context object with a `container` property as a second parameter, similar to the step function.
-
+In the compensation function, you resolve the Brand Module's service from the Medusa container, then use its generated `deleteBrands` method to delete the brand created by the step. This method accepts the ID of the brand to delete.
-The `deleteBrands` method accepts an ID or an array of IDs of brands to delete.
+
+
+Learn more about the generated `delete` method's usage in [this reference](!resources!/service-factory-reference/methods/delete).
-So, when an error occurs during the workflow, the brand that was created by the step is deleted to maintain data consistency.
+So, if an error occurs during the workflow's execution, the brand that was created by the step is deleted to maintain data consistency.
---
-## Add Step to Workflow
+## 2. Create createBrandWorkflow
-Go back to the workflow at `src/workflows/create-brand/index.ts` and import the step you created:
+You can now create the workflow that runs the `createBrandStep`. A workflow is created in a TypeScript or JavaScript file under the `src/workflows` directory. In the file, you use the `createWorkflow` function imported from `@medusajs/framework/workflows-sdk` to create the workflow.
+
+So, create the file `src/workflows/create-brand/index.ts` with the following content:
```ts
+import {
+ createWorkflow,
+ WorkflowResponse,
+} from "@medusajs/framework/workflows-sdk"
import { createBrandStep } from "./steps/create-brand"
+
+type CreateBrandInput = {
+ name: string
+}
+
+export const createBrandWorkflow = createWorkflow(
+ "create-brand",
+ (input: CreateBrandInput) => {
+ const brand = createBrandStep(input)
+
+ return new WorkflowResponse(brand)
+ }
+)
```
-Then, replace the `TODO` with the following:
+You create the `createBrandWorkflow` using the `createWorkflow` function. This function accepts two parameters: the workflow's unique name, and the workflow's constructor function holding the workflow's implementation.
-```ts
-const brand = createBrandStep(input)
+The constructor function accepts the workflow's input as a parameter. In the function, you invoke the `createBrandStep` you created in the previous step to create a brand.
-return new WorkflowResponse(brand)
-```
-
-You use the `createBrandStep` to create the brand and return it in the workflow's response.
+A workflow must return an instance of `WorkflowResponse`. It accepts as a parameter the data to return to the workflow's executor.
---
-## Next Step: Create Brand API Route
+## Next Steps: Expose Create Brand API Route
-In the next step, you'll create an API route that allows admin users to create a brand using this workflow.
+You now have a `createBrandWorkflow` that you can execute to create a brand.
+
+In the next chapter, you'll add an API route that allows admin users to create a brand. You'll learn how to create the API route, and execute in it the workflow you implemented in this chapter.
diff --git a/www/apps/book/generated/edit-dates.mjs b/www/apps/book/generated/edit-dates.mjs
index a55e753673..a74ac6a104 100644
--- a/www/apps/book/generated/edit-dates.mjs
+++ b/www/apps/book/generated/edit-dates.mjs
@@ -91,7 +91,7 @@ export const generatedEditDates = {
"app/learn/advanced-development/workflows/variable-manipulation/page.mdx": "2024-11-14T16:11:24.538Z",
"app/learn/customization/custom-features/api-route/page.mdx": "2024-09-12T12:42:34.201Z",
"app/learn/customization/custom-features/module/page.mdx": "2024-11-28T09:25:29.098Z",
- "app/learn/customization/custom-features/workflow/page.mdx": "2024-09-30T08:43:53.133Z",
+ "app/learn/customization/custom-features/workflow/page.mdx": "2024-11-28T10:47:28.084Z",
"app/learn/customization/extend-models/create-links/page.mdx": "2024-09-30T08:43:53.133Z",
"app/learn/customization/extend-models/extend-create-product/page.mdx": "2024-09-30T08:43:53.134Z",
"app/learn/customization/custom-features/page.mdx": "2024-11-28T08:21:55.207Z",
diff --git a/www/apps/book/sidebar.mjs b/www/apps/book/sidebar.mjs
index 630a13e507..2351f36262 100644
--- a/www/apps/book/sidebar.mjs
+++ b/www/apps/book/sidebar.mjs
@@ -103,7 +103,7 @@ export const sidebar = numberSidebarItems(
},
{
type: "link",
- title: "Create Brand Workflow",
+ title: "Brand Workflow",
path: "/learn/customization/custom-features/workflow",
},
{