@jimmy2822/claude-code-sub-agents-mode
Version:
TypeScript Clean Architecture Multi-Agent Framework for Claude Code CLI Integration
161 lines (140 loc) • 4.72 kB
text/typescript
/**
* Project Controller - Presentation Layer
* Handles HTTP requests for project management
*/
import { Request, Response } from 'express';
import { CreateProjectUseCase } from '../../application/use-cases/CreateProjectUseCase';
import { ApproveProjectUseCase } from '../../application/use-cases/ApproveProjectUseCase';
import { IProjectRepository } from '../../domain/repositories/IProjectRepository';
export class ProjectController {
constructor(
private projectRepository: IProjectRepository,
private createProjectUseCase: CreateProjectUseCase,
private approveProjectUseCase: ApproveProjectUseCase
) {}
async getStatus(req: Request, res: Response): Promise<void> {
try {
const projects = await this.projectRepository.findAll();
res.json({
status: 'running',
projects: projects.map(p => this.projectToDTO(p)),
port: 3011
});
} catch (error) {
res.status(500).json({ error: 'Failed to get status' });
}
}
async createProject(req: Request, res: Response): Promise<void> {
try {
const { requirement } = req.body;
if (!requirement) {
res.status(400).json({ error: 'Requirement is required' });
return;
}
const result = await this.createProjectUseCase.execute({ requirement });
if (result.success) {
res.status(201).json({
success: true,
project: this.projectToDTO(result.project),
message: result.message
});
} else {
res.status(400).json({
success: false,
error: result.message
});
}
} catch (error) {
res.status(500).json({
error: 'Failed to create project',
details: error instanceof Error ? error.message : 'Unknown error'
});
}
}
async approveProject(req: Request, res: Response): Promise<void> {
try {
const projectId = parseInt(req.params.id);
if (isNaN(projectId)) {
res.status(400).json({ error: 'Invalid project ID' });
return;
}
const result = await this.approveProjectUseCase.execute({ projectId });
if (result.success) {
res.json({
success: true,
message: result.message
});
} else {
res.status(400).json({
success: false,
error: result.message
});
}
} catch (error) {
res.status(500).json({
error: 'Failed to approve project',
details: error instanceof Error ? error.message : 'Unknown error'
});
}
}
async deleteProject(req: Request, res: Response): Promise<void> {
try {
const projectId = parseInt(req.params.id);
if (isNaN(projectId)) {
res.status(400).json({ error: 'Invalid project ID' });
return;
}
const project = await this.projectRepository.findById(projectId);
if (!project) {
res.status(404).json({ error: 'Project not found' });
return;
}
await this.projectRepository.delete(projectId);
res.json({
success: true,
message: `Project #${projectId} deleted`
});
} catch (error) {
res.status(500).json({
error: 'Failed to delete project',
details: error instanceof Error ? error.message : 'Unknown error'
});
}
}
async deleteAllProjects(req: Request, res: Response): Promise<void> {
try {
const projects = await this.projectRepository.findAll();
const projectIds = projects.map(p => p.id);
await this.projectRepository.deleteAll();
res.json({
success: true,
message: `Deleted ${projectIds.length} projects`,
deletedProjects: projectIds
});
} catch (error) {
res.status(500).json({
error: 'Failed to delete all projects',
details: error instanceof Error ? error.message : 'Unknown error'
});
}
}
private projectToDTO(project: any): any {
return {
id: project.id,
originalRequirement: project.originalRequirement,
status: project.status,
phase: project.phase,
requirements: project.requirements,
acceptanceCriteria: project.acceptanceCriteria,
plan: project.plan,
assignedAgents: project.assignedAgents,
progress: project.progress,
updates: project.updates,
createdAt: project.createdAt,
lastUpdated: project.lastUpdated,
estimatedComplexity: project.plan?.timeline?.estimatedDays <= 3 ? 'low' :
project.plan?.timeline?.estimatedDays <= 7 ? 'medium' : 'high',
suggestedAgents: project.plan?.resources || []
};
}
}