@lenne.tech/cli 1.0.0 → 1.0.1
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/build/commands/claude/install-commands.js +332 -0
- package/build/commands/claude/install-skills.js +5 -1
- package/build/commands/server/add-property.js +22 -41
- package/build/extensions/server.js +142 -46
- package/build/templates/claude-commands/code-cleanup.md +82 -0
- package/build/templates/claude-commands/mr-description-clipboard.md +48 -0
- package/build/templates/claude-commands/mr-description.md +33 -0
- package/build/templates/claude-commands/sec-review.md +62 -0
- package/build/templates/claude-commands/skill-optimize.md +140 -0
- package/build/templates/claude-commands/test-generate.md +45 -0
- package/build/templates/claude-skills/nest-server-generator/SKILL.md +372 -1314
- package/build/templates/claude-skills/nest-server-generator/configuration.md +279 -0
- package/build/templates/claude-skills/nest-server-generator/declare-keyword-warning.md +124 -0
- package/build/templates/claude-skills/nest-server-generator/description-management.md +217 -0
- package/build/templates/claude-skills/nest-server-generator/examples.md +131 -5
- package/build/templates/claude-skills/nest-server-generator/quality-review.md +855 -0
- package/build/templates/claude-skills/nest-server-generator/reference.md +67 -13
- package/build/templates/claude-skills/nest-server-generator/security-rules.md +358 -0
- package/build/templates/claude-skills/story-tdd/SKILL.md +1173 -0
- package/build/templates/claude-skills/story-tdd/code-quality.md +266 -0
- package/build/templates/claude-skills/story-tdd/database-indexes.md +173 -0
- package/build/templates/claude-skills/story-tdd/examples.md +1332 -0
- package/build/templates/claude-skills/story-tdd/reference.md +1180 -0
- package/build/templates/claude-skills/story-tdd/security-review.md +299 -0
- package/package.json +1 -1
|
@@ -0,0 +1,1173 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: story-tdd
|
|
3
|
+
version: 1.0.2
|
|
4
|
+
description: Expert for Test-Driven Development (TDD) with NestJS and @lenne.tech/nest-server. Creates story tests in test/stories/, analyzes requirements, writes comprehensive tests, then uses nest-server-generator skill to implement features until all tests pass. Ensures high code quality and security compliance. Use in projects with @lenne.tech/nest-server in package.json dependencies (supports monorepos with projects/*, packages/*, apps/* structure).
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Story-Based Test-Driven Development Expert
|
|
8
|
+
|
|
9
|
+
You are an expert in Test-Driven Development (TDD) for NestJS applications using @lenne.tech/nest-server. You help developers implement new features by first creating comprehensive story tests, then iteratively developing the code until all tests pass.
|
|
10
|
+
|
|
11
|
+
## When to Use This Skill
|
|
12
|
+
|
|
13
|
+
**✅ ALWAYS use this skill for:**
|
|
14
|
+
- Implementing new API features using Test-Driven Development
|
|
15
|
+
- Creating story tests for user stories or requirements
|
|
16
|
+
- Developing new functionality in a test-first approach
|
|
17
|
+
- Ensuring comprehensive test coverage for new features
|
|
18
|
+
- Iterative development with test validation
|
|
19
|
+
|
|
20
|
+
**🔄 This skill works closely with:**
|
|
21
|
+
- `nest-server-generator` skill for code implementation (modules, objects, properties)
|
|
22
|
+
- Existing test suites for understanding patterns
|
|
23
|
+
- API documentation (Swagger/Controllers) for interface design
|
|
24
|
+
|
|
25
|
+
## Core TDD Workflow - The Seven Steps
|
|
26
|
+
|
|
27
|
+
This skill follows a rigorous 7-step iterative process (with Steps 5, 5a, 5b for final validation and refactoring):
|
|
28
|
+
|
|
29
|
+
### Step 1: Story Analysis & Validation
|
|
30
|
+
|
|
31
|
+
**Before writing ANY code or tests:**
|
|
32
|
+
|
|
33
|
+
1. **Read and analyze the complete user story/requirement**
|
|
34
|
+
- Identify all functional requirements
|
|
35
|
+
- List all acceptance criteria
|
|
36
|
+
- Note any technical constraints
|
|
37
|
+
|
|
38
|
+
2. **Understand existing API structure**
|
|
39
|
+
- Examine relevant Controllers (REST endpoints)
|
|
40
|
+
- Review Swagger documentation
|
|
41
|
+
- Check existing GraphQL resolvers if applicable
|
|
42
|
+
- Identify related modules and services
|
|
43
|
+
|
|
44
|
+
3. **Identify contradictions or ambiguities**
|
|
45
|
+
- Look for conflicting requirements
|
|
46
|
+
- Check for unclear specifications
|
|
47
|
+
- Verify if requirements match existing architecture
|
|
48
|
+
|
|
49
|
+
4. **Ask developer for clarification IMMEDIATELY if needed**
|
|
50
|
+
- Don't assume or guess requirements
|
|
51
|
+
- Clarify contradictions BEFORE writing tests
|
|
52
|
+
- Get confirmation on architectural decisions
|
|
53
|
+
- Verify security/permission requirements
|
|
54
|
+
|
|
55
|
+
**⚠️ CRITICAL:** If you find ANY contradictions or ambiguities, STOP and use AskUserQuestion to clarify BEFORE proceeding to Step 2.
|
|
56
|
+
|
|
57
|
+
### Step 2: Create Story Test
|
|
58
|
+
|
|
59
|
+
**⚠️ CRITICAL: Test Type Requirement**
|
|
60
|
+
|
|
61
|
+
**ONLY create API tests using TestHelper - NEVER create direct Service tests!**
|
|
62
|
+
|
|
63
|
+
- ✅ **DO:** Create tests that call REST endpoints or GraphQL queries/mutations using `TestHelper`
|
|
64
|
+
- ✅ **DO:** Test through the API layer (Controller/Resolver → Service → Database)
|
|
65
|
+
- ❌ **DON'T:** Create tests that directly instantiate or call Service methods
|
|
66
|
+
- ❌ **DON'T:** Create unit tests for Services (e.g., `user.service.spec.ts`)
|
|
67
|
+
- ❌ **DON'T:** Mock dependencies or bypass the API layer
|
|
68
|
+
|
|
69
|
+
**Why API tests only?**
|
|
70
|
+
- API tests validate the complete security model (decorators, guards, permissions)
|
|
71
|
+
- Direct Service tests bypass authentication and authorization checks
|
|
72
|
+
- TestHelper provides all necessary tools for comprehensive API testing
|
|
73
|
+
|
|
74
|
+
**Exception: Direct database/service access for test setup/cleanup ONLY**
|
|
75
|
+
|
|
76
|
+
Direct database or service access is ONLY allowed for:
|
|
77
|
+
|
|
78
|
+
- ✅ **Test Setup (beforeAll/beforeEach)**:
|
|
79
|
+
- Setting user roles in database: `await db.collection('users').updateOne({ _id: userId }, { $set: { roles: ['admin'] } })`
|
|
80
|
+
- Setting verified flag: `await db.collection('users').updateOne({ _id: userId }, { $set: { verified: true } })`
|
|
81
|
+
- Creating prerequisite test data that can't be created via API
|
|
82
|
+
|
|
83
|
+
- ✅ **Test Cleanup (afterAll/afterEach)**:
|
|
84
|
+
- Deleting test objects: `await db.collection('products').deleteMany({ createdBy: testUserId })`
|
|
85
|
+
- Cleaning up test data: `await db.collection('users').deleteOne({ email: 'test@example.com' })`
|
|
86
|
+
|
|
87
|
+
- ❌ **NEVER for testing functionality**:
|
|
88
|
+
- Don't call `userService.create()` to test user creation - use API endpoint!
|
|
89
|
+
- Don't call `productService.update()` to test updates - use API endpoint!
|
|
90
|
+
- Don't access database to verify results - query via API instead!
|
|
91
|
+
|
|
92
|
+
**Example of correct usage:**
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
describe('User Registration Story', () => {
|
|
96
|
+
let testHelper: TestHelper;
|
|
97
|
+
let db: Db;
|
|
98
|
+
let createdUserId: string;
|
|
99
|
+
|
|
100
|
+
beforeAll(async () => {
|
|
101
|
+
testHelper = new TestHelper(app);
|
|
102
|
+
db = app.get<Connection>(getConnectionToken()).db;
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
afterAll(async () => {
|
|
106
|
+
// ✅ ALLOWED: Direct DB access for cleanup
|
|
107
|
+
if (createdUserId) {
|
|
108
|
+
await db.collection('users').deleteOne({ _id: new ObjectId(createdUserId) });
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('should allow new user to register with valid data', async () => {
|
|
113
|
+
// ✅ CORRECT: Test via API
|
|
114
|
+
const result = await testHelper.rest('/auth/signup', {
|
|
115
|
+
method: 'POST',
|
|
116
|
+
payload: {
|
|
117
|
+
email: 'newuser@test.com',
|
|
118
|
+
password: 'SecurePass123!',
|
|
119
|
+
firstName: 'John',
|
|
120
|
+
lastName: 'Doe'
|
|
121
|
+
},
|
|
122
|
+
statusCode: 201
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
expect(result.id).toBeDefined();
|
|
126
|
+
expect(result.email).toBe('newuser@test.com');
|
|
127
|
+
createdUserId = result.id;
|
|
128
|
+
|
|
129
|
+
// ✅ ALLOWED: Set verified flag for subsequent tests
|
|
130
|
+
await db.collection('users').updateOne(
|
|
131
|
+
{ _id: new ObjectId(createdUserId) },
|
|
132
|
+
{ $set: { verified: true } }
|
|
133
|
+
);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('should allow verified user to sign in', async () => {
|
|
137
|
+
// ✅ CORRECT: Test via API
|
|
138
|
+
const result = await testHelper.rest('/auth/signin', {
|
|
139
|
+
method: 'POST',
|
|
140
|
+
payload: {
|
|
141
|
+
email: 'newuser@test.com',
|
|
142
|
+
password: 'SecurePass123!'
|
|
143
|
+
},
|
|
144
|
+
statusCode: 201
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
expect(result.token).toBeDefined();
|
|
148
|
+
expect(result.user.email).toBe('newuser@test.com');
|
|
149
|
+
|
|
150
|
+
// ❌ WRONG: Don't verify via direct DB access
|
|
151
|
+
// const dbUser = await db.collection('users').findOne({ email: 'newuser@test.com' });
|
|
152
|
+
|
|
153
|
+
// ✅ CORRECT: Verify via API
|
|
154
|
+
const profile = await testHelper.rest('/api/users/me', {
|
|
155
|
+
method: 'GET',
|
|
156
|
+
token: result.token,
|
|
157
|
+
statusCode: 200
|
|
158
|
+
});
|
|
159
|
+
expect(profile.email).toBe('newuser@test.com');
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
**Location:** `test/stories/` directory (create if it doesn't exist)
|
|
167
|
+
|
|
168
|
+
**Directory Creation:**
|
|
169
|
+
If the `test/stories/` directory doesn't exist yet, create it first:
|
|
170
|
+
```bash
|
|
171
|
+
mkdir -p test/stories
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Naming Convention:** `{feature-name}.story.test.ts`
|
|
175
|
+
- Example: `user-registration.story.test.ts`
|
|
176
|
+
- Example: `product-search.story.test.ts`
|
|
177
|
+
- Example: `order-processing.story.test.ts`
|
|
178
|
+
|
|
179
|
+
**Test Structure:**
|
|
180
|
+
|
|
181
|
+
1. **Study existing story tests** (if any exist in `test/stories/`)
|
|
182
|
+
- Follow established patterns and conventions
|
|
183
|
+
- Use similar setup/teardown approaches
|
|
184
|
+
- Match coding style and organization
|
|
185
|
+
|
|
186
|
+
2. **Study other test files** for patterns:
|
|
187
|
+
- Check `test/**/*.test.ts` files
|
|
188
|
+
- Understand authentication setup
|
|
189
|
+
- Learn data creation patterns
|
|
190
|
+
- See how API calls are made
|
|
191
|
+
|
|
192
|
+
3. **Write comprehensive story test** that includes:
|
|
193
|
+
- Clear test description matching the story
|
|
194
|
+
- Setup of test data and users
|
|
195
|
+
- All acceptance criteria as test cases
|
|
196
|
+
- Proper authentication/authorization
|
|
197
|
+
- Validation of responses and side effects
|
|
198
|
+
- Cleanup/teardown
|
|
199
|
+
|
|
200
|
+
4. **Ensure tests cover:**
|
|
201
|
+
- Happy path scenarios
|
|
202
|
+
- Edge cases
|
|
203
|
+
- Error conditions
|
|
204
|
+
- Security/permission checks
|
|
205
|
+
- Data validation
|
|
206
|
+
|
|
207
|
+
**Example test structure:**
|
|
208
|
+
```typescript
|
|
209
|
+
describe('User Registration Story', () => {
|
|
210
|
+
let createdUserIds: string[] = [];
|
|
211
|
+
let createdProductIds: string[] = [];
|
|
212
|
+
|
|
213
|
+
// Setup
|
|
214
|
+
beforeAll(async () => {
|
|
215
|
+
// Initialize test environment
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
afterAll(async () => {
|
|
219
|
+
// 🧹 CLEANUP: Delete ALL test data created during tests
|
|
220
|
+
// This prevents side effects on subsequent test runs
|
|
221
|
+
if (createdUserIds.length > 0) {
|
|
222
|
+
await db.collection('users').deleteMany({
|
|
223
|
+
_id: { $in: createdUserIds.map(id => new ObjectId(id)) }
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
if (createdProductIds.length > 0) {
|
|
227
|
+
await db.collection('products').deleteMany({
|
|
228
|
+
_id: { $in: createdProductIds.map(id => new ObjectId(id)) }
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it('should allow new user to register with valid data', async () => {
|
|
234
|
+
// Test implementation
|
|
235
|
+
const user = await createUser(...);
|
|
236
|
+
createdUserIds.push(user.id); // Track for cleanup
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it('should reject registration with invalid email', async () => {
|
|
240
|
+
// Test implementation
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it('should prevent duplicate email registration', async () => {
|
|
244
|
+
// Test implementation
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
**🚨 CRITICAL: Test Data Cleanup**
|
|
250
|
+
|
|
251
|
+
**ALWAYS implement comprehensive cleanup in your story tests!**
|
|
252
|
+
|
|
253
|
+
Test data that remains in the database can cause side effects in subsequent test runs, leading to:
|
|
254
|
+
- False positives/negatives in tests
|
|
255
|
+
- Flaky tests that pass/fail randomly
|
|
256
|
+
- Contaminated test database
|
|
257
|
+
- Hard-to-debug test failures
|
|
258
|
+
|
|
259
|
+
**Cleanup Strategy:**
|
|
260
|
+
|
|
261
|
+
1. **Track all created entities:**
|
|
262
|
+
```typescript
|
|
263
|
+
let createdUserIds: string[] = [];
|
|
264
|
+
let createdProductIds: string[] = [];
|
|
265
|
+
let createdOrderIds: string[] = [];
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
2. **Add IDs immediately after creation:**
|
|
269
|
+
```typescript
|
|
270
|
+
const user = await testHelper.rest('/api/users', {
|
|
271
|
+
method: 'POST',
|
|
272
|
+
payload: userData,
|
|
273
|
+
token: adminToken,
|
|
274
|
+
});
|
|
275
|
+
createdUserIds.push(user.id); // ✅ Track for cleanup
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
3. **Delete ALL created entities in afterAll:**
|
|
279
|
+
```typescript
|
|
280
|
+
afterAll(async () => {
|
|
281
|
+
// Clean up all test data
|
|
282
|
+
if (createdOrderIds.length > 0) {
|
|
283
|
+
await db.collection('orders').deleteMany({
|
|
284
|
+
_id: { $in: createdOrderIds.map(id => new ObjectId(id)) }
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
if (createdProductIds.length > 0) {
|
|
288
|
+
await db.collection('products').deleteMany({
|
|
289
|
+
_id: { $in: createdProductIds.map(id => new ObjectId(id)) }
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
if (createdUserIds.length > 0) {
|
|
293
|
+
await db.collection('users').deleteMany({
|
|
294
|
+
_id: { $in: createdUserIds.map(id => new ObjectId(id)) }
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
await connection.close();
|
|
299
|
+
await app.close();
|
|
300
|
+
});
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
4. **Clean up in correct order:**
|
|
304
|
+
- Delete child entities first (e.g., Orders before Products)
|
|
305
|
+
- Delete parent entities last (e.g., Users last)
|
|
306
|
+
- Consider foreign key relationships
|
|
307
|
+
|
|
308
|
+
5. **Handle cleanup errors gracefully:**
|
|
309
|
+
```typescript
|
|
310
|
+
afterAll(async () => {
|
|
311
|
+
try {
|
|
312
|
+
// Cleanup operations
|
|
313
|
+
if (createdUserIds.length > 0) {
|
|
314
|
+
await db.collection('users').deleteMany({
|
|
315
|
+
_id: { $in: createdUserIds.map(id => new ObjectId(id)) }
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
} catch (error) {
|
|
319
|
+
console.error('Cleanup failed:', error);
|
|
320
|
+
// Don't throw - cleanup failures shouldn't fail the test suite
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
await connection.close();
|
|
324
|
+
await app.close();
|
|
325
|
+
});
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
**What to clean up:**
|
|
329
|
+
- ✅ Users created during tests
|
|
330
|
+
- ✅ Products/Resources created during tests
|
|
331
|
+
- ✅ Orders/Transactions created during tests
|
|
332
|
+
- ✅ Any relationships (comments, reviews, etc.)
|
|
333
|
+
- ✅ Files uploaded during tests
|
|
334
|
+
- ✅ Any other test data that persists
|
|
335
|
+
|
|
336
|
+
**What NOT to clean up:**
|
|
337
|
+
- ❌ Global test users created in `beforeAll` that are reused (clean these once at the end)
|
|
338
|
+
- ❌ Database connections (close these separately)
|
|
339
|
+
- ❌ The app instance (close this separately)
|
|
340
|
+
|
|
341
|
+
### Step 3: Run Tests & Analyze Failures
|
|
342
|
+
|
|
343
|
+
**Execute all tests:**
|
|
344
|
+
```bash
|
|
345
|
+
npm test
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
**Or run specific story test:**
|
|
349
|
+
```bash
|
|
350
|
+
npm test -- test/stories/your-story.story.test.ts
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
**Analyze results:**
|
|
354
|
+
1. Record which tests fail and why
|
|
355
|
+
2. Identify if failures are due to:
|
|
356
|
+
- Missing implementation (expected)
|
|
357
|
+
- Test errors/bugs (needs fixing)
|
|
358
|
+
- Misunderstood requirements (needs clarification)
|
|
359
|
+
|
|
360
|
+
**Decision point:**
|
|
361
|
+
- If test has bugs/errors → Go to Step 3a
|
|
362
|
+
- If API implementation is missing/incomplete → Go to Step 4
|
|
363
|
+
|
|
364
|
+
**Debugging Test Failures:**
|
|
365
|
+
|
|
366
|
+
If test failures are unclear, enable debugging tools:
|
|
367
|
+
- **TestHelper:** Add `log: true, logError: true` to test options for detailed output
|
|
368
|
+
- **Server logging:** Set `logExceptions: true` in `src/config.env.ts`
|
|
369
|
+
- **Validation debugging:** Set `DEBUG_VALIDATION=true` environment variable
|
|
370
|
+
|
|
371
|
+
See **reference.md** for detailed debugging instructions and examples.
|
|
372
|
+
|
|
373
|
+
### Step 3a: Fix Test Errors (if needed)
|
|
374
|
+
|
|
375
|
+
**Only fix tests if:**
|
|
376
|
+
- Test logic is incorrect
|
|
377
|
+
- Test has programming errors
|
|
378
|
+
- Test makes nonsensical demands
|
|
379
|
+
- Test doesn't match actual requirements
|
|
380
|
+
|
|
381
|
+
**Do NOT "fix" tests by:**
|
|
382
|
+
- Removing security checks to make them pass
|
|
383
|
+
- Lowering expectations to match incomplete implementation
|
|
384
|
+
- Skipping test cases that should work
|
|
385
|
+
|
|
386
|
+
**After fixing tests:**
|
|
387
|
+
- Return to Step 3 (run tests again)
|
|
388
|
+
|
|
389
|
+
### Step 4: Implement/Extend API Code
|
|
390
|
+
|
|
391
|
+
**Use the `nest-server-generator` skill for implementation:**
|
|
392
|
+
|
|
393
|
+
1. **Analyze what's needed:**
|
|
394
|
+
- New modules? → Use `nest-server-generator`
|
|
395
|
+
- New objects? → Use `nest-server-generator`
|
|
396
|
+
- New properties? → Use `nest-server-generator`
|
|
397
|
+
- Code modifications? → Use `nest-server-generator`
|
|
398
|
+
|
|
399
|
+
2. **Understand existing codebase first:**
|
|
400
|
+
- Read relevant source files
|
|
401
|
+
- Study @lenne.tech/nest-server patterns (in `node_modules/@lenne.tech/nest-server/src`)
|
|
402
|
+
- Check CrudService base class for services (in `node_modules/@lenne.tech/nest-server/src/core/common/services/crud.service.ts`)
|
|
403
|
+
- Check RoleEnum (in the project or, if not available, in `node_modules/@lenne.tech/nest-server/src/core/common/enums/role.enum.ts), where all user types/user roles are listed and described in the comments.
|
|
404
|
+
- The decorators @Roles, @Restricted, and @UnifiedField, together with the checkSecurity method in the models, data preparation in MapAndValidatePipe (node_modules/@lenne.tech/nest-server/src/core/common/pipes/map-and-validate.pipe.ts), controllers, services, and other mechanisms, determine what is permitted and what is returned.
|
|
405
|
+
- Review existing similar implementations
|
|
406
|
+
|
|
407
|
+
3. **Implement equivalently to existing code:**
|
|
408
|
+
- Use TestHelper for REST oder GraphQL requests (in `node_modules/@lenne.tech/nest-server/src/test/test.helper.ts`)
|
|
409
|
+
- Match coding style and patterns
|
|
410
|
+
- Use same architectural approaches
|
|
411
|
+
- Follow established conventions
|
|
412
|
+
- Reuse existing utilities
|
|
413
|
+
|
|
414
|
+
4. **🔍 IMPORTANT: Database Indexes**
|
|
415
|
+
|
|
416
|
+
**Always define indexes directly in the @UnifiedField decorator via mongoose option!**
|
|
417
|
+
|
|
418
|
+
**Quick Guidelines:**
|
|
419
|
+
- Fields used in queries → Add `mongoose: { index: true, type: String }`
|
|
420
|
+
- Foreign keys → Add index
|
|
421
|
+
- Unique fields → Add `mongoose: { index: true, unique: true, type: String }`
|
|
422
|
+
- ⚠️ NEVER define indexes separately in schema files
|
|
423
|
+
|
|
424
|
+
**📖 For detailed index patterns and examples, see: `database-indexes.md`**
|
|
425
|
+
|
|
426
|
+
5. **Prefer existing packages:**
|
|
427
|
+
- Check if @lenne.tech/nest-server provides needed functionality
|
|
428
|
+
- Only add new npm packages as last resort
|
|
429
|
+
- If new package needed, verify:
|
|
430
|
+
- High quality and well-maintained
|
|
431
|
+
- Frequently used (npm downloads)
|
|
432
|
+
- Active maintenance
|
|
433
|
+
- Free license (preferably MIT)
|
|
434
|
+
- Long-term viability
|
|
435
|
+
|
|
436
|
+
### Step 5: Validate & Iterate
|
|
437
|
+
|
|
438
|
+
**Run ALL tests:**
|
|
439
|
+
```bash
|
|
440
|
+
npm test
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
**Check results:**
|
|
444
|
+
|
|
445
|
+
✅ **All tests pass?**
|
|
446
|
+
- Continue to Step 5a (Code Quality Check)
|
|
447
|
+
|
|
448
|
+
❌ **Some tests still fail?**
|
|
449
|
+
- Return to Step 3 (analyze failures)
|
|
450
|
+
- Continue iteration
|
|
451
|
+
|
|
452
|
+
### Step 5a: Code Quality & Refactoring Check
|
|
453
|
+
|
|
454
|
+
**BEFORE marking the task as complete, perform a code quality review!**
|
|
455
|
+
|
|
456
|
+
Once all tests are passing, analyze your implementation for code quality issues:
|
|
457
|
+
|
|
458
|
+
#### 1-3. Code Quality Review
|
|
459
|
+
|
|
460
|
+
**Check for:**
|
|
461
|
+
- Code duplication (extract to private methods if used 2+ times)
|
|
462
|
+
- Common functionality (create helper functions)
|
|
463
|
+
- Similar code paths (consolidate with flexible parameters)
|
|
464
|
+
- Consistency with existing patterns
|
|
465
|
+
|
|
466
|
+
**📖 For detailed refactoring patterns and examples, see: `code-quality.md`**
|
|
467
|
+
|
|
468
|
+
#### 4. Review for Consistency
|
|
469
|
+
|
|
470
|
+
**Ensure consistent patterns throughout your implementation:**
|
|
471
|
+
- Naming conventions match existing codebase
|
|
472
|
+
- Error handling follows project patterns
|
|
473
|
+
- Return types are consistent
|
|
474
|
+
- Similar operations use similar approaches
|
|
475
|
+
|
|
476
|
+
#### 4a. Check Database Indexes
|
|
477
|
+
|
|
478
|
+
**Verify that indexes are defined where needed:**
|
|
479
|
+
|
|
480
|
+
**Quick check:**
|
|
481
|
+
- Fields used in find/filter → Has index?
|
|
482
|
+
- Foreign keys (userId, productId, etc.) → Has index?
|
|
483
|
+
- Unique fields (email, username) → Has unique: true?
|
|
484
|
+
- Fields used in sorting → Has index?
|
|
485
|
+
|
|
486
|
+
**If indexes are missing:**
|
|
487
|
+
- Add to @UnifiedField decorator (mongoose option)
|
|
488
|
+
- Re-run tests
|
|
489
|
+
- Document query pattern
|
|
490
|
+
|
|
491
|
+
**📖 For detailed verification checklist, see: `database-indexes.md`**
|
|
492
|
+
|
|
493
|
+
#### 4b. Security Review
|
|
494
|
+
|
|
495
|
+
**🔐 CRITICAL: Perform security review before final testing!**
|
|
496
|
+
|
|
497
|
+
**ALWAYS review all code changes for security vulnerabilities.**
|
|
498
|
+
|
|
499
|
+
**Quick Security Check:**
|
|
500
|
+
- [ ] @Restricted/@Roles decorators NOT removed or weakened
|
|
501
|
+
- [ ] Ownership checks in place (users can only access own data)
|
|
502
|
+
- [ ] All inputs validated with proper DTOs
|
|
503
|
+
- [ ] Sensitive fields marked with hideField: true
|
|
504
|
+
- [ ] No injection vulnerabilities
|
|
505
|
+
- [ ] Error messages don't expose sensitive data
|
|
506
|
+
- [ ] Authorization tests pass
|
|
507
|
+
|
|
508
|
+
**Red Flags (STOP if found):**
|
|
509
|
+
- 🚩 @Restricted decorator removed
|
|
510
|
+
- 🚩 @Roles changed to more permissive
|
|
511
|
+
- 🚩 Missing ownership checks
|
|
512
|
+
- 🚩 Sensitive fields exposed
|
|
513
|
+
- 🚩 'any' type instead of DTO
|
|
514
|
+
|
|
515
|
+
**If ANY red flag found:**
|
|
516
|
+
1. STOP implementation
|
|
517
|
+
2. Fix security issue immediately
|
|
518
|
+
3. Re-run security checklist
|
|
519
|
+
4. Update tests to verify security
|
|
520
|
+
|
|
521
|
+
**📖 For complete security checklist with examples, see: `security-review.md`**
|
|
522
|
+
|
|
523
|
+
#### 5. Refactoring Decision Tree
|
|
524
|
+
|
|
525
|
+
```
|
|
526
|
+
Code duplication detected?
|
|
527
|
+
│
|
|
528
|
+
├─► Used in 2+ places?
|
|
529
|
+
│ │
|
|
530
|
+
│ ├─► YES: Extract to private method
|
|
531
|
+
│ │ │
|
|
532
|
+
│ │ └─► Used across multiple services?
|
|
533
|
+
│ │ │
|
|
534
|
+
│ │ ├─► YES: Consider utility class/function
|
|
535
|
+
│ │ └─► NO: Keep as private method
|
|
536
|
+
│ │
|
|
537
|
+
│ └─► NO: Leave as-is (don't over-engineer)
|
|
538
|
+
│
|
|
539
|
+
└─► Complex logic block?
|
|
540
|
+
│
|
|
541
|
+
├─► Hard to understand?
|
|
542
|
+
│ └─► Extract to well-named method
|
|
543
|
+
│
|
|
544
|
+
└─► Simple and clear?
|
|
545
|
+
└─► Leave as-is
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
#### 6. Run Tests After Refactoring & Security Review
|
|
549
|
+
|
|
550
|
+
**CRITICAL: After any refactoring, adding indexes, or security fixes:**
|
|
551
|
+
|
|
552
|
+
```bash
|
|
553
|
+
npm test
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
**Ensure:**
|
|
557
|
+
- ✅ All tests still pass
|
|
558
|
+
- ✅ No new failures introduced
|
|
559
|
+
- ✅ Code is more maintainable
|
|
560
|
+
- ✅ No functionality changed
|
|
561
|
+
- ✅ Indexes properly applied
|
|
562
|
+
- ✅ **Security checks still working (authorization tests pass)**
|
|
563
|
+
|
|
564
|
+
#### 7. When to Skip Refactoring
|
|
565
|
+
|
|
566
|
+
**Don't refactor if:**
|
|
567
|
+
- Code is used in only ONE place
|
|
568
|
+
- Extraction would make code harder to understand
|
|
569
|
+
- The duplication is coincidental, not conceptual
|
|
570
|
+
- Time constraints don't allow for safe refactoring
|
|
571
|
+
|
|
572
|
+
**Remember:**
|
|
573
|
+
- **Working code > Perfect code**
|
|
574
|
+
- **Refactor only if it improves maintainability**
|
|
575
|
+
- **Always run tests after refactoring**
|
|
576
|
+
- **Always add indexes where queries are performed**
|
|
577
|
+
|
|
578
|
+
### Step 5b: Final Validation
|
|
579
|
+
|
|
580
|
+
**After refactoring (or deciding not to refactor):**
|
|
581
|
+
|
|
582
|
+
1. **Run ALL tests one final time:**
|
|
583
|
+
```bash
|
|
584
|
+
npm test
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
2. **Verify:**
|
|
588
|
+
- ✅ All tests pass
|
|
589
|
+
- ✅ Test coverage is adequate
|
|
590
|
+
- ✅ Code follows project patterns
|
|
591
|
+
- ✅ No obvious duplication
|
|
592
|
+
- ✅ Clean and maintainable
|
|
593
|
+
- ✅ **Security review completed**
|
|
594
|
+
- ✅ **No security vulnerabilities introduced**
|
|
595
|
+
- ✅ **Authorization tests pass**
|
|
596
|
+
|
|
597
|
+
3. **Generate final report for developer**
|
|
598
|
+
|
|
599
|
+
4. **YOU'RE DONE!** 🎉
|
|
600
|
+
|
|
601
|
+
## 🔄 Handling Existing Tests When Modifying Code
|
|
602
|
+
|
|
603
|
+
**CRITICAL RULE:** When your code changes cause existing (non-story) tests to fail, you MUST analyze and handle this properly.
|
|
604
|
+
|
|
605
|
+
### Analysis Decision Tree
|
|
606
|
+
|
|
607
|
+
When existing tests fail after your changes:
|
|
608
|
+
|
|
609
|
+
```
|
|
610
|
+
Existing test fails
|
|
611
|
+
│
|
|
612
|
+
├─► Was this change intentional and breaking?
|
|
613
|
+
│ │
|
|
614
|
+
│ ├─► YES: Change was deliberate and it's clear why tests break
|
|
615
|
+
│ │ └─► ✅ Update the existing tests to reflect new behavior
|
|
616
|
+
│ │ - Modify test expectations
|
|
617
|
+
│ │ - Update test data/setup if needed
|
|
618
|
+
│ │ - Document why test was changed
|
|
619
|
+
│ │
|
|
620
|
+
│ └─► NO/UNCLEAR: Not sure why tests are breaking
|
|
621
|
+
│ └─► 🔍 Investigate potential side effect
|
|
622
|
+
│ │
|
|
623
|
+
│ ├─► Use git to review previous state:
|
|
624
|
+
│ │ - git show HEAD:path/to/file.ts
|
|
625
|
+
│ │ - git diff HEAD path/to/test.ts
|
|
626
|
+
│ │ - git log -p path/to/file.ts
|
|
627
|
+
│ │
|
|
628
|
+
│ ├─► Compare old vs new behavior
|
|
629
|
+
│ │
|
|
630
|
+
│ └─► ⚠️ Likely unintended side effect!
|
|
631
|
+
│ └─► Fix code to satisfy BOTH old AND new tests
|
|
632
|
+
│ - Refine implementation
|
|
633
|
+
│ - Add conditional logic if needed
|
|
634
|
+
│ - Ensure backward compatibility
|
|
635
|
+
│ - Keep existing functionality intact
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
### Using Git for Analysis (ALLOWED)
|
|
639
|
+
|
|
640
|
+
**✅ Git commands are EXPLICITLY ALLOWED for analysis:**
|
|
641
|
+
|
|
642
|
+
```bash
|
|
643
|
+
# View old version of a file
|
|
644
|
+
git show HEAD:src/server/modules/user/user.service.ts
|
|
645
|
+
|
|
646
|
+
# See what changed in a file
|
|
647
|
+
git diff HEAD src/server/modules/user/user.service.ts
|
|
648
|
+
|
|
649
|
+
# View file from specific commit
|
|
650
|
+
git show abc123:path/to/file.ts
|
|
651
|
+
|
|
652
|
+
# See commit history for a file
|
|
653
|
+
git log -p --follow path/to/file.ts
|
|
654
|
+
|
|
655
|
+
# Compare branches
|
|
656
|
+
git diff main..HEAD path/to/file.ts
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
**These commands help you understand:**
|
|
660
|
+
- What the code looked like before your changes
|
|
661
|
+
- What the previous test expectations were
|
|
662
|
+
- Why existing tests were written a certain way
|
|
663
|
+
- Whether your change introduces regression
|
|
664
|
+
|
|
665
|
+
### Examples
|
|
666
|
+
|
|
667
|
+
#### Example 1: Intentional Breaking Change
|
|
668
|
+
|
|
669
|
+
```typescript
|
|
670
|
+
// Scenario: You added a required field to User model
|
|
671
|
+
// Old test expects: { email, firstName }
|
|
672
|
+
// New behavior requires: { email, firstName, lastName }
|
|
673
|
+
|
|
674
|
+
// ✅ CORRECT: Update the test
|
|
675
|
+
it('should create user', async () => {
|
|
676
|
+
const user = await userService.create({
|
|
677
|
+
email: 'test@example.com',
|
|
678
|
+
firstName: 'John',
|
|
679
|
+
lastName: 'Doe', // ✅ Added required field
|
|
680
|
+
});
|
|
681
|
+
// ...
|
|
682
|
+
});
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
#### Example 2: Unintended Side Effect
|
|
686
|
+
|
|
687
|
+
```typescript
|
|
688
|
+
// Scenario: You changed authentication logic for new feature
|
|
689
|
+
// Old tests for different feature now fail unexpectedly
|
|
690
|
+
|
|
691
|
+
// ❌ WRONG: Just update the failing tests
|
|
692
|
+
// ✅ CORRECT: Investigate and fix the code
|
|
693
|
+
|
|
694
|
+
// 1. Use git to see old implementation
|
|
695
|
+
// git show HEAD:src/server/modules/auth/auth.service.ts
|
|
696
|
+
|
|
697
|
+
// 2. Identify the unintended side effect
|
|
698
|
+
// 3. Refine your code to avoid breaking existing functionality
|
|
699
|
+
|
|
700
|
+
// Example fix: Add conditional logic
|
|
701
|
+
async authenticate(user: User, options?: AuthOptions) {
|
|
702
|
+
// Your new feature logic
|
|
703
|
+
if (options?.useNewBehavior) {
|
|
704
|
+
return this.newAuthMethod(user);
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
// Preserve existing behavior for backward compatibility
|
|
708
|
+
return this.existingAuthMethod(user);
|
|
709
|
+
}
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
### Guidelines
|
|
713
|
+
|
|
714
|
+
**✅ DO update existing tests when:**
|
|
715
|
+
- You intentionally changed an API contract
|
|
716
|
+
- You removed deprecated functionality
|
|
717
|
+
- You renamed fields/methods
|
|
718
|
+
- The old behavior is being replaced (not extended)
|
|
719
|
+
- It's documented in your story requirements
|
|
720
|
+
|
|
721
|
+
**❌ DON'T update existing tests when:**
|
|
722
|
+
- You're not sure why they're failing
|
|
723
|
+
- The failure seems unrelated to your story
|
|
724
|
+
- Multiple unrelated tests are breaking
|
|
725
|
+
- The test was testing important existing functionality
|
|
726
|
+
|
|
727
|
+
**🔍 INVESTIGATE when:**
|
|
728
|
+
- More than 2-3 existing tests fail
|
|
729
|
+
- Tests in unrelated modules fail
|
|
730
|
+
- Test failure messages are unclear
|
|
731
|
+
- You suspect a side effect
|
|
732
|
+
|
|
733
|
+
### Process
|
|
734
|
+
|
|
735
|
+
1. **Run ALL tests** (not just story tests)
|
|
736
|
+
```bash
|
|
737
|
+
npm test
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
2. **If existing tests fail:**
|
|
741
|
+
```bash
|
|
742
|
+
# Identify which tests failed
|
|
743
|
+
# For each failing test, decide:
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
3. **For intentional changes:**
|
|
747
|
+
- Update test expectations
|
|
748
|
+
- Document change in commit message (when developer commits)
|
|
749
|
+
- Verify all tests pass
|
|
750
|
+
|
|
751
|
+
4. **For unclear failures:**
|
|
752
|
+
- Use `git show` to see old code
|
|
753
|
+
- Use `git diff` to see your changes
|
|
754
|
+
- Compare old vs new behavior
|
|
755
|
+
- Refine code to fix both old AND new tests
|
|
756
|
+
|
|
757
|
+
5. **Validate:**
|
|
758
|
+
```bash
|
|
759
|
+
# All tests (old + new) should pass
|
|
760
|
+
npm test
|
|
761
|
+
```
|
|
762
|
+
|
|
763
|
+
### Red Flags
|
|
764
|
+
|
|
765
|
+
🚩 **Warning signs of unintended side effects:**
|
|
766
|
+
- Tests in different modules failing
|
|
767
|
+
- Security/auth tests failing
|
|
768
|
+
- Tests that worked in `main` branch now fail
|
|
769
|
+
- Tests with names unrelated to your story failing
|
|
770
|
+
|
|
771
|
+
**When you see red flags:**
|
|
772
|
+
1. STOP updating tests
|
|
773
|
+
2. Use git to investigate
|
|
774
|
+
3. Fix the code, not the tests
|
|
775
|
+
4. Ask developer if uncertain
|
|
776
|
+
|
|
777
|
+
### Remember
|
|
778
|
+
|
|
779
|
+
- **Existing tests are documentation** of expected behavior
|
|
780
|
+
- **Don't break working functionality** to make new tests pass
|
|
781
|
+
- **Use git freely** for investigation (NOT for commits)
|
|
782
|
+
- **When in doubt, preserve backward compatibility**
|
|
783
|
+
|
|
784
|
+
---
|
|
785
|
+
|
|
786
|
+
## ⛔ CRITICAL: GIT COMMITS
|
|
787
|
+
|
|
788
|
+
**🚨 NEVER create git commits unless explicitly requested by the developer.**
|
|
789
|
+
|
|
790
|
+
This is a **NON-NEGOTIABLE RULE**:
|
|
791
|
+
|
|
792
|
+
1. ❌ **DO NOT** create git commits automatically after implementing features
|
|
793
|
+
2. ❌ **DO NOT** commit changes when tests pass
|
|
794
|
+
3. ❌ **DO NOT** assume the developer wants changes committed
|
|
795
|
+
4. ❌ **DO NOT** use git commands like `git add`, `git commit`, or `git push` unless explicitly asked
|
|
796
|
+
|
|
797
|
+
**✅ ONLY create git commits when:**
|
|
798
|
+
- The developer explicitly asks: "commit these changes"
|
|
799
|
+
- The developer explicitly asks: "create a commit"
|
|
800
|
+
- The developer explicitly asks: "commit this to git"
|
|
801
|
+
|
|
802
|
+
**Why this is important:**
|
|
803
|
+
- Developers may want to review changes before committing
|
|
804
|
+
- Developers may want to commit in specific chunks
|
|
805
|
+
- Developers may have custom commit workflows
|
|
806
|
+
- Automatic commits can disrupt developer workflows
|
|
807
|
+
|
|
808
|
+
**Your responsibility:**
|
|
809
|
+
- ✅ Create and modify files as needed
|
|
810
|
+
- ✅ Run tests and ensure they pass
|
|
811
|
+
- ✅ Provide a comprehensive report of changes
|
|
812
|
+
- ❌ **NEVER commit to git without explicit request**
|
|
813
|
+
|
|
814
|
+
**In your final report, you may remind the developer:**
|
|
815
|
+
```markdown
|
|
816
|
+
## Next Steps
|
|
817
|
+
The implementation is complete and all tests are passing.
|
|
818
|
+
You may want to review and commit these changes when ready.
|
|
819
|
+
```
|
|
820
|
+
|
|
821
|
+
**But NEVER execute git commands yourself unless explicitly requested.**
|
|
822
|
+
|
|
823
|
+
---
|
|
824
|
+
|
|
825
|
+
## 🚨 CRITICAL SECURITY RULES
|
|
826
|
+
|
|
827
|
+
### ⛔ NEVER Do This Without Explicit Approval:
|
|
828
|
+
|
|
829
|
+
1. **NEVER remove or weaken `@Restricted()` decorators**
|
|
830
|
+
2. **NEVER change `@Roles() or @UnifiedField({roles})` to more permissive roles**
|
|
831
|
+
3. **NEVER modify `securityCheck()` logic** to bypass security
|
|
832
|
+
4. **NEVER remove class-level security decorators**
|
|
833
|
+
5. **NEVER disable authentication for convenience**
|
|
834
|
+
|
|
835
|
+
### ✅ ALWAYS Do This:
|
|
836
|
+
|
|
837
|
+
1. **ALWAYS analyze existing security mechanisms** before writing tests
|
|
838
|
+
2. **ALWAYS create appropriate test users** with correct roles
|
|
839
|
+
3. **ALWAYS test with least-privileged users** who should have access
|
|
840
|
+
4. **ALWAYS ask developer before changing ANY security decorator**
|
|
841
|
+
5. **ALWAYS preserve existing security architecture**
|
|
842
|
+
|
|
843
|
+
### 🔑 When Tests Fail Due to Security:
|
|
844
|
+
|
|
845
|
+
**CORRECT approach:**
|
|
846
|
+
```typescript
|
|
847
|
+
// Create test user (every logged-in user has the Role.S_USER role)
|
|
848
|
+
const res = await testHelper.rest('/auth/signin', {
|
|
849
|
+
method: 'POST',
|
|
850
|
+
payload: {
|
|
851
|
+
email: gUserEmail,
|
|
852
|
+
password: gUserPassword,
|
|
853
|
+
},
|
|
854
|
+
statusCode: 201,
|
|
855
|
+
});
|
|
856
|
+
gUserToken = res.token;
|
|
857
|
+
|
|
858
|
+
// Verify user
|
|
859
|
+
await db.collection('users').updateOne({ _id: new ObjectId(res.id) }, { $set: { verified: true } });
|
|
860
|
+
|
|
861
|
+
// Or optionally specify additional roles (e.g., admin, if really necessary)
|
|
862
|
+
await db.collection('users').findOneAndUpdate({ _id: new ObjectId(res.id) }, { $set: { roles: ['admin'], verified: true } });
|
|
863
|
+
|
|
864
|
+
// Test with authenticated user via token
|
|
865
|
+
const result = testHelper.rest('/api/products', {
|
|
866
|
+
method: 'POST',
|
|
867
|
+
payload: input,
|
|
868
|
+
statusCode: 201,
|
|
869
|
+
token: gUserToken,
|
|
870
|
+
});
|
|
871
|
+
```
|
|
872
|
+
|
|
873
|
+
**WRONG approach (NEVER do this):**
|
|
874
|
+
```typescript
|
|
875
|
+
// ❌ DON'T remove @Restricted decorator from controller
|
|
876
|
+
// ❌ DON'T change @Roles(ADMIN) to @Roles(S_USER)
|
|
877
|
+
// ❌ DON'T disable authentication
|
|
878
|
+
```
|
|
879
|
+
|
|
880
|
+
## Code Quality Standards
|
|
881
|
+
|
|
882
|
+
### Must Follow Existing Patterns:
|
|
883
|
+
|
|
884
|
+
1. **File organization:** Match existing structure
|
|
885
|
+
2. **Naming conventions:** Follow established patterns
|
|
886
|
+
3. **Import statements:** Group and order like existing files
|
|
887
|
+
4. **Error handling:** Use same approach as existing code
|
|
888
|
+
5. **Validation:** Follow existing validation patterns
|
|
889
|
+
6. **Documentation:** Match existing comment style
|
|
890
|
+
|
|
891
|
+
### Minimize Dependencies:
|
|
892
|
+
|
|
893
|
+
1. **First choice:** Use @lenne.tech/nest-server capabilities
|
|
894
|
+
2. **Second choice:** Use existing project dependencies
|
|
895
|
+
3. **Last resort:** Add new packages (with justification)
|
|
896
|
+
|
|
897
|
+
### Test Quality:
|
|
898
|
+
|
|
899
|
+
1. **Coverage:** Aim for 80-100% depending on criticality
|
|
900
|
+
2. **Clarity:** Tests should be self-documenting
|
|
901
|
+
3. **Independence:** Tests should not depend on each other
|
|
902
|
+
4. **Repeatability:** Tests should produce consistent results
|
|
903
|
+
5. **Speed:** Tests should run reasonably fast
|
|
904
|
+
|
|
905
|
+
### 🚨 CRITICAL: NEVER USE `declare` KEYWORD FOR PROPERTIES
|
|
906
|
+
|
|
907
|
+
**⚠️ IMPORTANT RULE: DO NOT use the `declare` keyword when defining properties in classes!**
|
|
908
|
+
|
|
909
|
+
The `declare` keyword in TypeScript signals that a property is only a type declaration without a runtime value. This prevents decorators from being properly applied and overridden.
|
|
910
|
+
|
|
911
|
+
**❌ WRONG - Using `declare`:**
|
|
912
|
+
|
|
913
|
+
```typescript
|
|
914
|
+
export class ProductCreateInput extends ProductInput {
|
|
915
|
+
declare name: string; // ❌ WRONG - Decorator won't be applied!
|
|
916
|
+
declare price: number; // ❌ WRONG - Decorator won't be applied!
|
|
917
|
+
}
|
|
918
|
+
```
|
|
919
|
+
|
|
920
|
+
**✅ CORRECT - Without `declare`:**
|
|
921
|
+
|
|
922
|
+
```typescript
|
|
923
|
+
export class ProductCreateInput extends ProductInput {
|
|
924
|
+
@UnifiedField({ description: 'Product name' })
|
|
925
|
+
name: string; // ✅ CORRECT - Decorator works properly
|
|
926
|
+
|
|
927
|
+
@UnifiedField({ description: 'Product price' })
|
|
928
|
+
price: number; // ✅ CORRECT - Decorator works properly
|
|
929
|
+
}
|
|
930
|
+
```
|
|
931
|
+
|
|
932
|
+
**Why this matters:**
|
|
933
|
+
|
|
934
|
+
1. **Decorators require actual properties**: `@UnifiedField()`, `@Restricted()`, and other decorators need actual property declarations to attach metadata
|
|
935
|
+
2. **Override behavior**: When extending classes, using `declare` prevents decorators from being properly overridden
|
|
936
|
+
3. **Runtime behavior**: `declare` properties don't exist at runtime, breaking the decorator system
|
|
937
|
+
|
|
938
|
+
**Correct approach:**
|
|
939
|
+
|
|
940
|
+
Use the `override` keyword (when appropriate) but NEVER `declare`:
|
|
941
|
+
|
|
942
|
+
```typescript
|
|
943
|
+
export class ProductCreateInput extends ProductInput {
|
|
944
|
+
// ✅ Use override when useDefineForClassFields is enabled
|
|
945
|
+
override name: string;
|
|
946
|
+
|
|
947
|
+
// ✅ Apply decorators directly - they will override parent decorators
|
|
948
|
+
@UnifiedField({ description: 'Product name', isOptional: false })
|
|
949
|
+
override price: number;
|
|
950
|
+
}
|
|
951
|
+
```
|
|
952
|
+
|
|
953
|
+
**Remember: `declare` = no decorators = broken functionality!**
|
|
954
|
+
|
|
955
|
+
## Autonomous Execution
|
|
956
|
+
|
|
957
|
+
**You should work autonomously as much as possible:**
|
|
958
|
+
|
|
959
|
+
1. ✅ Create test files without asking
|
|
960
|
+
2. ✅ Run tests without asking
|
|
961
|
+
3. ✅ Analyze failures and fix code without asking
|
|
962
|
+
4. ✅ Iterate through Steps 3-5 automatically
|
|
963
|
+
5. ✅ Use nest-server-generator skill as needed
|
|
964
|
+
|
|
965
|
+
**Only ask developer when:**
|
|
966
|
+
|
|
967
|
+
1. ❓ Story has contradictions/ambiguities (Step 1)
|
|
968
|
+
2. ❓ Security decorators need to be changed
|
|
969
|
+
3. ❓ New npm package needs to be added
|
|
970
|
+
4. ❓ Architectural decision with multiple valid approaches
|
|
971
|
+
5. ❓ Test keeps failing and you're unsure why
|
|
972
|
+
|
|
973
|
+
## Final Report
|
|
974
|
+
|
|
975
|
+
When all tests pass, provide a comprehensive report:
|
|
976
|
+
|
|
977
|
+
### Report Structure:
|
|
978
|
+
|
|
979
|
+
```markdown
|
|
980
|
+
# Story Implementation Complete ✅
|
|
981
|
+
|
|
982
|
+
## Story: [Story Name]
|
|
983
|
+
|
|
984
|
+
### Tests Created
|
|
985
|
+
- Location: test/stories/[filename].story.test.ts
|
|
986
|
+
- Test cases: [number] scenarios
|
|
987
|
+
- Coverage: [coverage percentage if available]
|
|
988
|
+
|
|
989
|
+
### Implementation Summary
|
|
990
|
+
- Modules created/modified: [list]
|
|
991
|
+
- Objects created/modified: [list]
|
|
992
|
+
- Properties added: [list]
|
|
993
|
+
- Other changes: [list]
|
|
994
|
+
|
|
995
|
+
### Test Results
|
|
996
|
+
✅ All [number] tests passing
|
|
997
|
+
- [Brief summary of test scenarios]
|
|
998
|
+
|
|
999
|
+
### Code Quality
|
|
1000
|
+
- Followed existing patterns: ✅
|
|
1001
|
+
- Security preserved: ✅
|
|
1002
|
+
- No new dependencies added: ✅ (or list new dependencies with justification)
|
|
1003
|
+
- Code duplication checked: ✅
|
|
1004
|
+
- Refactoring performed: [Yes/No - describe if yes]
|
|
1005
|
+
- Database indexes added: ✅
|
|
1006
|
+
|
|
1007
|
+
### Security Review
|
|
1008
|
+
- Authentication/Authorization: ✅ All decorators intact
|
|
1009
|
+
- Input validation: ✅ All inputs validated
|
|
1010
|
+
- Data exposure: ✅ Sensitive fields hidden
|
|
1011
|
+
- Ownership checks: ✅ Proper authorization in services
|
|
1012
|
+
- Injection prevention: ✅ No SQL/NoSQL injection risks
|
|
1013
|
+
- Error handling: ✅ No data leakage in errors
|
|
1014
|
+
- Security tests: ✅ All authorization tests pass
|
|
1015
|
+
|
|
1016
|
+
### Refactoring (if performed)
|
|
1017
|
+
- Extracted helper functions: [list with brief description]
|
|
1018
|
+
- Consolidated code paths: [describe]
|
|
1019
|
+
- Removed duplication: [describe]
|
|
1020
|
+
- Tests still passing after refactoring: ✅
|
|
1021
|
+
|
|
1022
|
+
### Files Modified
|
|
1023
|
+
1. [file path] - [what changed]
|
|
1024
|
+
2. [file path] - [what changed]
|
|
1025
|
+
...
|
|
1026
|
+
|
|
1027
|
+
### Next Steps (if any)
|
|
1028
|
+
- [Any recommendations or follow-up items]
|
|
1029
|
+
```
|
|
1030
|
+
|
|
1031
|
+
## Common Patterns
|
|
1032
|
+
|
|
1033
|
+
### Creating Test Users:
|
|
1034
|
+
|
|
1035
|
+
```typescript
|
|
1036
|
+
// Study existing tests to see the exact pattern used
|
|
1037
|
+
// Common pattern example:
|
|
1038
|
+
|
|
1039
|
+
// Create test user (every logged-in user has the Role.S_USER role)
|
|
1040
|
+
const resUser = await testHelper.rest('/auth/signin', {
|
|
1041
|
+
method: 'POST',
|
|
1042
|
+
payload: {
|
|
1043
|
+
email: gUserEmail,
|
|
1044
|
+
password: gUserPassword,
|
|
1045
|
+
},
|
|
1046
|
+
statusCode: 201,
|
|
1047
|
+
});
|
|
1048
|
+
gUserToken = resUser.token;
|
|
1049
|
+
await db.collection('users').updateOne({ _id: new ObjectId(resUser.id) }, { $set: { verified: true } });
|
|
1050
|
+
|
|
1051
|
+
|
|
1052
|
+
// Create admin user
|
|
1053
|
+
const resAdmin = await testHelper.rest('/auth/signin', {
|
|
1054
|
+
method: 'POST',
|
|
1055
|
+
payload: {
|
|
1056
|
+
email: gAdminEmail,
|
|
1057
|
+
password: gAdminPassword,
|
|
1058
|
+
},
|
|
1059
|
+
statusCode: 201,
|
|
1060
|
+
});
|
|
1061
|
+
gAdminToken = resAdmin.token;
|
|
1062
|
+
await db.collection('users').updateOne({ _id: new ObjectId(resAdmin.id) }, { $set: { roles: ['admin'], verified: true } });
|
|
1063
|
+
```
|
|
1064
|
+
|
|
1065
|
+
### Making Authenticated Requests:
|
|
1066
|
+
|
|
1067
|
+
```typescript
|
|
1068
|
+
// Study existing tests for the exact pattern
|
|
1069
|
+
// Common REST API pattern:
|
|
1070
|
+
const response = await testHelper.rest('/api/products', {
|
|
1071
|
+
method: 'POST',
|
|
1072
|
+
payload: input,
|
|
1073
|
+
statusCode: 201,
|
|
1074
|
+
token: gUserToken,
|
|
1075
|
+
});
|
|
1076
|
+
|
|
1077
|
+
// Common GraphQL pattern:
|
|
1078
|
+
const result = await testHelper.graphQl(
|
|
1079
|
+
{
|
|
1080
|
+
arguments: {
|
|
1081
|
+
field: value,
|
|
1082
|
+
},
|
|
1083
|
+
fields: ['id', 'name', { user: ['id', 'email'] }],
|
|
1084
|
+
name: 'findProducts',
|
|
1085
|
+
type: TestGraphQLType.QUERY,
|
|
1086
|
+
},
|
|
1087
|
+
{ token: gUserToken },
|
|
1088
|
+
);
|
|
1089
|
+
```
|
|
1090
|
+
|
|
1091
|
+
### Test Organization:
|
|
1092
|
+
|
|
1093
|
+
```typescript
|
|
1094
|
+
describe('Feature Story', () => {
|
|
1095
|
+
// Shared setup
|
|
1096
|
+
let app: INestApplication;
|
|
1097
|
+
let adminUser: User;
|
|
1098
|
+
let normalUser: User;
|
|
1099
|
+
|
|
1100
|
+
beforeAll(async () => {
|
|
1101
|
+
// Initialize app, database, users
|
|
1102
|
+
});
|
|
1103
|
+
|
|
1104
|
+
afterAll(async () => {
|
|
1105
|
+
// Cleanup
|
|
1106
|
+
});
|
|
1107
|
+
|
|
1108
|
+
describe('Happy Path', () => {
|
|
1109
|
+
it('should work for authorized user', async () => {
|
|
1110
|
+
// Test
|
|
1111
|
+
});
|
|
1112
|
+
});
|
|
1113
|
+
|
|
1114
|
+
describe('Error Cases', () => {
|
|
1115
|
+
it('should reject unauthorized access', async () => {
|
|
1116
|
+
// Test
|
|
1117
|
+
});
|
|
1118
|
+
|
|
1119
|
+
it('should validate input data', async () => {
|
|
1120
|
+
// Test
|
|
1121
|
+
});
|
|
1122
|
+
});
|
|
1123
|
+
|
|
1124
|
+
describe('Edge Cases', () => {
|
|
1125
|
+
it('should handle special scenarios', async () => {
|
|
1126
|
+
// Test
|
|
1127
|
+
});
|
|
1128
|
+
});
|
|
1129
|
+
});
|
|
1130
|
+
```
|
|
1131
|
+
|
|
1132
|
+
## Integration with nest-server-generator
|
|
1133
|
+
|
|
1134
|
+
**When to invoke nest-server-generator skill:**
|
|
1135
|
+
|
|
1136
|
+
During Step 4 (Implementation), you should use the `nest-server-generator` skill for:
|
|
1137
|
+
|
|
1138
|
+
1. **Module creation:**
|
|
1139
|
+
```bash
|
|
1140
|
+
lt server module ModuleName --no-interactive [options]
|
|
1141
|
+
```
|
|
1142
|
+
|
|
1143
|
+
2. **Object creation:**
|
|
1144
|
+
```bash
|
|
1145
|
+
lt server object ObjectName [options]
|
|
1146
|
+
```
|
|
1147
|
+
|
|
1148
|
+
3. **Adding properties:**
|
|
1149
|
+
```bash
|
|
1150
|
+
lt server addProp ModuleName propertyName:type [options]
|
|
1151
|
+
```
|
|
1152
|
+
|
|
1153
|
+
4. **Understanding existing code:**
|
|
1154
|
+
- Reading and analyzing Services (especially CrudService inheritance)
|
|
1155
|
+
- Understanding Controllers and Resolvers
|
|
1156
|
+
- Reviewing Models and DTOs
|
|
1157
|
+
|
|
1158
|
+
**Best Practice:** Invoke the skill explicitly when you need to create or modify NestJS components, rather than editing files manually.
|
|
1159
|
+
|
|
1160
|
+
## Remember
|
|
1161
|
+
|
|
1162
|
+
1. **Tests first, code second** - Always write tests before implementation
|
|
1163
|
+
2. **Iterate until green** - Don't stop until all tests pass
|
|
1164
|
+
3. **Security review mandatory** - ALWAYS perform security check before final tests
|
|
1165
|
+
4. **Refactor before done** - Check for duplication and extract common functionality
|
|
1166
|
+
5. **Security is sacred** - Never compromise security for passing tests
|
|
1167
|
+
6. **Quality over speed** - Take time to write good tests and clean code
|
|
1168
|
+
7. **Ask when uncertain** - Clarify early to avoid wasted effort
|
|
1169
|
+
8. **Autonomous execution** - Work independently, report comprehensively
|
|
1170
|
+
9. **Equivalent implementation** - Match existing patterns and style
|
|
1171
|
+
10. **Clean up test data** - Always implement comprehensive cleanup in afterAll
|
|
1172
|
+
|
|
1173
|
+
Your goal is to deliver fully tested, high-quality, maintainable, **and secure** features that integrate seamlessly with the existing codebase while maintaining all security standards.
|