0
# Container & Dependency Injection
1
2
Enhanced Awilix dependency injection container with additional registration patterns optimized for Medusa's service architecture, including array-based registration and scoped container creation.
3
4
## Capabilities
5
6
### MedusaContainer Type
7
8
Extended Awilix container type with additional methods for enhanced dependency injection patterns.
9
10
```typescript { .api }
11
import { AwilixContainer } from "awilix";
12
13
type MedusaContainer = AwilixContainer & {
14
/** Register multiple services under the same name as an array */
15
registerAdd: <T>(name: string, registration: T) => MedusaContainer;
16
/** Create a scoped container with inherited registerAdd functionality */
17
createScope: () => MedusaContainer;
18
};
19
```
20
21
### Container Creation
22
23
Creates an enhanced Medusa container with additional registration capabilities.
24
25
```typescript { .api }
26
/**
27
* Creates an enhanced Awilix container with additional registration methods
28
* @param args - Arguments passed to Awilix createContainer function
29
* @returns Enhanced container with registerAdd and enhanced createScope methods
30
*/
31
function createMedusaContainer(...args): MedusaContainer;
32
```
33
34
**Usage Examples:**
35
36
```typescript
37
import { createMedusaContainer } from "medusa-core-utils";
38
import { asClass, asFunction, asValue } from "awilix";
39
40
// Create a new container
41
const container = createMedusaContainer();
42
43
// Standard Awilix registration
44
container.register({
45
userService: asClass(UserService).singleton(),
46
database: asValue(databaseConnection),
47
logger: asFunction(() => new Logger()).singleton()
48
});
49
50
// Enhanced array-based registration with registerAdd
51
container.registerAdd("eventHandlers", asClass(UserCreatedHandler));
52
container.registerAdd("eventHandlers", asClass(UserUpdatedHandler));
53
container.registerAdd("eventHandlers", asClass(UserDeletedHandler));
54
55
// Resolve all event handlers as an array
56
const handlers = container.resolve("eventHandlers");
57
// handlers is an array containing instances of all registered handlers
58
59
// Create scoped containers
60
const requestScope = container.createScope();
61
requestScope.register({
62
requestId: asValue(generateRequestId()),
63
currentUser: asValue(user)
64
});
65
```
66
67
### Array Registration (registerAdd)
68
69
Register multiple services under the same name, creating an array of resolved services.
70
71
```typescript { .api }
72
/**
73
* Register a service to be added to an array of services under the given name
74
* @param name - The name to register the service under
75
* @param registration - The Awilix registration (asClass, asFunction, asValue)
76
* @returns The container instance for chaining
77
*/
78
registerAdd<T>(name: string, registration: T): MedusaContainer;
79
```
80
81
**Usage Examples:**
82
83
```typescript
84
import { createMedusaContainer } from "medusa-core-utils";
85
import { asClass, asFunction } from "awilix";
86
87
const container = createMedusaContainer();
88
89
// Register multiple middleware functions
90
container.registerAdd("middleware", asFunction(() => authMiddleware));
91
container.registerAdd("middleware", asFunction(() => loggingMiddleware));
92
container.registerAdd("middleware", asFunction(() => errorHandlingMiddleware));
93
94
// Register multiple validators
95
container.registerAdd("validators", asClass(EmailValidator));
96
container.registerAdd("validators", asClass(PhoneValidator));
97
container.registerAdd("validators", asClass(AddressValidator));
98
99
// Resolve all registered items as arrays
100
const middlewareList = container.resolve("middleware");
101
const validatorList = container.resolve("validators");
102
103
// Use in application
104
middlewareList.forEach(middleware => app.use(middleware));
105
validatorList.forEach(validator => registerValidator(validator));
106
```
107
108
### Scoped Containers
109
110
Create isolated container scopes that inherit from the parent container while maintaining enhanced functionality.
111
112
```typescript { .api }
113
/**
114
* Create a scoped container that inherits registrations from parent
115
* @returns New scoped container with registerAdd functionality
116
*/
117
createScope(): MedusaContainer;
118
```
119
120
**Usage Examples:**
121
122
```typescript
123
import { createMedusaContainer } from "medusa-core-utils";
124
import { asValue, asClass } from "awilix";
125
126
const container = createMedusaContainer();
127
128
// Register global services
129
container.register({
130
database: asValue(databaseConnection),
131
logger: asClass(Logger).singleton()
132
});
133
134
// Create request-scoped container
135
app.use((req, res, next) => {
136
const requestScope = container.createScope();
137
138
// Add request-specific registrations
139
requestScope.register({
140
requestId: asValue(req.id),
141
currentUser: asValue(req.user),
142
requestLogger: asValue(logger.child({ requestId: req.id }))
143
});
144
145
// Request scope can still use registerAdd
146
requestScope.registerAdd("requestHandlers", asClass(AuthHandler));
147
requestScope.registerAdd("requestHandlers", asClass(ValidationHandler));
148
149
req.container = requestScope;
150
next();
151
});
152
153
// In route handlers
154
app.get("/users", (req, res) => {
155
const userService = req.container.resolve("userService");
156
const handlers = req.container.resolve("requestHandlers");
157
158
// Process request with scoped dependencies
159
});
160
```