npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@g1cloud/api-gen

v1.0.0

Published

CLI tool to generate OpenAPI v3 YAML from Spring Boot Java source code

Downloads

46

Readme

@g1cloud/api-gen

Spring Boot Java 소스 코드에서 OpenAPI v3 YAML 스펙을 생성하는 CLI 도구입니다.

기능

  • Java 소스 파싱: java-parser를 사용하여 Java 파일에서 클래스 및 메서드 정보 추출
  • REST Controller 분석: @RestController, @Controller 및 HTTP 매핑 어노테이션 감지
  • 파라미터 추출: @RequestParam, @PathVariable, @RequestHeader, @RequestBody 지원
  • 응답 분석: 반환 타입 추출 및 응답 스키마 생성
  • 보안 어노테이션 파싱: @PreAuthorize, @PostAuthorize, @Secured 어노테이션 분석
  • SpEL 표현식 파싱: Spring Security 표현식에서 역할(role) 및 권한(authority) 추출
  • DTO 스키마 생성: 요청/응답 DTO에 대한 스키마 재귀적 생성
  • 특수 타입 처리:
    • SearchParam: 페이지네이션 파라미터 자동 추가 (offset, limit, filter, sort)
    • PaginatedList<T>: 페이지네이션 헤더 추가 (X-Total-Count, X-Offset, X-Limit)

설치

# 의존성 설치
pnpm install

# 프로젝트 빌드
pnpm build

# 또는 ts-node로 직접 실행
pnpm dev -- --source ./examples --output ./test-output.yaml

사용법

# 기본 사용법 - 단일 통합 YAML 파일 생성
npx spring-to-openapi --source ./src/main/java --output ./openapi.yaml

# 컨트롤러별 모드 - 각 컨트롤러마다 별도 YAML 파일 생성
npx spring-to-openapi --source ./src/main/java --out-dir ./api-docs

# 모든 옵션 사용
npx spring-to-openapi \
  --source ./src/main/java \
  --output ./openapi.yaml \
  --title "My API" \
  --api-version "1.0.0" \
  --base-path "/api"

CLI 옵션

| 옵션 | 단축 | 설명 | 기본값 | |--------|-------|-------------|---------| | --source | -s | Java 소스 코드 디렉토리 경로 | (필수) | | --output | -o | 출력 YAML 파일 경로 (단일 통합 파일) | openapi.yaml | | --out-dir | -d | 출력 디렉토리 경로 (컨트롤러별 YAML 생성) | (없음) | | --title | -t | API 제목 | API Documentation | | --api-version | | API 버전 | 1.0.0 | | --base-path | -b | API 기본 경로 | (없음) |

참고: --output--out-dir은 상호 배타적입니다. 단일 통합 파일은 --output을, 컨트롤러별 YAML 파일 생성은 --out-dir을 사용하세요.

예제

입력: Java Controller

@RestController
@RequestMapping("/api/users")
public class UserController {

    @GetMapping
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<PaginatedList<UserDTO>> searchUsers(SearchParam searchParam) {
        return ResponseEntity.ok(new PaginatedList<>());
    }

    @GetMapping("/{id}")
    @PreAuthorize("hasAnyRole('USER', 'ADMIN')")
    public ResponseEntity<UserDTO> getUserById(@PathVariable Long id) {
        return ResponseEntity.ok(new UserDTO());
    }

    @PutMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN') or (#id == authentication.principal.id and hasRole('USER'))")
    public ResponseEntity<UserDTO> updateUser(
            @PathVariable Long id,
            @Valid @RequestBody UpdateUserRequest request) {
        return ResponseEntity.ok(new UserDTO());
    }
}

출력: OpenAPI YAML

openapi: 3.0.0
info:
  title: My API
  version: 1.0.0
paths:
  /api/users:
    get:
      summary: Search users
      operationId: user_searchUsers
      parameters:
        - name: offset
          in: query
          schema:
            type: integer
          description: Pagination offset
        - name: limit
          in: query
          schema:
            type: integer
          description: Pagination limit
        - name: filter
          in: query
          schema:
            $ref: '#/components/schemas/Filter'
        - name: sort
          in: query
          schema:
            $ref: '#/components/schemas/Sort'
      responses:
        '200':
          description: Successful response
          headers:
            X-Total-Count:
              schema:
                type: integer
              description: Total number of items
            X-Offset:
              schema:
                type: integer
              description: Current offset
            X-Limit:
              schema:
                type: integer
              description: Current limit
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedListUserDTO'
      security:
        - bearerAuth: []
      x-required-roles:
        - ROLE_USER

  /api/users/{id}:
    get:
      summary: Get user by ID
      operationId: user_getUserById
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserDTO'
      security:
        - bearerAuth: []
      x-required-roles:
        - ROLE_USER
        - ROLE_ADMIN

    put:
      summary: Update user
      operationId: user_updateUser
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
            format: int64
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateUserRequest'
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserDTO'
      security:
        - bearerAuth: []
      x-required-roles:
        - ROLE_ADMIN
        - ROLE_USER
      x-security-expression: "hasRole('ADMIN') or (#id == authentication.principal.id and hasRole('USER'))"

