registerControllers()
What?
Instantiates and wires Controller classes that handle the logic for specific routes.
Why?
Controllers bridge the gap between HTTP requests and business logic. CoreServer needs to know about them to map route handlers (e.g., 'Account.login') to actual method calls.
How to use
public async initControllers() {
await this.registerControllers([
AccountController,
CartController,
OrderController
]);
}
Under the Hood: The Controller Registry
- Instantiation: Every controller is instantiated by the
CoreServer, which passes itself (the server instance) to the controller's constructor. - Map Storage: The framework stores these instances in a
Map<string, BaseController>. - Naming Convention: The key in the map is automatically derived by stripping "Controller" from the class name (e.g.,
AccountControllerbecomesAccount).
The Bigger Picture: Controllers as Orchestrators
Controllers are the glue of the server. They don't exist in isolation; they are the intersection of Routes (which trigger them) and Services (which they consume).
Connection to Services (Inward)
Controllers use the @Inject() decorator to pull services from the DI Container. Because registerServices() happens before registerControllers(), the services are already declared and ready to be resolved when the controller is instantiated.
export class AccountController extends BaseController {
@Inject()
private readonly accountService: AccountService; // Wired via DI
}
Connection to Routes (Outward)
Routes are defined as a static configuration array. Instead of passing an anonymous function, Archibald uses a String Handler pattern to link a route to a controller method.
// Route Configuration
{
method: RouteMethod.GET,
path: '/users/address',
handler: 'AccountController.getAddress' // Links to the registered instance
}
Under the Hood: String Resolution
When registerRoute encounters a string handler, it performs the following logic:
- Parsing: Splits the string by
.to identify the controller key and the method name (e.g.,['AccountController', 'getAddress']). - Lookup: Retrieves the controller instance from the internal
controllersMap. - Binding: Wraps the method call in a Hapi handler and uses
.bind(controller). This is critical as it ensures thatthisinside the controller method correctly points to the controller instance, allowing access to its@Inject()ed services.