- Get Started
- Product
- Resources
- Tools & SDKs
- Framework
- Reference
- Get Started
- Product
- Resources
- Tools & SDKs
- Framework
- Reference
Workflow Constraints
This chapter lists constraints of defining a workflow or its steps.
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.
This creates restrictions related to variable manipulations, using if-conditions, and other constraints. This chapter lists these constraints and provides their alternatives.
Workflow Constraints#
No Async Functions#
The function passed to createWorkflow
can’t be an async function:
No Direct Variable Manipulation#
You can’t directly manipulate variables within the workflow's constructor function.
Instead, use transform
from the Workflows SDK:
1// Don't2const myWorkflow = createWorkflow(3 "hello-world", 4 function (input: WorkflowInput) {5 const str1 = step1(input)6 const str2 = step2(input)7 8 return new WorkflowResponse({9 message: `${str1}${str2}`,10 })11})12 13// Do14const myWorkflow = createWorkflow(15 "hello-world", 16 function (input: WorkflowInput) {17 const str1 = step1(input)18 const str2 = step2(input)19 20 const result = transform(21 {22 str1,23 str2,24 },25 (input) => ({26 message: `${input.str1}${input.str2}`,27 })28 )29 30 return new WorkflowResponse(result)31})
Create Dates in transform#
When you use new Date()
in a workflow's constructor function, the date is evaluated when Medusa creates the internal representation of the workflow, not during execution.
Instead, create the date using transform
.
For example:
1// Don't2const myWorkflow = createWorkflow(3 "hello-world", 4 function (input: WorkflowInput) {5 const today = new Date()6 7 return new WorkflowResponse({8 today,9 })10})11 12// Do13const myWorkflow = createWorkflow(14 "hello-world", 15 function (input: WorkflowInput) {16 const today = transform({}, () => new Date())17 18 return new WorkflowResponse({19 today,20 })21})
No If Conditions#
You can't use if-conditions in a workflow.
Instead, use when-then from the Workflows SDK:
1// Don't2const myWorkflow = createWorkflow(3 "hello-world", 4 function (input: WorkflowInput) {5 if (input.is_active) {6 // perform an action7 }8})9 10// Do (explained in the next chapter)11const myWorkflow = createWorkflow(12 "hello-world", 13 function (input: WorkflowInput) {14 when(input, (input) => {15 return input.is_active16 })17 .then(() => {18 // perform an action19 })20})
You can also pair multiple when-then
blocks to implement an if-else
condition as explained in this chapter.
No Conditional Operators#
You can't use conditional operators in a workflow, such as ??
or ||
.
Instead, use transform
to store the desired value in a variable.
Logical Or (||) Alternative#
1// Don't2const myWorkflow = createWorkflow(3 "hello-world", 4 function (input: WorkflowInput) {5 const message = input.message || "Hello"6})7 8// Do9// other imports...10import { transform } from "@medusajs/framework/workflows-sdk"11 12const myWorkflow = createWorkflow(13 "hello-world", 14 function (input: WorkflowInput) {15 const message = transform(16 {17 input,18 },19 (data) => data.input.message || "hello"20 )21})
Nullish Coalescing (??) Alternative#
1// Don't2const myWorkflow = createWorkflow(3 "hello-world", 4 function (input: WorkflowInput) {5 const message = input.message ?? "Hello"6})7 8// Do9// other imports...10import { transform } from "@medusajs/framework/workflows-sdk"11 12const myWorkflow = createWorkflow(13 "hello-world", 14 function (input: WorkflowInput) {15 const message = transform(16 {17 input,18 },19 (data) => data.input.message ?? "hello"20 )21})
Double Not (!!) Alternative#
1// Don't2const myWorkflow = createWorkflow(3 "hello-world", 4 function (input: WorkflowInput) {5 step1({6 isActive: !!input.is_active,7 })8})9 10// Do11// other imports...12import { transform } from "@medusajs/framework/workflows-sdk"13 14const myWorkflow = createWorkflow(15 "hello-world", 16 function (input: WorkflowInput) {17 const isActive = transform(18 {19 input,20 },21 (data) => !!data.input.is_active22 )23 24 step1({25 isActive,26 })27})
Ternary Alternative#
1// Don't2const myWorkflow = createWorkflow(3 "hello-world", 4 function (input: WorkflowInput) {5 step1({6 message: input.is_active ? "active" : "inactive",7 })8})9 10// Do11// other imports...12import { transform } from "@medusajs/framework/workflows-sdk"13 14const myWorkflow = createWorkflow(15 "hello-world", 16 function (input: WorkflowInput) {17 const message = transform(18 {19 input,20 },21 (data) => {22 return data.input.is_active ? "active" : "inactive"23 }24 )25 26 step1({27 message,28 })29})
Optional Chaining (?.) Alternative#
1// Don't2const myWorkflow = createWorkflow(3 "hello-world", 4 function (input: WorkflowInput) {5 step1({6 name: input.customer?.name,7 })8})9 10// Do11// other imports...12import { transform } from "@medusajs/framework/workflows-sdk"13 14const myWorkflow = createWorkflow(15 "hello-world", 16 function (input: WorkflowInput) {17 const name = transform(18 {19 input,20 },21 (data) => data.input.customer?.name22 )23 24 step1({25 name,26 })27})
Step Constraints#
Returned Values#
A step must only return serializable values, such as primitive values or an object.
Values of other types, such as Maps, aren't allowed.
1// Don't2import { 3 createStep,4 StepResponse,5} from "@medusajs/framework/workflows-sdk"6 7const step1 = createStep(8 "step-1",9 (input, { container }) => {10 const myMap = new Map()11 12 // ...13 14 return new StepResponse({15 myMap,16 })17 }18)19 20// Do21import { 22 createStep,23 StepResponse,24} from "@medusajs/framework/workflows-sdk"25 26const step1 = createStep(27 "step-1",28 (input, { container }) => {29 const myObj: Record<string, unknown> = {}30 31 // ...32 33 return new StepResponse({34 myObj,35 })36 }37)