developer-ai 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.
- package/README.md +241 -0
- package/bin/developer-ai.js +2 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +219 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +82 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/schema.d.ts +115 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +29 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/constants.d.ts +8 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +8 -0
- package/dist/constants.js.map +1 -0
- package/dist/core/agent.d.ts +38 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/agent.js +155 -0
- package/dist/core/agent.js.map +1 -0
- package/dist/core/system-prompt.d.ts +6 -0
- package/dist/core/system-prompt.d.ts.map +1 -0
- package/dist/core/system-prompt.js +44 -0
- package/dist/core/system-prompt.js.map +1 -0
- package/dist/core/types.d.ts +42 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +6 -0
- package/dist/core/types.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/client.d.ts +13 -0
- package/dist/mcp/client.d.ts.map +1 -0
- package/dist/mcp/client.js +202 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/providers/ollama.d.ts +13 -0
- package/dist/providers/ollama.d.ts.map +1 -0
- package/dist/providers/ollama.js +60 -0
- package/dist/providers/ollama.js.map +1 -0
- package/dist/providers/openai.d.ts +9 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +40 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/skills/loader.d.ts +25 -0
- package/dist/skills/loader.d.ts.map +1 -0
- package/dist/skills/loader.js +93 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/tests/tools.test.d.ts +2 -0
- package/dist/tests/tools.test.d.ts.map +1 -0
- package/dist/tests/tools.test.js +170 -0
- package/dist/tests/tools.test.js.map +1 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +19 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/list-files.d.ts +3 -0
- package/dist/tools/list-files.d.ts.map +1 -0
- package/dist/tools/list-files.js +60 -0
- package/dist/tools/list-files.js.map +1 -0
- package/dist/tools/read-file.d.ts +3 -0
- package/dist/tools/read-file.d.ts.map +1 -0
- package/dist/tools/read-file.js +46 -0
- package/dist/tools/read-file.js.map +1 -0
- package/dist/tools/registry.d.ts +24 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +37 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/run-command.d.ts +3 -0
- package/dist/tools/run-command.d.ts.map +1 -0
- package/dist/tools/run-command.js +114 -0
- package/dist/tools/run-command.js.map +1 -0
- package/dist/tools/search-text.d.ts +3 -0
- package/dist/tools/search-text.d.ts.map +1 -0
- package/dist/tools/search-text.js +103 -0
- package/dist/tools/search-text.js.map +1 -0
- package/dist/tools/utils.d.ts +6 -0
- package/dist/tools/utils.d.ts.map +1 -0
- package/dist/tools/utils.js +14 -0
- package/dist/tools/utils.js.map +1 -0
- package/dist/tools/web-search.d.ts +3 -0
- package/dist/tools/web-search.d.ts.map +1 -0
- package/dist/tools/web-search.js +80 -0
- package/dist/tools/web-search.js.map +1 -0
- package/dist/tools/write-file.d.ts +3 -0
- package/dist/tools/write-file.d.ts.map +1 -0
- package/dist/tools/write-file.js +66 -0
- package/dist/tools/write-file.js.map +1 -0
- package/package.json +54 -0
- package/skills/accessibility/SKILL.md +496 -0
- package/skills/api-design/SKILL.md +419 -0
- package/skills/code-review/SKILL.md +267 -0
- package/skills/debugging/SKILL.md +332 -0
- package/skills/documentation/SKILL.md +496 -0
- package/skills/error-handling/SKILL.md +504 -0
- package/skills/git-workflow/SKILL.md +448 -0
- package/skills/human-like-coding/SKILL.md +400 -0
- package/skills/performance-optimization/SKILL.md +412 -0
- package/skills/prompt-engineering/SKILL.md +362 -0
- package/skills/refactoring/SKILL.md +457 -0
- package/skills/security-audit/SKILL.md +453 -0
- package/skills/testing-strategy/SKILL.md +501 -0
- package/skills/webapp-testing/SKILL.md +309 -0
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: api-design
|
|
3
|
+
description: Guide for designing RESTful and GraphQL APIs. Use when creating new APIs, refactoring existing endpoints, or establishing API conventions. Covers REST principles, versioning, error handling, authentication, and documentation.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# API Design Skill
|
|
7
|
+
|
|
8
|
+
This skill provides comprehensive guidance for designing clean, consistent, and developer-friendly APIs.
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
Good API design creates intuitive interfaces that are easy to use, maintain, and evolve. This skill covers REST API design principles and best practices.
|
|
13
|
+
|
|
14
|
+
## REST API Principles
|
|
15
|
+
|
|
16
|
+
### Resource Naming
|
|
17
|
+
|
|
18
|
+
**Use Nouns, Not Verbs**
|
|
19
|
+
```
|
|
20
|
+
# GOOD
|
|
21
|
+
GET /users
|
|
22
|
+
GET /users/123
|
|
23
|
+
POST /users
|
|
24
|
+
PUT /users/123
|
|
25
|
+
DELETE /users/123
|
|
26
|
+
|
|
27
|
+
# BAD
|
|
28
|
+
GET /getUsers
|
|
29
|
+
POST /createUser
|
|
30
|
+
PUT /updateUser
|
|
31
|
+
DELETE /deleteUser
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Use Plural Names**
|
|
35
|
+
```
|
|
36
|
+
# GOOD
|
|
37
|
+
/users
|
|
38
|
+
/products
|
|
39
|
+
/orders
|
|
40
|
+
|
|
41
|
+
# BAD (inconsistent)
|
|
42
|
+
/user
|
|
43
|
+
/product
|
|
44
|
+
/order
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Use Kebab-Case**
|
|
48
|
+
```
|
|
49
|
+
# GOOD
|
|
50
|
+
/user-profiles
|
|
51
|
+
/order-items
|
|
52
|
+
|
|
53
|
+
# BAD
|
|
54
|
+
/userProfiles
|
|
55
|
+
/user_profiles
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### HTTP Methods
|
|
59
|
+
|
|
60
|
+
| Method | Use Case | Idempotent |
|
|
61
|
+
|--------|----------|------------|
|
|
62
|
+
| GET | Retrieve resources | Yes |
|
|
63
|
+
| POST | Create new resources | No |
|
|
64
|
+
| PUT | Replace entire resource | Yes |
|
|
65
|
+
| PATCH | Partial update | Yes |
|
|
66
|
+
| DELETE | Remove resource | Yes |
|
|
67
|
+
|
|
68
|
+
### Resource Relationships
|
|
69
|
+
|
|
70
|
+
**Nested Resources**
|
|
71
|
+
```
|
|
72
|
+
# User's orders
|
|
73
|
+
GET /users/123/orders
|
|
74
|
+
|
|
75
|
+
# Order's items
|
|
76
|
+
GET /orders/456/items
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Keep Nesting Shallow**
|
|
80
|
+
```
|
|
81
|
+
# GOOD (max 2 levels)
|
|
82
|
+
GET /users/123/orders
|
|
83
|
+
|
|
84
|
+
# BAD (too deep)
|
|
85
|
+
GET /users/123/orders/456/items/789/variants
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Request & Response Design
|
|
89
|
+
|
|
90
|
+
### Request Body
|
|
91
|
+
|
|
92
|
+
**POST/PUT Request**
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"name": "John Doe",
|
|
96
|
+
"email": "john@example.com",
|
|
97
|
+
"role": "admin"
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**PATCH Request (Partial Update)**
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"name": "Jane Doe"
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Response Format
|
|
109
|
+
|
|
110
|
+
**Single Resource**
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"id": "123",
|
|
114
|
+
"name": "John Doe",
|
|
115
|
+
"email": "john@example.com",
|
|
116
|
+
"createdAt": "2024-01-15T10:30:00Z",
|
|
117
|
+
"updatedAt": "2024-01-20T14:45:00Z"
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**Collection with Pagination**
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"data": [
|
|
125
|
+
{ "id": "1", "name": "Item 1" },
|
|
126
|
+
{ "id": "2", "name": "Item 2" }
|
|
127
|
+
],
|
|
128
|
+
"pagination": {
|
|
129
|
+
"page": 1,
|
|
130
|
+
"perPage": 20,
|
|
131
|
+
"total": 150,
|
|
132
|
+
"totalPages": 8
|
|
133
|
+
},
|
|
134
|
+
"links": {
|
|
135
|
+
"self": "/items?page=1",
|
|
136
|
+
"next": "/items?page=2",
|
|
137
|
+
"last": "/items?page=8"
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Status Codes
|
|
143
|
+
|
|
144
|
+
### Success Codes
|
|
145
|
+
- **200 OK** - Successful GET, PUT, PATCH
|
|
146
|
+
- **201 Created** - Successful POST with new resource
|
|
147
|
+
- **204 No Content** - Successful DELETE
|
|
148
|
+
|
|
149
|
+
### Client Error Codes
|
|
150
|
+
- **400 Bad Request** - Invalid request body
|
|
151
|
+
- **401 Unauthorized** - Missing/invalid authentication
|
|
152
|
+
- **403 Forbidden** - Authenticated but not authorized
|
|
153
|
+
- **404 Not Found** - Resource doesn't exist
|
|
154
|
+
- **409 Conflict** - Resource conflict (duplicate)
|
|
155
|
+
- **422 Unprocessable Entity** - Validation errors
|
|
156
|
+
|
|
157
|
+
### Server Error Codes
|
|
158
|
+
- **500 Internal Server Error** - Server-side error
|
|
159
|
+
- **503 Service Unavailable** - Temporary outage
|
|
160
|
+
|
|
161
|
+
## Error Handling
|
|
162
|
+
|
|
163
|
+
### Error Response Format
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
"error": {
|
|
167
|
+
"code": "VALIDATION_ERROR",
|
|
168
|
+
"message": "Validation failed",
|
|
169
|
+
"details": [
|
|
170
|
+
{
|
|
171
|
+
"field": "email",
|
|
172
|
+
"message": "Invalid email format"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"field": "name",
|
|
176
|
+
"message": "Name is required"
|
|
177
|
+
}
|
|
178
|
+
]
|
|
179
|
+
},
|
|
180
|
+
"requestId": "req_abc123"
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Error Code Convention
|
|
185
|
+
```javascript
|
|
186
|
+
// Define consistent error codes
|
|
187
|
+
const ErrorCodes = {
|
|
188
|
+
VALIDATION_ERROR: 'VALIDATION_ERROR',
|
|
189
|
+
NOT_FOUND: 'NOT_FOUND',
|
|
190
|
+
UNAUTHORIZED: 'UNAUTHORIZED',
|
|
191
|
+
FORBIDDEN: 'FORBIDDEN',
|
|
192
|
+
CONFLICT: 'CONFLICT',
|
|
193
|
+
INTERNAL_ERROR: 'INTERNAL_ERROR',
|
|
194
|
+
};
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Authentication
|
|
198
|
+
|
|
199
|
+
### JWT Authentication
|
|
200
|
+
```
|
|
201
|
+
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### API Key Authentication
|
|
205
|
+
```
|
|
206
|
+
X-API-Key: your-api-key
|
|
207
|
+
```
|
|
208
|
+
or
|
|
209
|
+
```
|
|
210
|
+
Authorization: ApiKey your-api-key
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Versioning
|
|
214
|
+
|
|
215
|
+
### URL Versioning (Recommended)
|
|
216
|
+
```
|
|
217
|
+
/api/v1/users
|
|
218
|
+
/api/v2/users
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Header Versioning
|
|
222
|
+
```
|
|
223
|
+
Accept: application/vnd.api+json;version=1
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## Filtering, Sorting & Pagination
|
|
227
|
+
|
|
228
|
+
### Filtering
|
|
229
|
+
```
|
|
230
|
+
GET /users?status=active&role=admin
|
|
231
|
+
GET /products?price[gte]=100&price[lte]=500
|
|
232
|
+
GET /orders?createdAt[after]=2024-01-01
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Sorting
|
|
236
|
+
```
|
|
237
|
+
GET /users?sort=name # Ascending
|
|
238
|
+
GET /users?sort=-createdAt # Descending
|
|
239
|
+
GET /users?sort=role,-name # Multiple fields
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Pagination
|
|
243
|
+
|
|
244
|
+
**Offset-based**
|
|
245
|
+
```
|
|
246
|
+
GET /users?page=2&perPage=20
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
**Cursor-based (for large datasets)**
|
|
250
|
+
```
|
|
251
|
+
GET /users?cursor=abc123&limit=20
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## Rate Limiting
|
|
255
|
+
|
|
256
|
+
### Response Headers
|
|
257
|
+
```
|
|
258
|
+
X-RateLimit-Limit: 1000
|
|
259
|
+
X-RateLimit-Remaining: 998
|
|
260
|
+
X-RateLimit-Reset: 1640000000
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Rate Limit Error
|
|
264
|
+
```json
|
|
265
|
+
{
|
|
266
|
+
"error": {
|
|
267
|
+
"code": "RATE_LIMIT_EXCEEDED",
|
|
268
|
+
"message": "Too many requests",
|
|
269
|
+
"retryAfter": 60
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## API Documentation
|
|
275
|
+
|
|
276
|
+
### OpenAPI Specification
|
|
277
|
+
```yaml
|
|
278
|
+
openapi: 3.0.0
|
|
279
|
+
info:
|
|
280
|
+
title: User API
|
|
281
|
+
version: 1.0.0
|
|
282
|
+
|
|
283
|
+
paths:
|
|
284
|
+
/users:
|
|
285
|
+
get:
|
|
286
|
+
summary: List all users
|
|
287
|
+
parameters:
|
|
288
|
+
- name: page
|
|
289
|
+
in: query
|
|
290
|
+
schema:
|
|
291
|
+
type: integer
|
|
292
|
+
default: 1
|
|
293
|
+
responses:
|
|
294
|
+
'200':
|
|
295
|
+
description: Successful response
|
|
296
|
+
content:
|
|
297
|
+
application/json:
|
|
298
|
+
schema:
|
|
299
|
+
$ref: '#/components/schemas/UserList'
|
|
300
|
+
|
|
301
|
+
components:
|
|
302
|
+
schemas:
|
|
303
|
+
User:
|
|
304
|
+
type: object
|
|
305
|
+
properties:
|
|
306
|
+
id:
|
|
307
|
+
type: string
|
|
308
|
+
name:
|
|
309
|
+
type: string
|
|
310
|
+
email:
|
|
311
|
+
type: string
|
|
312
|
+
format: email
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## Implementation Example
|
|
316
|
+
|
|
317
|
+
### Express.js API
|
|
318
|
+
```javascript
|
|
319
|
+
const express = require('express');
|
|
320
|
+
const app = express();
|
|
321
|
+
|
|
322
|
+
// GET /users
|
|
323
|
+
app.get('/api/v1/users', async (req, res) => {
|
|
324
|
+
try {
|
|
325
|
+
const { page = 1, perPage = 20, sort, status } = req.query;
|
|
326
|
+
|
|
327
|
+
const users = await User.findMany({
|
|
328
|
+
where: status ? { status } : undefined,
|
|
329
|
+
skip: (page - 1) * perPage,
|
|
330
|
+
take: perPage,
|
|
331
|
+
orderBy: parseSort(sort),
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
const total = await User.count();
|
|
335
|
+
|
|
336
|
+
res.json({
|
|
337
|
+
data: users,
|
|
338
|
+
pagination: {
|
|
339
|
+
page: Number(page),
|
|
340
|
+
perPage: Number(perPage),
|
|
341
|
+
total,
|
|
342
|
+
totalPages: Math.ceil(total / perPage),
|
|
343
|
+
},
|
|
344
|
+
});
|
|
345
|
+
} catch (error) {
|
|
346
|
+
res.status(500).json({
|
|
347
|
+
error: {
|
|
348
|
+
code: 'INTERNAL_ERROR',
|
|
349
|
+
message: 'An error occurred',
|
|
350
|
+
},
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
// POST /users
|
|
356
|
+
app.post('/api/v1/users', async (req, res) => {
|
|
357
|
+
try {
|
|
358
|
+
const { name, email } = req.body;
|
|
359
|
+
|
|
360
|
+
// Validation
|
|
361
|
+
const errors = validateUser({ name, email });
|
|
362
|
+
if (errors.length) {
|
|
363
|
+
return res.status(422).json({
|
|
364
|
+
error: {
|
|
365
|
+
code: 'VALIDATION_ERROR',
|
|
366
|
+
message: 'Validation failed',
|
|
367
|
+
details: errors,
|
|
368
|
+
},
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const user = await User.create({ name, email });
|
|
373
|
+
|
|
374
|
+
res.status(201).json(user);
|
|
375
|
+
} catch (error) {
|
|
376
|
+
if (error.code === 'P2002') {
|
|
377
|
+
return res.status(409).json({
|
|
378
|
+
error: {
|
|
379
|
+
code: 'CONFLICT',
|
|
380
|
+
message: 'User with this email already exists',
|
|
381
|
+
},
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
throw error;
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
## API Design Checklist
|
|
390
|
+
|
|
391
|
+
### Naming & Structure
|
|
392
|
+
- [ ] Resources use plural nouns
|
|
393
|
+
- [ ] URLs use kebab-case
|
|
394
|
+
- [ ] Relationships modeled with nested routes
|
|
395
|
+
- [ ] Nesting kept shallow (max 2 levels)
|
|
396
|
+
|
|
397
|
+
### Requests & Responses
|
|
398
|
+
- [ ] Consistent response format
|
|
399
|
+
- [ ] Appropriate HTTP methods used
|
|
400
|
+
- [ ] Status codes follow standards
|
|
401
|
+
- [ ] Error responses include code and details
|
|
402
|
+
|
|
403
|
+
### Features
|
|
404
|
+
- [ ] Filtering support
|
|
405
|
+
- [ ] Sorting support
|
|
406
|
+
- [ ] Pagination implemented
|
|
407
|
+
- [ ] Rate limiting configured
|
|
408
|
+
|
|
409
|
+
### Security
|
|
410
|
+
- [ ] Authentication required where needed
|
|
411
|
+
- [ ] Authorization checks in place
|
|
412
|
+
- [ ] Input validation on all endpoints
|
|
413
|
+
- [ ] Sensitive data not exposed
|
|
414
|
+
|
|
415
|
+
### Documentation
|
|
416
|
+
- [ ] OpenAPI spec maintained
|
|
417
|
+
- [ ] Examples provided
|
|
418
|
+
- [ ] Error codes documented
|
|
419
|
+
- [ ] Authentication documented
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-review
|
|
3
|
+
description: Guide for conducting thorough code reviews. Use when reviewing pull requests, providing feedback on code quality, checking for security issues, performance problems, or maintainability concerns. Includes checklists and best practices for effective code review.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Code Review Skill
|
|
7
|
+
|
|
8
|
+
This skill provides comprehensive guidance for conducting effective code reviews that improve code quality and team collaboration.
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
Code reviews serve multiple purposes: catching bugs, ensuring code quality, sharing knowledge, and maintaining consistency. This skill helps you conduct thorough, constructive reviews.
|
|
13
|
+
|
|
14
|
+
## Code Review Checklist
|
|
15
|
+
|
|
16
|
+
### Functionality
|
|
17
|
+
- [ ] Code does what it's supposed to do
|
|
18
|
+
- [ ] Edge cases are handled
|
|
19
|
+
- [ ] Error handling is appropriate
|
|
20
|
+
- [ ] No obvious bugs or logic errors
|
|
21
|
+
- [ ] Feature requirements are met
|
|
22
|
+
|
|
23
|
+
### Code Quality
|
|
24
|
+
- [ ] Code is readable and understandable
|
|
25
|
+
- [ ] Functions are focused and single-purpose
|
|
26
|
+
- [ ] No unnecessary complexity
|
|
27
|
+
- [ ] DRY principle followed (no excessive duplication)
|
|
28
|
+
- [ ] Naming is clear and consistent
|
|
29
|
+
|
|
30
|
+
### Security
|
|
31
|
+
- [ ] No hardcoded secrets or credentials
|
|
32
|
+
- [ ] Input validation is present
|
|
33
|
+
- [ ] SQL injection prevention (parameterized queries)
|
|
34
|
+
- [ ] XSS prevention (proper escaping)
|
|
35
|
+
- [ ] Authentication/authorization checks in place
|
|
36
|
+
- [ ] Sensitive data handled properly
|
|
37
|
+
|
|
38
|
+
### Performance
|
|
39
|
+
- [ ] No obvious performance issues
|
|
40
|
+
- [ ] Database queries are optimized
|
|
41
|
+
- [ ] No N+1 query problems
|
|
42
|
+
- [ ] Appropriate caching considerations
|
|
43
|
+
- [ ] Memory leaks addressed
|
|
44
|
+
|
|
45
|
+
### Testing
|
|
46
|
+
- [ ] Adequate test coverage
|
|
47
|
+
- [ ] Tests are meaningful (not just for coverage)
|
|
48
|
+
- [ ] Edge cases tested
|
|
49
|
+
- [ ] Tests are maintainable
|
|
50
|
+
|
|
51
|
+
### Documentation
|
|
52
|
+
- [ ] Complex logic is commented
|
|
53
|
+
- [ ] Public APIs are documented
|
|
54
|
+
- [ ] README updated if needed
|
|
55
|
+
- [ ] Breaking changes documented
|
|
56
|
+
|
|
57
|
+
## Feedback Guidelines
|
|
58
|
+
|
|
59
|
+
### Be Constructive
|
|
60
|
+
**Good:**
|
|
61
|
+
```
|
|
62
|
+
Consider using `Array.map()` here instead of a for loop -
|
|
63
|
+
it's more idiomatic and makes the transformation clearer.
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Avoid:**
|
|
67
|
+
```
|
|
68
|
+
This loop is wrong. Use map.
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Be Specific
|
|
72
|
+
**Good:**
|
|
73
|
+
```
|
|
74
|
+
This function is doing too much - it's handling both
|
|
75
|
+
validation and database operations. Consider splitting into
|
|
76
|
+
`validateUser()` and `saveUser()` for better testability.
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Avoid:**
|
|
80
|
+
```
|
|
81
|
+
Break this up.
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Ask Questions When Unsure
|
|
85
|
+
**Good:**
|
|
86
|
+
```
|
|
87
|
+
I'm not sure I understand the reason for this approach.
|
|
88
|
+
Could you explain why we're caching this result here?
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Acknowledge Good Work
|
|
92
|
+
```
|
|
93
|
+
Nice use of the builder pattern here!
|
|
94
|
+
Makes the complex object creation much more readable.
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Common Issues to Look For
|
|
98
|
+
|
|
99
|
+
### Security Issues
|
|
100
|
+
|
|
101
|
+
**Hardcoded Secrets**
|
|
102
|
+
```javascript
|
|
103
|
+
// BAD
|
|
104
|
+
const apiKey = "sk-1234567890abcdef";
|
|
105
|
+
|
|
106
|
+
// GOOD
|
|
107
|
+
const apiKey = process.env.API_KEY;
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**SQL Injection**
|
|
111
|
+
```javascript
|
|
112
|
+
// BAD
|
|
113
|
+
const query = `SELECT * FROM users WHERE id = ${userId}`;
|
|
114
|
+
|
|
115
|
+
// GOOD
|
|
116
|
+
const query = 'SELECT * FROM users WHERE id = $1';
|
|
117
|
+
await db.query(query, [userId]);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**XSS Vulnerabilities**
|
|
121
|
+
```javascript
|
|
122
|
+
// BAD
|
|
123
|
+
element.innerHTML = userInput;
|
|
124
|
+
|
|
125
|
+
// GOOD
|
|
126
|
+
element.textContent = userInput;
|
|
127
|
+
// or use proper sanitization
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Performance Issues
|
|
131
|
+
|
|
132
|
+
**N+1 Queries**
|
|
133
|
+
```javascript
|
|
134
|
+
// BAD
|
|
135
|
+
const users = await User.findAll();
|
|
136
|
+
for (const user of users) {
|
|
137
|
+
user.posts = await Post.findAll({ where: { userId: user.id } });
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// GOOD
|
|
141
|
+
const users = await User.findAll({
|
|
142
|
+
include: [{ model: Post }]
|
|
143
|
+
});
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Unnecessary Re-renders (React)**
|
|
147
|
+
```javascript
|
|
148
|
+
// BAD - creates new object every render
|
|
149
|
+
<Component style={{ color: 'red' }} />
|
|
150
|
+
|
|
151
|
+
// GOOD
|
|
152
|
+
const styles = { color: 'red' };
|
|
153
|
+
<Component style={styles} />
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Code Smells
|
|
157
|
+
|
|
158
|
+
**Long Functions**
|
|
159
|
+
- Over 50 lines usually means it should be split
|
|
160
|
+
- Hard to test, hard to understand
|
|
161
|
+
|
|
162
|
+
**Deep Nesting**
|
|
163
|
+
```javascript
|
|
164
|
+
// BAD
|
|
165
|
+
if (condition1) {
|
|
166
|
+
if (condition2) {
|
|
167
|
+
if (condition3) {
|
|
168
|
+
// do something
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// GOOD - early returns
|
|
174
|
+
if (!condition1) return;
|
|
175
|
+
if (!condition2) return;
|
|
176
|
+
if (!condition3) return;
|
|
177
|
+
// do something
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Magic Numbers**
|
|
181
|
+
```javascript
|
|
182
|
+
// BAD
|
|
183
|
+
if (user.age >= 18) { }
|
|
184
|
+
setTimeout(fn, 86400000);
|
|
185
|
+
|
|
186
|
+
// GOOD
|
|
187
|
+
const LEGAL_AGE = 18;
|
|
188
|
+
const ONE_DAY_MS = 24 * 60 * 60 * 1000;
|
|
189
|
+
if (user.age >= LEGAL_AGE) { }
|
|
190
|
+
setTimeout(fn, ONE_DAY_MS);
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Review Process
|
|
194
|
+
|
|
195
|
+
### Before Reviewing
|
|
196
|
+
1. Understand the context (read the PR description)
|
|
197
|
+
2. Understand what problem is being solved
|
|
198
|
+
3. Check related issues/tickets
|
|
199
|
+
|
|
200
|
+
### During Review
|
|
201
|
+
1. Start with high-level structure
|
|
202
|
+
2. Look for architectural issues first
|
|
203
|
+
3. Then dive into implementation details
|
|
204
|
+
4. Run the code locally if needed
|
|
205
|
+
5. Check test coverage
|
|
206
|
+
|
|
207
|
+
### After Review
|
|
208
|
+
1. Summarize your feedback
|
|
209
|
+
2. Indicate approval/changes needed clearly
|
|
210
|
+
3. Be available for discussion
|
|
211
|
+
|
|
212
|
+
## Handling Disagreements
|
|
213
|
+
|
|
214
|
+
### When You Disagree
|
|
215
|
+
1. Focus on technical merits, not preferences
|
|
216
|
+
2. Provide evidence or examples
|
|
217
|
+
3. Be open to being wrong
|
|
218
|
+
4. Escalate to team if needed
|
|
219
|
+
|
|
220
|
+
### When to Block vs Suggest
|
|
221
|
+
**Block for:**
|
|
222
|
+
- Security vulnerabilities
|
|
223
|
+
- Data loss risks
|
|
224
|
+
- Breaking changes without migration
|
|
225
|
+
- Critical bugs
|
|
226
|
+
|
|
227
|
+
**Suggest for:**
|
|
228
|
+
- Style preferences
|
|
229
|
+
- Minor optimizations
|
|
230
|
+
- Alternative approaches
|
|
231
|
+
|
|
232
|
+
## Review Response Templates
|
|
233
|
+
|
|
234
|
+
### Approval
|
|
235
|
+
```
|
|
236
|
+
LGTM! Clean implementation. One minor suggestion
|
|
237
|
+
that can be addressed in a follow-up PR: [suggestion]
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Request Changes
|
|
241
|
+
```
|
|
242
|
+
Good progress! A few things need addressing before merge:
|
|
243
|
+
|
|
244
|
+
1. [Critical] Security: Need to sanitize user input on line 45
|
|
245
|
+
2. [Important] The database query could cause N+1 issues
|
|
246
|
+
3. [Minor] Consider renaming `data` to `userData` for clarity
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Questions
|
|
250
|
+
```
|
|
251
|
+
Looks good overall. A few questions:
|
|
252
|
+
|
|
253
|
+
1. Why did we choose [approach A] over [approach B]?
|
|
254
|
+
2. How does this interact with [other feature]?
|
|
255
|
+
3. Are there any edge cases we should consider for [scenario]?
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Self-Review Checklist
|
|
259
|
+
|
|
260
|
+
Before submitting your own PR:
|
|
261
|
+
- [ ] Code compiles and runs
|
|
262
|
+
- [ ] All tests pass
|
|
263
|
+
- [ ] Linter shows no errors
|
|
264
|
+
- [ ] PR description is clear
|
|
265
|
+
- [ ] Changes are focused and atomic
|
|
266
|
+
- [ ] No debugging code left in
|
|
267
|
+
- [ ] Sensitive data not exposed
|