docs: document when-then name
This commit is contained in:
@@ -8,19 +8,17 @@ In this chapter, you'll learn how to execute an action based on a condition in a
|
||||
|
||||
## Why If-Conditions Aren'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.
|
||||
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't use an if-condition that checks a variable's value, as the condition will be evaluated when Medusa creates the internal representation of the workflow, rather than during execution.
|
||||
|
||||
Instead, use when-then from the Workflows SDK.
|
||||
Instead, use when-then from the Workflows SDK. It allows you to perform steps in a workflow only if a condition that you specify is satisified.
|
||||
|
||||
---
|
||||
|
||||
## What is the When-Then Utility?
|
||||
## How to use When-Then?
|
||||
|
||||
when-then from the Workflows SDK executes an action if a condition is satisfied. The `when` function accepts as a parameter a function that returns a boolean value, and the `then` function is chained to `when`. `then` accepts as a parameter a function that's executed if `when`'s parameter function returns a `true` value.
|
||||
The Workflows SDK provides a `when` function that is used to check whether a condition is true. You chain a `then` function to `when` that specifies the steps to execute if the condition in `when` is satisfied.
|
||||
|
||||
For example:
|
||||
|
||||
@@ -77,4 +75,101 @@ In this code snippet, you execute the `isActiveStep` only if the `input.is_activ
|
||||
|
||||
To specify the action to perform if the condition is satisfied, chain a `then` function to `when` and pass it a callback function.
|
||||
|
||||
The callback function is only executed if `when`'s second parameter function returns a `true` value.
|
||||
The callback function is only executed if `when`'s second parameter function returns a `true` value.
|
||||
|
||||
---
|
||||
|
||||
## Implementing If-Else with When-Then
|
||||
|
||||
when-then doesn't support if-else conditions. Instead, use two `when-then` conditions in your workflow.
|
||||
|
||||
For example:
|
||||
|
||||
export const ifElseHighlights = [
|
||||
["7", "when", "This when-then block acts as an if condition."],
|
||||
["16", "when", "This when-then block acts as an else condiiton."]
|
||||
]
|
||||
|
||||
```ts highlights={ifElseHighlights}
|
||||
const workflow = createWorkflow(
|
||||
"workflow",
|
||||
function (input: {
|
||||
is_active: boolean
|
||||
}) {
|
||||
|
||||
const isActiveResult = when(
|
||||
input,
|
||||
(input) => {
|
||||
return input.is_active
|
||||
}
|
||||
).then(() => {
|
||||
return isActiveStep()
|
||||
})
|
||||
|
||||
const notIsActiveResult = when(
|
||||
input,
|
||||
(input) => {
|
||||
return input.is_active
|
||||
}
|
||||
).then(() => {
|
||||
return notIsActiveStep()
|
||||
})
|
||||
|
||||
// ...
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
In the above workflow, you use two `when-then` blocks. The first one performs a step if `input.is_active` is `true`, and the second performs a step if `input.is_active` is `false`, acting as an else condition.
|
||||
|
||||
---
|
||||
|
||||
## Specify Name for When-Then
|
||||
|
||||
Internally, `when-then` blocks have a unique name similar to a step. When you return a step's result in a `when-then` block, the block's name is derived from the step's name. For example:
|
||||
|
||||
```ts
|
||||
const isActiveResult = when(
|
||||
input,
|
||||
(input) => {
|
||||
return input.is_active
|
||||
}
|
||||
).then(() => {
|
||||
return isActiveStep()
|
||||
})
|
||||
```
|
||||
|
||||
This `when-then` block's internal name will be `when-then-is-active`, where `is-active` is the step's name.
|
||||
|
||||
However, if you need to return in your `when-then` block something other than a step's result, you need to specify a unique step name for that block. Otherwise, Medusa will generate a random name for it which can cause unexpected errors in production.
|
||||
|
||||
You pass a name for `when-then` as a first parameter of `when`, whose signature can accept three parameters in this case. For example:
|
||||
|
||||
export const nameHighlights = [
|
||||
["2", `"check-is-active"`, "The when-then block's name."],
|
||||
["10", "return", "`then` returns a value other than the step's result."]
|
||||
]
|
||||
|
||||
```ts highlights={nameHighlights}
|
||||
const { isActive } = when(
|
||||
"check-is-active",
|
||||
input,
|
||||
(input) => {
|
||||
return input.is_active
|
||||
}
|
||||
).then(() => {
|
||||
const isActive = isActiveStep()
|
||||
|
||||
return {
|
||||
isActive
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Since `then` returns a value different than the step's result, you pass to the `when` function the following parameters:
|
||||
|
||||
1. A unique name to be assigned to the `when-then` block.
|
||||
2. Either an object or the workflow's input. This data is passed as a parameter to the function in `when`'s second parameter.
|
||||
3. A function that returns a boolean indicating whether to execute the action in `then`.
|
||||
|
||||
The second and third parameters are the same as the parameters you previously passed to `when`.
|
||||
|
||||
@@ -157,6 +157,8 @@ const myWorkflow = createWorkflow(
|
||||
})
|
||||
```
|
||||
|
||||
You can also pair multiple `when-then` blocks to implement an `if-else` condition as explained in [this chapter](../conditions/page.mdx).
|
||||
|
||||
### No Conditional Operators
|
||||
|
||||
You can't use conditional operators in a workflow, such as `??` or `||`.
|
||||
|
||||
@@ -32,11 +32,11 @@ export const generatedEditDates = {
|
||||
"app/learn/fundamentals/data-models/default-properties/page.mdx": "2024-10-21T13:30:21.368Z",
|
||||
"app/learn/fundamentals/workflows/advanced-example/page.mdx": "2024-09-11T10:46:59.975Z",
|
||||
"app/learn/fundamentals/events-and-subscribers/emit-event/page.mdx": "2024-11-25T16:19:32.168Z",
|
||||
"app/learn/fundamentals/workflows/conditions/page.mdx": "2024-12-09T15:55:51.565Z",
|
||||
"app/learn/fundamentals/workflows/conditions/page.mdx": "2024-12-11T08:44:00.239Z",
|
||||
"app/learn/fundamentals/modules/module-link-directions/page.mdx": "2024-07-24T09:16:01+02:00",
|
||||
"app/learn/fundamentals/admin/page.mdx": "2024-10-23T07:08:55.898Z",
|
||||
"app/learn/fundamentals/workflows/long-running-workflow/page.mdx": "2024-12-04T07:37:59.822Z",
|
||||
"app/learn/fundamentals/workflows/constructor-constraints/page.mdx": "2024-12-09T14:43:35.160Z",
|
||||
"app/learn/fundamentals/workflows/constructor-constraints/page.mdx": "2024-12-11T08:36:08.282Z",
|
||||
"app/learn/fundamentals/data-models/write-migration/page.mdx": "2024-11-11T15:27:59.794Z",
|
||||
"app/learn/fundamentals/data-models/manage-relationships/page.mdx": "2024-10-28T04:22:21.328Z",
|
||||
"app/learn/fundamentals/modules/remote-query/page.mdx": "2024-07-21T21:20:24+02:00",
|
||||
|
||||
@@ -599,7 +599,7 @@ export const subscriptionWorkflow1Highlights = [
|
||||
["16", "createWorkflow", "Create a workflow."],
|
||||
["23", "transform", "Set the customer ID to an empty string if not provided."],
|
||||
["28", "when", "If email is not set, try to retrieve customer by its ID."],
|
||||
["44", "transform", "Set the email either to the one in the input or the specified customer's email."],
|
||||
["48", "transform", "Set the email either to the one in the input or the specified customer's email."],
|
||||
]
|
||||
|
||||
```ts title="src/workflows/create-restock-subscription/index.ts" highlights={subscriptionWorkflow1Highlights}
|
||||
@@ -630,9 +630,13 @@ export const createRestockSubscriptionWorkflow = createWorkflow(
|
||||
}, (data) => {
|
||||
return data.customer.customer_id || ""
|
||||
})
|
||||
const retrievedCustomer = when({ customer }, ({ customer }) => {
|
||||
return !customer.email
|
||||
}).then(() => {
|
||||
const retrievedCustomer = when(
|
||||
"retrieve-customer-by-id",
|
||||
{ customer },
|
||||
({ customer }) => {
|
||||
return !customer.email
|
||||
}
|
||||
).then(() => {
|
||||
// @ts-ignore
|
||||
const { data } = useQueryGraphStep({
|
||||
entity: "customer",
|
||||
|
||||
@@ -1669,11 +1669,11 @@ export const createDpoWorkflowHighlights = [
|
||||
["27", "completeCartWorkflow", "Create an order for the cart."],
|
||||
["33", "useQueryGraphStep", "Retrieve the order's items and their associated variants and linked digital products."],
|
||||
["57", "when", "Check whether the order has any digital products."],
|
||||
["60", "then", "Perform the callback function if an order has digital products."],
|
||||
["63", "createDigitalProductOrderStep", "Create the digital product order."],
|
||||
["67", "createRemoteLinkStep", "Link the digital product order to the Medusa order."],
|
||||
["76", "createOrderFulfillmentWorkflow", "Create a fulfillment for the digital products in the order."],
|
||||
["90", "emitEventStep", "Emit the `digital_product_order.created` event."]
|
||||
["63", "then", "Perform the callback function if an order has digital products."],
|
||||
["66", "createDigitalProductOrderStep", "Create the digital product order."],
|
||||
["70", "createRemoteLinkStep", "Link the digital product order to the Medusa order."],
|
||||
["79", "createOrderFulfillmentWorkflow", "Create a fulfillment for the digital products in the order."],
|
||||
["93", "emitEventStep", "Emit the `digital_product_order.created` event."]
|
||||
]
|
||||
|
||||
```ts title="src/workflows/create-digital-product-order/index.ts" highlights={createDpoWorkflowHighlights} collapsibleLines="1-17" expandMoreLabel="Show Imports"
|
||||
@@ -1733,10 +1733,13 @@ const createDigitalProductOrderWorkflow = createWorkflow(
|
||||
}
|
||||
)
|
||||
|
||||
const digital_product_order = when(itemsWithDigitalProducts, (itemsWithDigitalProducts) => {
|
||||
return itemsWithDigitalProducts.length
|
||||
})
|
||||
.then(() => {
|
||||
const digital_product_order = when(
|
||||
"create-digital-product-order-condition",
|
||||
itemsWithDigitalProducts,
|
||||
(itemsWithDigitalProducts) => {
|
||||
return itemsWithDigitalProducts.length
|
||||
}
|
||||
).then(() => {
|
||||
const {
|
||||
digital_product_order,
|
||||
} = createDigitalProductOrderStep({
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
export const metadata = {
|
||||
title: `Workflow Errors`,
|
||||
}
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
## When-Then Error: Handler for action X Not Found
|
||||
|
||||
The following error may occur in production if you use a `when-then` block in your workflow:
|
||||
|
||||
```plain
|
||||
custom-workflow:when-then-01JE8Z0M1FXSE2NCK1G04S0RR2:invoke - Handler for action \"when-then-01JE8Z0M1FXSE2NCK1G04S0RR2\" not found...
|
||||
```
|
||||
|
||||
This occurs if the `when-then` block doesn't return a step's result and doesn't have a name specified. You can resolve it by passing a name as a first parameter of `when`:
|
||||
|
||||
```ts
|
||||
const result = when(
|
||||
"custom-when-condition",
|
||||
// ... rest of the parameters
|
||||
)
|
||||
```
|
||||
|
||||
Learn more about passing a name for `when-then` in [this documentation](!docs!/learn/fundamentals/workflows/conditions#specify-name-for-when-then)
|
||||
@@ -126,7 +126,7 @@ export const generatedEditDates = {
|
||||
"app/nextjs-starter/page.mdx": "2024-12-10T08:44:33.783Z",
|
||||
"app/recipes/b2b/page.mdx": "2024-10-03T13:07:44.153Z",
|
||||
"app/recipes/commerce-automation/page.mdx": "2024-10-16T08:52:01.585Z",
|
||||
"app/recipes/digital-products/examples/standard/page.mdx": "2024-12-09T16:18:45.973Z",
|
||||
"app/recipes/digital-products/examples/standard/page.mdx": "2024-12-11T08:46:17.435Z",
|
||||
"app/recipes/digital-products/page.mdx": "2024-10-03T13:07:44.147Z",
|
||||
"app/recipes/ecommerce/page.mdx": "2024-10-22T11:01:01.218Z",
|
||||
"app/recipes/integrate-ecommerce-stack/page.mdx": "2024-12-09T13:03:35.846Z",
|
||||
@@ -5687,5 +5687,6 @@ export const generatedEditDates = {
|
||||
"references/modules/sales_channel_models/page.mdx": "2024-12-10T14:55:13.205Z",
|
||||
"references/types/DmlTypes/types/types.DmlTypes.KnownDataTypes/page.mdx": "2024-12-10T14:54:55.434Z",
|
||||
"references/types/DmlTypes/types/types.DmlTypes.RelationshipTypes/page.mdx": "2024-12-10T14:54:55.435Z",
|
||||
"app/recipes/commerce-automation/restock-notification/page.mdx": "2024-12-10T14:15:39.178Z"
|
||||
"app/recipes/commerce-automation/restock-notification/page.mdx": "2024-12-11T08:47:27.471Z",
|
||||
"app/troubleshooting/workflow-errors/page.mdx": "2024-12-11T08:44:36.598Z"
|
||||
}
|
||||
+1916
-4856
File diff suppressed because it is too large
Load Diff
@@ -9309,6 +9309,14 @@ export const generatedSidebar = [
|
||||
"path": "/troubleshooting/dist-imports",
|
||||
"title": "Importing from /dist",
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/troubleshooting/workflow-errors",
|
||||
"title": "Workflow Errors",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -2249,6 +2249,11 @@ export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
path: "/troubleshooting/dist-imports",
|
||||
title: "Importing from /dist",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/troubleshooting/workflow-errors",
|
||||
title: "Workflow Errors",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user