You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Your workflow isn't reusable by other applications. Use a step that performs what a hook handler would instead.
17
+
Medusa exposes hooks in many of its workflows to allow you to inject custom functionality.
20
18
21
-
</Note>
19
+
You can also expose your own hooks in your workflows to allow other developers to consume them. This is useful when you're creating a workflow in a [plugin](../../plugins/page.mdx) and you want plugin users to extend the workflow's functionality.
20
+
21
+
For example, you are creating a blog plugin and you want to allow developers to perform custom validation before a blog post is created. You can expose a hook in your workflow that developers can consume to perform their custom validation.
22
+
23
+
If your workflow is not in a plugin, you probably don't need to expose a hook as you can perform the necessary actions directly in the workflow.
22
24
23
25
---
24
26
@@ -29,62 +31,94 @@ To expose a hook in your workflow, use `createHook` from the Workflows SDK.
29
31
For example:
30
32
31
33
exportconst hookHighlights = [
32
-
["13", "createHook", "Add a hook to the workflow."],
33
-
["14", `"productCreated"`, "The hook's name."],
34
-
["15", "productId", "The data to pass to the hook handler."],
34
+
["12", "createHook", "Add a hook to the workflow."],
35
+
["13", `"validate"`, "The hook's name."],
36
+
["14", "", "The data to pass to the hook handler."],
35
37
["19", "hooks", "Return the list of hooks in the workflow."]
1. The first is a string indicating the hook's name. You use this to consume the hook later.
66
-
2. The second is the input to pass to the hook handler.
67
+
1. The first is a string indicating the hook's name. Developers consuming the hook will use this name to access the hook.
68
+
2. The second is the input to pass to the hook handler. Developers consuming the hook will receive this input in the hook handler.
67
69
68
-
The workflow must also pass an object having a `hooks` property as a second parameter to the `WorkflowResponse` constructor. Its value is an array of the workflow's hooks.
70
+
You must also return the hook in the workflow's response by passing a `hooks` property to the `WorkflowResponse`'s second parameter object. Its value is an array of the workflow's hooks.
69
71
70
72
### How to Consume the Hook?
71
73
72
-
To consume the hook of the workflow, create the file `src/workflows/hooks/my-workflow.ts` with the following content:
74
+
To consume the hook of the workflow, create the file `src/workflows/hooks/create-blog-post.ts` with the following content:
73
75
74
76
exportconst handlerHighlights = [
75
-
["3", "productCreated", "Invoke the hook, passing it a step function as a parameter."],
77
+
["4", "validate", "Invoke the hook, passing it a step function as a parameter."],
The hook is available on the workflow's `hooks` property using its name `productCreated`.
97
+
The hook is available on the workflow's `hooks` property using its name `validate`.
89
98
90
99
You invoke the hook, passing a step function (the hook handler) as a parameter.
100
+
101
+
The hook handler is essentially a step function. You can perform in it any actions you perform in a step. For example, you can throw an error, which would stop the workflow execution.
102
+
103
+
You can also access the Medusa container in the hook handler to perform actions like using Query or module services.
@@ -9504,6 +9504,64 @@ So, always rollback the migration before deleting it.
9504
9504
9505
9505
To learn more about the Medusa CLI's database commands, refer to [this CLI reference](https://docs.medusajs.com/resources/medusa-cli/commands/db/index.html.md).
9506
9506
9507
+
***
9508
+
9509
+
## Data Migration Scripts
9510
+
9511
+
In some use cases, you may need to perform data migration after updates to the database. For example, after you added a `Site` data model to the Blog Module, you want to assign all existing posts and authors to a default site. Another example is updating data stored in a third-party system.
9512
+
9513
+
In those scenarios, you can instead create a data migration script. They are asynchronous function that the Medusa application executes once when you run the `npx medusa db:migrate command`.
9514
+
9515
+
### How to Create a Data Migration Script
9516
+
9517
+
You can create data migration scripts in a TypeScript or JavaScript file under the `src/migration-scripts` directory. The file must export an asynchronous function that will be executed when the `db:migrate` command is executed.
9518
+
9519
+
For example, to create a data migration script for the Blog Module example, create the file `src/migration-scripts/migrate-blog-data.ts` with the following content:
import { MedusaModule } from "@medusajs/framework/modules-sdk";
9523
+
import { ExecArgs } from "@medusajs/framework/types";
9524
+
import { BLOG_MODULE } from "../modules/blog";
9525
+
import { createWorkflow } from "@medusajs/framework/workflows-sdk";
9526
+
9527
+
export default async function migrateBlogData({ container }: ExecArgs) {
9528
+
// Check that the blog module exists
9529
+
if (!MedusaModule.isInstalled(BLOG_MODULE)) {
9530
+
return
9531
+
}
9532
+
9533
+
await migrateBlogDataWorkflow(container).run({})
9534
+
}
9535
+
9536
+
const migrateBlogDataWorkflow = createWorkflow(
9537
+
"migrate-blog-data",
9538
+
() => {
9539
+
// Assuming you have these steps
9540
+
createDefaultSiteStep()
9541
+
9542
+
assignBlogDataToSiteStep()
9543
+
}
9544
+
)
9545
+
```
9546
+
9547
+
In the above example, you default export an asynchronous function that receives an object parameter with the [Medusa Container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md) property.
9548
+
9549
+
In the function, you first ensure that the Blog Module is installed to avoid errors otherwise. Then, you run a workflow that you've created in the same file that performs the necessary data migration.
9550
+
9551
+
#### Test Data Migration Script
9552
+
9553
+
To test out the data migration script, run the migration command:
9554
+
9555
+
```bash
9556
+
npx medusa db:migrate
9557
+
```
9558
+
9559
+
Medusa will run any pending migrations and migration scripts, including your script.
9560
+
9561
+
If the script runs successfully, Medusa won't run the script again.
9562
+
9563
+
If there are errors in the script, you'll receive an error in the migration script logs. Medusa will keep running the script every time you run the migration command until it runs successfully.
9564
+
9507
9565
9508
9566
# Environment Variables
9509
9567
@@ -16008,11 +16066,17 @@ The next time you start the Medusa application, it will run this job every day a
16008
16066
16009
16067
In this chapter, you'll learn how to expose a hook in your workflow.
16010
16068
16011
-
## When to Expose a Hook
16069
+
Refer to the [Workflow Hooks](https://docs.medusajs.com/learn/fundamentals/workflows/workflow-hooks/index.html.md) chapter to learn what a workflow hook is and how to consume Medusa's workflow hooks.
16070
+
16071
+
## When to Expose a Hook?
16072
+
16073
+
Medusa exposes hooks in many of its workflows to allow you to inject custom functionality.
16012
16074
16013
-
Your workflow is reusable in other applications, and you allow performing an external action at some point in your workflow.
16075
+
You can also expose your own hooks in your workflows to allow other developers to consume them. This is useful when you're creating a workflow in a [plugin](https://docs.medusajs.com/learn/fundamentals/plugins/index.html.md) and you want plugin users to extend the workflow's functionality.
16014
16076
16015
-
Your workflow isn't reusable by other applications. Use a step that performs what a hook handler would instead.
16077
+
For example, you are creating a blog plugin and you want to allow developers to perform custom validation before a blog post is created. You can expose a hook in your workflow that developers can consume to perform their custom validation.
16078
+
16079
+
If your workflow is not in a plugin, you probably don't need to expose a hook as you can perform the necessary actions directly in the workflow.
16016
16080
16017
16081
***
16018
16082
@@ -16022,56 +16086,88 @@ To expose a hook in your workflow, use `createHook` from the Workflows SDK.
1. The first is a string indicating the hook's name. You use this to consume the hook later.
16053
-
2. The second is the input to pass to the hook handler.
16116
+
1. The first is a string indicating the hook's name. Developers consuming the hook will use this name to access the hook.
16117
+
2. The second is the input to pass to the hook handler. Developers consuming the hook will receive this input in the hook handler.
16054
16118
16055
-
The workflow must also pass an object having a `hooks` property as a second parameter to the `WorkflowResponse` constructor. Its value is an array of the workflow's hooks.
16119
+
You must also return the hook in the workflow's response by passing a `hooks` property to the `WorkflowResponse`'s second parameter object. Its value is an array of the workflow's hooks.
16056
16120
16057
16121
### How to Consume the Hook?
16058
16122
16059
-
To consume the hook of the workflow, create the file `src/workflows/hooks/my-workflow.ts` with the following content:
16123
+
To consume the hook of the workflow, create the file `src/workflows/hooks/create-blog-post.ts` with the following content:
import { MedusaError } from "@medusajs/framework/utils"
16127
+
import { createBlogPostWorkflow } from "../create-blog-post"
16063
16128
16064
-
myWorkflow.hooks.productCreated(
16065
-
async ({ productId }, { container }) => {
16129
+
createBlogPostWorkflow.hooks.validate(
16130
+
async ({ post }, { container }) => {
16066
16131
// TODO perform an action
16132
+
if (!post.additional_data.custom_title) {
16133
+
throw new MedusaError(
16134
+
MedusaError.Types.INVALID_DATA,
16135
+
"Custom title is required"
16136
+
)
16137
+
}
16067
16138
}
16068
16139
)
16069
16140
```
16070
16141
16071
-
The hook is available on the workflow's `hooks` property using its name `productCreated`.
16142
+
The hook is available on the workflow's `hooks` property using its name `validate`.
16072
16143
16073
16144
You invoke the hook, passing a step function (the hook handler) as a parameter.
16074
16145
16146
+
The hook handler is essentially a step function. You can perform in it any actions you perform in a step. For example, you can throw an error, which would stop the workflow execution.
16147
+
16148
+
You can also access the Medusa container in the hook handler to perform actions like using Query or module services.
Learn more about the hook handler in the [Workflow Hooks](https://docs.medusajs.com/learn/fundamentals/workflows/workflow-hooks/index.html.md) chapter.
0 commit comments