0
# Component System
1
2
The Component system in LoopBack Core provides a modular architecture for packaging and contributing functionality to applications. Components can declare controllers, providers, servers, lifecycle observers, services, bindings, and even sub-components, making applications highly composable and extensible.
3
4
## Capabilities
5
6
### Component Interface
7
8
The core interface that defines what resources a component can contribute to an application.
9
10
```typescript { .api }
11
/**
12
* A component declares a set of artifacts so that they can be contributed to
13
* an application as a group
14
*/
15
interface Component {
16
/** An array of controller classes */
17
controllers?: ControllerClass[];
18
19
/** A map of providers to be bound to the application context */
20
providers?: ProviderMap;
21
22
/** A map of classes to be bound to the application context */
23
classes?: ClassMap;
24
25
/** A map of name/class pairs for servers */
26
servers?: { [name: string]: Constructor<Server> };
27
28
/** An array of lifecycle observer classes */
29
lifeCycleObservers?: Constructor<LifeCycleObserver>[];
30
31
/** An array of service or provider classes */
32
services?: ServiceOrProviderClass[];
33
34
/** An array of bindings to be added to the application context */
35
bindings?: Binding[];
36
37
/** An array of component classes */
38
components?: Constructor<Component>[];
39
40
/** Other properties */
41
[prop: string]: any;
42
}
43
```
44
45
**Usage Examples:**
46
47
```typescript
48
import { Component, ControllerClass, LifeCycleObserver } from "@loopback/core";
49
50
// Basic component with controllers
51
class ProductComponent implements Component {
52
controllers = [ProductController, CategoryController];
53
}
54
55
// Comprehensive component
56
class EcommerceComponent implements Component {
57
controllers = [
58
ProductController,
59
CategoryController,
60
OrderController
61
];
62
63
providers = {
64
'services.payment': PaymentServiceProvider,
65
'services.shipping': ShippingServiceProvider
66
};
67
68
classes = {
69
'repositories.product': ProductRepository,
70
'repositories.order': OrderRepository
71
};
72
73
servers = {
74
'webhook': WebhookServer
75
};
76
77
lifeCycleObservers = [
78
DatabaseMigrationObserver,
79
CacheWarmupObserver
80
];
81
82
services = [
83
EmailService,
84
LoggingService
85
];
86
87
bindings = [
88
Binding.bind('config.ecommerce').to({
89
currency: 'USD',
90
taxRate: 0.08
91
})
92
];
93
94
components = [
95
AuthenticationComponent,
96
ValidationComponent
97
];
98
}
99
```
100
101
### Component Mounting
102
103
Function that mounts a component instance to an application, registering all declared resources.
104
105
```typescript { .api }
106
/**
107
* Mount a component to an Application.
108
*/
109
function mountComponent(app: Application, component: Component): void;
110
```
111
112
**Usage Examples:**
113
114
```typescript
115
import { Application, mountComponent, Component } from "@loopback/core";
116
117
class MyComponent implements Component {
118
controllers = [UserController];
119
providers = {
120
'services.logger': LoggerProvider
121
};
122
}
123
124
const app = new Application();
125
const componentInstance = new MyComponent();
126
127
// Mount component manually
128
mountComponent(app, componentInstance);
129
130
// Typically done automatically when using app.component()
131
app.component(MyComponent); // This calls mountComponent internally
132
```
133
134
### Provider Map
135
136
Map interface for organizing provider classes by binding key.
137
138
```typescript { .api }
139
/**
140
* A map of provider classes to be bound to a context
141
*/
142
interface ProviderMap {
143
[key: string]: Constructor<Provider<BoundValue>>;
144
}
145
```
146
147
**Usage Examples:**
148
149
```typescript
150
import { Component, Provider, ProviderMap } from "@loopback/core";
151
152
// Email service provider
153
class EmailServiceProvider implements Provider<EmailService> {
154
value(): EmailService {
155
return new EmailService({
156
apiKey: process.env.EMAIL_API_KEY,
157
baseUrl: 'https://api.emailservice.com'
158
});
159
}
160
}
161
162
// Configuration provider
163
class AppConfigProvider implements Provider<AppConfig> {
164
value(): AppConfig {
165
return {
166
database: {
167
host: process.env.DB_HOST || 'localhost',
168
port: parseInt(process.env.DB_PORT || '5432')
169
},
170
redis: {
171
url: process.env.REDIS_URL || 'redis://localhost:6379'
172
}
173
};
174
}
175
}
176
177
// Component using provider map
178
class CoreServicesComponent implements Component {
179
providers: ProviderMap = {
180
'services.email': EmailServiceProvider,
181
'services.config': AppConfigProvider,
182
'services.logger': LoggerServiceProvider,
183
'services.metrics': MetricsServiceProvider
184
};
185
}
186
```
187
188
### Class Map
189
190
Map interface for organizing regular classes by binding key.
191
192
```typescript { .api }
193
/**
194
* A map of classes to be bound to a context
195
*/
196
interface ClassMap {
197
[key: string]: Constructor<BoundValue>;
198
}
199
```
200
201
**Usage Examples:**
202
203
```typescript
204
import { Component, ClassMap } from "@loopback/core";
205
206
// Repository classes
207
class UserRepository {
208
constructor(
209
@inject('datasources.db') private datasource: DataSource
210
) {}
211
212
async findById(id: string): Promise<User | null> {
213
// Repository implementation
214
return null;
215
}
216
}
217
218
class ProductRepository {
219
constructor(
220
@inject('datasources.db') private datasource: DataSource
221
) {}
222
223
async findByCategory(category: string): Promise<Product[]> {
224
// Repository implementation
225
return [];
226
}
227
}
228
229
// Component using class map
230
class RepositoryComponent implements Component {
231
classes: ClassMap = {
232
'repositories.user': UserRepository,
233
'repositories.product': ProductRepository,
234
'repositories.order': OrderRepository,
235
'services.cache': CacheService
236
};
237
}
238
```
239
240
### Component Composition
241
242
Components can include other components, enabling hierarchical composition and modularity.
243
244
**Usage Examples:**
245
246
```typescript
247
import { Component } from "@loopback/core";
248
249
// Base authentication component
250
class AuthenticationComponent implements Component {
251
providers = {
252
'auth.strategy.jwt': JwtStrategyProvider,
253
'auth.strategy.oauth': OAuthStrategyProvider
254
};
255
256
services = [
257
TokenService,
258
UserService
259
];
260
}
261
262
// Authorization component that builds on authentication
263
class AuthorizationComponent implements Component {
264
components = [
265
AuthenticationComponent // Include authentication
266
];
267
268
providers = {
269
'auth.rbac': RoleBasedAccessControlProvider,
270
'auth.permissions': PermissionServiceProvider
271
};
272
}
273
274
// Main application component that includes everything
275
class AppComponent implements Component {
276
components = [
277
AuthorizationComponent, // This transitively includes AuthenticationComponent
278
LoggingComponent,
279
DatabaseComponent
280
];
281
282
controllers = [
283
AppController,
284
HealthController
285
];
286
}
287
```
288
289
### Server Component Integration
290
291
Components can contribute server implementations for different protocols.
292
293
**Usage Examples:**
294
295
```typescript
296
import { Component, Server, LifeCycleObserver } from "@loopback/core";
297
298
class RestServer implements Server, LifeCycleObserver {
299
listening = false;
300
301
async start(): Promise<void> {
302
// Start REST server
303
this.listening = true;
304
}
305
306
async stop(): Promise<void> {
307
// Stop REST server
308
this.listening = false;
309
}
310
}
311
312
class GraphQLServer implements Server, LifeCycleObserver {
313
listening = false;
314
315
async start(): Promise<void> {
316
// Start GraphQL server
317
this.listening = true;
318
}
319
320
async stop(): Promise<void> {
321
// Stop GraphQL server
322
this.listening = false;
323
}
324
}
325
326
// Multi-protocol component
327
class ApiComponent implements Component {
328
servers = {
329
'rest': RestServer,
330
'graphql': GraphQLServer
331
};
332
333
controllers = [
334
RestApiController,
335
GraphQLController
336
];
337
338
lifeCycleObservers = [
339
ServerStartupObserver,
340
ServerHealthCheckObserver
341
];
342
}
343
```
344
345
### Binding Integration
346
347
Components can contribute pre-configured bindings for complex setup scenarios.
348
349
**Usage Examples:**
350
351
```typescript
352
import { Component, Binding, BindingScope } from "@loopback/core";
353
354
class DatabaseComponent implements Component {
355
bindings = [
356
// Database connection binding
357
Binding.bind('datasources.primary')
358
.toProvider(DatabaseConnectionProvider)
359
.inScope(BindingScope.SINGLETON),
360
361
// Connection pool configuration
362
Binding.bind('config.database.pool')
363
.to({
364
min: 2,
365
max: 10,
366
acquireTimeoutMillis: 60000,
367
createTimeoutMillis: 30000
368
}),
369
370
// Migration configuration
371
Binding.bind('config.database.migrations')
372
.to({
373
directory: './migrations',
374
autoRun: process.env.NODE_ENV !== 'production'
375
})
376
];
377
378
lifeCycleObservers = [
379
DatabaseMigrationObserver
380
];
381
}
382
```
383
384
### Service Integration
385
386
Components can contribute services and providers for application-wide functionality.
387
388
**Usage Examples:**
389
390
```typescript
391
import { Component, ServiceOrProviderClass } from "@loopback/core";
392
393
// Service classes
394
class EmailService {
395
async sendEmail(to: string, subject: string, body: string): Promise<void> {
396
// Implementation
397
}
398
}
399
400
class SmsService {
401
async sendSms(to: string, message: string): Promise<void> {
402
// Implementation
403
}
404
}
405
406
// Provider for external API
407
class WeatherServiceProvider implements Provider<WeatherService> {
408
value(): WeatherService {
409
return new WeatherService(process.env.WEATHER_API_KEY);
410
}
411
}
412
413
// Communication services component
414
class CommunicationComponent implements Component {
415
services: ServiceOrProviderClass[] = [
416
EmailService,
417
SmsService,
418
WeatherServiceProvider,
419
NotificationService
420
];
421
422
providers = {
423
'services.communication.config': CommunicationConfigProvider
424
};
425
}
426
```
427
428
## Types
429
430
```typescript { .api }
431
interface ProviderMap {
432
[key: string]: Constructor<Provider<BoundValue>>;
433
}
434
435
interface ClassMap {
436
[key: string]: Constructor<BoundValue>;
437
}
438
439
type ControllerClass<T = any> = Constructor<T>;
440
441
type ServiceOrProviderClass<T = any> =
442
| Constructor<T | Provider<T>>
443
| DynamicValueProviderClass<T>;
444
```