or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application.mdcomponents.mdcontext-api.mdextensions.mdindex.mdlifecycle.mdservices.md

components.mddocs/

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

```