components:
  schemas:
    UserDTO:
      type: object
      properties:
        id:
          type: integer
          format: int64
        firstName:
          type: string
          minLength: 2
          maxLength: 50
        lastName:
          type: string
          minLength: 2
          maxLength: 50
        email:
          type: string
      required:
        - firstName
        - lastName
        - email

    Filter:
      type: object
      description: Filter conditions
      additionalProperties: true

    Sort:
      type: object
      description: Sort conditions
      properties:
        field:
          type: string
        direction:
          type: string
          enum:
            - ASC
            - DESC

  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

특수 타입 처리

SearchParam

메서드 파라미터가 SearchParam 타입인 경우, 생성기가 자동으로 페이지네이션 쿼리 파라미터를 추가합니다:

  • offset (integer) - 페이지네이션 오프셋
  • limit (integer) - 페이지네이션 제한
  • filter (object) - 필터 조건 (Filter 스키마 참조)
  • sort (object) - 정렬 조건 (Sort 스키마 참조)

PaginatedList

메서드가 PaginatedList<T>를 반환하는 경우, 생성기가:

  1. 응답에 페이지네이션 헤더를 추가합니다:

    • X-Total-Count - 전체 항목 수
    • X-Offset - 현재 오프셋
    • X-Limit - 현재 제한
  2. 다음 구조의 PaginatedListT 스키마를 생성합니다:

    PaginatedListUserDTO:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/UserDTO'
        total:
          type: integer
        offset:
          type: integer
        limit:
          type: integer

보안 표현식

생성기가 @PreAuthorize@PostAuthorize의 SpEL 표현식을 파싱합니다:

  • hasRole('ADMIN') 같은 단순 표현식 → x-required-roles: [ROLE_ADMIN]
  • hasAnyRole('USER', 'ADMIN')의 다중 역할 → x-required-roles: [ROLE_USER, ROLE_ADMIN]
  • 복잡한 표현식은 x-security-expression에 보존

유효성 검사 어노테이션

생성기가 DTO 필드의 다음 유효성 검사 어노테이션을 인식합니다:

| 어노테이션 | OpenAPI 매핑 | |------------|-----------------| | @NotNull, @NotBlank, @NotEmpty | required: true | | @Size(min, max) | minLength, maxLength | | @Min(value) | minimum | | @Max(value) | maximum | | @Pattern(regexp) | pattern | | @Email | pattern (이메일 정규식) |

프로젝트 구조

api-gen/
├── src/
│   ├── index.ts                  # CLI 진입점
│   ├── parser/
│   │   ├── javaParser.ts         # Java 파일 파싱
│   │   └── astAnalyzer.ts        # AST 분석 유틸리티
│   ├── analyzer/
│   │   ├── controllerAnalyzer.ts # Controller 감지
│   │   ├── parameterAnalyzer.ts  # 파라미터 추출
│   │   ├── responseAnalyzer.ts   # 응답 분석
│   │   ├── securityAnalyzer.ts   # 보안 어노테이션 파싱
│   │   └── schemaGenerator.ts    # DTO 스키마 생성
│   ├── generator/
│   │   └── openapiGenerator.ts   # OpenAPI YAML 생성
│   └── types/
│       └── index.ts              # TypeScript 타입 정의
├── examples/                     # 샘플 Java 파일
├── package.json
├── tsconfig.json
└── README.md

개발

# 의존성 설치
pnpm install

# 개발 모드로 실행
pnpm dev -- --source ./examples

# 프로덕션 빌드
pnpm build

# 테스트 실행 (예제 파일 사용)
pnpm test

실제 사용 예시

pnpm start --source /git/g1cloud2/g1cloud-sales --output ./out/g1cloud-sales.yaml --title "G1cloud Sales API" --api-version "2.0.0-SNAPSHOT"

npx @redocly/cli build-docs ./out/g1cloud-sales.yaml -o ./out/g1cloud-sales.html
pnpm start --source /git/g1cloud2/g1cloud-sales \
    --api-source /git/g1cloud2/g1cloud-sales/g1cloud-sales-app \
    --output ./out/g1cloud-sales-app.yaml \
    --title "G1cloud Sales API" \
    --api-version "2.0.0-SNAPSHOT"

npx @redocly/cli build-docs \
    ./out/g1cloud-sales-app.yaml \
    -o ./out/g1cloud-sales-app.html
pnpm start --source /git/g1cloud2/g1cloud-sales-service \
    --api-source /git/g1cloud2/g1cloud-sales-service/module-basis \
    --output ./out/g1cloud-sales-basis.yaml \
    --title "G1cloud Sales Basis API" \
    --api-version "2.0.0-SNAPSHOT"

npx @redocly/cli build-docs \
    ./out/g1cloud-sales-basis.yaml \
    -o ./out/g1cloud-sales-basis.html