axim-restdoc-generator

📁 axim-one/gradle-restdoc-generator 📅 8 days ago
4
总安装量
4
周安装量
#48857
全站排名
安装命令
npx skills add https://github.com/axim-one/gradle-restdoc-generator --skill axim-restdoc-generator

Agent 安装分布

opencode 4
gemini-cli 4
antigravity 4
claude-code 4
github-copilot 4
codex 4

Skill 文档

Axim Gradle RestDoc Generator

A Gradle plugin that auto-generates REST API documentation by scanning Spring Boot @RestController classes and their Javadoc comments.

Version: 2.0.7 Requirements: Java 17+, Gradle 7.0+, Spring Boot Repository: https://github.com/Axim-one/gradle-restdoc-generator

Installation

build.gradle (buildscript)

buildscript {
    repositories {
        maven { url 'https://jitpack.io' }
    }
    dependencies {
        classpath 'com.github.Axim-one:gradle-restdoc-generator:2.0.7'
    }
}

apply plugin: 'gradle-restdoc-generator'

settings.gradle (Plugin DSL)

pluginManagement {
    repositories {
        maven { url 'https://jitpack.io' }
        gradlePluginPortal()
    }
    resolutionStrategy {
        eachPlugin {
            if (requested.id.id == 'gradle-restdoc-generator') {
                useModule("com.github.Axim-one:gradle-restdoc-generator:${requested.version}")
            }
        }
    }
}
plugins {
    id 'gradle-restdoc-generator' version '2.0.6'
}

Configuration DSL

restMetaGenerator {
    // Required
    documentPath = 'build/docs'
    basePackage = 'com.example'
    serviceId = 'my-service'

    // Service info (optional)
    serviceName = 'My Service'
    apiServerUrl = 'https://api.example.com'
    serviceVersion = 'v1.0'
    introductionFile = 'docs/introduction.md'

    // Error code / response class (optional)
    errorCodeClass = 'com.example.exception.ErrorCode'
    errorResponseClass = 'com.example.dto.ApiErrorResponse'    // v2.0.5+

    // Authentication — apiKey (optional, type='token' also works)
    auth {
        type = 'apiKey'           // or 'token' (backward-compatible alias)
        headerKey = 'Access-Token'
        value = '{{accessToken}}'
        in = 'header'             // 'header' (default), 'query', 'cookie'
        descriptionFile = 'docs/auth.md'
    }

    // Authentication — Bearer (v2.0.7+)
    // auth {
    //     type = 'http'
    //     scheme = 'bearer'
    //     bearerFormat = 'JWT'    // optional
    //     value = '{{accessToken}}'
    //     descriptionFile = 'docs/auth.md'
    // }

    // Authentication — Basic (v2.0.7+)
    // auth {
    //     type = 'http'
    //     scheme = 'basic'
    //     value = '{{username}}:{{password}}'
    //     descriptionFile = 'docs/auth.md'
    // }

    // Common headers (optional)
    header('X-Custom-Header', 'default-value', 'Header description')

    // Postman environments (optional)
    environment('DEV') {
        variable('base_url', 'https://dev.api.example.com')
        variable('token', 'dev-token')
    }
    environment('PROD') {
        variable('base_url', 'https://api.example.com')
        variable('token', '')
    }

    // Postman sync (optional)
    postmanApiKey = ''
    postmanWorkSpaceId = ''

    debug = false
}

DSL Property Reference

Property Required Default Description
documentPath Yes — Output directory (relative to project root)
basePackage Yes — Package(s) to scan (comma-separated for multiple)
serviceId Yes — Service unique ID (used as JSON filename)
serviceName No "" Display name (OpenAPI title)
apiServerUrl No "" API base URL (OpenAPI servers)
serviceVersion No "v1.0" API version (OpenAPI version)
introductionFile No "" Markdown file path for service description
errorCodeClass No "" ErrorCode class FQCN (fallback: framework default)
errorResponseClass No "" Error Response DTO FQCN (v2.0.5+, fallback: ApiError)
postmanApiKey No "" Postman API Key (empty = skip sync)
postmanWorkSpaceId No "" Postman Workspace ID
debug Yes false Enable debug logging

Auth DSL Properties (v2.0.7+)

Property Default Description
type "" Auth type: "token"/"apiKey" (API key) or "http" (Bearer/Basic)
headerKey "" Header/parameter name (apiKey type only)
value "" Auth value (token, "user:pass" for basic)
descriptionFile "" Markdown file path for auth description
in "header" apiKey location: "header", "query", "cookie"
scheme "" HTTP auth scheme: "bearer", "basic" (http type only)
bearerFormat "" Token format hint, e.g. "JWT" (bearer only)

Javadoc Tags

Write Javadoc on controller methods to enrich the generated documentation:

/**
 * 사용자 정보를 조회합니다.
 *
 * @param userId 사용자 ID
 * @return 사용자 정보
 * @response 200 성공
 * @response 404 사용자를 찾을 수 없음
 * @group 사용자 관리
 * @auth true
 * @header X-Request-Id 요청 추적 ID
 * @error UserNotFoundException
 */
@GetMapping("/users/{userId}")
public UserDto getUser(@PathVariable Long userId) { ... }

Tag Reference

