javi-forge 1.2.0 → 1.3.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 (228) hide show
  1. package/ci-local/ci-local.sh +20 -8
  2. package/package.json +1 -1
  3. package/ai-config/.skillignore +0 -15
  4. package/ai-config/AUTO_INVOKE.md +0 -300
  5. package/ai-config/agents/_TEMPLATE.md +0 -93
  6. package/ai-config/agents/business/api-designer.md +0 -1657
  7. package/ai-config/agents/business/business-analyst.md +0 -1331
  8. package/ai-config/agents/business/product-strategist.md +0 -206
  9. package/ai-config/agents/business/project-manager.md +0 -178
  10. package/ai-config/agents/business/requirements-analyst.md +0 -1277
  11. package/ai-config/agents/business/technical-writer.md +0 -1679
  12. package/ai-config/agents/creative/ux-designer.md +0 -205
  13. package/ai-config/agents/data-ai/ai-engineer.md +0 -487
  14. package/ai-config/agents/data-ai/analytics-engineer.md +0 -953
  15. package/ai-config/agents/data-ai/data-engineer.md +0 -173
  16. package/ai-config/agents/data-ai/data-scientist.md +0 -672
  17. package/ai-config/agents/data-ai/mlops-engineer.md +0 -814
  18. package/ai-config/agents/data-ai/prompt-engineer.md +0 -772
  19. package/ai-config/agents/development/angular-expert.md +0 -620
  20. package/ai-config/agents/development/backend-architect.md +0 -795
  21. package/ai-config/agents/development/database-specialist.md +0 -212
  22. package/ai-config/agents/development/frontend-specialist.md +0 -686
  23. package/ai-config/agents/development/fullstack-engineer.md +0 -668
  24. package/ai-config/agents/development/golang-pro.md +0 -338
  25. package/ai-config/agents/development/java-enterprise.md +0 -400
  26. package/ai-config/agents/development/javascript-pro.md +0 -422
  27. package/ai-config/agents/development/nextjs-pro.md +0 -474
  28. package/ai-config/agents/development/python-pro.md +0 -570
  29. package/ai-config/agents/development/react-pro.md +0 -487
  30. package/ai-config/agents/development/rust-pro.md +0 -246
  31. package/ai-config/agents/development/spring-boot-4-expert.md +0 -326
  32. package/ai-config/agents/development/typescript-pro.md +0 -336
  33. package/ai-config/agents/development/vue-specialist.md +0 -605
  34. package/ai-config/agents/infrastructure/cloud-architect.md +0 -472
  35. package/ai-config/agents/infrastructure/deployment-manager.md +0 -358
  36. package/ai-config/agents/infrastructure/devops-engineer.md +0 -455
  37. package/ai-config/agents/infrastructure/incident-responder.md +0 -519
  38. package/ai-config/agents/infrastructure/kubernetes-expert.md +0 -705
  39. package/ai-config/agents/infrastructure/monitoring-specialist.md +0 -674
  40. package/ai-config/agents/infrastructure/performance-engineer.md +0 -658
  41. package/ai-config/agents/orchestrator.md +0 -241
  42. package/ai-config/agents/quality/accessibility-auditor.md +0 -1204
  43. package/ai-config/agents/quality/code-reviewer-compact.md +0 -123
  44. package/ai-config/agents/quality/code-reviewer.md +0 -363
  45. package/ai-config/agents/quality/dependency-manager.md +0 -743
  46. package/ai-config/agents/quality/e2e-test-specialist.md +0 -1005
  47. package/ai-config/agents/quality/performance-tester.md +0 -1086
  48. package/ai-config/agents/quality/security-auditor.md +0 -133
  49. package/ai-config/agents/quality/test-engineer.md +0 -453
  50. package/ai-config/agents/specialists/api-designer.md +0 -87
  51. package/ai-config/agents/specialists/backend-architect.md +0 -73
  52. package/ai-config/agents/specialists/code-reviewer.md +0 -77
  53. package/ai-config/agents/specialists/db-optimizer.md +0 -75
  54. package/ai-config/agents/specialists/devops-engineer.md +0 -83
  55. package/ai-config/agents/specialists/documentation-writer.md +0 -78
  56. package/ai-config/agents/specialists/frontend-developer.md +0 -75
  57. package/ai-config/agents/specialists/performance-analyst.md +0 -82
  58. package/ai-config/agents/specialists/refactor-specialist.md +0 -74
  59. package/ai-config/agents/specialists/security-auditor.md +0 -74
  60. package/ai-config/agents/specialists/test-engineer.md +0 -81
  61. package/ai-config/agents/specialists/ux-consultant.md +0 -76
  62. package/ai-config/agents/specialized/agent-generator.md +0 -1190
  63. package/ai-config/agents/specialized/blockchain-developer.md +0 -149
  64. package/ai-config/agents/specialized/code-migrator.md +0 -892
  65. package/ai-config/agents/specialized/context-manager.md +0 -978
  66. package/ai-config/agents/specialized/documentation-writer.md +0 -1078
  67. package/ai-config/agents/specialized/ecommerce-expert.md +0 -1756
  68. package/ai-config/agents/specialized/embedded-engineer.md +0 -1714
  69. package/ai-config/agents/specialized/error-detective.md +0 -1034
  70. package/ai-config/agents/specialized/fintech-specialist.md +0 -1659
  71. package/ai-config/agents/specialized/freelance-project-planner-v2.md +0 -1988
  72. package/ai-config/agents/specialized/freelance-project-planner-v3.md +0 -2136
  73. package/ai-config/agents/specialized/freelance-project-planner-v4.md +0 -4503
  74. package/ai-config/agents/specialized/freelance-project-planner.md +0 -722
  75. package/ai-config/agents/specialized/game-developer.md +0 -1963
  76. package/ai-config/agents/specialized/healthcare-dev.md +0 -1620
  77. package/ai-config/agents/specialized/mobile-developer.md +0 -188
  78. package/ai-config/agents/specialized/parallel-plan-executor.md +0 -506
  79. package/ai-config/agents/specialized/plan-executor.md +0 -485
  80. package/ai-config/agents/specialized/solo-dev-planner-modular/00-INDEX.md +0 -485
  81. package/ai-config/agents/specialized/solo-dev-planner-modular/01-CORE.md +0 -3493
  82. package/ai-config/agents/specialized/solo-dev-planner-modular/02-SELF-CORRECTION.md +0 -778
  83. package/ai-config/agents/specialized/solo-dev-planner-modular/03-PROGRESSIVE-SETUP.md +0 -918
  84. package/ai-config/agents/specialized/solo-dev-planner-modular/04-DEPLOYMENT.md +0 -1537
  85. package/ai-config/agents/specialized/solo-dev-planner-modular/05-TESTING.md +0 -2633
  86. package/ai-config/agents/specialized/solo-dev-planner-modular/06-OPERATIONS.md +0 -5610
  87. package/ai-config/agents/specialized/solo-dev-planner-modular/INSTALL.md +0 -335
  88. package/ai-config/agents/specialized/solo-dev-planner-modular/QUICK-REFERENCE.txt +0 -215
  89. package/ai-config/agents/specialized/solo-dev-planner-modular/README.md +0 -260
  90. package/ai-config/agents/specialized/solo-dev-planner-modular/START-HERE.md +0 -379
  91. package/ai-config/agents/specialized/solo-dev-planner-modular/WORKFLOW-DIAGRAM.md +0 -355
  92. package/ai-config/agents/specialized/solo-dev-planner-modular/solo-dev-planner.md +0 -279
  93. package/ai-config/agents/specialized/template-writer.md +0 -347
  94. package/ai-config/agents/specialized/test-runner.md +0 -99
  95. package/ai-config/agents/specialized/vibekanban-smart-worker.md +0 -244
  96. package/ai-config/agents/specialized/wave-executor.md +0 -138
  97. package/ai-config/agents/specialized/workflow-optimizer.md +0 -1114
  98. package/ai-config/commands/git/changelog.md +0 -32
  99. package/ai-config/commands/git/ci-local.md +0 -70
  100. package/ai-config/commands/git/commit.md +0 -35
  101. package/ai-config/commands/git/fix-issue.md +0 -23
  102. package/ai-config/commands/git/pr-create.md +0 -42
  103. package/ai-config/commands/git/pr-review.md +0 -50
  104. package/ai-config/commands/git/worktree.md +0 -39
  105. package/ai-config/commands/refactoring/cleanup.md +0 -24
  106. package/ai-config/commands/refactoring/dead-code.md +0 -40
  107. package/ai-config/commands/refactoring/extract.md +0 -31
  108. package/ai-config/commands/testing/e2e.md +0 -30
  109. package/ai-config/commands/testing/tdd.md +0 -36
  110. package/ai-config/commands/testing/test-coverage.md +0 -30
  111. package/ai-config/commands/testing/test-fix.md +0 -24
  112. package/ai-config/commands/workflow/generate-agents-md.md +0 -85
  113. package/ai-config/commands/workflow/planning.md +0 -47
  114. package/ai-config/commands/workflows/compound.md +0 -89
  115. package/ai-config/commands/workflows/diagnose.md +0 -70
  116. package/ai-config/commands/workflows/discover.md +0 -86
  117. package/ai-config/commands/workflows/plan.md +0 -77
  118. package/ai-config/commands/workflows/review.md +0 -78
  119. package/ai-config/commands/workflows/work.md +0 -75
  120. package/ai-config/config.yaml +0 -18
  121. package/ai-config/hooks/_TEMPLATE.md +0 -96
  122. package/ai-config/hooks/block-dangerous-commands.md +0 -75
  123. package/ai-config/hooks/commit-guard.md +0 -90
  124. package/ai-config/hooks/context-loader.md +0 -73
  125. package/ai-config/hooks/improve-prompt.md +0 -91
  126. package/ai-config/hooks/learning-log.md +0 -72
  127. package/ai-config/hooks/model-router.md +0 -86
  128. package/ai-config/hooks/secret-scanner.md +0 -64
  129. package/ai-config/hooks/skill-validator.md +0 -102
  130. package/ai-config/hooks/task-artifact.md +0 -114
  131. package/ai-config/hooks/validate-workflow.md +0 -100
  132. package/ai-config/prompts/base.md +0 -71
  133. package/ai-config/prompts/modes/debug.md +0 -34
  134. package/ai-config/prompts/modes/deploy.md +0 -40
  135. package/ai-config/prompts/modes/research.md +0 -32
  136. package/ai-config/prompts/modes/review.md +0 -33
  137. package/ai-config/prompts/review-policy.md +0 -79
  138. package/ai-config/skills/_TEMPLATE.md +0 -157
  139. package/ai-config/skills/backend/api-gateway/SKILL.md +0 -254
  140. package/ai-config/skills/backend/bff-concepts/SKILL.md +0 -239
  141. package/ai-config/skills/backend/bff-spring/SKILL.md +0 -364
  142. package/ai-config/skills/backend/chi-router/SKILL.md +0 -396
  143. package/ai-config/skills/backend/error-handling/SKILL.md +0 -255
  144. package/ai-config/skills/backend/exceptions-spring/SKILL.md +0 -323
  145. package/ai-config/skills/backend/fastapi/SKILL.md +0 -302
  146. package/ai-config/skills/backend/gateway-spring/SKILL.md +0 -390
  147. package/ai-config/skills/backend/go-backend/SKILL.md +0 -457
  148. package/ai-config/skills/backend/gradle-multimodule/SKILL.md +0 -274
  149. package/ai-config/skills/backend/graphql-concepts/SKILL.md +0 -352
  150. package/ai-config/skills/backend/graphql-spring/SKILL.md +0 -398
  151. package/ai-config/skills/backend/grpc-concepts/SKILL.md +0 -283
  152. package/ai-config/skills/backend/grpc-spring/SKILL.md +0 -445
  153. package/ai-config/skills/backend/jwt-auth/SKILL.md +0 -412
  154. package/ai-config/skills/backend/notifications-concepts/SKILL.md +0 -259
  155. package/ai-config/skills/backend/recommendations-concepts/SKILL.md +0 -261
  156. package/ai-config/skills/backend/search-concepts/SKILL.md +0 -263
  157. package/ai-config/skills/backend/search-spring/SKILL.md +0 -375
  158. package/ai-config/skills/backend/spring-boot-4/SKILL.md +0 -172
  159. package/ai-config/skills/backend/websockets/SKILL.md +0 -532
  160. package/ai-config/skills/data-ai/ai-ml/SKILL.md +0 -423
  161. package/ai-config/skills/data-ai/analytics-concepts/SKILL.md +0 -195
  162. package/ai-config/skills/data-ai/analytics-spring/SKILL.md +0 -340
  163. package/ai-config/skills/data-ai/duckdb-analytics/SKILL.md +0 -440
  164. package/ai-config/skills/data-ai/langchain/SKILL.md +0 -238
  165. package/ai-config/skills/data-ai/mlflow/SKILL.md +0 -302
  166. package/ai-config/skills/data-ai/onnx-inference/SKILL.md +0 -290
  167. package/ai-config/skills/data-ai/powerbi/SKILL.md +0 -352
  168. package/ai-config/skills/data-ai/pytorch/SKILL.md +0 -274
  169. package/ai-config/skills/data-ai/scikit-learn/SKILL.md +0 -321
  170. package/ai-config/skills/data-ai/vector-db/SKILL.md +0 -301
  171. package/ai-config/skills/database/graph-databases/SKILL.md +0 -218
  172. package/ai-config/skills/database/graph-spring/SKILL.md +0 -361
  173. package/ai-config/skills/database/pgx-postgres/SKILL.md +0 -512
  174. package/ai-config/skills/database/redis-cache/SKILL.md +0 -343
  175. package/ai-config/skills/database/sqlite-embedded/SKILL.md +0 -388
  176. package/ai-config/skills/database/timescaledb/SKILL.md +0 -320
  177. package/ai-config/skills/docs/api-documentation/SKILL.md +0 -293
  178. package/ai-config/skills/docs/docs-spring/SKILL.md +0 -377
  179. package/ai-config/skills/docs/mustache-templates/SKILL.md +0 -190
  180. package/ai-config/skills/docs/technical-docs/SKILL.md +0 -447
  181. package/ai-config/skills/frontend/astro-ssr/SKILL.md +0 -441
  182. package/ai-config/skills/frontend/frontend-design/SKILL.md +0 -54
  183. package/ai-config/skills/frontend/frontend-web/SKILL.md +0 -368
  184. package/ai-config/skills/frontend/mantine-ui/SKILL.md +0 -396
  185. package/ai-config/skills/frontend/tanstack-query/SKILL.md +0 -439
  186. package/ai-config/skills/frontend/zod-validation/SKILL.md +0 -417
  187. package/ai-config/skills/frontend/zustand-state/SKILL.md +0 -350
  188. package/ai-config/skills/infrastructure/chaos-engineering/SKILL.md +0 -244
  189. package/ai-config/skills/infrastructure/chaos-spring/SKILL.md +0 -378
  190. package/ai-config/skills/infrastructure/devops-infra/SKILL.md +0 -435
  191. package/ai-config/skills/infrastructure/docker-containers/SKILL.md +0 -420
  192. package/ai-config/skills/infrastructure/kubernetes/SKILL.md +0 -456
  193. package/ai-config/skills/infrastructure/opentelemetry/SKILL.md +0 -546
  194. package/ai-config/skills/infrastructure/traefik-proxy/SKILL.md +0 -474
  195. package/ai-config/skills/infrastructure/woodpecker-ci/SKILL.md +0 -315
  196. package/ai-config/skills/mobile/ionic-capacitor/SKILL.md +0 -504
  197. package/ai-config/skills/mobile/mobile-ionic/SKILL.md +0 -448
  198. package/ai-config/skills/prompt-improver/SKILL.md +0 -125
  199. package/ai-config/skills/quality/ghagga-review/SKILL.md +0 -216
  200. package/ai-config/skills/references/hooks-patterns/SKILL.md +0 -238
  201. package/ai-config/skills/references/mcp-servers/SKILL.md +0 -275
  202. package/ai-config/skills/references/plugins-reference/SKILL.md +0 -110
  203. package/ai-config/skills/references/skills-reference/SKILL.md +0 -420
  204. package/ai-config/skills/references/subagent-templates/SKILL.md +0 -193
  205. package/ai-config/skills/systems-iot/modbus-protocol/SKILL.md +0 -410
  206. package/ai-config/skills/systems-iot/mqtt-rumqttc/SKILL.md +0 -408
  207. package/ai-config/skills/systems-iot/rust-systems/SKILL.md +0 -386
  208. package/ai-config/skills/systems-iot/tokio-async/SKILL.md +0 -324
  209. package/ai-config/skills/testing/playwright-e2e/SKILL.md +0 -289
  210. package/ai-config/skills/testing/testcontainers/SKILL.md +0 -299
  211. package/ai-config/skills/testing/vitest-testing/SKILL.md +0 -381
  212. package/ai-config/skills/workflow/ci-local-guide/SKILL.md +0 -118
  213. package/ai-config/skills/workflow/claude-automation-recommender/SKILL.md +0 -299
  214. package/ai-config/skills/workflow/claude-md-improver/SKILL.md +0 -158
  215. package/ai-config/skills/workflow/finishing-a-development-branch/SKILL.md +0 -117
  216. package/ai-config/skills/workflow/git-github/SKILL.md +0 -334
  217. package/ai-config/skills/workflow/git-github/references/examples.md +0 -160
  218. package/ai-config/skills/workflow/git-workflow/SKILL.md +0 -214
  219. package/ai-config/skills/workflow/ide-plugins/SKILL.md +0 -277
  220. package/ai-config/skills/workflow/ide-plugins-intellij/SKILL.md +0 -401
  221. package/ai-config/skills/workflow/obsidian-brain-workflow/SKILL.md +0 -199
  222. package/ai-config/skills/workflow/using-git-worktrees/SKILL.md +0 -100
  223. package/ai-config/skills/workflow/verification-before-completion/SKILL.md +0 -73
  224. package/ai-config/skills/workflow/wave-workflow/SKILL.md +0 -178
  225. package/schemas/agent.schema.json +0 -34
  226. package/schemas/ai-config.schema.json +0 -28
  227. package/schemas/plugin.schema.json +0 -62
  228. package/schemas/skill.schema.json +0 -44
