docs: improvements + additions to module docs (#9152)
- Split Module and Module Links to their own chapters - Add new docs on db operations and transactions in modules, multiple services, links with custom columns, etc... - Added a list of registered dependencies in a module container
This commit is contained in:
@@ -8,8 +8,8 @@ In this chapter, you'll learn how modules are isolated, and what that means for
|
||||
|
||||
<Note title="Summary">
|
||||
|
||||
- Modules can't access resources, such as services, from other modules.
|
||||
- You can use Medusa's tools, as explained in the next chapters, to extend a modules' features or implement features across modules.
|
||||
- Modules can't access resources, such as services or data models, from other modules.
|
||||
- Use Medusa's linking concepts, as explained in the [Module Links chapters](../../module-links/page.mdx), to extend a module's data models and retrieve data across modules.
|
||||
|
||||
</Note>
|
||||
|
||||
@@ -21,12 +21,93 @@ For example, your custom module can't resolve the Product Module's main service
|
||||
|
||||
---
|
||||
|
||||
## How to Implement Custom Features Across Modules?
|
||||
## Why are Modules Isolated
|
||||
|
||||
In your Medusa application, you want to implement features that span across modules, or you want to extend an existing module's features and customize them for your own use case.
|
||||
Some of the module isolation's benefits include:
|
||||
|
||||
For example, you want to extend the Product Module to add new properties to the `Product` data model.
|
||||
- Integrate your module into any Medusa application without side-effects to your setup.
|
||||
- Replace existing modules with your custom implementation, if your use case is drastically different.
|
||||
- Use modules in other environments, such as Edge functions and Next.js apps.
|
||||
|
||||
Medusa provides the tools to implement these use cases while maintaining isolation between modules.
|
||||
---
|
||||
|
||||
The next chapters explain these tools and how to use them in your custom development.
|
||||
## How to Extend Data Model of Another Module?
|
||||
|
||||
To extend the data model of another module, such as the `product` data model of the Product Module, use Medusa's linking concepts as explained in the [Module Links chapters](../../module-links/page.mdx).
|
||||
|
||||
---
|
||||
|
||||
## How to Use Services of Other Modules?
|
||||
|
||||
If you're building a feature that uses functionalities from different modules, use a workflow whose steps resolve the modules' services to perform these functionalities.
|
||||
|
||||
Workflows ensure data consistency through their roll-back mechanism and tracking of each execution's status, steps, input, and output.
|
||||
|
||||
### Example
|
||||
|
||||
For example, consider you have two modules:
|
||||
|
||||
1. A module that stores and manages brands in your application.
|
||||
2. A module that integrates a third-party Content Management System (CMS).
|
||||
|
||||
To sync brands from your application to the third-party system, create the following steps:
|
||||
|
||||
export const stepsHighlights = [
|
||||
["1", "retrieveBrandsStep", "A step that retrieves brands using a brand module."],
|
||||
["14", "createBrandsInCmsStep", "A step that creates brands using a CMS module."],
|
||||
["25", "", "Add a compensation function to the step if an error occurs."]
|
||||
]
|
||||
|
||||
```ts title="Example Steps" highlights={stepsHighlights}
|
||||
const retrieveBrandsStep = createStep(
|
||||
"retrieve-brands",
|
||||
async (_, { container }) => {
|
||||
const brandModuleService = container.resolve(
|
||||
"brandModuleService"
|
||||
)
|
||||
|
||||
const brands = await brandModuleService.listBrands()
|
||||
|
||||
return new StepResponse(brands)
|
||||
}
|
||||
)
|
||||
|
||||
const createBrandsInCmsStep = createStep(
|
||||
"create-brands-in-cms",
|
||||
async ({ brands }, { container }) => {
|
||||
const cmsModuleService = container.resolve(
|
||||
"cmsModuleService"
|
||||
)
|
||||
|
||||
const cmsBrands = await cmsModuleService.createBrands(brands)
|
||||
|
||||
return new StepResponse(cmsBrands, cmsBrands)
|
||||
},
|
||||
async (brands, { container }) => {
|
||||
const cmsModuleService = container.resolve(
|
||||
"cmsModuleService"
|
||||
)
|
||||
|
||||
await cmsModuleService.deleteBrands(
|
||||
brands.map((brand) => brand.id)
|
||||
)
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
The `retrieveBrandsStep` retrieves the brands from a brand module, and the `createBrandsInCmsStep` creates the brands in a third-party system using a CMS module.
|
||||
|
||||
Then, create the following workflow that uses these steps:
|
||||
|
||||
```ts title="Example Workflow"
|
||||
export const syncBrandsWorkflow = createWorkflow(
|
||||
"sync-brands",
|
||||
() => {
|
||||
const brands = retrieveBrandsStep()
|
||||
|
||||
updateBrandsInCmsStep({ brands })
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
You can then use this workflow in an API route, scheduled job, or other resources that use this functionality.
|
||||
|
||||
Reference in New Issue
Block a user