@g1cloud/api-gen 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/.claude/settings.local.json +22 -0
  2. package/CLAUDE.md +63 -0
  3. package/README.md +379 -0
  4. package/dist/analyzer/controllerAnalyzer.d.ts +20 -0
  5. package/dist/analyzer/controllerAnalyzer.d.ts.map +1 -0
  6. package/dist/analyzer/controllerAnalyzer.js +101 -0
  7. package/dist/analyzer/controllerAnalyzer.js.map +1 -0
  8. package/dist/analyzer/parameterAnalyzer.d.ts +19 -0
  9. package/dist/analyzer/parameterAnalyzer.d.ts.map +1 -0
  10. package/dist/analyzer/parameterAnalyzer.js +207 -0
  11. package/dist/analyzer/parameterAnalyzer.js.map +1 -0
  12. package/dist/analyzer/responseAnalyzer.d.ts +12 -0
  13. package/dist/analyzer/responseAnalyzer.d.ts.map +1 -0
  14. package/dist/analyzer/responseAnalyzer.js +116 -0
  15. package/dist/analyzer/responseAnalyzer.js.map +1 -0
  16. package/dist/analyzer/schemaGenerator.d.ts +6 -0
  17. package/dist/analyzer/schemaGenerator.d.ts.map +1 -0
  18. package/dist/analyzer/schemaGenerator.js +347 -0
  19. package/dist/analyzer/schemaGenerator.js.map +1 -0
  20. package/dist/analyzer/securityAnalyzer.d.ts +6 -0
  21. package/dist/analyzer/securityAnalyzer.d.ts.map +1 -0
  22. package/dist/analyzer/securityAnalyzer.js +177 -0
  23. package/dist/analyzer/securityAnalyzer.js.map +1 -0
  24. package/dist/generator/openapiGenerator.d.ts +14 -0
  25. package/dist/generator/openapiGenerator.d.ts.map +1 -0
  26. package/dist/generator/openapiGenerator.js +340 -0
  27. package/dist/generator/openapiGenerator.js.map +1 -0
  28. package/dist/index.d.ts +3 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +218 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/lib.d.ts +61 -0
  33. package/dist/lib.d.ts.map +1 -0
  34. package/dist/lib.js +199 -0
  35. package/dist/lib.js.map +1 -0
  36. package/dist/mcp-server.d.ts +9 -0
  37. package/dist/mcp-server.d.ts.map +1 -0
  38. package/dist/mcp-server.js +257 -0
  39. package/dist/mcp-server.js.map +1 -0
  40. package/dist/mcp-server.mjs +45586 -0
  41. package/dist/parser/astAnalyzer.d.ts +87 -0
  42. package/dist/parser/astAnalyzer.d.ts.map +1 -0
  43. package/dist/parser/astAnalyzer.js +321 -0
  44. package/dist/parser/astAnalyzer.js.map +1 -0
  45. package/dist/parser/javaParser.d.ts +10 -0
  46. package/dist/parser/javaParser.d.ts.map +1 -0
  47. package/dist/parser/javaParser.js +805 -0
  48. package/dist/parser/javaParser.js.map +1 -0
  49. package/dist/types/index.d.ts +217 -0
  50. package/dist/types/index.d.ts.map +1 -0
  51. package/dist/types/index.js +3 -0
  52. package/dist/types/index.js.map +1 -0
  53. package/examples/CreateUserRequest.java +80 -0
  54. package/examples/DepartmentDTO.java +45 -0
  55. package/examples/Filter.java +39 -0
  56. package/examples/PaginatedList.java +71 -0
  57. package/examples/ProductController.java +136 -0
  58. package/examples/ProductDTO.java +129 -0
  59. package/examples/RoleDTO.java +47 -0
  60. package/examples/SearchParam.java +55 -0
  61. package/examples/Sort.java +70 -0
  62. package/examples/UpdateUserRequest.java +74 -0
  63. package/examples/UserController.java +98 -0
  64. package/examples/UserDTO.java +119 -0
  65. package/package.json +51 -0
  66. package/prompt/01_Initial.md +358 -0
  67. package/prompt/02_/354/266/224/352/260/200.md +31 -0
  68. package/src/analyzer/controllerAnalyzer.ts +125 -0
  69. package/src/analyzer/parameterAnalyzer.ts +259 -0
  70. package/src/analyzer/responseAnalyzer.ts +142 -0
  71. package/src/analyzer/schemaGenerator.ts +412 -0
  72. package/src/analyzer/securityAnalyzer.ts +200 -0
  73. package/src/generator/openapiGenerator.ts +378 -0
  74. package/src/index.ts +212 -0
  75. package/src/lib.ts +240 -0
  76. package/src/mcp-server.ts +310 -0
  77. package/src/parser/astAnalyzer.ts +373 -0
  78. package/src/parser/javaParser.ts +901 -0
  79. package/src/types/index.ts +238 -0
  80. package/test-boolean.yaml +607 -0
  81. package/test-filter.yaml +576 -0
  82. package/test-inner.ts +59 -0
  83. package/test-output.yaml +650 -0
  84. package/test-paginated.yaml +585 -0
  85. package/tsconfig.json +20 -0
  86. package/tsup.config.ts +30 -0
