スキル一覧に戻る
CongDon1207

api-design

by CongDon1207

Copy .* folder and AGENTS.md then paste /root of project

5🍴 1📅 2026年1月18日
GitHubで見るManusで実行

SKILL.md


name: api-design description: Use when designing or modifying REST API endpoints, controller structure, route patterns, request/response DTOs. Triggers on keywords like "API endpoint", "REST", "controller", "route", "HTTP", "request body", "response". allowed-tools: Read, Write, Edit, Bash, Grep, Glob, Task, TodoWrite infer: true

REST API Design

Expert API design agent for EasyPlatform following platform patterns and REST best practices.

Controller Pattern

[ApiController]
[Route("api/[controller]")]
[PlatformAuthorize]  // Require authentication
public class EmployeeController : PlatformBaseController
{
    // GET api/employee - List with filtering
    [HttpGet]
    public async Task<IActionResult> GetList([FromQuery] GetEmployeeListQuery query)
        => Ok(await Cqrs.SendAsync(query));

    // GET api/employee/{id} - Single by ID
    [HttpGet("{id}")]
    public async Task<IActionResult> GetById(string id)
        => Ok(await Cqrs.SendAsync(new GetEmployeeByIdQuery { Id = id }));

    // POST api/employee - Create/Update
    [HttpPost]
    [PlatformAuthorize(Roles = "Admin,Manager")]
    public async Task<IActionResult> Save([FromBody] SaveEmployeeCommand command)
        => Ok(await Cqrs.SendAsync(command));

    // DELETE api/employee/{id} - Delete
    [HttpDelete("{id}")]
    [PlatformAuthorize(Roles = "Admin")]
    public async Task<IActionResult> Delete(string id)
        => Ok(await Cqrs.SendAsync(new DeleteEmployeeCommand { Id = id }));

    // POST api/employee/search - Complex search
    [HttpPost("search")]
    public async Task<IActionResult> Search([FromBody] SearchEmployeesQuery query)
        => Ok(await Cqrs.SendAsync(query));

    // POST api/employee/{id}/action - Custom action
    [HttpPost("{id}/activate")]
    public async Task<IActionResult> Activate(string id)
        => Ok(await Cqrs.SendAsync(new ActivateEmployeeCommand { Id = id }));
}

Route Naming Conventions

ActionHTTP MethodRoute PatternExample
ListGET/api/{resource}GET /api/employees
Get by IDGET/api/{resource}/{id}GET /api/employees/123
Create/UpdatePOST/api/{resource}POST /api/employees
DeleteDELETE/api/{resource}/{id}DELETE /api/employees/123
Complex SearchPOST/api/{resource}/searchPOST /api/employees/search
Custom ActionPOST/api/{resource}/{id}/{action}POST /api/employees/123/activate
Nested ResourceGET/api/{parent}/{id}/{child}GET /api/departments/1/employees

Request/Response DTOs

Query DTO (GET requests)

// Simple query params - use record
public record GetEmployeeListQuery : PlatformCqrsPagedQuery<GetEmployeeListQueryResult, EmployeeDto>
{
    public List<EmploymentStatus>? Statuses { get; init; }
    public string? SearchText { get; init; }
    public string? DepartmentId { get; init; }
}

Command DTO (POST/PUT/DELETE)

public sealed class SaveEmployeeCommand : PlatformCqrsCommand<SaveEmployeeCommandResult>
{
    public string? Id { get; set; }  // Null for create
    public string FirstName { get; set; } = string.Empty;
    public string LastName { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;

    public override PlatformValidationResult<IPlatformCqrsRequest> Validate()
    {
        return base.Validate()
            .And(_ => FirstName.IsNotNullOrEmpty(), "FirstName is required")
            .And(_ => Email.IsNotNullOrEmpty(), "Email is required")
            .And(_ => Email.Contains("@"), "Invalid email format");
    }
}

Response DTO

// For single entity
public sealed class SaveEmployeeCommandResult : PlatformCqrsCommandResult
{
    public EmployeeDto Entity { get; set; } = null!;
}

// For paged list
public sealed class GetEmployeeListQueryResult : PlatformCqrsPagedQueryResult<EmployeeDto>
{
    public Dictionary<EmploymentStatus, int> StatusCounts { get; set; } = new();

    public GetEmployeeListQueryResult(List<Employee> items, int total, GetEmployeeListQuery req, Dictionary<EmploymentStatus, int> counts)
        : base(items.SelectList(e => new EmployeeDto(e)), total, req)
    {
        StatusCounts = counts;
    }
}

Authorization Patterns

// Controller level - all endpoints
[PlatformAuthorize]
public class SecureController : PlatformBaseController { }

// Endpoint level - specific roles
[HttpPost]
[PlatformAuthorize(Roles = "Admin,Manager")]
public async Task<IActionResult> AdminOnly() { }

// Handler level - business validation
protected override async Task<PlatformValidationResult<T>> ValidateRequestAsync(...)
{
    return await validation
        .And(_ => RequestContext.HasRole("Admin") || RequestContext.UserId() == req.TargetUserId,
            "Can only modify own data or be Admin");
}

File Upload Endpoints

[HttpPost("upload")]
[RequestSizeLimit(50 * 1024 * 1024)]  // 50MB
public async Task<IActionResult> Upload([FromForm] UploadCommand command)
    => Ok(await Cqrs.SendAsync(command));

public sealed class UploadCommand : PlatformCqrsCommand<UploadCommandResult>
{
    [FromForm]
    public IFormFile File { get; set; } = null!;

    [FromForm]
    public string? Description { get; set; }
}

Error Response Format

// Platform handles errors automatically with standard format
{
    "type": "validation",
    "title": "Validation Error",
    "status": 400,
    "errors": {
        "email": ["Email is required", "Invalid email format"],
        "firstName": ["FirstName is required"]
    }
}

// Business errors
{
    "type": "business",
    "title": "Business Rule Violation",
    "status": 422,
    "detail": "Employee is already assigned to this department"
}

API Design Checklist

  • RESTful route naming (plural nouns, lowercase)?
  • Appropriate HTTP methods?
  • Proper authorization attributes?
  • Validation in Command/Query Validate()?
  • Consistent response format?
  • Paging for list endpoints?
  • Error handling follows platform patterns?

Anti-Patterns

  • Verbs in URLs: Use /employees/123/activate not /activateEmployee
  • Missing Authorization: Always add [PlatformAuthorize]
  • Validation in Controller: Move to Command/Query Validate()
  • Business Logic in Controller: Keep controllers thin, logic in handlers
  • Inconsistent Naming: Follow {Resource}Controller pattern

スコア

総合スコア

50/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です