Add Common Mistakes sections to remaining 4 skills
- project-rules: directory structure, naming, response format, bilingual comments - security: password hashing, secrets, input validation, logging sensitive data - testing-patterns: implementation details, shared state, mocking, edge cases - api-design: RESTful URLs, response format, status codes, pagination 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -485,6 +485,50 @@ export function errorHandler(
|
||||
- Document error responses
|
||||
- Version your documentation
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
1. **Using Verbs in URLs**: Non-RESTful endpoints
|
||||
```
|
||||
# ❌ BAD: Verb in URL
|
||||
POST /api/v1/createUser
|
||||
GET /api/v1/getUserById/123
|
||||
|
||||
# ✅ GOOD: RESTful resources
|
||||
POST /api/v1/users
|
||||
GET /api/v1/users/123
|
||||
```
|
||||
|
||||
2. **Inconsistent Response Format**: Different structures for different endpoints
|
||||
```typescript
|
||||
// ❌ BAD: Inconsistent
|
||||
res.json({ user: data }); // One endpoint
|
||||
res.json({ result: data }); // Another endpoint
|
||||
|
||||
// ✅ GOOD: Consistent structure
|
||||
res.json({ success: true, data }); // All endpoints
|
||||
```
|
||||
|
||||
3. **Wrong HTTP Status Codes**: Using 200 for errors
|
||||
```typescript
|
||||
// ❌ BAD: 200 with error
|
||||
res.status(200).json({ error: 'Not found' });
|
||||
|
||||
// ✅ GOOD: Appropriate status
|
||||
res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: 'User not found' } });
|
||||
```
|
||||
|
||||
4. **Missing Pagination**: Returning all records
|
||||
```typescript
|
||||
// ❌ BAD: Returns everything
|
||||
const users = await prisma.user.findMany();
|
||||
|
||||
// ✅ GOOD: Paginated
|
||||
const users = await prisma.user.findMany({
|
||||
skip: (page - 1) * limit,
|
||||
take: limit,
|
||||
});
|
||||
```
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| HTTP Method | Action | Idempotent | Status Codes |
|
||||
|
||||
@@ -248,6 +248,51 @@ docker-compose ps
|
||||
docker-compose up -d --build
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
1. **Wrong Directory Structure**: Placing files in wrong locations
|
||||
```
|
||||
# ❌ BAD: Controllers outside modules
|
||||
src/controllers/user.controller.ts
|
||||
|
||||
# ✅ GOOD: Controllers inside modules
|
||||
src/modules/user/user.controller.ts
|
||||
```
|
||||
|
||||
2. **Inconsistent Naming**: Mixing naming conventions
|
||||
```typescript
|
||||
// ❌ BAD: Mixed naming
|
||||
UserService.ts
|
||||
user_repository.ts
|
||||
userController.ts
|
||||
|
||||
// ✅ GOOD: Consistent kebab-case
|
||||
user.service.ts
|
||||
user.repository.ts
|
||||
user.controller.ts
|
||||
```
|
||||
|
||||
3. **Wrong Response Format**: Not following API response standard
|
||||
```typescript
|
||||
// ❌ BAD: Inconsistent format
|
||||
res.json({ user: data });
|
||||
res.json({ error: "Not found" });
|
||||
|
||||
// ✅ GOOD: Standard format
|
||||
res.json({ success: true, data: user });
|
||||
res.json({ success: false, error: { code: 'NOT_FOUND', message: 'User not found' } });
|
||||
```
|
||||
|
||||
4. **Missing Bilingual Comments**: Only one language
|
||||
```typescript
|
||||
// ❌ BAD: English only
|
||||
// Initialize database
|
||||
|
||||
// ✅ GOOD: Bilingual
|
||||
// EN: Initialize database connection
|
||||
// VI: Khởi tạo kết nối database
|
||||
```
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Category | Pattern/Standard |
|
||||
|
||||
@@ -789,6 +789,47 @@ export class SecurityIncidentService {
|
||||
}
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
1. **Weak Password Hashing**: Using insufficient bcrypt rounds
|
||||
```typescript
|
||||
// ❌ BAD: Low cost factor
|
||||
const hash = await bcrypt.hash(password, 8);
|
||||
|
||||
// ✅ GOOD: Use cost 12
|
||||
const hash = await bcrypt.hash(password, 12);
|
||||
```
|
||||
|
||||
2. **Storing Secrets in Code**: Hardcoded credentials
|
||||
```typescript
|
||||
// ❌ BAD: Hardcoded secret
|
||||
const JWT_SECRET = "my-secret-key";
|
||||
|
||||
// ✅ GOOD: Use environment variable
|
||||
const JWT_SECRET = process.env.JWT_SECRET;
|
||||
if (!JWT_SECRET) throw new Error('JWT_SECRET required');
|
||||
```
|
||||
|
||||
3. **Missing Input Validation**: Not validating user input
|
||||
```typescript
|
||||
// ❌ BAD: No validation
|
||||
const user = await prisma.user.findUnique({ where: { id: req.params.id } });
|
||||
|
||||
// ✅ GOOD: Validate input
|
||||
const schema = z.object({ id: z.string().cuid() });
|
||||
const { id } = schema.parse(req.params);
|
||||
const user = await prisma.user.findUnique({ where: { id } });
|
||||
```
|
||||
|
||||
4. **Logging Sensitive Data**: Exposing secrets in logs
|
||||
```typescript
|
||||
// ❌ BAD: Logging password
|
||||
logger.info('User login', { email, password });
|
||||
|
||||
// ✅ GOOD: Sanitize before logging
|
||||
logger.info('User login', { email, password: '[REDACTED]' });
|
||||
```
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Security Area | Implementation |
|
||||
|
||||
@@ -492,6 +492,49 @@ test('should paginate results', async () => {
|
||||
- [ ] Keep test data realistic
|
||||
- [ ] Clean up after tests
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
1. **Testing Implementation Details**: Tests break on refactoring
|
||||
```typescript
|
||||
// ❌ BAD: Testing internal method
|
||||
expect(service['privateMethod']()).toBe(true);
|
||||
|
||||
// ✅ GOOD: Test public behavior
|
||||
expect(await service.processOrder(order)).toEqual({ success: true });
|
||||
```
|
||||
|
||||
2. **Shared Mutable State**: Tests affect each other
|
||||
```typescript
|
||||
// ❌ BAD: Shared state
|
||||
let counter = 0;
|
||||
test('first', () => { counter++; expect(counter).toBe(1); });
|
||||
test('second', () => { expect(counter).toBe(0); }); // Fails!
|
||||
|
||||
// ✅ GOOD: Reset in beforeEach
|
||||
let counter: number;
|
||||
beforeEach(() => { counter = 0; });
|
||||
```
|
||||
|
||||
3. **Not Mocking External Services**: Tests are slow and flaky
|
||||
```typescript
|
||||
// ❌ BAD: Real HTTP calls
|
||||
const response = await fetch('https://api.example.com/data');
|
||||
|
||||
// ✅ GOOD: Mock external services
|
||||
jest.spyOn(httpClient, 'get').mockResolvedValue({ data: mockData });
|
||||
```
|
||||
|
||||
4. **Missing Edge Cases**: Only testing happy path
|
||||
```typescript
|
||||
// ❌ BAD: Only success case
|
||||
test('creates user', async () => { ... });
|
||||
|
||||
// ✅ GOOD: Include error cases
|
||||
test('creates user', async () => { ... });
|
||||
test('throws on duplicate email', async () => { ... });
|
||||
test('validates email format', async () => { ... });
|
||||
```
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Test Type | Location | Speed | Mocking |
|
||||
|
||||
Reference in New Issue
Block a user