@@ -1,364 +0,0 @@
1
- ---
2
- name: bff-spring
3
- description: >
4
- Spring Boot BFF implementation. Client detection, response tailoring, service composition.
5
- Trigger: apigen-bff, BaseBffController, ClientType, TailorForClient, aggregation
6
- tools:
7
- - Read
8
- - Write
9
- - Edit
10
- - Bash
11
- - Grep
12
- metadata:
13
- author: apigen-team
14
- version: "1.0"
15
- tags: [bff, spring-boot, aggregation, java]
16
- scope: ["apigen-bff/**"]
17
- ---
18
-
19
- # BFF Spring Boot (apigen-bff)
20
-
21
- ## Configuration
22
-
23
- ```yaml
24
- apigen:
25
- bff:
26
- enabled: true
27
-
28
- client-detection:
29
- header: X-Client-Type
30
- fallback: WEB
31
-
32
- rate-limits:
33
- web:
34
- requests-per-minute: 1000
35
- mobile:
36
- requests-per-minute: 500
37
- iot:
38
- requests-per-minute: 100
39
-
40
- response-tailoring:
41
- enabled: true
42
- compress-mobile: true
43
-
44
- composition:
45
- timeout: 5s
46
- parallel-enabled: true
47
- ```
48
-
49
- ## Client Type Detection
50
-
51
- ```java
52
- public enum ClientType {
53
- WEB("web"),
54
- MOBILE_IOS("ios"),
55
- MOBILE_ANDROID("android"),
56
- TABLET("tablet"),
57
- TV("tv"),
58
- IOT("iot"),
59
- PARTNER("partner");
60
-
61
- public boolean isMobile() {
62
- return this == MOBILE_IOS || this == MOBILE_ANDROID;
63
- }
64
-
65
- public boolean requiresCompression() {
66
- return isMobile() || this == IOT;
67
- }
68
- }
69
- ```
70
-
71
- ## Annotations
72
-
73
- ```java
74
- @Target(ElementType.METHOD)
75
- @Retention(RetentionPolicy.RUNTIME)
76
- public @interface BffEndpoint {
77
- ClientType[] clients() default {};
78
- String[] include() default {};
79
- boolean aggregate() default false;
80
- }
81
-
82
- @Target(ElementType.METHOD)
83
- @Retention(RetentionPolicy.RUNTIME)
84
- public @interface TailorForClient {
85
- ClientType value();
86
- String[] fields() default {};
87
- boolean compress() default false;
88
- }
89
- ```
90
-
91
- ## Base BFF Controller
92
-
93
- ```java
94
- @RestController
95
- @RequestMapping("/bff")
96
- public abstract class BaseBffController {
97
-
98
- protected final QueryCompositionService compositionService;
99
- protected final ResponseTailoringService tailoringService;
100
- protected final CombinedRateLimitService rateLimitService;
101
-
102
- protected ClientType detectClient(HttpServletRequest request) {
103
- String clientHeader = request.getHeader("X-Client-Type");
104
- if (clientHeader != null) {
105
- return ClientType.fromValue(clientHeader);
106
- }
107
-
108
- String userAgent = request.getHeader("User-Agent");
109
- return ClientTypeDetector.fromUserAgent(userAgent);
110
- }
111
-
112
- protected <T> T tailorResponse(T response, ClientType clientType) {
113
- return tailoringService.tailor(response, clientType);
114
- }
115
- }
116
- ```
117
-
118
- ## Query Composition Service
119
-
120
- ```java
121
- @Service
122
- public class QueryCompositionServiceImpl implements QueryCompositionService {
123
-
124
- private final List<ServiceRequest> serviceRequests;
125
- private final ExecutorService executor;
126
-
127
- @Override
128
- public AggregatedResponse compose(List<String> includes,
129
- Map<String, Object> params) {
130
-
131
- List<CompletableFuture<ServiceResult>> futures = includes.stream()
132
- .map(include -> findServiceRequest(include))
133
- .map(sr -> CompletableFuture.supplyAsync(
134
- () -> executeService(sr, params), executor)
135
- .exceptionally(this::handleFailure))
136
- .toList();
137
-
138
- CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
139
- .orTimeout(5, TimeUnit.SECONDS)
140
- .join();
141
-
142
- return aggregateResults(futures);
143
- }
144
-
145
- private ServiceResult handleFailure(Throwable ex) {
146
- log.warn("Service call failed: {}", ex.getMessage());
147
- return ServiceResult.failure(ex.getMessage());
148
- }
149
- }
150
- ```
151
-
152
- ## Response Tailoring Service
153
-
154
- ```java
155
- @Service
156
- public class ResponseTailoringServiceImpl implements ResponseTailoringService {
157
-
158
- private final ObjectMapper objectMapper;
159
- private final Map<ClientType, Set<String>> fieldMappings;
160
-
161
- @Override
162
- @SuppressWarnings("unchecked")
163
- public <T> T tailor(T response, ClientType clientType) {
164
- if (response == null) return null;
165
-
166
- Set<String> allowedFields = fieldMappings.get(clientType);
167
- if (allowedFields == null || allowedFields.isEmpty()) {
168
- return response;
169
- }
170
-
171
- // Convert to map, filter fields, convert back
172
- Map<String, Object> map = objectMapper.convertValue(response, Map.class);
173
- Map<String, Object> filtered = filterFields(map, allowedFields);
174
-
175
- return (T) objectMapper.convertValue(filtered, response.getClass());
176
- }
177
-
178
- private Map<String, Object> filterFields(Map<String, Object> source,
179
- Set<String> allowed) {
180
- return source.entrySet().stream()
181
- .filter(e -> allowed.contains(e.getKey()))
182
- .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
183
- }
184
- }
185
- ```
186
-
187
- ## Aggregated Response Model
188
-
189
- ```java
190
- public record AggregatedResponse(
191
- Map<String, Object> data,
192
- Map<String, ErrorInfo> errors,
193
- ResponseMetadata metadata
194
- ) {
195
- public boolean hasErrors() {
196
- return errors != null && !errors.isEmpty();
197
- }
198
-
199
- public static Builder builder() {
200
- return new Builder();
201
- }
202
-
203
- public static class Builder {
204
- private final Map<String, Object> data = new HashMap<>();
205
- private final Map<String, ErrorInfo> errors = new HashMap<>();
206
-
207
- public Builder addData(String key, Object value) {
208
- data.put(key, value);
209
- return this;
210
- }
211
-
212
- public Builder addError(String key, String message) {
213
- errors.put(key, new ErrorInfo(message, null));
214
- return this;
215
- }
216
-
217
- public AggregatedResponse build() {
218
- return new AggregatedResponse(data, errors,
219
- new ResponseMetadata(Instant.now()));
220
- }
221
- }
222
- }
223
- ```
224
-
225
- ## BFF Endpoint Aspect
226
-
227
- ```java
228
- @Aspect
229
- @Component
230
- public class BffEndpointAspect {
231
-
232
- private final CombinedRateLimitService rateLimitService;
233
-
234
- @Around("@annotation(bffEndpoint)")
235
- public Object handleBffEndpoint(ProceedingJoinPoint joinPoint,
236
- BffEndpoint bffEndpoint) throws Throwable {
237
-
238
- HttpServletRequest request = getCurrentRequest();
239
- ClientType clientType = detectClient(request);
240
-
241
- // Check client type restriction
242
- if (bffEndpoint.clients().length > 0 &&
243
- !Arrays.asList(bffEndpoint.clients()).contains(clientType)) {
244
- throw new ClientTypeNotAllowedException(clientType);
245
- }
246
-
247
- // Apply rate limiting
248
- rateLimitService.checkLimit(clientType, request);
249
-
250
- return joinPoint.proceed();
251
- }
252
- }
253
- ```
254
-
255
- ## Example BFF Controller
256
-
257
- ```java
258
- @RestController
259
- @RequestMapping("/bff/v1")
260
- public class DashboardBffController extends BaseBffController {
261
-
262
- private final UserService userService;
263
- private final OrderService orderService;
264
- private final NotificationService notificationService;
265
-
266
- @GetMapping("/dashboard")
267
- @BffEndpoint(aggregate = true)
268
- public AggregatedResponse getDashboard(
269
- @RequestParam(defaultValue = "profile,notifications") String include,
270
- HttpServletRequest request) {
271
-
272
- ClientType client = detectClient(request);
273
- List<String> includes = Arrays.asList(include.split(","));
274
-
275
- AggregatedResponse.Builder builder = AggregatedResponse.builder();
276
-
277
- if (includes.contains("profile")) {
278
- UserDTO profile = userService.getCurrentUser();
279
- builder.addData("profile", tailorResponse(profile, client));
280
- }
281
-
282
- if (includes.contains("notifications")) {
283
- int limit = client.isMobile() ? 5 : 20;
284
- List<NotificationDTO> notifications =
285
- notificationService.getRecent(limit);
286
- builder.addData("notifications", notifications);
287
- }
288
-
289
- if (includes.contains("orders")) {
290
- List<OrderDTO> orders = orderService.getRecentOrders();
291
- builder.addData("orders", tailorResponse(orders, client));
292
- }
293
-
294
- return builder.build();
295
- }
296
-
297
- @GetMapping("/dashboard")
298
- @TailorForClient(value = ClientType.MOBILE_IOS,
299
- fields = {"id", "name", "avatarThumb"})
300
- public MobileDashboardResponse getMobileDashboard() {
301
- // iOS-specific optimized response
302
- }
303
- }
304
- ```
305
-
306
- ## Rate Limiting Service
307
-
308
- ```java
309
- @Service
310
- public class CombinedRateLimitServiceImpl implements CombinedRateLimitService {
311
-
312
- private final Map<ClientType, Bucket> buckets = new ConcurrentHashMap<>();
313
- private final BffProperties properties;
314
-
315
- @Override
316
- public void checkLimit(ClientType clientType, HttpServletRequest request) {
317
- Bucket bucket = buckets.computeIfAbsent(clientType, this::createBucket);
318
-
319
- if (!bucket.tryConsume(1)) {
320
- throw new RateLimitExceededException(
321
- "Rate limit exceeded for client type: " + clientType);
322
- }
323
- }
324
-
325
- private Bucket createBucket(ClientType clientType) {
326
- int rpm = properties.getRateLimits()
327
- .getOrDefault(clientType, 100);
328
-
329
- return Bucket.builder()
330
- .addLimit(Bandwidth.simple(rpm, Duration.ofMinutes(1)))
331
- .build();
332
- }
333
- }
334
- ```
335
-
336
- ## Testing
337
-
338
- ```java
339
- @WebMvcTest(DashboardBffController.class)
340
- class DashboardBffControllerTest {
341
-
342
- @Autowired
343
- private MockMvc mockMvc;
344
-
345
- @MockBean
346
- private UserService userService;
347
-
348
- @Test
349
- void shouldTailorResponseForMobile() throws Exception {
350
- when(userService.getCurrentUser()).thenReturn(fullUserDto());
351
-
352
- mockMvc.perform(get("/bff/v1/dashboard")
353
- .header("X-Client-Type", "ios"))
354
- .andExpect(status().isOk())
355
- .andExpect(jsonPath("$.data.profile.email").doesNotExist())
356
- .andExpect(jsonPath("$.data.profile.id").exists());
357
- }
358
- }
359
- ```
360
-
361
- ## Related Skills
362
-
363
- - `bff-concepts`: BFF pattern concepts
364
- - `spring-boot-4`: Spring Boot 4.0 patterns