Tag Description
@param Parameter description
@return Return value description
@response {code} {desc} HTTP response status code and description
@error {ExceptionClass} Link error group — auto-populates errors and responseStatus
@throws {ExceptionClass} Same as @error (standard Javadoc tag)
@group API group name (maps to Postman folder)
@auth true Mark endpoint as requiring authentication
@header {name} {desc} Document a custom header
@className Override generated class name

NOTE: Method signature throws clauses are also auto-detected and linked to error groups (no Javadoc tag needed).

Error Code Documentation

Exception classes with public static final ErrorCode fields are auto-scanned:

public class UserNotFoundException extends RuntimeException {
    public static final ErrorCode USER_NOT_FOUND =
        new ErrorCode("USER_001", "error.user.notfound");
    public static final ErrorCode USER_DELETED =
        new ErrorCode("USER_002", "error.user.deleted");

    public UserNotFoundException(ErrorCode errorCode) {
        super(HttpStatus.NOT_FOUND, errorCode);
    }
}

Error Code/Response Class Resolution (2-level priority)

  1. DSL explicit — errorCodeClass / errorResponseClass in build.gradle
  2. Framework default — one.axim.framework.rest.exception.ErrorCode / one.axim.framework.rest.model.ApiError

Linking Errors to APIs

Use @error / @throws Javadoc tags or method throws clause:

/**
 * 사용자 상세 조회
 * @error UserNotFoundException
 */
@GetMapping("/users/{id}")
public UserDto getUser(@PathVariable Long id) { ... }

// Or: auto-detected from throws clause
@GetMapping("/users/{id}/status")
public UserStatus getUserStatus(@PathVariable Long id) throws AuthException { ... }

Pagination Support

Spring Data Pageable/Page<T> are auto-recognized:

@GetMapping(name = "사용자 페이징 조회", value = "/paged")
public Page<UserDto> getUsers(Pageable pageable) { ... }

Auto-generated:

  • Query params: page (default: 0), size (default: 20), sort
  • Response model: content, totalElements, totalPages, size, number, numberOfElements, first, last, empty, sort
  • API JSON: isPaging: true, pagingType: "spring"

ApiResult Wrapper Unwrapping

ApiResult<T> wrapper types are auto-unwrapped:

// Single → returnClass: "UserDto"
public ApiResult<UserDto> getUser() { ... }

// List → returnClass: "UserDto", isArrayReturn: true
public ApiResult<List<UserDto>> getUsers() { ... }

// Paging → returnClass: "UserDto", isPaging: true, pagingType: "spring"
public ApiResult<Page<UserDto>> getUsersPaged(Pageable pageable) { ... }

Running the Plugin

./gradlew restMetaGenerator

Output Structure

build/docs/
├── {serviceId}.json          # Service definition
├── openapi.json              # OpenAPI 3.0.3 spec
├── spec-bundle.json          # Integrated bundle (service + APIs + models + errors)
├── api/
│   └── {ControllerName}.json # Per-controller API definitions
├── model/
│   └── {ClassName}.json      # Model/DTO definitions
└── error/
    ├── errors.json           # Error code groups
    └── error-response.json   # Error response model structure

spec-bundle.json Structure

The bundle JSON combines all outputs into a single file for UI consumption:

{
  "service": {
    "serviceId": "my-service",
    "name": "My Service",
    "apiServerUrl": "https://api.example.com",
    "version": "v1.0",
    "introduction": "...",
    "auth": { "type": "token", "headerKey": "Authorization", ... },
    "headers": [...]
  },
  "apis": [
    {
      "id": "getUser",
      "name": "사용자 조회",
      "method": "GET",
      "urlMapping": "/users/{id}",
      "returnClass": "com.example.dto.UserDto",
      "parameters": [...],
      "responseStatus": { "200": "성공", "404": "사용자를 찾을 수 없음" },
      "errors": [{ "exception": "UserNotFoundException", "status": 404, "codes": [...] }]
    }
  ],
  "models": {
    "com.example.dto.UserDto": {
      "name": "UserDto",
      "type": "Object",
      "fields": [{ "name": "id", "type": "Long" }, ...]
    }
  },
  "errors": [
    {
      "group": "User Not Found",
      "exception": "UserNotFoundException",
      "status": 404,
      "codes": [{ "code": "USER_001", "name": "USER_NOT_FOUND", "message": "..." }]
    }
  ],
  "errorResponse": {
    "name": "ApiErrorResponse",
    "type": "Object",
    "fields": [...]
  }
}

Execution Pipeline

The restMetaGenerator task runs in this order:

  1. Error Code Scan — Collect ErrorCode fields from Exception classes
  2. API Document Generation — Scan @RestController → generate per-controller/model JSON
  3. Error JSON Write — Output errors.json + error-response.json
  4. OpenAPI Spec — Generate openapi.json (OpenAPI 3.0.3)
  5. Spec Bundle — Generate spec-bundle.json
  6. Postman Sync — Sync Collection/Environment (if configured)

Changelog

  • v2.0.7 — Auth DSL extension: apiKey/http (Bearer/Basic) support for OpenAPI securitySchemes and Postman auth
  • v2.0.6 — Fixed empty version causing //path, fixed ArrayIndexOutOfBoundsException for path-less mappings
  • v2.0.5 — Added errorResponseClass DSL property
  • v2.0.4 — OpenAPI 3.0.3, spec-bundle.json, error code scanning, @error/@throws tags
  • v2.0.3 — Fixed inner class enum ClassNotFoundException
  • v2.0.2 — Spring Pageable/Page recognition, ApiResult unwrapping