3.6.1. Variable Manipulation in Workflows with transform

In this chapter, you'll learn how to use transform from the Workflows SDK to manipulate variables in a workflow.

Why Variable Manipulation isn't Allowed in Workflows#

Medusa creates an internal representation of the workflow definition you pass to createWorkflow to track and store its steps.

At that point, variables in the workflow don't have any values. They only do when you execute the workflow.

So, you can only pass variables as parameters to steps. But, in a workflow, you can't change a variable's value or, if the variable is an array, loop over its items.

Instead, use transform from the Workflows SDK.


What is the transform Utility?#

transform creates a new variable as the result of manipulating other variables.

For example, consider you have two strings as the output of two steps:

Code
1const str1 = step1()2const str2 = step2()

To concatenate the strings, you create a new variable str3 using the transform function:

Code
1import { 2  createWorkflow,3  WorkflowResponse,4  transform,5} from "@medusajs/framework/workflows-sdk"6// step imports...7
8const myWorkflow = createWorkflow(9  "hello-world", 10  function (input) {11    const str1 = step1(input)12    const str2 = step2(input)13
14    const str3 = transform(15      { str1, str2 },16      (data) => `${data.str1}${data.str2}`17    )18
19    return new WorkflowResponse(str3)20  }21)

transform accepts two parameters:

  1. The first parameter is an object of variables to manipulate. The object is passed as a parameter to transform's second parameter function.
  2. The second parameter is the function performing the variable manipulation.

The value returned by the second parameter function is returned by transform. So, the str3 variable holds the concatenated string.

You can use the returned value in the rest of the workflow, either to pass it as an input to other steps or to return it in the workflow's response.


Example: Looping Over Array#

Use transform to loop over arrays to create another variable from the array's items.

For example:

Code
6// step imports...7
8type WorkflowInput = {9  items: {10    id: string11    name: string12  }[]13}14
15const myWorkflow = createWorkflow(16  "hello-world", 17  function ({ items }: WorkflowInput) {18    const ids = transform(19      { items },20      (data) => data.items.map((item) => item.id)21    )22    23    doSomethingStep(ids)24
25    // ...26  }27)

This workflow receives an items array in its input.

You use transform to create an ids variable, which is an array of strings holding the id of each item in the items array.

You then pass the ids variable as a parameter to the doSomethingStep.


Example: Creating a Date#

If you create a date with new Date() in a workflow's constructor function, Medusa evaluates the date's value when it creates the internal representation of the workflow, not when the workflow is executed.

So, use transform instead to create a date variable with new Date().

For example:

Code
1const myWorkflow = createWorkflow(2  "hello-world",3  () => {4    const today = transform({}, () => new Date())5
6    doSomethingStep(today)7  }8)

In this workflow, today is only evaluated when the workflow is executed.


Caveats#

Transform Evaluation#

transform's value is only evaluated if you pass its output to a step or in the workflow response.

For example, if you have the following workflow:

Code
1const myWorkflow = createWorkflow(2  "hello-world", 3  function (input) {4    const str = transform(5      { input },6      (data) => `${data.input.str1}${data.input.str2}`7    )8
9    return new WorkflowResponse("done")10  }11)

Since str's value isn't used as a step's input or passed to WorkflowResponse, its value is never evaluated.

Data Validation#

transform should only be used to perform variable or data manipulation.

If you want to perform some validation on the data, use a step or when-then instead.

For example:

Code
1// DON'T2const myWorkflow = createWorkflow(3  "hello-world", 4  function (input) {5    const str = transform(6      { input },7      (data) => {8        if (!input.str1) {9          throw new Error("Not allowed!")10        }11      }12    )13  }14)15
16// DO17const validateHasStr1Step = createStep(18  "validate-has-str1",19  ({ input }) => {20    if (!input.str1) {21      throw new Error("Not allowed!")22    }23  }24)25
26const myWorkflow = createWorkflow(27  "hello-world", 28  function (input) {29    validateHasStr1({30      input,31    })32
33    // workflow continues its execution only if 34    // the step doesn't throw the error.35  }36)
Was this chapter helpful?
Edit this page