From aca7907d810f14fd6a15405034596b1c3fdec788 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Thu, 28 Nov 2024 14:47:59 +0200 Subject: [PATCH] docs: revise create brand workflow (#10346) * docs: revise create brand workflow * small fix --- .../custom-features/module/page.mdx | 2 +- .../custom-features/workflow/page.mdx | 134 +++++++++--------- www/apps/book/generated/edit-dates.mjs | 2 +- www/apps/book/sidebar.mjs | 2 +- 4 files changed, 73 insertions(+), 67 deletions(-) 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", }, {