Controller Mapping

Map OpenAPI operations to controller methods using the x-controller and x-action extensions.

Extension Reference

ExtensionTypeDescription
x-controllerstringPath to the controller file (relative to server.controllers)
x-actionstringMethod name to invoke on the controller

Controllers are resolved through the IoC container, allowing full dependency injection:

server/controller/user.ts
// server/controller/user.ts
import { Component, Inject } from '@noego/ioc';
import { Request, Response } from 'express';
import { UserService } from '../service/user';

@Component()
export class UserController {
  constructor(
    @Inject(UserService) private userService: UserService
  ) {}

  async list(req: Request, res: Response) {
    const users = await this.userService.findAll();
    res.json(users);
  }

  async getById(req: Request, res: Response) {
    const user = await this.userService.findById(req.params.id);
    if (!user) {
      return res.status(404).json({ error: 'User not found' });
    }
    res.json(user);
  }

  async update(req: Request, res: Response) {
    const user = await this.userService.update(req.params.id, req.body);
    res.json(user);
  }
}

Nested Controllers

Controllers can be nested inside folders. The x-controller value uses forward slashes to reflect the folder structure under the server.controllers root.

Example: if server.controllers is src/server/controller, then billing/invoice.controller resolves to src/server/controller/billing/invoice.controller.ts.

src/server/openapi/modules/billing.yaml
module:
  billing:
    basePath: /api/billing
    paths:
      /invoices/{id}:
        get:
          x-controller: billing/invoice.controller
          x-action: get
          summary: Get invoice

Middleware

Controllers are invoked after any route middleware has run. Keep this page focused on controller mapping; middleware declarations, resolution rules, named exports, and test patterns are covered in the dedicated guide.

Read the Dinner middleware guide
NoEgo

© 2025 NoEgo. All rights reserved.