oh-my-customcode 0.1.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.
- package/LICENSE +21 -0
- package/README.md +287 -0
- package/dist/cli/index.js +13299 -0
- package/dist/index.js +927 -0
- package/package.json +74 -0
- package/templates/.claude/contexts/dev.md +20 -0
- package/templates/.claude/contexts/ecomode.md +63 -0
- package/templates/.claude/contexts/index.yaml +41 -0
- package/templates/.claude/contexts/research.md +28 -0
- package/templates/.claude/contexts/review.md +23 -0
- package/templates/.claude/hooks/hooks.json +185 -0
- package/templates/.claude/hooks/hud/index.yaml +27 -0
- package/templates/.claude/hooks/hud/update-status.sh +32 -0
- package/templates/.claude/hooks/index.yaml +46 -0
- package/templates/.claude/hooks/memory-persistence/pre-compact.sh +37 -0
- package/templates/.claude/hooks/memory-persistence/session-end.sh +64 -0
- package/templates/.claude/hooks/memory-persistence/session-start.sh +41 -0
- package/templates/.claude/hooks/strategic-compact/suggest-compact.sh +50 -0
- package/templates/.claude/install-hooks.sh +100 -0
- package/templates/.claude/rules/MAY-optimization.md +93 -0
- package/templates/.claude/rules/MUST-agent-design.md +107 -0
- package/templates/.claude/rules/MUST-agent-identification.md +108 -0
- package/templates/.claude/rules/MUST-continuous-improvement.md +132 -0
- package/templates/.claude/rules/MUST-intent-transparency.md +199 -0
- package/templates/.claude/rules/MUST-language-policy.md +62 -0
- package/templates/.claude/rules/MUST-orchestrator-coordination.md +266 -0
- package/templates/.claude/rules/MUST-parallel-execution.md +341 -0
- package/templates/.claude/rules/MUST-permissions.md +84 -0
- package/templates/.claude/rules/MUST-safety.md +69 -0
- package/templates/.claude/rules/MUST-sync-verification.md +219 -0
- package/templates/.claude/rules/MUST-tool-identification.md +112 -0
- package/templates/.claude/rules/SHOULD-ecomode.md +145 -0
- package/templates/.claude/rules/SHOULD-error-handling.md +102 -0
- package/templates/.claude/rules/SHOULD-hud-statusline.md +89 -0
- package/templates/.claude/rules/SHOULD-interaction.md +103 -0
- package/templates/.claude/rules/SHOULD-memory-integration.md +114 -0
- package/templates/.claude/rules/SHOULD-pipeline-mode.md +165 -0
- package/templates/.claude/rules/index.yaml +125 -0
- package/templates/.claude/uninstall-hooks.sh +52 -0
- package/templates/CLAUDE.md.en +259 -0
- package/templates/CLAUDE.md.ko +259 -0
- package/templates/agents/index.yaml +237 -0
- package/templates/agents/infra-engineer/aws-expert/AGENT.md +47 -0
- package/templates/agents/infra-engineer/aws-expert/index.yaml +27 -0
- package/templates/agents/infra-engineer/docker-expert/AGENT.md +47 -0
- package/templates/agents/infra-engineer/docker-expert/index.yaml +27 -0
- package/templates/agents/manager/creator/AGENT.md +274 -0
- package/templates/agents/manager/creator/index.yaml +66 -0
- package/templates/agents/manager/gitnerd/AGENT.md +91 -0
- package/templates/agents/manager/gitnerd/index.yaml +55 -0
- package/templates/agents/manager/sauron/AGENT.md +153 -0
- package/templates/agents/manager/sauron/index.yaml +52 -0
- package/templates/agents/manager/supplier/AGENT.md +142 -0
- package/templates/agents/manager/supplier/index.yaml +31 -0
- package/templates/agents/manager/sync-checker/AGENT.md +34 -0
- package/templates/agents/manager/sync-checker/index.yaml +32 -0
- package/templates/agents/manager/updater/AGENT.md +125 -0
- package/templates/agents/manager/updater/index.yaml +31 -0
- package/templates/agents/orchestrator/dev-lead/AGENT.md +116 -0
- package/templates/agents/orchestrator/dev-lead/index.yaml +73 -0
- package/templates/agents/orchestrator/planner/AGENT.md +102 -0
- package/templates/agents/orchestrator/planner/index.yaml +38 -0
- package/templates/agents/orchestrator/qa-lead/AGENT.md +92 -0
- package/templates/agents/orchestrator/qa-lead/index.yaml +40 -0
- package/templates/agents/orchestrator/secretary/AGENT.md +132 -0
- package/templates/agents/orchestrator/secretary/index.yaml +55 -0
- package/templates/agents/qa-team/qa-engineer/AGENT.md +98 -0
- package/templates/agents/qa-team/qa-engineer/index.yaml +59 -0
- package/templates/agents/qa-team/qa-planner/AGENT.md +75 -0
- package/templates/agents/qa-team/qa-planner/index.yaml +47 -0
- package/templates/agents/qa-team/qa-writer/AGENT.md +98 -0
- package/templates/agents/qa-team/qa-writer/index.yaml +44 -0
- package/templates/agents/sw-architect/documenter/AGENT.md +120 -0
- package/templates/agents/sw-architect/documenter/index.yaml +39 -0
- package/templates/agents/sw-architect/speckit-agent/AGENT.md +127 -0
- package/templates/agents/sw-architect/speckit-agent/index.yaml +78 -0
- package/templates/agents/sw-engineer/backend/express-expert/AGENT.md +132 -0
- package/templates/agents/sw-engineer/backend/express-expert/index.yaml +36 -0
- package/templates/agents/sw-engineer/backend/fastapi-expert/AGENT.md +47 -0
- package/templates/agents/sw-engineer/backend/fastapi-expert/index.yaml +27 -0
- package/templates/agents/sw-engineer/backend/go-backend-expert/AGENT.md +47 -0
- package/templates/agents/sw-engineer/backend/go-backend-expert/index.yaml +27 -0
- package/templates/agents/sw-engineer/backend/nestjs-expert/AGENT.md +107 -0
- package/templates/agents/sw-engineer/backend/nestjs-expert/index.yaml +43 -0
- package/templates/agents/sw-engineer/backend/springboot-expert/AGENT.md +103 -0
- package/templates/agents/sw-engineer/backend/springboot-expert/index.yaml +69 -0
- package/templates/agents/sw-engineer/frontend/svelte-agent/AGENT.md +71 -0
- package/templates/agents/sw-engineer/frontend/svelte-agent/index.yaml +41 -0
- package/templates/agents/sw-engineer/frontend/vercel-agent/AGENT.md +67 -0
- package/templates/agents/sw-engineer/frontend/vercel-agent/index.yaml +43 -0
- package/templates/agents/sw-engineer/frontend/vuejs-agent/AGENT.md +71 -0
- package/templates/agents/sw-engineer/frontend/vuejs-agent/index.yaml +48 -0
- package/templates/agents/sw-engineer/language/golang-expert/AGENT.md +47 -0
- package/templates/agents/sw-engineer/language/golang-expert/index.yaml +27 -0
- package/templates/agents/sw-engineer/language/java21-expert/AGENT.md +122 -0
- package/templates/agents/sw-engineer/language/java21-expert/index.yaml +51 -0
- package/templates/agents/sw-engineer/language/kotlin-expert/AGENT.md +47 -0
- package/templates/agents/sw-engineer/language/kotlin-expert/index.yaml +27 -0
- package/templates/agents/sw-engineer/language/python-expert/AGENT.md +47 -0
- package/templates/agents/sw-engineer/language/python-expert/index.yaml +27 -0
- package/templates/agents/sw-engineer/language/rust-expert/AGENT.md +47 -0
- package/templates/agents/sw-engineer/language/rust-expert/index.yaml +27 -0
- package/templates/agents/sw-engineer/language/typescript-expert/AGENT.md +47 -0
- package/templates/agents/sw-engineer/language/typescript-expert/index.yaml +27 -0
- package/templates/agents/sw-engineer/tooling/bun-expert/AGENT.md +73 -0
- package/templates/agents/sw-engineer/tooling/bun-expert/index.yaml +46 -0
- package/templates/agents/sw-engineer/tooling/npm-expert/AGENT.md +160 -0
- package/templates/agents/sw-engineer/tooling/npm-expert/index.yaml +45 -0
- package/templates/agents/sw-engineer/tooling/optimizer/AGENT.md +170 -0
- package/templates/agents/sw-engineer/tooling/optimizer/index.yaml +45 -0
- package/templates/agents/system/memory-keeper/AGENT.md +126 -0
- package/templates/agents/system/memory-keeper/index.yaml +45 -0
- package/templates/agents/system/naggy/AGENT.md +72 -0
- package/templates/agents/system/naggy/index.yaml +35 -0
- package/templates/commands/COMMANDS.md +136 -0
- package/templates/commands/creator/agent.md +121 -0
- package/templates/commands/dev/refactor.md +126 -0
- package/templates/commands/dev/review.md +82 -0
- package/templates/commands/git/branch.yaml +8 -0
- package/templates/commands/git/commit.yaml +4 -0
- package/templates/commands/git/pr.yaml +4 -0
- package/templates/commands/git/status.yaml +4 -0
- package/templates/commands/git/sync.yaml +4 -0
- package/templates/commands/index.yaml +225 -0
- package/templates/commands/intent/explain.md +144 -0
- package/templates/commands/memory/recall.md +164 -0
- package/templates/commands/memory/save.md +128 -0
- package/templates/commands/naggy/add.yaml +8 -0
- package/templates/commands/naggy/done.yaml +8 -0
- package/templates/commands/naggy/list.yaml +4 -0
- package/templates/commands/naggy/priority.yaml +11 -0
- package/templates/commands/naggy/remind.yaml +4 -0
- package/templates/commands/npm/audit.yaml +62 -0
- package/templates/commands/npm/publish.yaml +52 -0
- package/templates/commands/npm/version.yaml +62 -0
- package/templates/commands/optimize/analyze.yaml +34 -0
- package/templates/commands/optimize/bundle.yaml +50 -0
- package/templates/commands/optimize/report.yaml +56 -0
- package/templates/commands/pipeline/list.md +81 -0
- package/templates/commands/pipeline/run.md +127 -0
- package/templates/commands/sauron/quick.yaml +4 -0
- package/templates/commands/sauron/report.yaml +4 -0
- package/templates/commands/sauron/watch.yaml +4 -0
- package/templates/commands/supplier/audit.md +133 -0
- package/templates/commands/supplier/fix.md +121 -0
- package/templates/commands/sync/agents.yaml +4 -0
- package/templates/commands/sync/check.yaml +4 -0
- package/templates/commands/sync/commands.yaml +4 -0
- package/templates/commands/sync/docs.yaml +4 -0
- package/templates/commands/sync/fix.yaml +4 -0
- package/templates/commands/system/help.md +137 -0
- package/templates/commands/system/lists.md +86 -0
- package/templates/commands/system/status.md +163 -0
- package/templates/commands/updater/docs.md +165 -0
- package/templates/commands/updater/external.md +214 -0
- package/templates/guides/aws/common-patterns.md +169 -0
- package/templates/guides/aws/index.yaml +26 -0
- package/templates/guides/aws/well-architected.md +143 -0
- package/templates/guides/claude-code/01-overview.md +42 -0
- package/templates/guides/claude-code/03-tools.md +107 -0
- package/templates/guides/claude-code/04-agent-skills.md +90 -0
- package/templates/guides/claude-code/05-agent-sdk.md +129 -0
- package/templates/guides/claude-code/06-mcp.md +165 -0
- package/templates/guides/claude-code/07-prompt-engineering.md +100 -0
- package/templates/guides/claude-code/08-testing.md +58 -0
- package/templates/guides/claude-code/09-guardrails.md +80 -0
- package/templates/guides/claude-code/10-monitoring.md +89 -0
- package/templates/guides/claude-code/index.yaml +51 -0
- package/templates/guides/docker/compose-best-practices.md +284 -0
- package/templates/guides/docker/dockerfile-best-practices.md +262 -0
- package/templates/guides/docker/index.yaml +26 -0
- package/templates/guides/fastapi/best-practices.md +232 -0
- package/templates/guides/fastapi/index.yaml +21 -0
- package/templates/guides/go-backend/index.yaml +26 -0
- package/templates/guides/go-backend/project-layout.md +243 -0
- package/templates/guides/go-backend/uber-style.md +212 -0
- package/templates/guides/golang/concurrency.md +282 -0
- package/templates/guides/golang/effective-go.md +309 -0
- package/templates/guides/golang/error-handling.md +250 -0
- package/templates/guides/golang/index.yaml +27 -0
- package/templates/guides/index.yaml +101 -0
- package/templates/guides/kotlin/coding-conventions.md +247 -0
- package/templates/guides/kotlin/idioms.md +234 -0
- package/templates/guides/kotlin/index.yaml +26 -0
- package/templates/guides/python/index.yaml +26 -0
- package/templates/guides/python/pep8-style-guide.md +202 -0
- package/templates/guides/python/zen-of-python.md +79 -0
- package/templates/guides/rust/error-handling.md +262 -0
- package/templates/guides/rust/index.yaml +26 -0
- package/templates/guides/rust/ownership.md +180 -0
- package/templates/guides/springboot/best-practices.md +361 -0
- package/templates/guides/springboot/index.yaml +22 -0
- package/templates/guides/typescript/advanced-types.md +225 -0
- package/templates/guides/typescript/index.yaml +26 -0
- package/templates/guides/typescript/type-system.md +219 -0
- package/templates/guides/web-design/accessibility.md +66 -0
- package/templates/guides/web-design/index.yaml +20 -0
- package/templates/guides/web-design/performance.md +102 -0
- package/templates/pipelines/examples/code-review.yaml +66 -0
- package/templates/pipelines/index.yaml +18 -0
- package/templates/pipelines/templates/pipeline-template.yaml +50 -0
- package/templates/skills/backend/fastapi-best-practices/SKILL.md +269 -0
- package/templates/skills/backend/fastapi-best-practices/index.yaml +25 -0
- package/templates/skills/backend/go-backend-best-practices/SKILL.md +337 -0
- package/templates/skills/backend/go-backend-best-practices/index.yaml +26 -0
- package/templates/skills/backend/springboot-best-practices/SKILL.md +356 -0
- package/templates/skills/backend/springboot-best-practices/index.yaml +27 -0
- package/templates/skills/development/go-best-practices/SKILL.md +202 -0
- package/templates/skills/development/go-best-practices/index.yaml +25 -0
- package/templates/skills/development/kotlin-best-practices/SKILL.md +255 -0
- package/templates/skills/development/kotlin-best-practices/index.yaml +27 -0
- package/templates/skills/development/python-best-practices/SKILL.md +221 -0
- package/templates/skills/development/python-best-practices/index.yaml +25 -0
- package/templates/skills/development/react-best-practices/SKILL.md +100 -0
- package/templates/skills/development/react-best-practices/index.yaml +39 -0
- package/templates/skills/development/rust-best-practices/SKILL.md +266 -0
- package/templates/skills/development/rust-best-practices/index.yaml +26 -0
- package/templates/skills/development/typescript-best-practices/SKILL.md +320 -0
- package/templates/skills/development/typescript-best-practices/index.yaml +28 -0
- package/templates/skills/development/vercel-deploy/SKILL.md +73 -0
- package/templates/skills/development/vercel-deploy/index.yaml +30 -0
- package/templates/skills/development/web-design-guidelines/SKILL.md +117 -0
- package/templates/skills/development/web-design-guidelines/index.yaml +34 -0
- package/templates/skills/index.yaml +129 -0
- package/templates/skills/infrastructure/aws-best-practices/SKILL.md +279 -0
- package/templates/skills/infrastructure/aws-best-practices/index.yaml +27 -0
- package/templates/skills/infrastructure/docker-best-practices/SKILL.md +274 -0
- package/templates/skills/infrastructure/docker-best-practices/index.yaml +26 -0
- package/templates/skills/orchestration/intent-detection/SKILL.md +214 -0
- package/templates/skills/orchestration/intent-detection/index.yaml +30 -0
- package/templates/skills/orchestration/intent-detection/patterns/agent-triggers.yaml +333 -0
- package/templates/skills/orchestration/pipeline-execution/SKILL.md +188 -0
- package/templates/skills/orchestration/pipeline-execution/index.yaml +27 -0
- package/templates/skills/system/memory-management/SKILL.md +194 -0
- package/templates/skills/system/memory-management/index.yaml +30 -0
- package/templates/skills/system/result-aggregation/SKILL.md +163 -0
- package/templates/skills/system/result-aggregation/index.yaml +36 -0
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
# Spring Boot Best Practices Skill
|
|
2
|
+
|
|
3
|
+
> **Category**: Backend
|
|
4
|
+
> **Source**: Internal (based on Spring documentation and Baeldung)
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
|
|
8
|
+
Apply Spring Boot patterns for building enterprise-grade applications.
|
|
9
|
+
|
|
10
|
+
## Rules
|
|
11
|
+
|
|
12
|
+
### 1. Project Structure
|
|
13
|
+
|
|
14
|
+
```yaml
|
|
15
|
+
structure:
|
|
16
|
+
layout: layered architecture
|
|
17
|
+
packages:
|
|
18
|
+
- controller: REST endpoints
|
|
19
|
+
- service: Business logic
|
|
20
|
+
- repository: Data access
|
|
21
|
+
- model/entity: Domain objects
|
|
22
|
+
- dto: Data transfer objects
|
|
23
|
+
- config: Configuration classes
|
|
24
|
+
- exception: Custom exceptions
|
|
25
|
+
|
|
26
|
+
example: |
|
|
27
|
+
com.example.app/
|
|
28
|
+
├── controller/
|
|
29
|
+
│ └── UserController.java
|
|
30
|
+
├── service/
|
|
31
|
+
│ ├── UserService.java
|
|
32
|
+
│ └── impl/UserServiceImpl.java
|
|
33
|
+
├── repository/
|
|
34
|
+
│ └── UserRepository.java
|
|
35
|
+
├── model/
|
|
36
|
+
│ └── User.java
|
|
37
|
+
├── dto/
|
|
38
|
+
│ ├── UserRequest.java
|
|
39
|
+
│ └── UserResponse.java
|
|
40
|
+
├── config/
|
|
41
|
+
│ └── SecurityConfig.java
|
|
42
|
+
└── exception/
|
|
43
|
+
└── UserNotFoundException.java
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 2. Dependency Injection
|
|
47
|
+
|
|
48
|
+
```yaml
|
|
49
|
+
prefer:
|
|
50
|
+
- Constructor injection over field injection
|
|
51
|
+
- Interface-based dependencies
|
|
52
|
+
- @RequiredArgsConstructor with final fields
|
|
53
|
+
|
|
54
|
+
patterns: |
|
|
55
|
+
// GOOD: Constructor injection
|
|
56
|
+
@Service
|
|
57
|
+
@RequiredArgsConstructor
|
|
58
|
+
public class UserService {
|
|
59
|
+
private final UserRepository userRepository;
|
|
60
|
+
private final EmailService emailService;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// AVOID: Field injection
|
|
64
|
+
@Service
|
|
65
|
+
public class UserService {
|
|
66
|
+
@Autowired
|
|
67
|
+
private UserRepository userRepository; // Not recommended
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 3. REST API Design
|
|
72
|
+
|
|
73
|
+
```yaml
|
|
74
|
+
controller:
|
|
75
|
+
annotations:
|
|
76
|
+
- "@RestController"
|
|
77
|
+
- "@RequestMapping with base path"
|
|
78
|
+
- "@Validated for input validation"
|
|
79
|
+
|
|
80
|
+
patterns: |
|
|
81
|
+
@RestController
|
|
82
|
+
@RequestMapping("/api/v1/users")
|
|
83
|
+
@RequiredArgsConstructor
|
|
84
|
+
public class UserController {
|
|
85
|
+
|
|
86
|
+
private final UserService userService;
|
|
87
|
+
|
|
88
|
+
@GetMapping("/{id}")
|
|
89
|
+
public ResponseEntity<UserResponse> getUser(@PathVariable Long id) {
|
|
90
|
+
return ResponseEntity.ok(userService.findById(id));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@PostMapping
|
|
94
|
+
@ResponseStatus(HttpStatus.CREATED)
|
|
95
|
+
public UserResponse createUser(@Valid @RequestBody UserRequest request) {
|
|
96
|
+
return userService.create(request);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@PutMapping("/{id}")
|
|
100
|
+
public UserResponse updateUser(
|
|
101
|
+
@PathVariable Long id,
|
|
102
|
+
@Valid @RequestBody UserRequest request
|
|
103
|
+
) {
|
|
104
|
+
return userService.update(id, request);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@DeleteMapping("/{id}")
|
|
108
|
+
@ResponseStatus(HttpStatus.NO_CONTENT)
|
|
109
|
+
public void deleteUser(@PathVariable Long id) {
|
|
110
|
+
userService.delete(id);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 4. Service Layer
|
|
116
|
+
|
|
117
|
+
```yaml
|
|
118
|
+
principles:
|
|
119
|
+
- Business logic in service layer
|
|
120
|
+
- Transaction boundaries at service level
|
|
121
|
+
- Interface + implementation pattern
|
|
122
|
+
|
|
123
|
+
patterns: |
|
|
124
|
+
public interface UserService {
|
|
125
|
+
UserResponse findById(Long id);
|
|
126
|
+
UserResponse create(UserRequest request);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
@Service
|
|
130
|
+
@Transactional(readOnly = true)
|
|
131
|
+
@RequiredArgsConstructor
|
|
132
|
+
public class UserServiceImpl implements UserService {
|
|
133
|
+
|
|
134
|
+
private final UserRepository userRepository;
|
|
135
|
+
private final UserMapper userMapper;
|
|
136
|
+
|
|
137
|
+
@Override
|
|
138
|
+
public UserResponse findById(Long id) {
|
|
139
|
+
User user = userRepository.findById(id)
|
|
140
|
+
.orElseThrow(() -> new UserNotFoundException(id));
|
|
141
|
+
return userMapper.toResponse(user);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@Override
|
|
145
|
+
@Transactional
|
|
146
|
+
public UserResponse create(UserRequest request) {
|
|
147
|
+
User user = userMapper.toEntity(request);
|
|
148
|
+
return userMapper.toResponse(userRepository.save(user));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### 5. Data Access
|
|
154
|
+
|
|
155
|
+
```yaml
|
|
156
|
+
repository:
|
|
157
|
+
use: Spring Data JPA
|
|
158
|
+
custom_queries: "@Query annotation or method naming"
|
|
159
|
+
|
|
160
|
+
patterns: |
|
|
161
|
+
public interface UserRepository extends JpaRepository<User, Long> {
|
|
162
|
+
|
|
163
|
+
Optional<User> findByEmail(String email);
|
|
164
|
+
|
|
165
|
+
@Query("SELECT u FROM User u WHERE u.status = :status")
|
|
166
|
+
List<User> findByStatus(@Param("status") UserStatus status);
|
|
167
|
+
|
|
168
|
+
@Query(value = "SELECT * FROM users WHERE created_at > :date",
|
|
169
|
+
nativeQuery = true)
|
|
170
|
+
List<User> findRecentUsers(@Param("date") LocalDateTime date);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
entity: |
|
|
174
|
+
@Entity
|
|
175
|
+
@Table(name = "users")
|
|
176
|
+
@Getter
|
|
177
|
+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
|
178
|
+
public class User {
|
|
179
|
+
|
|
180
|
+
@Id
|
|
181
|
+
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
182
|
+
private Long id;
|
|
183
|
+
|
|
184
|
+
@Column(nullable = false, unique = true)
|
|
185
|
+
private String email;
|
|
186
|
+
|
|
187
|
+
@Enumerated(EnumType.STRING)
|
|
188
|
+
private UserStatus status;
|
|
189
|
+
|
|
190
|
+
@CreatedDate
|
|
191
|
+
private LocalDateTime createdAt;
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### 6. Exception Handling
|
|
196
|
+
|
|
197
|
+
```yaml
|
|
198
|
+
global_handler:
|
|
199
|
+
use: "@ControllerAdvice"
|
|
200
|
+
custom_exceptions: domain-specific
|
|
201
|
+
|
|
202
|
+
patterns: |
|
|
203
|
+
@RestControllerAdvice
|
|
204
|
+
public class GlobalExceptionHandler {
|
|
205
|
+
|
|
206
|
+
@ExceptionHandler(UserNotFoundException.class)
|
|
207
|
+
@ResponseStatus(HttpStatus.NOT_FOUND)
|
|
208
|
+
public ErrorResponse handleUserNotFound(UserNotFoundException ex) {
|
|
209
|
+
return new ErrorResponse("USER_NOT_FOUND", ex.getMessage());
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
@ExceptionHandler(MethodArgumentNotValidException.class)
|
|
213
|
+
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
|
214
|
+
public ErrorResponse handleValidation(MethodArgumentNotValidException ex) {
|
|
215
|
+
List<String> errors = ex.getBindingResult()
|
|
216
|
+
.getFieldErrors()
|
|
217
|
+
.stream()
|
|
218
|
+
.map(e -> e.getField() + ": " + e.getDefaultMessage())
|
|
219
|
+
.toList();
|
|
220
|
+
return new ErrorResponse("VALIDATION_ERROR", errors);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### 7. Configuration
|
|
226
|
+
|
|
227
|
+
```yaml
|
|
228
|
+
profiles:
|
|
229
|
+
use: application-{profile}.yml
|
|
230
|
+
externalize: sensitive values
|
|
231
|
+
|
|
232
|
+
patterns: |
|
|
233
|
+
# application.yml
|
|
234
|
+
spring:
|
|
235
|
+
profiles:
|
|
236
|
+
active: ${SPRING_PROFILES_ACTIVE:local}
|
|
237
|
+
datasource:
|
|
238
|
+
url: ${DATABASE_URL}
|
|
239
|
+
username: ${DATABASE_USERNAME}
|
|
240
|
+
password: ${DATABASE_PASSWORD}
|
|
241
|
+
|
|
242
|
+
# application-local.yml
|
|
243
|
+
spring:
|
|
244
|
+
datasource:
|
|
245
|
+
url: jdbc:h2:mem:testdb
|
|
246
|
+
driver-class-name: org.h2.Driver
|
|
247
|
+
|
|
248
|
+
configuration_class: |
|
|
249
|
+
@Configuration
|
|
250
|
+
@ConfigurationProperties(prefix = "app")
|
|
251
|
+
@Validated
|
|
252
|
+
public class AppProperties {
|
|
253
|
+
|
|
254
|
+
@NotBlank
|
|
255
|
+
private String name;
|
|
256
|
+
|
|
257
|
+
@Min(1)
|
|
258
|
+
private int maxConnections;
|
|
259
|
+
|
|
260
|
+
// getters, setters
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### 8. Security
|
|
265
|
+
|
|
266
|
+
```yaml
|
|
267
|
+
principles:
|
|
268
|
+
- Use Spring Security
|
|
269
|
+
- Externalize secrets
|
|
270
|
+
- Implement proper authentication
|
|
271
|
+
|
|
272
|
+
patterns: |
|
|
273
|
+
@Configuration
|
|
274
|
+
@EnableWebSecurity
|
|
275
|
+
@RequiredArgsConstructor
|
|
276
|
+
public class SecurityConfig {
|
|
277
|
+
|
|
278
|
+
private final JwtTokenProvider tokenProvider;
|
|
279
|
+
|
|
280
|
+
@Bean
|
|
281
|
+
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
|
282
|
+
return http
|
|
283
|
+
.csrf(csrf -> csrf.disable())
|
|
284
|
+
.sessionManagement(session ->
|
|
285
|
+
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
|
286
|
+
.authorizeHttpRequests(auth -> auth
|
|
287
|
+
.requestMatchers("/api/v1/auth/**").permitAll()
|
|
288
|
+
.requestMatchers("/api/v1/admin/**").hasRole("ADMIN")
|
|
289
|
+
.anyRequest().authenticated())
|
|
290
|
+
.addFilterBefore(jwtFilter(), UsernamePasswordAuthenticationFilter.class)
|
|
291
|
+
.build();
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### 9. Testing
|
|
297
|
+
|
|
298
|
+
```yaml
|
|
299
|
+
layers:
|
|
300
|
+
unit: "@MockBean, Mockito"
|
|
301
|
+
integration: "@SpringBootTest"
|
|
302
|
+
slice: "@WebMvcTest, @DataJpaTest"
|
|
303
|
+
|
|
304
|
+
patterns: |
|
|
305
|
+
// Controller test
|
|
306
|
+
@WebMvcTest(UserController.class)
|
|
307
|
+
class UserControllerTest {
|
|
308
|
+
|
|
309
|
+
@Autowired
|
|
310
|
+
private MockMvc mockMvc;
|
|
311
|
+
|
|
312
|
+
@MockBean
|
|
313
|
+
private UserService userService;
|
|
314
|
+
|
|
315
|
+
@Test
|
|
316
|
+
void getUser_shouldReturnUser() throws Exception {
|
|
317
|
+
given(userService.findById(1L))
|
|
318
|
+
.willReturn(new UserResponse(1L, "test@example.com"));
|
|
319
|
+
|
|
320
|
+
mockMvc.perform(get("/api/v1/users/1"))
|
|
321
|
+
.andExpect(status().isOk())
|
|
322
|
+
.andExpect(jsonPath("$.email").value("test@example.com"));
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Repository test
|
|
327
|
+
@DataJpaTest
|
|
328
|
+
class UserRepositoryTest {
|
|
329
|
+
|
|
330
|
+
@Autowired
|
|
331
|
+
private UserRepository userRepository;
|
|
332
|
+
|
|
333
|
+
@Test
|
|
334
|
+
void findByEmail_shouldReturnUser() {
|
|
335
|
+
User user = userRepository.save(new User("test@example.com"));
|
|
336
|
+
|
|
337
|
+
Optional<User> found = userRepository.findByEmail("test@example.com");
|
|
338
|
+
|
|
339
|
+
assertThat(found).isPresent();
|
|
340
|
+
assertThat(found.get().getEmail()).isEqualTo("test@example.com");
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## Application
|
|
346
|
+
|
|
347
|
+
When writing Spring Boot code:
|
|
348
|
+
|
|
349
|
+
1. **Always** use constructor injection
|
|
350
|
+
2. **Always** use layered architecture
|
|
351
|
+
3. **Prefer** interface-based services
|
|
352
|
+
4. **Use** DTOs for API contracts
|
|
353
|
+
5. **Handle** exceptions globally
|
|
354
|
+
6. **Externalize** configuration
|
|
355
|
+
7. **Secure** endpoints properly
|
|
356
|
+
8. **Test** each layer appropriately
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Spring Boot Best Practices Skill
|
|
2
|
+
|
|
3
|
+
metadata:
|
|
4
|
+
name: springboot-best-practices
|
|
5
|
+
category: backend
|
|
6
|
+
description: Spring Boot patterns for enterprise Java applications
|
|
7
|
+
|
|
8
|
+
source:
|
|
9
|
+
type: internal
|
|
10
|
+
reference:
|
|
11
|
+
- https://docs.spring.io/spring-boot/docs/current/reference/html/
|
|
12
|
+
- https://spring.io/guides
|
|
13
|
+
- https://www.baeldung.com/spring-boot
|
|
14
|
+
|
|
15
|
+
provides:
|
|
16
|
+
- Project structure patterns
|
|
17
|
+
- Dependency injection best practices
|
|
18
|
+
- REST API design guidelines
|
|
19
|
+
- Service layer patterns
|
|
20
|
+
- Data access patterns
|
|
21
|
+
- Exception handling
|
|
22
|
+
- Configuration management
|
|
23
|
+
- Security implementation
|
|
24
|
+
- Testing strategies
|
|
25
|
+
|
|
26
|
+
used_by:
|
|
27
|
+
- springboot-expert
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# Go Best Practices Skill
|
|
2
|
+
|
|
3
|
+
> **Category**: Development
|
|
4
|
+
> **Source**: Internal (based on Effective Go)
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
|
|
8
|
+
Apply idiomatic Go patterns and best practices from official Go documentation.
|
|
9
|
+
|
|
10
|
+
## Rules
|
|
11
|
+
|
|
12
|
+
### 1. Formatting
|
|
13
|
+
|
|
14
|
+
```yaml
|
|
15
|
+
rules:
|
|
16
|
+
- Use gofmt for all code formatting
|
|
17
|
+
- Indentation uses tabs, not spaces
|
|
18
|
+
- No line length limit, but break long lines sensibly
|
|
19
|
+
- Let gofmt handle alignment
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### 2. Naming Conventions
|
|
23
|
+
|
|
24
|
+
```yaml
|
|
25
|
+
package_names:
|
|
26
|
+
- Short, concise, lowercase, single-word
|
|
27
|
+
- No underscores or mixedCaps
|
|
28
|
+
- Name is basename of source directory
|
|
29
|
+
- Example: bufio, not bufIO or buf_io
|
|
30
|
+
|
|
31
|
+
getters:
|
|
32
|
+
- No "Get" prefix for getters
|
|
33
|
+
- obj.Owner() not obj.GetOwner()
|
|
34
|
+
- Setter can use "Set": obj.SetOwner(user)
|
|
35
|
+
|
|
36
|
+
interface_names:
|
|
37
|
+
- One-method interfaces: method name + "er"
|
|
38
|
+
- Reader, Writer, Formatter, CloseNotifier
|
|
39
|
+
- Avoid stealing standard names unless same signature
|
|
40
|
+
|
|
41
|
+
mixedCaps:
|
|
42
|
+
- Use MixedCaps or mixedCaps, never underscores
|
|
43
|
+
- Exported: MixedCaps (uppercase first)
|
|
44
|
+
- Unexported: mixedCaps (lowercase first)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 3. Control Structures
|
|
48
|
+
|
|
49
|
+
```yaml
|
|
50
|
+
if_statements:
|
|
51
|
+
- Accept initialization statement
|
|
52
|
+
- Prefer: if err := file.Chmod(0664); err != nil
|
|
53
|
+
- Omit else when if ends with break/continue/return
|
|
54
|
+
- Avoid unnecessary else
|
|
55
|
+
|
|
56
|
+
for_loops:
|
|
57
|
+
- Go's only loop construct
|
|
58
|
+
- for init; condition; post { } - like C for
|
|
59
|
+
- for condition { } - like C while
|
|
60
|
+
- for { } - infinite loop
|
|
61
|
+
- Use range for strings, slices, arrays, maps, channels
|
|
62
|
+
|
|
63
|
+
switch:
|
|
64
|
+
- Cases don't fall through by default
|
|
65
|
+
- Use fallthrough keyword if needed
|
|
66
|
+
- Multiple cases: case '0', '1', '2'
|
|
67
|
+
- Type switch: switch v := x.(type)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 4. Functions
|
|
71
|
+
|
|
72
|
+
```yaml
|
|
73
|
+
multiple_returns:
|
|
74
|
+
- Return multiple values for result + error
|
|
75
|
+
- func (file *File) Write(b []byte) (n int, err error)
|
|
76
|
+
|
|
77
|
+
named_results:
|
|
78
|
+
- Document return values with names
|
|
79
|
+
- Can simplify code but use judiciously
|
|
80
|
+
- Unnamed returns OK for short functions
|
|
81
|
+
|
|
82
|
+
defer:
|
|
83
|
+
- Executes when function returns
|
|
84
|
+
- LIFO order for multiple defers
|
|
85
|
+
- Use for cleanup: unlock mutexes, close files
|
|
86
|
+
- Arguments evaluated when defer executes, not when called
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 5. Data
|
|
90
|
+
|
|
91
|
+
```yaml
|
|
92
|
+
new_vs_make:
|
|
93
|
+
- new(T): allocates zeroed storage, returns *T
|
|
94
|
+
- make(T, args): creates slices, maps, channels only
|
|
95
|
+
- make returns initialized (not zeroed) value of type T
|
|
96
|
+
|
|
97
|
+
slices:
|
|
98
|
+
- Backed by arrays, can grow
|
|
99
|
+
- append() to add elements
|
|
100
|
+
- copy() for safe duplication
|
|
101
|
+
- Slice of slice shares underlying array
|
|
102
|
+
|
|
103
|
+
maps:
|
|
104
|
+
- Reference type, nil until initialized
|
|
105
|
+
- make(map[KeyType]ValueType)
|
|
106
|
+
- Comma ok idiom: val, ok := map[key]
|
|
107
|
+
- delete(map, key) to remove
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 6. Methods
|
|
111
|
+
|
|
112
|
+
```yaml
|
|
113
|
+
pointer_vs_value_receivers:
|
|
114
|
+
- Pointer receiver: can modify, no copy overhead
|
|
115
|
+
- Value receiver: safe from modification
|
|
116
|
+
- If any method needs pointer, all should use pointer
|
|
117
|
+
- Rule: values immutable, pointers mutable
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 7. Interfaces
|
|
121
|
+
|
|
122
|
+
```yaml
|
|
123
|
+
design:
|
|
124
|
+
- Interfaces define behavior, not data
|
|
125
|
+
- Small interfaces (1-3 methods) preferred
|
|
126
|
+
- Accept interfaces, return structs
|
|
127
|
+
- If type implements interface, it satisfies implicitly
|
|
128
|
+
|
|
129
|
+
common_interfaces:
|
|
130
|
+
- io.Reader: Read(p []byte) (n int, err error)
|
|
131
|
+
- io.Writer: Write(p []byte) (n int, err error)
|
|
132
|
+
- fmt.Stringer: String() string
|
|
133
|
+
- error: Error() string
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### 8. Concurrency
|
|
137
|
+
|
|
138
|
+
```yaml
|
|
139
|
+
goroutines:
|
|
140
|
+
- Lightweight, multiplexed onto OS threads
|
|
141
|
+
- go function() to start
|
|
142
|
+
- Don't communicate by sharing memory
|
|
143
|
+
- Share memory by communicating
|
|
144
|
+
|
|
145
|
+
channels:
|
|
146
|
+
- Primary synchronization mechanism
|
|
147
|
+
- ch := make(chan int) - unbuffered
|
|
148
|
+
- ch := make(chan int, 100) - buffered
|
|
149
|
+
- Send: ch <- v
|
|
150
|
+
- Receive: v := <-ch
|
|
151
|
+
- Close: close(ch)
|
|
152
|
+
|
|
153
|
+
patterns:
|
|
154
|
+
- Don't leak goroutines - ensure they exit
|
|
155
|
+
- Use context for cancellation
|
|
156
|
+
- select for multiple channel operations
|
|
157
|
+
- sync.WaitGroup for goroutine coordination
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### 9. Error Handling
|
|
161
|
+
|
|
162
|
+
```yaml
|
|
163
|
+
principles:
|
|
164
|
+
- Errors are values, handle them explicitly
|
|
165
|
+
- Check errors immediately after call
|
|
166
|
+
- Return errors, don't panic
|
|
167
|
+
- Add context when propagating: fmt.Errorf("op failed: %w", err)
|
|
168
|
+
|
|
169
|
+
panic_recover:
|
|
170
|
+
- Panic for unrecoverable errors only
|
|
171
|
+
- Library functions should return errors, not panic
|
|
172
|
+
- Recover only in deferred functions
|
|
173
|
+
- Convert internal panics to errors at package boundary
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### 10. Project Structure
|
|
177
|
+
|
|
178
|
+
```yaml
|
|
179
|
+
packages:
|
|
180
|
+
- One package per directory
|
|
181
|
+
- Package name matches directory name
|
|
182
|
+
- main package for executables
|
|
183
|
+
- Avoid circular imports
|
|
184
|
+
|
|
185
|
+
files:
|
|
186
|
+
- doc.go for package documentation
|
|
187
|
+
- _test.go suffix for test files
|
|
188
|
+
- Group related types and functions
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Application
|
|
192
|
+
|
|
193
|
+
When writing or reviewing Go code:
|
|
194
|
+
|
|
195
|
+
1. **Always** run `gofmt` or `goimports`
|
|
196
|
+
2. **Always** handle returned errors
|
|
197
|
+
3. **Prefer** composition over inheritance
|
|
198
|
+
4. **Prefer** small interfaces
|
|
199
|
+
5. **Prefer** channels for goroutine communication
|
|
200
|
+
6. **Avoid** global state
|
|
201
|
+
7. **Avoid** init() when possible
|
|
202
|
+
8. **Document** exported identifiers
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Go Best Practices Skill
|
|
2
|
+
|
|
3
|
+
metadata:
|
|
4
|
+
name: go-best-practices
|
|
5
|
+
category: development
|
|
6
|
+
description: Idiomatic Go patterns from Effective Go
|
|
7
|
+
|
|
8
|
+
source:
|
|
9
|
+
type: internal
|
|
10
|
+
reference: https://go.dev/doc/effective_go
|
|
11
|
+
|
|
12
|
+
provides:
|
|
13
|
+
- Go code formatting standards
|
|
14
|
+
- Naming conventions
|
|
15
|
+
- Control structure patterns
|
|
16
|
+
- Function design patterns
|
|
17
|
+
- Data structure usage
|
|
18
|
+
- Method receiver guidelines
|
|
19
|
+
- Interface design
|
|
20
|
+
- Concurrency patterns
|
|
21
|
+
- Error handling patterns
|
|
22
|
+
- Project structure guidelines
|
|
23
|
+
|
|
24
|
+
used_by:
|
|
25
|
+
- golang-expert
|