CodePilot
Configuration

API Overview

Express REST API architecture, routes, middleware, and validation patterns.

The CodePilot API is built with Express 5 and TypeScript. It handles all HTTP requests from the frontend, GitHub webhooks, and serves as the producer for background jobs.

Architecture

Request → Middleware Stack → Route Handler → Response

                ├── Authentication (JWT verification)
                ├── Rate Limiting
                ├── Request Validation (Zod)
                ├── Error Handling
                └── Logging (Pino)

API Structure

apps/api/src/
├── modules/           # Feature modules
│   ├── auth/          # Login, logout, token refresh
│   ├── ai/            # Chat, code review endpoints
│   ├── github/        # GitHub integration, webhooks
│   ├── repository/    # Repository CRUD, ingestion
│   └── user/          # User profile, settings
├── routes/            # Route definitions
├── middlewares/       # Shared middleware
├── queue/             # BullMQ producers
├── jobs/              # Scheduled cron jobs
└── index.ts           # Server entry point

Route Examples

Repository Endpoints

MethodPathDescription
GET/api/repositoriesList user's repositories
GET/api/repositories/:idGet repository details
POST/api/repositories/ingestStart repository ingestion
GET/api/repositories/:id/statusGet ingestion status

AI Endpoints

MethodPathDescription
POST/api/ai/chatSend a chat query about a repository
GET/api/ai/searchSemantic search across repository

Auth Endpoints

MethodPathDescription
GET/api/auth/githubInitiate GitHub OAuth
GET/api/auth/github/callbackOAuth callback
POST/api/auth/refreshRefresh access token
POST/api/auth/logoutEnd session

Middleware

Authentication

JWT-based authentication middleware verifies the access token on protected routes:

async function authenticate(req: Request, res: Response, next: NextFunction) {
  const token = req.headers.authorization?.replace("Bearer ", "");
  if (!token) return res.status(401).json({ error: "Unauthorized" });

  try {
    const payload = jwt.verify(token, process.env.ACCESS_TOKEN_SECRET!);
    req.user = payload;
    next();
  } catch {
    return res.status(401).json({ error: "Invalid token" });
  }
}

Zod Validation

Request bodies are validated using Zod schemas:

import { z } from "zod";

const chatSchema = z.object({
  repositoryId: z.string().cuid(),
  message: z.string().min(1).max(5000),
});

function validate(schema: z.ZodSchema) {
  return (req: Request, res: Response, next: NextFunction) => {
    const result = schema.safeParse(req.body);
    if (!result.success) {
      return res.status(400).json({ errors: result.error.flatten() });
    }
    req.body = result.data;
    next();
  };
}

Error Handling

A centralized error handler catches all unhandled errors:

function errorHandler(err: Error, req: Request, res: Response, next: NextFunction) {
  logger.error(err);
  res.status(500).json({
    error: process.env.NODE_ENV === "production"
      ? "Internal server error"
      : err.message,
  });
}

Logging

Pino provides structured JSON logging:

import pino from "pino";

const logger = pino({
  level: process.env.NODE_ENV === "production" ? "info" : "debug",
  transport: process.env.NODE_ENV !== "production"
    ? { target: "pino-pretty" }
    : undefined,
});

CORS

CORS is configured to allow requests from the frontend:

app.use(cors({
  origin: process.env.FRONTEND_URL,
  credentials: true,
}));

Health Check

app.get("/api/health", (req, res) => {
  res.json({ status: "ok", timestamp: new Date().toISOString() });
});

On this page