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:
Shahed Nasser
2024-10-01 14:20:54 +03:00
committed by GitHub
parent 1ad7e7583f
commit fb67d90b64
32 changed files with 1138 additions and 102 deletions
@@ -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.