# API Controllers

Controllers are the core building blocks of the Interface API. They group route handlers under a shared base path and provide a structured way to organize HTTP endpoints.

## Create a controller

The `Controller` function creates a controller class bound to a root location path.

```typescript
import { Controller } from "@antelopejs/interface-api";

class MyController extends Controller("/api") {
  // Route handlers go here
}
```

## Controller hierarchy

Controllers support hierarchical nesting through the `extend` method. Each sub-controller inherits its parent's path prefix.

```typescript
import { Controller } from "@antelopejs/interface-api";

// Handles routes at /api
class ApiController extends Controller("/api") {
  // API methods
}

// Handles routes at /api/users
class UsersController extends ApiController.extend("users") {
  // User-specific methods
}
```

## Partial controllers

The `PartialController` function creates a controller that shares the same location as an existing controller. This is useful when you want to split routes across multiple files while sharing the same controller context and computed properties.

```typescript
import { Controller, PartialController, Get } from "@antelopejs/interface-api";

// Original controller
class UsersController extends Controller("/users") {
  @Get()
  async listUsers() {
    return { users: [] };
  }
}

// Partial controller at the same /users path
class UsersAdminController extends PartialController(UsersController) {
  @Get("admin")
  async listAdminUsers() {
    return { admins: [] };
  }
}
```

## Controller instances

Each HTTP request creates a new controller instance. The `GetControllerInstance` function retrieves a controller instance for the current request context, which is useful for reusing functionality across controllers.

```typescript
import {
  GetControllerInstance,
  Controller,
  Get,
  RequestContext,
  Context,
} from "@antelopejs/interface-api";

class UserController extends Controller("/users") {
  async fetchUser(id: string) {
    // Shared logic
    return { id, name: "Example User" };
  }
}

class OrderController extends Controller("/orders") {
  @Get(":id")
  async getOrder(@Context() context: RequestContext) {
    // Reuse UserController logic within the current request
    const userCtrl = await GetControllerInstance(UserController, context);
    const user = await userCtrl.fetchUser("user-123");
    return { order: { id: "order-1", user } };
  }
}
```

The function ensures that computed properties and injected parameters are properly initialized before returning the instance.

## Route handlers

Controllers contain methods decorated with HTTP method decorators that define route handlers.

```typescript
import { Controller, Get, Post, Delete, HTTPResult } from "@antelopejs/interface-api";

class UsersController extends Controller("/users") {
  @Get()
  async listUsers() {
    return { users: ["user1", "user2"] };
  }

  @Get(":id")
  async getUser() {
    return { id: "user123", name: "Sample User" };
  }

  @Post()
  async createUser() {
    return new HTTPResult(201, { id: "new-user-id", name: "New User" });
  }

  @Delete(":id")
  async deleteUser() {
    return new HTTPResult(204);
  }
}
```

## Handler modes

The API supports different handler modes that control when and how a method executes.

### Prefix handlers

Prefix handlers run before the main handler. They are ideal for authentication, validation, and request preprocessing. If a prefix handler returns a value, that value becomes the response and the main handler is skipped.

```typescript
import { Controller, Get, Prefix, HTTPResult } from "@antelopejs/interface-api";

class UsersController extends Controller("/users") {
  @Prefix("get", ":id")
  async validateUserExists() {
    const userExists = true; // Check database
    if (!userExists) {
      return new HTTPResult(404, { error: "User not found" });
    }
    // Returning nothing allows execution to continue to the main handler
  }

  @Get(":id")
  async getUser() {
    return { id: "user123", name: "Sample User" };
  }
}
```

### Postfix handlers

Postfix handlers run after the main handler completes. They are useful for response modification, logging, and cleanup.

> **Warning:** If a postfix handler returns a value, all subsequent postfix handlers are skipped.

```typescript
import { Controller, Get, Postfix, Result, HTTPResult } from "@antelopejs/interface-api";

class UsersController extends Controller("/users") {
  @Get(":id")
  async getUser() {
    return { id: "user123", name: "Sample User" };
  }

  @Postfix("get", ":id")
  async logUserAccess(@Result() result: HTTPResult) {
    result.addHeader("X-Accessed-At", new Date().toISOString());
  }
}
```

### Monitor handlers

Monitor handlers run after request processing completes, regardless of success or failure. Their return value is ignored. Use them for logging, metrics, or other observation tasks.

```typescript
import { Controller, Get, Monitor, Context, RequestContext } from "@antelopejs/interface-api";

class UsersController extends Controller("/users") {
  @Get(":id")
  async getUser() {
    return { id: "user123", name: "Sample User" };
  }

  @Monitor("get", ":id")
  async logRequest(@Context() ctx: RequestContext) {
    const status = ctx.response.getStatus();
    const message = ctx.error ? String(ctx.error) : "ok";
    console.log(`GET /users/:id -> ${status} (${message})`);
  }
}
```

### WebSocket handlers

WebSocket handlers manage persistent connections using the `@WebsocketHandler` decorator.

```typescript
import { Controller, WebsocketHandler, Connection } from "@antelopejs/interface-api";

class ChatController extends Controller("/chat") {
  @WebsocketHandler()
  async handleChat(@Connection() connection: any) {
    connection.on("message", (data: string) => {
      connection.send("Echo: " + data);
    });

    connection.on("close", () => {
      console.log("Connection closed");
    });
  }
}
```

## Handler priority

Handlers can be assigned priorities to control execution order. This is especially useful when multiple prefix or postfix handlers match the same route.

```typescript
import { Controller, Prefix, HandlerPriority, HTTPResult } from "@antelopejs/interface-api";

class SecuredController extends Controller("/api") {
  @Prefix("get", "*", HandlerPriority.HIGHEST)
  async checkAuthentication() {
    const isAuthenticated = true;
    if (!isAuthenticated) {
      return new HTTPResult(401, { error: "Unauthorized" });
    }
  }

  @Prefix("get", "*", HandlerPriority.HIGH)
  async checkAuthorization() {
    const isAuthorized = true;
    if (!isAuthorized) {
      return new HTTPResult(403, { error: "Forbidden" });
    }
  }
}
```

The available priority levels are:

| Priority                    | Value | Description      |
| --------------------------- | ----- | ---------------- |
| `HandlerPriority.HIGHEST`   | 0     | Executes first   |
| `HandlerPriority.HIGH`      | 1     | High priority    |
| `HandlerPriority.NORMAL`    | 2     | Default priority |
| `HandlerPriority.LOW`       | 3     | Low priority     |
| `HandlerPriority.LOWEST`    | 4     | Executes last    |

## The `Listen` function

The `Listen` function starts listening on all configured servers.

```typescript
import { Listen } from "@antelopejs/interface-api";

await Listen();
```
