javi-forge 1.0.0 → 1.2.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.
@@ -0,0 +1,293 @@
1
+ ---
2
+ name: api-documentation
3
+ description: >
4
+ API documentation concepts. OpenAPI/Swagger, interactive docs, versioning, examples.
5
+ Trigger: API docs, OpenAPI, Swagger, Redoc, documentation, API reference
6
+ tools:
7
+ - Read
8
+ - Write
9
+ - Edit
10
+ - Grep
11
+ metadata:
12
+ author: apigen-team
13
+ version: "1.0"
14
+ tags: [documentation, openapi, swagger, api]
15
+ scope: ["**/docs/**"]
16
+ ---
17
+
18
+ # API Documentation Concepts
19
+
20
+ ## OpenAPI Specification (OAS)
21
+
22
+ ### Structure
23
+ ```yaml
24
+ openapi: 3.1.0
25
+ info:
26
+ title: My API
27
+ version: 1.0.0
28
+ description: API description with **markdown** support
29
+
30
+ servers:
31
+ - url: https://api.example.com/v1
32
+ description: Production
33
+ - url: https://staging-api.example.com/v1
34
+ description: Staging
35
+
36
+ paths:
37
+ /users:
38
+ get:
39
+ summary: List users
40
+ operationId: listUsers
41
+ tags: [Users]
42
+ parameters:
43
+ - name: page
44
+ in: query
45
+ schema:
46
+ type: integer
47
+ default: 1
48
+ responses:
49
+ '200':
50
+ description: Successful response
51
+ content:
52
+ application/json:
53
+ schema:
54
+ $ref: '#/components/schemas/UserList'
55
+
56
+ components:
57
+ schemas:
58
+ User:
59
+ type: object
60
+ required: [id, email]
61
+ properties:
62
+ id:
63
+ type: string
64
+ format: uuid
65
+ email:
66
+ type: string
67
+ format: email
68
+ ```
69
+
70
+ ### Key Elements
71
+ ```
72
+ Info: API metadata, contact, license
73
+ Servers: Base URLs for environments
74
+ Paths: Endpoints and operations
75
+ Components: Reusable schemas, parameters, responses
76
+ Tags: Logical grouping of operations
77
+ Security: Authentication schemes
78
+ ```
79
+
80
+ ## Documentation Tools
81
+
82
+ ### Swagger UI
83
+ ```
84
+ Features:
85
+ - Interactive API explorer
86
+ - Try it out functionality
87
+ - Authorization support
88
+ - Request/response examples
89
+
90
+ Best for:
91
+ - Developer testing
92
+ - Internal documentation
93
+ - Quick prototyping
94
+ ```
95
+
96
+ ### Redoc
97
+ ```
98
+ Features:
99
+ - Clean, professional look
100
+ - Three-panel layout
101
+ - Search functionality
102
+ - No interactivity (reference only)
103
+
104
+ Best for:
105
+ - Public API documentation
106
+ - Customer-facing docs
107
+ - Embedded in websites
108
+ ```
109
+
110
+ ### Stoplight
111
+ ```
112
+ Features:
113
+ - Design-first approach
114
+ - Mock servers
115
+ - Style guides
116
+ - Git integration
117
+
118
+ Best for:
119
+ - API design
120
+ - Enterprise documentation
121
+ - Team collaboration
122
+ ```
123
+
124
+ ## Documentation Best Practices
125
+
126
+ ### Descriptions
127
+ ```yaml
128
+ # Good: Explains purpose and context
129
+ description: |
130
+ Retrieves a paginated list of users in the organization.
131
+ Results are sorted by creation date, newest first.
132
+
133
+ **Note:** Requires `users:read` permission.
134
+
135
+ # Bad: States the obvious
136
+ description: Gets users
137
+ ```
138
+
139
+ ### Examples
140
+ ```yaml
141
+ # Provide realistic examples
142
+ schema:
143
+ type: object
144
+ properties:
145
+ email:
146
+ type: string
147
+ format: email
148
+ example: john.doe@example.com
149
+ createdAt:
150
+ type: string
151
+ format: date-time
152
+ example: "2024-01-15T10:30:00Z"
153
+
154
+ # Multiple examples for different scenarios
155
+ examples:
156
+ admin:
157
+ summary: Admin user
158
+ value:
159
+ id: "123"
160
+ email: "admin@example.com"
161
+ role: "admin"
162
+ regular:
163
+ summary: Regular user
164
+ value:
165
+ id: "456"
166
+ email: "user@example.com"
167
+ role: "user"
168
+ ```
169
+
170
+ ### Error Responses
171
+ ```yaml
172
+ responses:
173
+ '400':
174
+ description: Validation error
175
+ content:
176
+ application/problem+json:
177
+ schema:
178
+ $ref: '#/components/schemas/ProblemDetail'
179
+ examples:
180
+ invalidEmail:
181
+ summary: Invalid email format
182
+ value:
183
+ type: "https://api.example.com/errors/validation"
184
+ title: "Validation Error"
185
+ status: 400
186
+ detail: "Invalid email format"
187
+ errors:
188
+ - field: "email"
189
+ message: "Must be a valid email address"
190
+ ```
191
+
192
+ ## API Versioning Documentation
193
+
194
+ ### URL Versioning
195
+ ```yaml
196
+ servers:
197
+ - url: https://api.example.com/v1
198
+ - url: https://api.example.com/v2
199
+
200
+ paths:
201
+ /v1/users:
202
+ deprecated: true
203
+ x-deprecation-date: 2024-06-01
204
+ ```
205
+
206
+ ### Header Versioning
207
+ ```yaml
208
+ parameters:
209
+ - name: API-Version
210
+ in: header
211
+ required: false
212
+ schema:
213
+ type: string
214
+ default: "2024-01-01"
215
+ enum:
216
+ - "2024-01-01"
217
+ - "2023-06-01"
218
+ ```
219
+
220
+ ## Authentication Documentation
221
+
222
+ ```yaml
223
+ components:
224
+ securitySchemes:
225
+ bearerAuth:
226
+ type: http
227
+ scheme: bearer
228
+ bearerFormat: JWT
229
+ description: |
230
+ JWT token obtained from `/auth/login`.
231
+ Token expires after 1 hour.
232
+
233
+ apiKey:
234
+ type: apiKey
235
+ in: header
236
+ name: X-API-Key
237
+ description: |
238
+ API key for server-to-server communication.
239
+ Contact support to obtain a key.
240
+
241
+ oauth2:
242
+ type: oauth2
243
+ flows:
244
+ authorizationCode:
245
+ authorizationUrl: https://auth.example.com/authorize
246
+ tokenUrl: https://auth.example.com/token
247
+ scopes:
248
+ users:read: Read user information
249
+ users:write: Create and update users
250
+ ```
251
+
252
+ ## Changelog & Migration
253
+
254
+ ```markdown
255
+ ## API Changelog
256
+
257
+ ### v2.0.0 (2024-01-15)
258
+ #### Breaking Changes
259
+ - `GET /users` now returns paginated response
260
+ - `email` field renamed to `emailAddress`
261
+
262
+ #### New Features
263
+ - Added `GET /users/{id}/preferences`
264
+ - Added filtering by `status` parameter
265
+
266
+ ### v1.5.0 (2023-12-01)
267
+ #### Deprecations
268
+ - `GET /users/all` deprecated, use `GET /users` with pagination
269
+ ```
270
+
271
+ ## Documentation-as-Code
272
+
273
+ ```
274
+ Benefits:
275
+ - Version controlled
276
+ - Review process
277
+ - CI/CD integration
278
+ - Single source of truth
279
+
280
+ Workflow:
281
+ 1. Write OpenAPI spec (YAML/JSON)
282
+ 2. Review changes via PR
283
+ 3. Generate docs on merge
284
+ 4. Deploy to documentation site
285
+ 5. Generate SDKs from spec
286
+ ```
287
+
288
+ ## Related Skills
289
+
290
+ - `docs-spring`: Spring Boot API documentation
291
+ - `apigen-architecture`: Overall system architecture
292
+
293
+
@@ -0,0 +1,377 @@
1
+ ---
2
+ name: docs-spring
3
+ description: >
4
+ Spring Boot API documentation. SpringDoc, Swagger UI, Redoc, custom themes.
5
+ Trigger: apigen-docs, SpringDoc, Swagger, OpenAPI, @Operation, @Schema
6
+ tools:
7
+ - Read
8
+ - Write
9
+ - Edit
10
+ - Bash
11
+ - Grep
12
+ metadata:
13
+ author: apigen-team
14
+ version: "1.0"
15
+ tags: [documentation, spring-boot, springdoc, java]
16
+ scope: ["apigen-docs/**"]
17
+ ---
18
+
19
+ # API Documentation Spring Boot (apigen-docs)
20
+
21
+ ## Configuration
22
+
23
+ ```yaml
24
+ apigen:
25
+ docs:
26
+ enabled: true
27
+
28
+ openapi:
29
+ title: ${spring.application.name}
30
+ version: ${app.version:1.0.0}
31
+ description: API Documentation
32
+ contact:
33
+ name: API Support
34
+ email: support@example.com
35
+ license:
36
+ name: Apache 2.0
37
+ url: https://www.apache.org/licenses/LICENSE-2.0
38
+
39
+ swagger-ui:
40
+ enabled: true
41
+ path: /swagger-ui
42
+ theme: dark # default, dark, feeling-blue
43
+ try-it-out: true
44
+
45
+ redoc:
46
+ enabled: true
47
+ path: /redoc
48
+
49
+ graphql-playground:
50
+ enabled: true
51
+ path: /graphql-playground
52
+
53
+ springdoc:
54
+ api-docs:
55
+ path: /api-docs
56
+ show-actuator: false
57
+ packages-to-scan: com.example.api
58
+ ```
59
+
60
+ ## OpenAPI Configuration
61
+
62
+ ```java
63
+ @Configuration
64
+ @EnableConfigurationProperties(DocsProperties.class)
65
+ public class OpenApiConfiguration {
66
+
67
+ @Bean
68
+ public OpenAPI customOpenAPI(DocsProperties props) {
69
+ return new OpenAPI()
70
+ .info(new Info()
71
+ .title(props.getOpenapi().getTitle())
72
+ .version(props.getOpenapi().getVersion())
73
+ .description(props.getOpenapi().getDescription())
74
+ .contact(new Contact()
75
+ .name(props.getOpenapi().getContact().getName())
76
+ .email(props.getOpenapi().getContact().getEmail()))
77
+ .license(new License()
78
+ .name(props.getOpenapi().getLicense().getName())
79
+ .url(props.getOpenapi().getLicense().getUrl())))
80
+ .externalDocs(new ExternalDocumentation()
81
+ .description("API Guide")
82
+ .url("https://docs.example.com"))
83
+ .components(new Components()
84
+ .addSecuritySchemes("bearerAuth", securityScheme()))
85
+ .security(List.of(new SecurityRequirement().addList("bearerAuth")));
86
+ }
87
+
88
+ private SecurityScheme securityScheme() {
89
+ return new SecurityScheme()
90
+ .type(SecurityScheme.Type.HTTP)
91
+ .scheme("bearer")
92
+ .bearerFormat("JWT")
93
+ .description("JWT token from /auth/login endpoint");
94
+ }
95
+
96
+ @Bean
97
+ public GroupedOpenApi publicApi() {
98
+ return GroupedOpenApi.builder()
99
+ .group("public")
100
+ .pathsToMatch("/api/**")
101
+ .pathsToExclude("/api/admin/**")
102
+ .build();
103
+ }
104
+
105
+ @Bean
106
+ public GroupedOpenApi adminApi() {
107
+ return GroupedOpenApi.builder()
108
+ .group("admin")
109
+ .pathsToMatch("/api/admin/**")
110
+ .build();
111
+ }
112
+ }
113
+ ```
114
+
115
+ ## Controller Annotations
116
+
117
+ ```java
118
+ @RestController
119
+ @RequestMapping("/api/users")
120
+ @Tag(name = "Users", description = "User management operations")
121
+ @SecurityRequirement(name = "bearerAuth")
122
+ public class UserController {
123
+
124
+ @Operation(
125
+ summary = "Get user by ID",
126
+ description = "Retrieves a user by their unique identifier",
127
+ responses = {
128
+ @ApiResponse(
129
+ responseCode = "200",
130
+ description = "User found",
131
+ content = @Content(schema = @Schema(implementation = UserDTO.class))),
132
+ @ApiResponse(
133
+ responseCode = "404",
134
+ description = "User not found",
135
+ content = @Content(schema = @Schema(implementation = ProblemDetail.class)))
136
+ }
137
+ )
138
+ @GetMapping("/{id}")
139
+ public UserDTO getUser(
140
+ @Parameter(description = "User ID", example = "123e4567-e89b-12d3-a456-426614174000")
141
+ @PathVariable UUID id) {
142
+ return userService.findById(id);
143
+ }
144
+
145
+ @Operation(
146
+ summary = "Create user",
147
+ description = "Creates a new user account"
148
+ )
149
+ @ApiResponse(responseCode = "201", description = "User created")
150
+ @ApiResponse(responseCode = "400", description = "Invalid input")
151
+ @ApiResponse(responseCode = "409", description = "Email already exists")
152
+ @PostMapping
153
+ @ResponseStatus(HttpStatus.CREATED)
154
+ public UserDTO createUser(
155
+ @RequestBody @Valid
156
+ @io.swagger.v3.oas.annotations.parameters.RequestBody(
157
+ description = "User to create",
158
+ required = true,
159
+ content = @Content(
160
+ examples = @ExampleObject(
161
+ name = "Example user",
162
+ value = """
163
+ {
164
+ "email": "john@example.com",
165
+ "name": "John Doe",
166
+ "password": "SecurePass123!"
167
+ }
168
+ """
169
+ )
170
+ )
171
+ )
172
+ CreateUserRequest request) {
173
+ return userService.create(request);
174
+ }
175
+
176
+ @Operation(
177
+ summary = "List users",
178
+ description = "Returns a paginated list of users"
179
+ )
180
+ @GetMapping
181
+ public Page<UserDTO> listUsers(
182
+ @Parameter(description = "Page number (0-indexed)")
183
+ @RequestParam(defaultValue = "0") int page,
184
+
185
+ @Parameter(description = "Page size")
186
+ @RequestParam(defaultValue = "20") int size,
187
+
188
+ @Parameter(description = "Filter by status")
189
+ @RequestParam(required = false) UserStatus status) {
190
+ return userService.findAll(PageRequest.of(page, size), status);
191
+ }
192
+ }
193
+ ```
194
+
195
+ ## Schema Annotations
196
+
197
+ ```java
198
+ @Schema(description = "User data transfer object")
199
+ public record UserDTO(
200
+ @Schema(description = "Unique user identifier",
201
+ example = "123e4567-e89b-12d3-a456-426614174000",
202
+ accessMode = Schema.AccessMode.READ_ONLY)
203
+ UUID id,
204
+
205
+ @Schema(description = "User email address",
206
+ example = "john@example.com",
207
+ requiredMode = Schema.RequiredMode.REQUIRED)
208
+ String email,
209
+
210
+ @Schema(description = "User display name",
211
+ example = "John Doe",
212
+ maxLength = 100)
213
+ String name,
214
+
215
+ @Schema(description = "User account status",
216
+ defaultValue = "ACTIVE")
217
+ UserStatus status,
218
+
219
+ @Schema(description = "Account creation timestamp",
220
+ accessMode = Schema.AccessMode.READ_ONLY)
221
+ Instant createdAt
222
+ ) {}
223
+
224
+ @Schema(description = "Request to create a new user")
225
+ public record CreateUserRequest(
226
+ @Schema(description = "Email address", example = "john@example.com")
227
+ @Email @NotBlank
228
+ String email,
229
+
230
+ @Schema(description = "Display name", example = "John Doe")
231
+ @NotBlank @Size(max = 100)
232
+ String name,
233
+
234
+ @Schema(description = "Password (min 8 chars, must contain uppercase, lowercase, digit)",
235
+ example = "SecurePass123!",
236
+ minLength = 8)
237
+ @NotBlank @Size(min = 8)
238
+ String password
239
+ ) {}
240
+ ```
241
+
242
+ ## Custom Swagger UI Theme
243
+
244
+ ```java
245
+ @Bean
246
+ public SwaggerUiConfigProperties swaggerUiConfig() {
247
+ SwaggerUiConfigProperties props = new SwaggerUiConfigProperties();
248
+ props.setPath("/swagger-ui");
249
+ props.setTryItOutEnabled(true);
250
+ props.setFilter(true);
251
+ props.setShowExtensions(true);
252
+ props.setPersistAuthorization(true);
253
+ return props;
254
+ }
255
+
256
+ // Custom CSS for dark theme
257
+ @Bean
258
+ public WebMvcConfigurer swaggerUiCustomizer() {
259
+ return new WebMvcConfigurer() {
260
+ @Override
261
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
262
+ registry.addResourceHandler("/swagger-ui/custom.css")
263
+ .addResourceLocations("classpath:/static/swagger/");
264
+ }
265
+ };
266
+ }
267
+ ```
268
+
269
+ ## Redoc Configuration
270
+
271
+ ```java
272
+ @Controller
273
+ @ConditionalOnProperty(prefix = "apigen.docs.redoc", name = "enabled", havingValue = "true")
274
+ public class RedocController {
275
+
276
+ @GetMapping("/redoc")
277
+ public String redoc(Model model) {
278
+ model.addAttribute("specUrl", "/api-docs");
279
+ model.addAttribute("options", Map.of(
280
+ "hideDownloadButton", false,
281
+ "hideHostname", false,
282
+ "expandResponses", "200,201",
283
+ "theme", Map.of(
284
+ "colors", Map.of(
285
+ "primary", Map.of("main", "#1976d2")
286
+ )
287
+ )
288
+ ));
289
+ return "redoc";
290
+ }
291
+ }
292
+ ```
293
+
294
+ ```html
295
+ <!-- templates/redoc.html -->
296
+ <!DOCTYPE html>
297
+ <html>
298
+ <head>
299
+ <title>API Documentation</title>
300
+ <link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700" rel="stylesheet">
301
+ <style>body { margin: 0; padding: 0; }</style>
302
+ </head>
303
+ <body>
304
+ <redoc spec-url="/api-docs" th:attr="spec-url=${specUrl}"></redoc>
305
+ <script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"></script>
306
+ </body>
307
+ </html>
308
+ ```
309
+
310
+ ## OpenAPI Customizer
311
+
312
+ ```java
313
+ @Component
314
+ public class ApiDocsCustomizer implements OpenApiCustomizer {
315
+
316
+ @Override
317
+ public void customise(OpenAPI openApi) {
318
+ // Add common headers
319
+ openApi.getPaths().values().forEach(pathItem ->
320
+ pathItem.readOperations().forEach(operation -> {
321
+ if (operation.getParameters() == null) {
322
+ operation.setParameters(new ArrayList<>());
323
+ }
324
+ operation.getParameters().add(new Parameter()
325
+ .name("X-Request-ID")
326
+ .in("header")
327
+ .description("Request correlation ID")
328
+ .schema(new StringSchema().format("uuid")));
329
+ })
330
+ );
331
+
332
+ // Add server list
333
+ openApi.setServers(List.of(
334
+ new Server().url("https://api.example.com").description("Production"),
335
+ new Server().url("https://staging.api.example.com").description("Staging"),
336
+ new Server().url("http://localhost:8080").description("Local")
337
+ ));
338
+ }
339
+ }
340
+ ```
341
+
342
+ ## REST Controller for Docs
343
+
344
+ ```java
345
+ @RestController
346
+ @RequestMapping("/api/docs")
347
+ public class DocsController {
348
+
349
+ private final ResourceLoader resourceLoader;
350
+
351
+ @GetMapping("/openapi.yaml")
352
+ public ResponseEntity<Resource> getOpenApiYaml() {
353
+ Resource resource = resourceLoader.getResource("classpath:openapi/api.yaml");
354
+ return ResponseEntity.ok()
355
+ .contentType(MediaType.parseMediaType("application/x-yaml"))
356
+ .body(resource);
357
+ }
358
+
359
+ @GetMapping("/changelog")
360
+ public ResponseEntity<String> getChangelog() throws IOException {
361
+ Resource resource = resourceLoader.getResource("classpath:docs/CHANGELOG.md");
362
+ String content = StreamUtils.copyToString(
363
+ resource.getInputStream(), StandardCharsets.UTF_8);
364
+ return ResponseEntity.ok()
365
+ .contentType(MediaType.TEXT_MARKDOWN)
366
+ .body(content);
367
+ }
368
+ }
369
+ ```
370
+
371
+ ## Related Skills
372
+
373
+ - `api-documentation`: API documentation concepts
374
+ - `spring-boot-4`: Spring Boot 4.0 patterns
375
+ - `apigen-architecture`: Overall system architecture
376
+
377
+