ai-devx 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/LICENSE +21 -0
- package/README.md +325 -0
- package/bin/cli.js +65 -0
- package/package.json +63 -0
- package/src/commands/init.js +86 -0
- package/src/commands/status.js +60 -0
- package/src/commands/update.js +77 -0
- package/src/config.js +72 -0
- package/src/utils/fileSystem.js +64 -0
- package/src/utils/logger.js +18 -0
- package/templates/.agent/.gitignore +6 -0
- package/templates/.agent/agents/backend-specialist.md +147 -0
- package/templates/.agent/agents/database-architect.md +164 -0
- package/templates/.agent/agents/debugger.md +128 -0
- package/templates/.agent/agents/devops-engineer.md +185 -0
- package/templates/.agent/agents/frontend-specialist.md +122 -0
- package/templates/.agent/agents/orchestrator.md +137 -0
- package/templates/.agent/agents/project-planner.md +127 -0
- package/templates/.agent/agents/security-auditor.md +122 -0
- package/templates/.agent/agents/test-engineer.md +176 -0
- package/templates/.agent/scripts/checklist.js +260 -0
- package/templates/.agent/scripts/security_scan.js +251 -0
- package/templates/.agent/skills/api-patterns/SKILL.md +236 -0
- package/templates/.agent/skills/database-design/SKILL.md +303 -0
- package/templates/.agent/skills/docker-expert/SKILL.md +286 -0
- package/templates/.agent/skills/react-best-practices/SKILL.md +246 -0
- package/templates/.agent/skills/testing-patterns/SKILL.md +262 -0
- package/templates/.agent/workflows/create.md +131 -0
- package/templates/.agent/workflows/debug.md +138 -0
- package/templates/.agent/workflows/deploy.md +163 -0
- package/templates/.agent/workflows/plan.md +153 -0
- package/templates/.agent/workflows/security.md +181 -0
- package/templates/.agent/workflows/test.md +165 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: api-patterns
|
|
3
|
+
description: REST API design patterns, authentication, and best practices
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
requires: []
|
|
6
|
+
related:
|
|
7
|
+
- backend-specialist
|
|
8
|
+
- security-best-practices
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# API Patterns Skill
|
|
12
|
+
|
|
13
|
+
## REST API Design
|
|
14
|
+
|
|
15
|
+
### Resource Naming
|
|
16
|
+
- Use nouns, not verbs
|
|
17
|
+
- Use plural forms
|
|
18
|
+
- Use kebab-case for multi-word resources
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
✅ GET /users
|
|
22
|
+
✅ GET /users/:id
|
|
23
|
+
✅ POST /users
|
|
24
|
+
✅ PUT /users/:id
|
|
25
|
+
✅ DELETE /users/:id
|
|
26
|
+
✅ GET /user-profiles
|
|
27
|
+
|
|
28
|
+
❌ GET /getUsers
|
|
29
|
+
❌ GET /getUserById
|
|
30
|
+
❌ POST /createUser
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### HTTP Methods
|
|
34
|
+
| Method | Action | Idempotent |
|
|
35
|
+
|--------|--------|------------|
|
|
36
|
+
| GET | Read | Yes |
|
|
37
|
+
| POST | Create | No |
|
|
38
|
+
| PUT | Update (full) | Yes |
|
|
39
|
+
| PATCH | Update (partial) | No |
|
|
40
|
+
| DELETE | Remove | Yes |
|
|
41
|
+
|
|
42
|
+
### Status Codes
|
|
43
|
+
- **200** - OK (GET, PUT, PATCH, DELETE)
|
|
44
|
+
- **201** - Created (POST)
|
|
45
|
+
- **204** - No Content (DELETE)
|
|
46
|
+
- **400** - Bad Request
|
|
47
|
+
- **401** - Unauthorized
|
|
48
|
+
- **403** - Forbidden
|
|
49
|
+
- **404** - Not Found
|
|
50
|
+
- **409** - Conflict
|
|
51
|
+
- **422** - Unprocessable Entity
|
|
52
|
+
- **500** - Internal Server Error
|
|
53
|
+
|
|
54
|
+
### Response Format
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"success": true,
|
|
58
|
+
"data": {
|
|
59
|
+
"id": "123",
|
|
60
|
+
"name": "John Doe"
|
|
61
|
+
},
|
|
62
|
+
"meta": {
|
|
63
|
+
"page": 1,
|
|
64
|
+
"limit": 10,
|
|
65
|
+
"total": 100
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Error Response
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"success": false,
|
|
74
|
+
"error": {
|
|
75
|
+
"code": "VALIDATION_ERROR",
|
|
76
|
+
"message": "Invalid input data",
|
|
77
|
+
"details": [
|
|
78
|
+
{
|
|
79
|
+
"field": "email",
|
|
80
|
+
"message": "Invalid email format"
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Authentication Patterns
|
|
88
|
+
|
|
89
|
+
### JWT Authentication
|
|
90
|
+
```typescript
|
|
91
|
+
// Login endpoint
|
|
92
|
+
POST /auth/login
|
|
93
|
+
{
|
|
94
|
+
"email": "user@example.com",
|
|
95
|
+
"password": "password123"
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Response
|
|
99
|
+
{
|
|
100
|
+
"success": true,
|
|
101
|
+
"data": {
|
|
102
|
+
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
|
|
103
|
+
"refreshToken": "eyJhbGciOiJIUzI1NiIs...",
|
|
104
|
+
"expiresIn": 3600
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Protected endpoint
|
|
109
|
+
GET /users
|
|
110
|
+
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### API Key Authentication
|
|
114
|
+
```
|
|
115
|
+
GET /api/resources
|
|
116
|
+
X-API-Key: your-api-key-here
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Pagination Patterns
|
|
120
|
+
|
|
121
|
+
### Offset Pagination
|
|
122
|
+
```
|
|
123
|
+
GET /users?page=1&limit=20
|
|
124
|
+
|
|
125
|
+
Response:
|
|
126
|
+
{
|
|
127
|
+
"data": [...],
|
|
128
|
+
"meta": {
|
|
129
|
+
"page": 1,
|
|
130
|
+
"limit": 20,
|
|
131
|
+
"total": 100,
|
|
132
|
+
"totalPages": 5
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Cursor Pagination
|
|
138
|
+
```
|
|
139
|
+
GET /users?cursor=xyz&limit=20
|
|
140
|
+
|
|
141
|
+
Response:
|
|
142
|
+
{
|
|
143
|
+
"data": [...],
|
|
144
|
+
"meta": {
|
|
145
|
+
"nextCursor": "abc",
|
|
146
|
+
"hasMore": true
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Filtering & Sorting
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
GET /users?role=admin&status=active&sort=-created_at,name
|
|
155
|
+
|
|
156
|
+
// Multiple filters (OR)
|
|
157
|
+
GET /users?role=admin,moderator
|
|
158
|
+
|
|
159
|
+
// Range filters
|
|
160
|
+
GET /orders?created_at[gte]=2024-01-01&created_at[lte]=2024-12-31
|
|
161
|
+
|
|
162
|
+
// Full-text search
|
|
163
|
+
GET /products?q=laptop&category=electronics
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Validation Patterns
|
|
167
|
+
|
|
168
|
+
### Input Validation
|
|
169
|
+
```typescript
|
|
170
|
+
// Using Zod
|
|
171
|
+
const createUserSchema = z.object({
|
|
172
|
+
email: z.string().email(),
|
|
173
|
+
password: z.string().min(8),
|
|
174
|
+
name: z.string().min(1).max(100),
|
|
175
|
+
age: z.number().int().min(0).optional()
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// Middleware
|
|
179
|
+
app.post('/users', validate(createUserSchema), createUserHandler);
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Rate Limiting
|
|
183
|
+
```
|
|
184
|
+
Headers:
|
|
185
|
+
X-RateLimit-Limit: 100
|
|
186
|
+
X-RateLimit-Remaining: 95
|
|
187
|
+
X-RateLimit-Reset: 1640995200
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## API Versioning
|
|
191
|
+
|
|
192
|
+
### URL Versioning
|
|
193
|
+
```
|
|
194
|
+
/api/v1/users
|
|
195
|
+
/api/v2/users
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Header Versioning
|
|
199
|
+
```
|
|
200
|
+
Accept: application/vnd.api+json;version=1
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Best Practices
|
|
204
|
+
|
|
205
|
+
### 1. Idempotency
|
|
206
|
+
```
|
|
207
|
+
Idempotency-Key: unique-key-for-request
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### 2. Caching Headers
|
|
211
|
+
```
|
|
212
|
+
Cache-Control: max-age=3600
|
|
213
|
+
ETag: "abc123"
|
|
214
|
+
Last-Modified: Wed, 21 Oct 2024 07:28:00 GMT
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### 3. Request IDs
|
|
218
|
+
```
|
|
219
|
+
X-Request-ID: uuid-for-tracing
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### 4. Documentation
|
|
223
|
+
- Use OpenAPI/Swagger
|
|
224
|
+
- Include examples
|
|
225
|
+
- Document error cases
|
|
226
|
+
|
|
227
|
+
## Security Checklist
|
|
228
|
+
- [ ] HTTPS only
|
|
229
|
+
- [ ] Input validation
|
|
230
|
+
- [ ] Authentication on protected routes
|
|
231
|
+
- [ ] Authorization checks
|
|
232
|
+
- [ ] Rate limiting
|
|
233
|
+
- [ ] CORS configuration
|
|
234
|
+
- [ ] Security headers
|
|
235
|
+
- [ ] SQL injection prevention
|
|
236
|
+
- [ ] XSS protection
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: database-design
|
|
3
|
+
description: Database schema design, normalization, and optimization patterns
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
requires: []
|
|
6
|
+
related:
|
|
7
|
+
- backend-specialist
|
|
8
|
+
- sql-optimization
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Database Design Skill
|
|
12
|
+
|
|
13
|
+
## Design Principles
|
|
14
|
+
|
|
15
|
+
### ACID Properties
|
|
16
|
+
- **Atomicity**: All operations succeed or fail together
|
|
17
|
+
- **Consistency**: Database remains in valid state
|
|
18
|
+
- **Isolation**: Concurrent transactions don't interfere
|
|
19
|
+
- **Durability**: Committed data persists
|
|
20
|
+
|
|
21
|
+
### Normalization
|
|
22
|
+
|
|
23
|
+
#### 1NF - First Normal Form
|
|
24
|
+
- Atomic values (no arrays/objects in columns)
|
|
25
|
+
- Each cell contains single value
|
|
26
|
+
|
|
27
|
+
```sql
|
|
28
|
+
-- ❌ Not 1NF
|
|
29
|
+
CREATE TABLE orders (
|
|
30
|
+
id INT PRIMARY KEY,
|
|
31
|
+
items VARCHAR(255) -- "item1, item2, item3"
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
-- ✅ 1NF
|
|
35
|
+
CREATE TABLE order_items (
|
|
36
|
+
order_id INT,
|
|
37
|
+
item_name VARCHAR(255),
|
|
38
|
+
quantity INT
|
|
39
|
+
);
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
#### 2NF - Second Normal Form
|
|
43
|
+
- Must be in 1NF
|
|
44
|
+
- No partial dependencies (non-key columns depend on full PK)
|
|
45
|
+
|
|
46
|
+
```sql
|
|
47
|
+
-- ❌ Not 2NF (price depends only on product_id, not order_id)
|
|
48
|
+
CREATE TABLE order_items (
|
|
49
|
+
order_id INT,
|
|
50
|
+
product_id INT,
|
|
51
|
+
product_name VARCHAR(255),
|
|
52
|
+
product_price DECIMAL,
|
|
53
|
+
quantity INT,
|
|
54
|
+
PRIMARY KEY (order_id, product_id)
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
-- ✅ 2NF
|
|
58
|
+
CREATE TABLE products (
|
|
59
|
+
id INT PRIMARY KEY,
|
|
60
|
+
name VARCHAR(255),
|
|
61
|
+
price DECIMAL
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
CREATE TABLE order_items (
|
|
65
|
+
order_id INT,
|
|
66
|
+
product_id INT,
|
|
67
|
+
quantity INT,
|
|
68
|
+
PRIMARY KEY (order_id, product_id)
|
|
69
|
+
);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
#### 3NF - Third Normal Form
|
|
73
|
+
- Must be in 2NF
|
|
74
|
+
- No transitive dependencies
|
|
75
|
+
|
|
76
|
+
```sql
|
|
77
|
+
-- ❌ Not 3NF (category_description depends on category, not directly on product)
|
|
78
|
+
CREATE TABLE products (
|
|
79
|
+
id INT PRIMARY KEY,
|
|
80
|
+
name VARCHAR(255),
|
|
81
|
+
category VARCHAR(255),
|
|
82
|
+
category_description TEXT
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
-- ✅ 3NF
|
|
86
|
+
CREATE TABLE categories (
|
|
87
|
+
id INT PRIMARY KEY,
|
|
88
|
+
name VARCHAR(255),
|
|
89
|
+
description TEXT
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
CREATE TABLE products (
|
|
93
|
+
id INT PRIMARY KEY,
|
|
94
|
+
name VARCHAR(255),
|
|
95
|
+
category_id INT,
|
|
96
|
+
FOREIGN KEY (category_id) REFERENCES categories(id)
|
|
97
|
+
);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Schema Design Patterns
|
|
101
|
+
|
|
102
|
+
### User Management
|
|
103
|
+
```sql
|
|
104
|
+
CREATE TABLE users (
|
|
105
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
106
|
+
email VARCHAR(255) UNIQUE NOT NULL,
|
|
107
|
+
password_hash VARCHAR(255) NOT NULL,
|
|
108
|
+
name VARCHAR(255) NOT NULL,
|
|
109
|
+
role VARCHAR(50) DEFAULT 'user',
|
|
110
|
+
is_active BOOLEAN DEFAULT true,
|
|
111
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
112
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
CREATE TABLE user_profiles (
|
|
116
|
+
user_id UUID PRIMARY KEY,
|
|
117
|
+
bio TEXT,
|
|
118
|
+
avatar_url VARCHAR(500),
|
|
119
|
+
phone VARCHAR(20),
|
|
120
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
121
|
+
);
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### E-Commerce
|
|
125
|
+
```sql
|
|
126
|
+
CREATE TABLE products (
|
|
127
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
128
|
+
name VARCHAR(255) NOT NULL,
|
|
129
|
+
description TEXT,
|
|
130
|
+
price DECIMAL(10,2) NOT NULL,
|
|
131
|
+
stock_quantity INT DEFAULT 0,
|
|
132
|
+
category_id UUID,
|
|
133
|
+
is_active BOOLEAN DEFAULT true,
|
|
134
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
CREATE TABLE orders (
|
|
138
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
139
|
+
user_id UUID NOT NULL,
|
|
140
|
+
status VARCHAR(50) DEFAULT 'pending',
|
|
141
|
+
total_amount DECIMAL(10,2) NOT NULL,
|
|
142
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
143
|
+
FOREIGN KEY (user_id) REFERENCES users(id)
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
CREATE TABLE order_items (
|
|
147
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
148
|
+
order_id UUID NOT NULL,
|
|
149
|
+
product_id UUID NOT NULL,
|
|
150
|
+
quantity INT NOT NULL,
|
|
151
|
+
unit_price DECIMAL(10,2) NOT NULL,
|
|
152
|
+
FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE,
|
|
153
|
+
FOREIGN KEY (product_id) REFERENCES products(id)
|
|
154
|
+
);
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Many-to-Many Relationships
|
|
158
|
+
```sql
|
|
159
|
+
-- Users and Roles (Many-to-Many)
|
|
160
|
+
CREATE TABLE roles (
|
|
161
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
162
|
+
name VARCHAR(100) UNIQUE NOT NULL,
|
|
163
|
+
permissions JSONB
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
CREATE TABLE user_roles (
|
|
167
|
+
user_id UUID,
|
|
168
|
+
role_id UUID,
|
|
169
|
+
assigned_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
170
|
+
PRIMARY KEY (user_id, role_id),
|
|
171
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
172
|
+
FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE
|
|
173
|
+
);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Indexing Strategy
|
|
177
|
+
|
|
178
|
+
### When to Index
|
|
179
|
+
- Primary keys (automatic)
|
|
180
|
+
- Foreign keys
|
|
181
|
+
- Columns in WHERE clauses
|
|
182
|
+
- Columns in ORDER BY
|
|
183
|
+
- Columns in JOIN conditions
|
|
184
|
+
|
|
185
|
+
### Index Types
|
|
186
|
+
```sql
|
|
187
|
+
-- B-Tree Index (default)
|
|
188
|
+
CREATE INDEX idx_users_email ON users(email);
|
|
189
|
+
|
|
190
|
+
-- Unique Index
|
|
191
|
+
CREATE UNIQUE INDEX idx_users_email_unique ON users(email);
|
|
192
|
+
|
|
193
|
+
-- Composite Index
|
|
194
|
+
CREATE INDEX idx_orders_user_status ON orders(user_id, status);
|
|
195
|
+
|
|
196
|
+
-- Partial Index
|
|
197
|
+
CREATE INDEX idx_active_users ON users(email) WHERE is_active = true;
|
|
198
|
+
|
|
199
|
+
-- GIN Index (for JSONB, arrays)
|
|
200
|
+
CREATE INDEX idx_products_tags ON products USING GIN(tags);
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Index Best Practices
|
|
204
|
+
- Don't over-index (slows writes)
|
|
205
|
+
- Consider index selectivity
|
|
206
|
+
- Index order matters in composite indexes
|
|
207
|
+
- Regularly review and remove unused indexes
|
|
208
|
+
|
|
209
|
+
## Prisma Schema Example
|
|
210
|
+
|
|
211
|
+
```prisma
|
|
212
|
+
model User {
|
|
213
|
+
id String @id @default(uuid())
|
|
214
|
+
email String @unique
|
|
215
|
+
password String
|
|
216
|
+
name String
|
|
217
|
+
role Role @default(USER)
|
|
218
|
+
isActive Boolean @default(true)
|
|
219
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
220
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
221
|
+
|
|
222
|
+
profile Profile?
|
|
223
|
+
posts Post[]
|
|
224
|
+
orders Order[]
|
|
225
|
+
|
|
226
|
+
@@map("users")
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
model Profile {
|
|
230
|
+
id String @id @default(uuid())
|
|
231
|
+
bio String?
|
|
232
|
+
avatar String?
|
|
233
|
+
|
|
234
|
+
userId String @unique @map("user_id")
|
|
235
|
+
user User @relation(fields: [userId], references: [id])
|
|
236
|
+
|
|
237
|
+
@@map("profiles")
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
model Post {
|
|
241
|
+
id String @id @default(uuid())
|
|
242
|
+
title String
|
|
243
|
+
content String?
|
|
244
|
+
published Boolean @default(false)
|
|
245
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
246
|
+
|
|
247
|
+
authorId String @map("author_id")
|
|
248
|
+
author User @relation(fields: [authorId], references: [id])
|
|
249
|
+
|
|
250
|
+
@@index([authorId])
|
|
251
|
+
@@map("posts")
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
enum Role {
|
|
255
|
+
USER
|
|
256
|
+
ADMIN
|
|
257
|
+
MODERATOR
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Migration Strategy
|
|
262
|
+
|
|
263
|
+
### Best Practices
|
|
264
|
+
1. Always create migrations for schema changes
|
|
265
|
+
2. Test migrations on staging first
|
|
266
|
+
3. Backup before major migrations
|
|
267
|
+
4. Keep migrations reversible
|
|
268
|
+
5. Document breaking changes
|
|
269
|
+
|
|
270
|
+
### Migration Example
|
|
271
|
+
```sql
|
|
272
|
+
-- Up
|
|
273
|
+
CREATE TABLE new_feature (
|
|
274
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
275
|
+
name VARCHAR(255) NOT NULL
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
-- Down
|
|
279
|
+
DROP TABLE IF EXISTS new_feature;
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## Query Optimization
|
|
283
|
+
|
|
284
|
+
### N+1 Problem
|
|
285
|
+
```typescript
|
|
286
|
+
// ❌ N+1 queries
|
|
287
|
+
const users = await prisma.user.findMany();
|
|
288
|
+
for (const user of users) {
|
|
289
|
+
const posts = await prisma.post.findMany({
|
|
290
|
+
where: { authorId: user.id }
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// ✅ Single query with join
|
|
295
|
+
const users = await prisma.user.findMany({
|
|
296
|
+
include: { posts: true }
|
|
297
|
+
});
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### EXPLAIN ANALYZE
|
|
301
|
+
```sql
|
|
302
|
+
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com';
|
|
303
|
+
```
|