3.3.4. Module Container

In this chapter, you'll learn about the module container and how to resolve resources from it.

Since modules are isolated, each module has a local container used only by the resources of that module.

So, resources in the module, such as services or loaders, can only resolve other resources registered in the module's container, and some Framework tools that the Medusa application registers in the module's container.

List of Registered Resources#

Find a list of resources or dependencies registered in a module's container in the Container Resources reference.


Resolve Resources from the Module Container#

Resolve in Services#

A service's constructor accepts as a first parameter an object used to resolve resources registered in the module's container. To resolve a resource, add the resource's registration name as a property of the object.

For example, to resolve the Logger from the container:

Code
1import { Logger } from "@medusajs/framework/types"2
3type InjectedDependencies = {4  logger: Logger5}6
7export default class BlogModuleService {8  protected logger_: Logger9
10  constructor({ logger }: InjectedDependencies) {11    this.logger_ = logger12
13    this.logger_.info("[BlogModuleService]: Hello World!")14  }15
16  // ...17}

You can then use the logger in the service's methods.

Resolve in Loaders#

Loaders accept an object parameter with the property container. Its value is the module's container that can be used to resolve resources using its resolve method.

For example, to resolve the Logger in a loader:

Code
1import {2  LoaderOptions,3} from "@medusajs/framework/types"4import { 5  ContainerRegistrationKeys,6} from "@medusajs/framework/utils"7
8export default async function helloWorldLoader({9  container,10}: LoaderOptions) {11  const logger = container.resolve(ContainerRegistrationKeys.LOGGER)12
13  logger.info("[helloWorldLoader]: Hello, World!")14}

You can then use the logger in the loader's code.


Caveat: Resolving Module Services in Loaders#

Consider a module that has a main service BrandModuleService, and an internal service CmsService. Medusa will register both of these services in the module's container.

However, loaders are executed before any services are initialized and registered in the module's container. So, you can't resolve the BrandModuleService and CmsService in a loader.

Instead, if your main service extends the MedusaService service factory, you can resolve the internal services generated for each data model passed to the MedusaService function.

For example, if the BrandModuleService is defined as follows:

Code
1import { MedusaService } from "@medusajs/framework/utils"2import Brand from "./models/brand"3
4class BrandModuleService extends MedusaService({5  Brand,6}) {7}8
9export default BrandModuleService

Then, you can resolve the brandService that allows you to manage brands in the module's loader:

Code
1import {2  LoaderOptions,3} from "@medusajs/framework/types"4
5export default async function helloWorldLoader({6  container,7}: LoaderOptions) {8  const brandService = container.resolve("brandService")9
10  const brands = await brandService.list()11
12  console.log("[helloWorldLoader]: Brands:", brands)13}

Refer to the Service Factory reference for details on the available methods in the generated services.


Alternative to Resolving Other Modules' Services#

Since modules are isolated, you can't resolve resources that belong to other modules from the module's container. For example, you can't resolve the Product Module's service in the Blog Module's service.

Instead, to build commerce features that span multiple modules, you can create workflows. In those workflows, you can resolve services of all modules registered in the Medusa application, including the services of the Product and Blog modules.

Then, you can execute the workflows in API routes, subscribers, or scheduled jobs.

Learn more and find examples in the Module Isolation chapter.


Avoid Circular Dependencies#

When resolving resources in a module's services, make sure you don't create circular dependencies. For example, if BlogModuleService resolves CmsService, and CmsService resolves BlogModuleService, it will cause a circular dependency error.

Instead, you should generally only resolve services within the main service. For example, BlogModuleService can resolve CmsService, but CmsService should not resolve BlogModuleService.

Was this chapter helpful?
Ask Anything
FAQ
What is Medusa?
How can I create a module?
How can I create a data model?
How do I create a workflow?
How can I extend a data model in the Product Module?
Recipes
How do I build a marketplace with Medusa?
How do I build digital products with Medusa?
How do I build subscription-based purchases with Medusa?
What other recipes are available in the Medusa documentation?
Chat is cleared on refresh
Line break