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 pointRoute Examples
Repository Endpoints
| Method | Path | Description |
|---|---|---|
GET | /api/repositories | List user's repositories |
GET | /api/repositories/:id | Get repository details |
POST | /api/repositories/ingest | Start repository ingestion |
GET | /api/repositories/:id/status | Get ingestion status |
AI Endpoints
| Method | Path | Description |
|---|---|---|
POST | /api/ai/chat | Send a chat query about a repository |
GET | /api/ai/search | Semantic search across repository |
Auth Endpoints
| Method | Path | Description |
|---|---|---|
GET | /api/auth/github | Initiate GitHub OAuth |
GET | /api/auth/github/callback | OAuth callback |
POST | /api/auth/refresh | Refresh access token |
POST | /api/auth/logout | End 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() });
});