@@ -0,0 +1,358 @@
1
+ # Spring Boot → OpenAPI v3 YAML 생성기 개발
2
+
3
+ TypeScript로 Spring Boot 애플리케이션의 Java 소스코드를 분석하여 OpenAPI Specification v3 기반의 YAML 파일을 자동 생성하는 CLI 도구를 만들어주세요. 도구 이름은 `@g1cloud/api-gen` 으로 해주고, 현재 디렉토리 아래에 `api-gen` 디렉토리를 만들어 프로젝트 루트 디렉토리로 사용하세요.
4
+
5
+ ## 주요 기능 요구사항
6
+
7
+ ### 1. Java 소스코드 파싱
8
+ - `java-parser` 또는 `tree-sitter-java` NPM 패키지를 사용하여 Java 파일 파싱
9
+ - AST(Abstract Syntax Tree)를 분석하여 어노테이션 및 메서드 시그니처 추출
10
+
11
+ ### 2. RestController 분석
12
+ 다음 어노테이션들을 분석:
13
+ - `@RestController` / `@Controller` + `@ResponseBody`
14
+ - `@RequestMapping` (클래스/메서드 레벨)
15
+ - `@GetMapping`, `@PostMapping`, `@PutMapping`, `@DeleteMapping`, `@PatchMapping`
16
+
17
+ ### 3. 입력 파라미터 분석
18
+ 각 엔드포인트의 파라미터를 분석하여 OpenAPI 스키마 생성:
19
+ - `@RequestParam` → query parameters
20
+ - `@PathVariable` → path parameters
21
+ - `@RequestBody` → request body schema
22
+ - `@RequestHeader` → header parameters
23
+ - 파라미터의 타입, 필수 여부(`required`), 기본값(`defaultValue`) 추출
24
+
25
+ #### 특수 타입 처리: SearchParam
26
+ 파라미터에 `SearchParam` 타입의 객체가 있는 경우, 다음 query parameters를 자동으로 추가:
27
+ - `offset` (integer) - 페이지네이션 오프셋
28
+ - `limit` (integer) - 페이지네이션 제한
29
+ - `filter` (Filter 타입) - 필터 조건 (객체 스키마로 확장)
30
+ - `sort` (Sort 타입) - 정렬 조건 (객체 스키마로 확장)
31
+ ```yaml
32
+ # SearchParam 예시
33
+ parameters:
34
+ - name: offset
35
+ in: query
36
+ schema:
37
+ type: integer
38
+ description: Pagination offset
39
+ - name: limit
40
+ in: query
41
+ schema:
42
+ type: integer
43
+ description: Pagination limit
44
+ - name: filter
45
+ in: query
46
+ schema:
47
+ $ref: '#/components/schemas/Filter'
48
+ - name: sort
49
+ in: query
50
+ schema:
51
+ $ref: '#/components/schemas/Sort'
52
+ ```
53
+
54
+ ### 4. 출력 데이터 형식 분석
55
+ - 메서드 리턴 타입 분석 (`ResponseEntity<T>`, DTO 클래스 등)
56
+ - 리턴 타입의 클래스 구조를 분석하여 response schema 생성
57
+ - 중첩 객체(nested objects), 제네릭 타입 지원
58
+ - HTTP 상태 코드 추출
59
+
60
+ #### 특수 타입 처리: PaginatedList
61
+ 리턴 타입이 `PaginatedList` 또는 `PaginatedList<T>` 인 경우, response headers에 다음을 추가:
62
+ - `X-Total-Count` (integer) - 전체 아이템 개수
63
+ - `X-Offset` (integer) - 현재 오프셋
64
+ - `X-Limit` (integer) - 현재 제한 값
65
+ ```yaml
66
+ # PaginatedList 예시
67
+ responses:
68
+ '200':
69
+ description: Successful response
70
+ headers:
71
+ X-Total-Count:
72
+ schema:
73
+ type: integer
74
+ description: Total number of items
75
+ X-Offset:
76
+ schema:
77
+ type: integer
78
+ description: Current offset
79
+ X-Limit:
80
+ schema:
81
+ type: integer
82
+ description: Current limit
83
+ content:
84
+ application/json:
85
+ schema:
86
+ $ref: '#/components/schemas/PaginatedListUserDTO'
87
+ ```
88
+
89
+ ### 5. 보안/권한 분석
90
+ - `@PreAuthorize` / `@PostAuthorize` 어노테이션 분석
91
+ - `@Secured` 어노테이션 분석
92
+ - SpEL 표현식에서 역할(role) 및 권한(authority) 추출
93
+ - `hasRole('ADMIN')` → ROLE_ADMIN
94
+ - `hasAnyRole('USER', 'ADMIN')` → [ROLE_USER, ROLE_ADMIN]
95
+ - `hasAuthority('READ_PRIVILEGE')` → READ_PRIVILEGE
96
+ - **복잡한 SpEL 표현식 처리**: `hasRole`, `hasAnyRole`, `hasAuthority` 이외의 구문이 포함된 경우, 전체 SpEL 표현식을 `x-security-expression` 확장 필드에 그대로 기록
97
+ ```yaml
98
+ # 복잡한 SpEL 표현식 예시
99
+ paths:
100
+ /api/users/{id}:
101
+ put:
102
+ security:
103
+ - bearerAuth: []
104
+ x-required-roles:
105
+ - ROLE_USER
106
+ x-security-expression: "hasRole('ADMIN') or (#user.id == #id and hasRole('USER'))"
107
+ ```
108
+
109
+ - OpenAPI의 `security` 필드 또는 `x-required-roles` 확장 필드에 문서화
110
+
111
+ ### 6. DTO 스키마 생성
112
+ - `@RequestBody`와 리턴 타입에 사용된 DTO 클래스 재귀적 분석
113
+ - 필드 타입, 어노테이션(`@NotNull`, `@Size` 등) 분석
114
+ - OpenAPI components/schemas에 스키마 정의 생성
115
+ - `SearchParam`, `Filter`, `Sort`, `PaginatedList` 타입도 스키마로 정의
116
+
117
+ ## 기술 스택
118
+ - **언어**: TypeScript
119
+ - **Java 파서**: `java-parser` 또는 `tree-sitter-java`
120
+ - **YAML 생성**: `js-yaml`
121
+ - **CLI**: `commander` 또는 `yargs`
122
+
123
+ ## CLI 인터페이스
124
+ ```bash
125
+ # 사용 예시
126
+ npx spring-to-openapi \
127
+ --source ./src/main/java \
128
+ --output ./openapi.yaml \
129
+ --title "My API" \
130
+ --version "1.0.0" \
131
+ --base-path "/api"
132
+ ```
133
+
134
+ ### CLI 옵션
135
+ - `--source, -s`: Java 소스코드 디렉토리 경로 (필수)
136
+ - `--output, -o`: 출력 YAML 파일 경로 (기본값: `openapi.yaml`)
137
+ - `--title, -t`: API 제목 (기본값: `API Documentation`)
138
+ - `--version, -v`: API 버전 (기본값: `1.0.0`)
139
+ - `--base-path, -b`: API 베이스 경로 (선택)
140
+
141
+ ## 출력 형식 예시
142
+ ```yaml
143
+ openapi: 3.0.0
144
+ info:
145
+ title: My API
146
+ version: 1.0.0
147
+ servers:
148
+ - url: http://localhost:8080/api
149
+ paths:
150
+ /users:
151
+ get:
152
+ summary: Search users with pagination
153
+ parameters:
154
+ - name: offset
155
+ in: query
156
+ schema:
157
+ type: integer
158
+ description: Pagination offset
159
+ - name: limit
160
+ in: query
161
+ schema:
162
+ type: integer
163
+ description: Pagination limit
164
+ - name: filter
165
+ in: query
166
+ schema:
167
+ $ref: '#/components/schemas/Filter'
168
+ - name: sort
169
+ in: query
170
+ schema:
171
+ $ref: '#/components/schemas/Sort'
172
+ responses:
173
+ '200':
174
+ description: Successful response
175
+ headers:
176
+ X-Total-Count:
177
+ schema:
178
+ type: integer
179
+ description: Total number of items
180
+ X-Offset:
181
+ schema:
182
+ type: integer
183
+ description: Current offset
184
+ X-Limit:
185
+ schema:
186
+ type: integer
187
+ description: Current limit
188
+ content:
189
+ application/json:
190
+ schema:
191
+ $ref: '#/components/schemas/PaginatedListUserDTO'
192
+ security:
193
+ - bearerAuth: []
194
+ x-required-roles:
195
+ - ROLE_USER
196
+
197
+ /users/{id}:
198
+ get:
199
+ summary: Get user by ID
200
+ parameters:
201
+ - name: id
202
+ in: path
203
+ required: true
204
+ schema:
205
+ type: integer
206
+ responses:
207
+ '200':
208
+ description: Successful response
209
+ content:
210
+ application/json:
211
+ schema:
212
+ $ref: '#/components/schemas/UserDTO'
213
+ security:
214
+ - bearerAuth: []
215
+ x-required-roles:
216
+ - ROLE_USER
217
+ - ROLE_ADMIN
218
+
219
+ put:
220
+ summary: Update user
221
+ parameters:
222
+ - name: id
223
+ in: path
224
+ required: true
225
+ schema:
226
+ type: integer
227
+ requestBody:
228
+ required: true
229
+ content:
230
+ application/json:
231
+ schema:
232
+ $ref: '#/components/schemas/UserDTO'
233
+ responses:
234
+ '200':
235
+ description: Successful response
236
+ security:
237
+ - bearerAuth: []
238
+ x-security-expression: "hasRole('ADMIN') or (#user.id == #id and hasRole('USER'))"
239
+
240
+ components:
241
+ schemas:
242
+ UserDTO:
243
+ type: object
244
+ properties:
245
+ id:
246
+ type: integer
247
+ name:
248
+ type: string
249
+ email:
250
+ type: string
251
+
252
+ PaginatedListUserDTO:
253
+ type: object
254
+ properties:
255
+ items:
256
+ type: array
257
+ items:
258
+ $ref: '#/components/schemas/UserDTO'
259
+ total:
260
+ type: integer
261
+ offset:
262
+ type: integer
263
+ limit:
264
+ type: integer
265
+
266
+ Filter:
267
+ type: object
268
+ description: Filter conditions
269
+ additionalProperties: true
270
+
271
+ Sort:
272
+ type: object
273
+ description: Sort conditions
274
+ properties:
275
+ field:
276
+ type: string
277
+ direction:
278
+ type: string
279
+ enum: [ASC, DESC]
280
+
281
+ securitySchemes:
282
+ bearerAuth:
283
+ type: http
284
+ scheme: bearer
285
+ bearerFormat: JWT
286
+ ```
287
+
288
+ ## 추가 요구사항
289
+ - 에러 핸들링: 파싱 실패 시 명확한 에러 메시지 출력
290
+ - 로깅: 처리 진행 상황 표시 (발견된 컨트롤러 수, 엔드포인트 수 등)
291
+ - 테스트: 샘플 Java 파일로 테스트 가능하도록 예제 포함
292
+ - SearchParam을 사용하는 예제
293
+ - PaginatedList를 반환하는 예제
294
+ - 복잡한 SpEL 표현식을 사용하는 예제
295
+ - README.md: 설치 및 사용법 문서 작성
296
+
297
+ ## 프로젝트 구조
298
+ ```
299
+ spring-to-openapi/
300
+ ├── src/
301
+ │ ├── index.ts # CLI 진입점
302
+ │ ├── parser/
303
+ │ │ ├── javaParser.ts # Java 파싱 로직
304
+ │ │ └── astAnalyzer.ts # AST 분석
305
+ │ ├── analyzer/
306
+ │ │ ├── controllerAnalyzer.ts # RestController 분석
307
+ │ │ ├── parameterAnalyzer.ts # 파라미터 분석 (SearchParam 특수 처리)
308
+ │ │ ├── responseAnalyzer.ts # 응답 분석 (PaginatedList 특수 처리)
309
+ │ │ ├── securityAnalyzer.ts # 보안 어노테이션 분석 (SpEL 파싱)
310
+ │ │ └── schemaGenerator.ts # DTO 스키마 생성
311
+ │ ├── generator/
312
+ │ │ └── openapiGenerator.ts # OpenAPI YAML 생성
313
+ │ └── types/
314
+ │ └── index.ts # TypeScript 타입 정의
315
+ ├── examples/ # 테스트용 샘플 Java 파일
316
+ │ ├── UserController.java
317
+ │ ├── SearchParam.java
318
+ │ └── PaginatedList.java
319
+ ├── package.json
320
+ ├── tsconfig.json
321
+ └── README.md
322
+ ```
323
+
324
+ ## 특수 타입 처리 상세
325
+
326
+ ### SearchParam 감지 및 처리
327
+ 1. 메서드 파라미터 타입이 `SearchParam` 또는 이를 상속/구현하는 타입인지 확인
328
+ 2. 해당 파라미터가 발견되면 자동으로 `offset`, `limit`, `filter`, `sort` query parameters 추가
329
+ 3. `Filter`와 `Sort` 타입이 정의되어 있다면 해당 스키마를 components/schemas에 추가
330
+
331
+ ### PaginatedList 감지 및 처리
332
+ 1. 메서드 리턴 타입이 `PaginatedList` 또는 `PaginatedList<T>`인지 확인
333
+ 2. 제네릭 타입 `T`를 추출하여 실제 아이템 타입 파악
334
+ 3. Response에 `X-Total-Count`, `X-Offset`, `X-Limit` 헤더 자동 추가
335
+ 4. Response body 스키마는 PaginatedList 구조로 생성
336
+
337
+ ### SpEL 표현식 처리
338
+ 1. `@PreAuthorize`, `@PostAuthorize` 어노테이션의 값 추출
339
+ 2. 정규식으로 `hasRole()`, `hasAnyRole()`, `hasAuthority()` 패턴 매칭
340
+ 3. 단순 패턴에 매칭되면 역할/권한 추출하여 `x-required-roles`에 추가
341
+ 4. 복잡한 표현식(논리 연산자, 비교 연산자, 변수 참조 등 포함)이면 전체 표현식을 `x-security-expression`에 기록
342
+ 5. 두 필드 모두 존재할 수 있음 (간단한 역할 + 복잡한 전체 표현식)
343
+
344
+ ### MultiLangString 처리
345
+ 1. `MultiLangString` 은 `Map<String, String>` 형태로 처리
346
+ 2. OpenAPI 스키마에서 `type: object`로 정의하고, `additionalProperties: { type: string }` 사용
347
+
348
+ ### MultiLangStoredFile 처리
349
+ 1. `MultiLangStoredFile` 은 `Map<String, StoredFile>` 형태로 처리
350
+ 2. OpenAPI 스키마에서 `type: object`로 정의하고, `additionalProperties`에 `StoredFile` 스키마 참조 사용
351
+ 3. StoredFile 은 `net.g1project.bluecomm.model.StoredFile` 클래스 참고해서 처리
352
+
353
+ ### 그 외 Dto 분석 시 주의할 점
354
+ - static field 는 제외
355
+ - java.lang.Object 의 field 는 제외
356
+
357
+
358
+ 위 요구사항에 따라 완전히 동작하는 프로젝트를 생성해주세요.
@@ -0,0 +1,31 @@
1
+ # RestController 파일 별로 문서 생성
2
+
3
+ 디렉토리 하위의 @RestController annotation 이 추가된 파일을 검색해
4
+ 각각의 java 파일별로 별도의 yaml 파일을 생성하도록 할 것.
5
+ yaml 파일 명은 java 파일명과 동일하게 할 것.
6
+
7
+ 이렇게 하려면 output 을 파일로 받지 않고 디렉토리로 받아야 함. (--out-dir 처럼)
8
+
9
+ # javadoc 내용을 설명으로
10
+
11
+ Java 소스코드에 작성된 javadoc 내용을 OpenAPI 문서의 설명(description) 필드로 포함시켜줘.
12
+
13
+
14
+ # redoc 적용 스크립트
15
+
16
+ 각 yaml 파일 별로 @redocly/cli 를 실행하는 셸 스크립트 작성해줘.
17
+
18
+ 주어진 디렉토리 아래의 모든 yaml 파일에 대해서 아래처럼 실행
19
+
20
+ npx @redocly/cli build-docs (yaml 파일) -o (타겟 디렉토리)
21
+
22
+ # PaginatedList 스키마 정의
23
+
24
+ PaginatedList 가 response 로 리턴될 때는 items 만 의미가 있고, totalCount, offset, limit 등은 response header 로 전달되기 때문에 표시하지 않도록 해줘.
25
+ items 도 items property 는 명시하지 않고, 바로 배열 타입으로 정의되도록 해줘.
26
+
27
+ 예를 들어, PaginatedList<UserDto> 라면 마치 List<UserDto> 인 것처럼 response schema 가 생성되도록 해줘.
28
+
29
+ # SearchParam
30
+
31
+ SearchParam 의 Filter 와 Sort 는 그냥 object 타입으로 정의해줘.
@@ -0,0 +1,125 @@
1
+ import {
2
+ JavaClass,
3
+ JavaMethod,
4
+ ControllerInfo,
5
+ EndpointInfo,
6
+ HttpMethod,
7
+ ProcessingContext,
8
+ } from '../types';
9
+ import { ASTAnalyzer } from '../parser/astAnalyzer';
10
+ import { analyzeParameters } from './parameterAnalyzer';
11
+ import { analyzeResponse } from './responseAnalyzer';
12
+ import { analyzeMethodSecurity } from './securityAnalyzer';
13
+
14
+ export class ControllerAnalyzer {
15
+ private context: ProcessingContext;
16
+
17
+ constructor(context: ProcessingContext) {
18
+ this.context = context;
19
+ }
20
+
21
+ /**
22
+ * Analyze all Java classes and extract controller information
23
+ * If apiSourcePath is specified, only analyze controllers within that directory
24
+ */
25
+ analyzeControllers(): ControllerInfo[] {
26
+ const controllers: ControllerInfo[] = [];
27
+ const { apiSourcePath } = this.context;
28
+
29
+ for (const [, javaClass] of this.context.javaClasses) {
30
+ // If apiSourcePath is specified, only include controllers from that directory
31
+ if (apiSourcePath && !javaClass.filePath.startsWith(apiSourcePath)) {
32
+ continue;
33
+ }
34
+
35
+ if (ASTAnalyzer.isRestController(javaClass)) {
36
+ const controllerInfo = this.analyzeController(javaClass);
37
+ if (controllerInfo) {
38
+ controllers.push(controllerInfo);
39
+ }
40
+ }
41
+ }
42
+
43
+ return controllers;
44
+ }
45
+
46
+ /**
47
+ * Analyze a single controller class
48
+ */
49
+ private analyzeController(javaClass: JavaClass): ControllerInfo | null {
50
+ const basePath = ASTAnalyzer.getClassBasePath(javaClass);
51
+ const endpoints: EndpointInfo[] = [];
52
+
53
+ console.log(` Found controller: ${javaClass.name} (base path: ${basePath || '/'})`);
54
+
55
+ for (const method of javaClass.methods) {
56
+ if (ASTAnalyzer.isEndpointMethod(method)) {
57
+ const endpoint = this.analyzeEndpoint(javaClass, method, basePath);
58
+ if (endpoint) {
59
+ endpoints.push(endpoint);
60
+ console.log(` - ${endpoint.method.toUpperCase()} ${endpoint.path}`);
61
+ }
62
+ }
63
+ }
64
+
65
+ if (endpoints.length === 0) {
66
+ return null;
67
+ }
68
+
69
+ return {
70
+ className: javaClass.name,
71
+ basePath,
72
+ endpoints,
73
+ javaClass,
74
+ };
75
+ }
76
+
77
+ /**
78
+ * Analyze a single endpoint method
79
+ */
80
+ private analyzeEndpoint(javaClass: JavaClass, method: JavaMethod, basePath: string): EndpointInfo | null {
81
+ const httpMethod = ASTAnalyzer.getHttpMethod(method);
82
+ if (!httpMethod) {
83
+ return null;
84
+ }
85
+
86
+ const methodPath = ASTAnalyzer.getMethodPath(method);
87
+ const fullPath = ASTAnalyzer.combinePaths(basePath, methodPath);
88
+
89
+ // Get @param descriptions from javadoc
90
+ const paramDescriptions = method.javadocInfo?.params || {};
91
+
92
+ // Analyze parameters (pass javadoc @param descriptions)
93
+ const { parameters, requestBody, hasSearchParam } = analyzeParameters(method, this.context, paramDescriptions);
94
+
95
+ // Analyze response
96
+ const { responses, hasPaginatedList, paginatedListItemType } = analyzeResponse(
97
+ method,
98
+ this.context
99
+ );
100
+
101
+ // Analyze security
102
+ const security = analyzeMethodSecurity(method);
103
+
104
+ return {
105
+ path: fullPath,
106
+ method: httpMethod as HttpMethod,
107
+ operationId: ASTAnalyzer.generateOperationId(javaClass.name, method.name),
108
+ summary: ASTAnalyzer.generateSummary(method.name),
109
+ description: method.javadoc,
110
+ returnDescription: method.javadocInfo?.returns,
111
+ parameters,
112
+ requestBody,
113
+ responses,
114
+ security,
115
+ hasSearchParam,
116
+ hasPaginatedList,
117
+ paginatedListItemType,
118
+ };
119
+ }
120
+ }
121
+
122
+ export function analyzeControllers(context: ProcessingContext): ControllerInfo[] {
123
+ const analyzer = new ControllerAnalyzer(context);
124
+ return analyzer.analyzeControllers();
125
+ }