@lenne.tech/cli 1.2.0 → 1.3.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.
Files changed (36) hide show
  1. package/build/commands/claude/install-plugin.js +339 -0
  2. package/package.json +1 -1
  3. package/build/commands/claude/install-commands.js +0 -337
  4. package/build/commands/claude/install-mcps.js +0 -258
  5. package/build/commands/claude/install-skills.js +0 -693
  6. package/build/lib/mcp-registry.js +0 -80
  7. package/build/templates/claude-commands/code-cleanup.md +0 -82
  8. package/build/templates/claude-commands/commit-message.md +0 -21
  9. package/build/templates/claude-commands/create-story.md +0 -435
  10. package/build/templates/claude-commands/mr-description-clipboard.md +0 -48
  11. package/build/templates/claude-commands/mr-description.md +0 -33
  12. package/build/templates/claude-commands/sec-review.md +0 -62
  13. package/build/templates/claude-commands/skill-optimize.md +0 -481
  14. package/build/templates/claude-commands/test-generate.md +0 -45
  15. package/build/templates/claude-skills/building-stories-with-tdd/SKILL.md +0 -265
  16. package/build/templates/claude-skills/building-stories-with-tdd/code-quality.md +0 -276
  17. package/build/templates/claude-skills/building-stories-with-tdd/database-indexes.md +0 -182
  18. package/build/templates/claude-skills/building-stories-with-tdd/examples.md +0 -1383
  19. package/build/templates/claude-skills/building-stories-with-tdd/handling-existing-tests.md +0 -197
  20. package/build/templates/claude-skills/building-stories-with-tdd/reference.md +0 -1427
  21. package/build/templates/claude-skills/building-stories-with-tdd/security-review.md +0 -307
  22. package/build/templates/claude-skills/building-stories-with-tdd/workflow.md +0 -1004
  23. package/build/templates/claude-skills/generating-nest-servers/SKILL.md +0 -303
  24. package/build/templates/claude-skills/generating-nest-servers/configuration.md +0 -285
  25. package/build/templates/claude-skills/generating-nest-servers/declare-keyword-warning.md +0 -133
  26. package/build/templates/claude-skills/generating-nest-servers/description-management.md +0 -226
  27. package/build/templates/claude-skills/generating-nest-servers/examples.md +0 -893
  28. package/build/templates/claude-skills/generating-nest-servers/framework-guide.md +0 -259
  29. package/build/templates/claude-skills/generating-nest-servers/quality-review.md +0 -864
  30. package/build/templates/claude-skills/generating-nest-servers/reference.md +0 -487
  31. package/build/templates/claude-skills/generating-nest-servers/security-rules.md +0 -371
  32. package/build/templates/claude-skills/generating-nest-servers/verification-checklist.md +0 -262
  33. package/build/templates/claude-skills/generating-nest-servers/workflow-process.md +0 -1061
  34. package/build/templates/claude-skills/using-lt-cli/SKILL.md +0 -284
  35. package/build/templates/claude-skills/using-lt-cli/examples.md +0 -546
  36. package/build/templates/claude-skills/using-lt-cli/reference.md +0 -513
@@ -1,893 +0,0 @@
1
- ---
2
- name: nest-server-generator-examples
3
- version: 1.0.1
4
- description: Complete examples for generating NestJS server structures from specifications
5
- ---
6
-
7
- # NestJS Server Generator Examples
8
-
9
- ## Table of Contents
10
- - [Example 1: Library Management System](#example-1-library-management-system)
11
- - [Example 2: Hotel Booking System (Minimal)](#example-2-hotel-booking-system-minimal)
12
- - [Key Patterns Demonstrated](#key-patterns-demonstrated)
13
- - [Best Practices from Examples](#best-practices-from-examples)
14
- - [Quality Review Workflow Example](#quality-review-workflow-example)
15
-
16
- ## Example 1: Library Management System
17
-
18
- This example demonstrates all features:
19
- - SubObjects (embedded data)
20
- - Objects (base models)
21
- - Modules with inheritance
22
- - ENUMs
23
- - Arrays
24
- - Optional properties
25
- - References between modules
26
- - German/English descriptions
27
-
28
- ### Complete Specification
29
-
30
- ```
31
- ===========
32
-
33
- SubObject: Author // Author information
34
- - firstName: string // First name
35
- - lastName: string // Last name
36
- - birthDate?: Date // Date of birth
37
- - nationality?: string // Nationality
38
-
39
- ===
40
-
41
- SubObject: Publisher // Publisher details
42
- - name: string // Publisher name
43
- - city: string // City
44
- - country: string // Country
45
- - foundedYear?: number // Year founded
46
-
47
- ===
48
-
49
- SubObject: Review // Book review
50
- - rating: number // Rating (1-5)
51
- - comment?: string // Review comment
52
- - reviewerName: string // Name of reviewer
53
- - reviewDate: Date // Review date
54
-
55
- ===
56
-
57
- Object: BaseItem // Base library item
58
- Properties:
59
- - title: string // Titel
60
- - description?: string // Beschreibung
61
- - available: boolean // Verfügbar
62
- - location: string // Standort
63
-
64
- ===
65
-
66
- Module: Book // Book module
67
-
68
- Model: Book // Buch
69
- Extends: BaseItem
70
- - isbn: string // ISBN-Nummer
71
- - authors: Author[] // Autoren
72
- - publisher: Publisher // Verlag
73
- - publishYear: number // Erscheinungsjahr
74
- - pageCount: number // Seitenzahl
75
- - language: ENUM (ENGLISH, GERMAN, FRENCH, SPANISH, OTHER) // Sprache
76
- - genre: ENUM (FICTION, NON_FICTION, SCIENCE, HISTORY, BIOGRAPHY, CHILDREN, FANTASY, MYSTERY, ROMANCE) // Genre
77
- - coverImage?: string // Cover image URL
78
- - reviews?: Review[] // Bewertungen
79
- - borrowedBy?: Member // Current borrower
80
-
81
- ===
82
-
83
- Module: Member // Library member module
84
-
85
- Model: Member // Bibliotheksmitglied
86
- - memberNumber: string // Mitgliedsnummer
87
- - firstName: string // Vorname
88
- - lastName: string // Nachname
89
- - email: string // E-Mail-Adresse
90
- - phone?: string // Telefonnummer
91
- - joinDate: Date // Beitrittsdatum
92
- - status: ENUM (ACTIVE, SUSPENDED, EXPIRED) // Status
93
- - currentLoans: Book[] // Currently borrowed books
94
-
95
- ===
96
-
97
- Module: Loan // Loan tracking module
98
-
99
- Model: Loan // Ausleihe
100
- - member: Member // Mitglied
101
- - book: Book // Buch
102
- - loanDate: Date // Ausleihdatum
103
- - dueDate: Date // Fälligkeitsdatum
104
- - returnDate?: Date // Rückgabedatum
105
- - status: ENUM (ACTIVE, OVERDUE, RETURNED, LOST) // Status
106
- - renewalCount: number // Anzahl der Verlängerungen
107
- - fine?: number // Gebühr bei Verspätung
108
-
109
- ===========
110
- ```
111
-
112
- ### Generated Commands Sequence
113
-
114
- #### Step 1: Create SubObjects
115
-
116
- ```bash
117
- # Author SubObject
118
- lt server object --name Author \
119
- --prop-name-0 birthDate --prop-type-0 Date --prop-nullable-0 true \
120
- --prop-name-1 firstName --prop-type-1 string \
121
- --prop-name-2 lastName --prop-type-2 string \
122
- --prop-name-3 nationality --prop-type-3 string --prop-nullable-3 true
123
-
124
- # Publisher SubObject
125
- lt server object --name Publisher \
126
- --prop-name-0 city --prop-type-0 string \
127
- --prop-name-1 country --prop-type-1 string \
128
- --prop-name-2 foundedYear --prop-type-2 number --prop-nullable-2 true \
129
- --prop-name-3 name --prop-type-3 string
130
-
131
- # Review SubObject
132
- lt server object --name Review \
133
- --prop-name-0 comment --prop-type-0 string --prop-nullable-0 true \
134
- --prop-name-1 rating --prop-type-1 number \
135
- --prop-name-2 reviewDate --prop-type-2 Date \
136
- --prop-name-3 reviewerName --prop-type-3 string
137
- ```
138
-
139
- #### Step 2: Create Base Object
140
-
141
- ```bash
142
- # BaseItem Object
143
- lt server object --name BaseItem \
144
- --prop-name-0 available --prop-type-0 boolean \
145
- --prop-name-1 description --prop-type-1 string --prop-nullable-1 true \
146
- --prop-name-2 location --prop-type-2 string \
147
- --prop-name-3 title --prop-type-3 string
148
- ```
149
-
150
- #### Step 3: Create Modules
151
-
152
- ```bash
153
- # Member Module (create first as it's referenced by Book)
154
- lt server module --name Member --controller Both \
155
- --prop-name-0 email --prop-type-0 string \
156
- --prop-name-1 firstName --prop-type-1 string \
157
- --prop-name-2 joinDate --prop-type-2 Date \
158
- --prop-name-3 lastName --prop-type-3 string \
159
- --prop-name-4 memberNumber --prop-type-4 string \
160
- --prop-name-5 phone --prop-type-5 string --prop-nullable-5 true \
161
- --prop-name-6 status --prop-enum-6 MemberStatusEnum
162
-
163
- # Book Module (references Member)
164
- lt server module --name Book --controller Both \
165
- --prop-name-0 authors --prop-schema-0 Author --prop-array-0 true \
166
- --prop-name-1 borrowedBy --prop-type-1 ObjectId --prop-reference-1 Member --prop-nullable-1 true \
167
- --prop-name-2 coverImage --prop-type-2 string --prop-nullable-2 true \
168
- --prop-name-3 genre --prop-enum-3 BookGenreEnum \
169
- --prop-name-4 isbn --prop-type-4 string \
170
- --prop-name-5 language --prop-enum-5 BookLanguageEnum \
171
- --prop-name-6 pageCount --prop-type-6 number \
172
- --prop-name-7 publishYear --prop-type-7 number \
173
- --prop-name-8 publisher --prop-schema-8 Publisher \
174
- --prop-name-9 reviews --prop-schema-9 Review --prop-array-9 true --prop-nullable-9 true
175
-
176
- # Add currentLoans to Member (after Book is created)
177
- lt server addProp --type Module --element Member \
178
- --prop-name-0 currentLoans --prop-type-0 ObjectId --prop-reference-0 Book --prop-array-0 true
179
-
180
- # Loan Module (references both Member and Book)
181
- lt server module --name Loan --controller Both \
182
- --prop-name-0 book --prop-type-0 ObjectId --prop-reference-0 Book \
183
- --prop-name-1 dueDate --prop-type-1 Date \
184
- --prop-name-2 fine --prop-type-2 number --prop-nullable-2 true \
185
- --prop-name-3 loanDate --prop-type-3 Date \
186
- --prop-name-4 member --prop-type-4 ObjectId --prop-reference-4 Member \
187
- --prop-name-5 renewalCount --prop-type-5 number \
188
- --prop-name-6 returnDate --prop-type-6 Date --prop-nullable-6 true \
189
- --prop-name-7 status --prop-enum-7 LoanStatusEnum
190
- ```
191
-
192
- #### Step 4: Handle Inheritance
193
-
194
- Manually modify `book.model.ts`:
195
-
196
- ```typescript
197
- // Change from:
198
- import { CoreModel } from '@lenne.tech/nest-server';
199
- export class Book extends CoreModel { ... }
200
-
201
- // To:
202
- import { BaseItem } from '../../common/objects/base-item/base-item.object';
203
- export class Book extends BaseItem { ... }
204
- ```
205
-
206
- Manually update `book.input.ts` and `book-create.input.ts`:
207
-
208
- ```typescript
209
- // book-create.input.ts
210
- // Add required fields from BaseItem:
211
- // - title (required in BaseItem)
212
- // - available (required in BaseItem)
213
- // - location (required in BaseItem)
214
- // - description (optional in BaseItem)
215
- ```
216
-
217
- #### Step 5: Update Descriptions
218
-
219
- **⚠️ CRITICAL STEP - Extract descriptions from original specification and apply EVERYWHERE!**
220
-
221
- **Step 5.1: Extract from specification**
222
-
223
- Go back to the original specification and identify ALL comments:
224
-
225
- ```
226
- SubObject: Address
227
- - street: string // Straße
228
- - city: string // City name
229
- - zipCode: string // Postleitzahl
230
-
231
- Module: Book
232
- Model: Book
233
- Extends: BaseItem
234
- - isbn: string // ISBN-Nummer
235
- - author: string // Author name
236
- - publisher?: string // Verlag
237
- ```
238
-
239
- **Extracted mapping:**
240
- - Address.street → "Straße" (German)
241
- - Address.city → "City name" (English)
242
- - Address.zipCode → "Postleitzahl" (German)
243
- - Book.isbn → "ISBN-Nummer" (German)
244
- - Book.author → "Author name" (English)
245
- - Book.publisher → "Verlag" (German)
246
-
247
- **Step 5.2: Format descriptions**
248
-
249
- Apply format rules:
250
- - German → Translate and add: `ENGLISH (DEUTSCH)`
251
- - English → Keep as-is
252
- - **Fix typos only, preserve original wording!**
253
-
254
- ```
255
- Address.street → 'Street (Straße)' (preserve word "Straße", don't change to "Straßenname")
256
- Address.city → 'City name'
257
- Address.zipCode → 'Postal code (Postleitzahl)'
258
- Book.isbn → 'ISBN number (ISBN-Nummer)'
259
- Book.author → 'Author name'
260
- Book.publisher → 'Publisher (Verlag)' (preserve word "Verlag", don't expand)
261
- ```
262
-
263
- **⚠️ CRITICAL - Preserve Original Wording:**
264
-
265
- User comments may be predefined terms or referenced by external systems.
266
-
267
- **Examples of correct handling**:
268
- ```
269
- ✅ CORRECT:
270
- // Straße → 'Street (Straße)' (just translate)
271
- // Postleizahl → 'Postal code (Postleitzahl)' (fix typo, preserve word)
272
- // Produkt → 'Product (Produkt)' (don't add "name")
273
- // Status → 'Status (Status)' (same word)
274
-
275
- ❌ WRONG:
276
- // Straße → 'Street name (Straßenname)' (changed word!)
277
- // Produkt → 'Product name (Produktname)' (added word!)
278
- // Titel → 'Product title (Produkttitel)' (changed "Titel"!)
279
- ```
280
-
281
- **Step 5.3: Apply to ALL files**
282
-
283
- For Address SubObject (3 files):
284
-
285
- ```typescript
286
- // File: src/server/common/objects/address/address.object.ts
287
- @UnifiedField({ description: 'Street (Straße)' })
288
- street: string;
289
-
290
- @UnifiedField({ description: 'City name' })
291
- city: string;
292
-
293
- @UnifiedField({ description: 'Postal code (Postleitzahl)' })
294
- zipCode: string;
295
-
296
- // File: src/server/common/objects/address/address-create.input.ts
297
- @UnifiedField({ description: 'Street (Straße)' })
298
- street: string;
299
-
300
- @UnifiedField({ description: 'City name' })
301
- city: string;
302
-
303
- @UnifiedField({ description: 'Postal code (Postleitzahl)' })
304
- zipCode: string;
305
-
306
- // File: src/server/common/objects/address/address.input.ts
307
- @UnifiedField({ description: 'Street (Straße)' })
308
- street?: string;
309
-
310
- @UnifiedField({ description: 'City name' })
311
- city?: string;
312
-
313
- @UnifiedField({ description: 'Postal code (Postleitzahl)' })
314
- zipCode?: string;
315
- ```
316
-
317
- For Book Module (3 files):
318
-
319
- ```typescript
320
- // File: src/server/modules/book/book.model.ts
321
- @UnifiedField({ description: 'ISBN number (ISBN-Nummer)' })
322
- isbn: string;
323
-
324
- @UnifiedField({ description: 'Author name' })
325
- author: string;
326
-
327
- @UnifiedField({ description: 'Publisher (Verlag)' })
328
- publisher?: string;
329
-
330
- // File: src/server/modules/book/inputs/book-create.input.ts
331
- @UnifiedField({ description: 'ISBN number (ISBN-Nummer)' })
332
- isbn: string;
333
-
334
- @UnifiedField({ description: 'Author name' })
335
- author: string;
336
-
337
- @UnifiedField({ description: 'Publisher (Verlag)' })
338
- publisher?: string;
339
-
340
- // File: src/server/modules/book/inputs/book.input.ts
341
- @UnifiedField({ description: 'ISBN number (ISBN-Nummer)' })
342
- isbn?: string;
343
-
344
- @UnifiedField({ description: 'Author name' })
345
- author?: string;
346
-
347
- @UnifiedField({ description: 'Publisher (Verlag)' })
348
- publisher?: string;
349
- ```
350
-
351
- **Verification:**
352
- - ✅ Same description in ALL 3 files for each property
353
- - ✅ All German descriptions translated
354
- - ✅ All user comments extracted and applied
355
- - ✅ No inconsistencies
356
-
357
- #### Step 6: Create Enum Files
358
-
359
- ```typescript
360
- // src/server/common/enums/book-language.enum.ts
361
- export enum BookLanguageEnum {
362
- ENGLISH = 'ENGLISH',
363
- GERMAN = 'GERMAN',
364
- FRENCH = 'FRENCH',
365
- SPANISH = 'SPANISH',
366
- OTHER = 'OTHER',
367
- }
368
-
369
- // src/server/common/enums/book-genre.enum.ts
370
- export enum BookGenreEnum {
371
- FICTION = 'FICTION',
372
- NON_FICTION = 'NON_FICTION',
373
- SCIENCE = 'SCIENCE',
374
- HISTORY = 'HISTORY',
375
- BIOGRAPHY = 'BIOGRAPHY',
376
- CHILDREN = 'CHILDREN',
377
- FANTASY = 'FANTASY',
378
- MYSTERY = 'MYSTERY',
379
- ROMANCE = 'ROMANCE',
380
- }
381
-
382
- // src/server/common/enums/member-status.enum.ts
383
- export enum MemberStatusEnum {
384
- ACTIVE = 'ACTIVE',
385
- SUSPENDED = 'SUSPENDED',
386
- EXPIRED = 'EXPIRED',
387
- }
388
-
389
- // src/server/common/enums/loan-status.enum.ts
390
- export enum LoanStatusEnum {
391
- ACTIVE = 'ACTIVE',
392
- OVERDUE = 'OVERDUE',
393
- RETURNED = 'RETURNED',
394
- LOST = 'LOST',
395
- }
396
- ```
397
-
398
- #### Step 7: Create API Tests
399
-
400
- ```typescript
401
- // test/book/book.controller.test.ts
402
- import { TestHelper, TestGraphQLType } from '@lenne.tech/nest-server';
403
-
404
- describe('Book Controller', () => {
405
- let testHelper: TestHelper;
406
- let adminToken: string;
407
- let createdBookId: string;
408
-
409
- beforeAll(async () => {
410
- testHelper = new TestHelper(app);
411
-
412
- // Sign in as admin
413
- const authResult = await testHelper.graphQl({
414
- name: 'signIn',
415
- type: TestGraphQLType.MUTATION,
416
- arguments: { email: 'admin@test.com', password: 'password' },
417
- fields: ['token']
418
- });
419
- adminToken = authResult.token;
420
- });
421
-
422
- afterAll(async () => {
423
- // Clean up created book
424
- if (createdBookId) {
425
- await testHelper.graphQl({
426
- name: 'deleteBook',
427
- type: TestGraphQLType.MUTATION,
428
- arguments: { id: createdBookId },
429
- fields: ['id']
430
- }, { token: adminToken });
431
- }
432
- });
433
-
434
- it('should create book with all required fields', async () => {
435
- const result = await testHelper.graphQl({
436
- name: 'createBook',
437
- type: TestGraphQLType.MUTATION,
438
- arguments: {
439
- input: {
440
- isbn: '978-3-16-148410-0',
441
- title: 'Test Book',
442
- description: 'A test book',
443
- available: true,
444
- location: 'Shelf A1',
445
- authors: [{
446
- firstName: 'John',
447
- lastName: 'Doe'
448
- }],
449
- publisher: {
450
- name: 'Test Publisher',
451
- city: 'Berlin',
452
- country: 'Germany'
453
- },
454
- publishYear: 2023,
455
- pageCount: 300,
456
- language: 'ENGLISH',
457
- genre: 'FICTION'
458
- }
459
- },
460
- fields: ['id', 'isbn', 'title', 'pageCount']
461
- }, { token: adminToken });
462
-
463
- expect(result.isbn).toBe('978-3-16-148410-0');
464
- createdBookId = result.id;
465
- });
466
-
467
- it('should fail without required fields', async () => {
468
- const result = await testHelper.graphQl({
469
- name: 'createBook',
470
- type: TestGraphQLType.MUTATION,
471
- arguments: {
472
- input: {
473
- isbn: '978-3-16-148410-1'
474
- // Missing required fields
475
- }
476
- },
477
- fields: ['id']
478
- }, { token: adminToken, statusCode: 400 });
479
-
480
- expect(result.errors).toBeDefined();
481
- });
482
-
483
- it('should get all books', async () => {
484
- const result = await testHelper.graphQl({
485
- name: 'books',
486
- type: TestGraphQLType.QUERY,
487
- fields: ['id', 'isbn', 'title']
488
- }, { token: adminToken });
489
-
490
- expect(Array.isArray(result)).toBe(true);
491
- });
492
-
493
- it('should update book', async () => {
494
- const result = await testHelper.graphQl({
495
- name: 'updateBook',
496
- type: TestGraphQLType.MUTATION,
497
- arguments: {
498
- id: createdBookId,
499
- input: { pageCount: 350 }
500
- },
501
- fields: ['id', 'pageCount']
502
- }, { token: adminToken });
503
-
504
- expect(result.pageCount).toBe(350);
505
- });
506
-
507
- it('should delete book', async () => {
508
- const result = await testHelper.graphQl({
509
- name: 'deleteBook',
510
- type: TestGraphQLType.MUTATION,
511
- arguments: { id: createdBookId },
512
- fields: ['id']
513
- }, { token: adminToken });
514
-
515
- expect(result.id).toBe(createdBookId);
516
- createdBookId = null;
517
- });
518
- });
519
-
520
- // For REST API tests
521
- // test/book/book.controller.rest.test.ts
522
- describe('Book Controller (REST)', () => {
523
- let testHelper: TestHelper;
524
- let adminToken: string;
525
- let createdBookId: string;
526
-
527
- beforeAll(async () => {
528
- testHelper = new TestHelper(app);
529
- const authResult = await testHelper.rest('/auth/sign-in', {
530
- method: 'POST',
531
- payload: { email: 'admin@test.com', password: 'password' }
532
- });
533
- adminToken = authResult.token;
534
- });
535
-
536
- it('should create book via REST', async () => {
537
- const result = await testHelper.rest('/books', {
538
- method: 'POST',
539
- payload: {
540
- isbn: '978-3-16-148410-0',
541
- title: 'Test Book',
542
- available: true,
543
- location: 'Shelf A1',
544
- // ... other required fields
545
- },
546
- token: adminToken
547
- });
548
-
549
- expect(result.isbn).toBe('978-3-16-148410-0');
550
- createdBookId = result.id;
551
- });
552
-
553
- it('should get all books via REST', async () => {
554
- const result = await testHelper.rest('/books', { token: adminToken });
555
- expect(Array.isArray(result)).toBe(true);
556
- });
557
-
558
- afterAll(async () => {
559
- if (createdBookId) {
560
- await testHelper.rest(`/books/${createdBookId}`, {
561
- method: 'DELETE',
562
- token: adminToken
563
- });
564
- }
565
- });
566
- });
567
- ```
568
-
569
- ### Execution Todo List Example
570
-
571
- When processing this specification, create this todo list:
572
-
573
- ```
574
- 1. Create Author SubObject
575
- 2. Create Publisher SubObject
576
- 3. Create Review SubObject
577
- 4. Create BaseItem Object
578
- 5. Create Member Module
579
- 6. Create Book Module
580
- 7. Add currentLoans property to Member
581
- 8. Create Loan Module
582
- 9. Modify Book model to extend BaseItem
583
- 10. Update Book CreateInput with BaseItem required fields
584
- 11. Update all descriptions to "ENGLISH (DEUTSCH)" format
585
- 12. Create BookLanguageEnum file
586
- 13. Create BookGenreEnum file
587
- 14. Create MemberStatusEnum file
588
- 15. Create LoanStatusEnum file
589
- 16. Create Book controller tests
590
- 17. Create Book resolver tests
591
- 18. Create Member controller tests
592
- 19. Create Member resolver tests
593
- 20. Create Loan controller tests
594
- 21. Create Loan resolver tests
595
- 22. Run all tests
596
- 23. Verify all tests pass
597
- 24. Verify no TypeScript errors
598
- 25. Run lint and fix
599
- 26. Provide summary
600
- ```
601
-
602
- ## Example 2: Hotel Booking System (Minimal)
603
-
604
- A simpler example focusing on basic features:
605
-
606
- ```
607
- ===========
608
-
609
- SubObject: ContactDetails // Contact information
610
- - email: string // Email address
611
- - phone: string // Phone number
612
-
613
- ===
614
-
615
- Module: Guest // Guest module
616
-
617
- Model: Guest // Hotel guest
618
- - name: string // Full name
619
- - contact: ContactDetails // Contact information
620
- - checkInDate: Date // Check-in date
621
- - checkOutDate: Date // Check-out date
622
- - roomNumber: string // Room number
623
- - status: ENUM (CHECKED_IN, CHECKED_OUT, RESERVED, CANCELLED) // Booking status
624
-
625
- ===========
626
- ```
627
-
628
- ### Commands
629
-
630
- ```bash
631
- # SubObject
632
- lt server object --name ContactDetails \
633
- --prop-name-0 email --prop-type-0 string \
634
- --prop-name-1 phone --prop-type-1 string
635
-
636
- # Module
637
- lt server module --name Guest --controller Both \
638
- --prop-name-0 checkInDate --prop-type-0 Date \
639
- --prop-name-1 checkOutDate --prop-type-1 Date \
640
- --prop-name-2 contact --prop-schema-2 ContactDetails \
641
- --prop-name-3 name --prop-type-3 string \
642
- --prop-name-4 roomNumber --prop-type-4 string \
643
- --prop-name-5 status --prop-enum-5 GuestStatusEnum
644
-
645
- # Enum file
646
- # src/server/common/enums/guest-status.enum.ts
647
- export enum GuestStatusEnum {
648
- CHECKED_IN = 'CHECKED_IN',
649
- CHECKED_OUT = 'CHECKED_OUT',
650
- RESERVED = 'RESERVED',
651
- CANCELLED = 'CANCELLED',
652
- }
653
- ```
654
-
655
- ## Key Patterns Demonstrated
656
-
657
- ### 1. SubObject with Arrays
658
- ```
659
- - authors: Author[] // Multiple authors
660
- ```
661
- → `--prop-schema-X Author --prop-array-X true`
662
-
663
- ### 2. Optional Fields
664
- ```
665
- - description?: string // Optional description
666
- ```
667
- → `--prop-nullable-X true`
668
-
669
- ### 3. Enum Properties
670
- ```
671
- - status: ENUM (ACTIVE, INACTIVE) // Status
672
- ```
673
- → `--prop-enum-X StatusEnum` + create enum file
674
-
675
- ### 4. Module References
676
- ```
677
- - borrowedBy?: Member // Reference to member
678
- ```
679
- → `--prop-type-X ObjectId --prop-reference-X Member --prop-nullable-X true`
680
-
681
- ### 5. Inheritance
682
- ```
683
- Extends: BaseItem
684
- ```
685
- → Manually change model to extend BaseItem and update inputs
686
-
687
- ### 6. Circular References
688
- ```
689
- Member has currentLoans: Book[]
690
- Book has borrowedBy?: Member
691
- ```
692
- → Create both modules first, then use `addProp` for the second reference
693
-
694
- ## Best Practices from Examples
695
-
696
- 1. **Create SubObjects first**: Author, Publisher, Review before Book
697
- 2. **Create referenced modules early**: Member before Book (for borrowedBy)
698
- 3. **Handle circular refs with addProp**: Add currentLoans to Member after Book exists
699
- 4. **Alphabetical ordering**: All properties sorted in final files
700
- 5. **Proper descriptions**: "ENGLISH (DEUTSCH)" format throughout
701
- 6. **Complete enum files**: Create all enums immediately after modules
702
- 7. **Comprehensive tests**: Cover all CRUD operations and edge cases
703
- 8. **Quality review before reporting**: ALWAYS perform comprehensive quality review
704
-
705
- ## Quality Review Workflow Example
706
-
707
- **CRITICAL**: Before creating the final report, ALWAYS perform this quality review:
708
-
709
- ```bash
710
- # Step 1: Identify all changes
711
- git status --short
712
- git diff --name-only
713
-
714
- # Step 2: Test Management
715
-
716
- # Step 2.1: FIRST - Analyze existing tests thoroughly
717
- ls -la tests/
718
- ls -la tests/modules/
719
- find tests -name "*.e2e-spec.ts" -type f
720
-
721
- # Understand the test folder structure:
722
- # - tests/modules/<module-name>.e2e-spec.ts - for modules
723
- # - tests/common.e2e-spec.ts - for common functionality
724
- # - tests/project.e2e-spec.ts - for project-level tests
725
-
726
- # Read multiple test files to understand patterns
727
- cat tests/modules/user.e2e-spec.ts
728
- cat tests/modules/<another-module>.e2e-spec.ts
729
- cat tests/common.e2e-spec.ts
730
- cat tests/project.e2e-spec.ts
731
-
732
- # CRITICAL: Read and understand TestHelper source code
733
- cat node_modules/@lenne.tech/nest-server/src/test/test.helper.ts
734
-
735
- # Document TestHelper understanding:
736
- # - Available methods: graphQl(), rest(), constructor, initialization
737
- # - graphQl() signature: (options: GraphQLOptions, config?: RequestConfig)
738
- # - GraphQLOptions: { name, type (QUERY/MUTATION), arguments, fields }
739
- # - RequestConfig: { token, statusCode, headers }
740
- # - rest() signature: (method: HttpMethod, path: string, options?: RestOptions)
741
- # - HttpMethod: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'
742
- # - RestOptions: { body, token, statusCode, headers }
743
- # - Authentication: Pass token via config.token (both methods)
744
- # - Error handling: Specify expected statusCode for error cases
745
- # - Response: Returns parsed data directly
746
- # - When to use: graphQl() for GraphQL endpoints, rest() for REST endpoints
747
-
748
- # Document observed patterns:
749
- # - Test framework: Jest
750
- # - Test helper: TestHelper from @lenne.tech/nest-server
751
- # - Auth: Token-based via signIn mutation
752
- # - Setup: beforeAll initializes app and gets admin token
753
- # - Cleanup: afterAll deletes test data
754
- # - Assertions: expect() with Jest matchers
755
- # - Prerequisites: How are test users/related data created?
756
-
757
- # Verify existing tests pass BEFORE making changes
758
- npm run test:e2e
759
-
760
- # Step 2.2: For new modules - create test files in correct location
761
- # Example: Created Book module, need to create tests
762
-
763
- # IMPORTANT: Determine correct test location first!
764
- # - Module in src/server/modules/book? → tests/modules/book.e2e-spec.ts
765
- # - Common object/enum? → Add to tests/common.e2e-spec.ts
766
- # - Project-level? → Add to tests/project.e2e-spec.ts
767
-
768
- # Create new test file EXACTLY matching the pattern observed
769
- # tests/modules/book.e2e-spec.ts with:
770
- # - Same imports as existing tests
771
- # - Same beforeAll/afterAll structure
772
- # - Same authentication pattern
773
- # - Same prerequisite handling (e.g., create User first if Book needs User)
774
- # - Same assertion style
775
- # - All CRUD operations
776
- # - Authorization tests
777
- # - Required field validation
778
-
779
- # Step 2.3: For modified modules - update existing tests
780
- find tests -name "*user*.e2e-spec.ts"
781
- cat tests/modules/user.e2e-spec.ts # Read first!
782
-
783
- # Run tests before modifying
784
- npm run test:e2e
785
-
786
- # If you added a property to User, update tests to verify it
787
- # Run tests after modifying to ensure nothing broke
788
- npm run test:e2e
789
-
790
- # Step 3: Compare with existing code
791
- # Read existing modules to understand project patterns
792
- cat src/server/modules/user/user.model.ts
793
- cat src/server/modules/user/inputs/user-create.input.ts
794
-
795
- # Step 3: Critical analysis
796
- # For each generated file, check:
797
- # - Import ordering matches existing code
798
- # - Property ordering is alphabetical
799
- # - Decorator patterns match existing code
800
- # - Description format matches project style
801
- # - Indentation and formatting is consistent
802
-
803
- # Step 4: Apply optimizations
804
- # Fix any inconsistencies found:
805
- # - Reorder imports
806
- # - Reorder properties
807
- # - Fix formatting
808
- # - Improve descriptions
809
-
810
- # Step 5: Run all tests
811
- npm run build
812
- npm run lint
813
- npm run test:e2e
814
-
815
- # Step 6: Fix any failures and repeat
816
- # If tests fail:
817
- # - Analyze error
818
- # - Fix issue
819
- # - Re-run tests
820
- # - Repeat until all pass
821
-
822
- # Only after ALL checks pass → Create Final Report
823
- ```
824
-
825
- **Example findings during quality review**:
826
-
827
- ```
828
- Step 2.1: Analyzed existing tests
829
- ✅ Listed test structure: tests/modules/, tests/common.e2e-spec.ts, tests/project.e2e-spec.ts
830
- ✅ Read 3 existing test files (user, role, profile)
831
- ✅ Read and analyzed TestHelper source code (node_modules/@lenne.tech/nest-server/src/test/test.helper.ts)
832
- ✅ Documented TestHelper:
833
- - graphQl() method: signature, GraphQLOptions, RequestConfig
834
- - rest() method: signature, HttpMethod, RestOptions
835
- - When to use graphQl() vs rest()
836
- - Authentication handling (token in config for both methods)
837
- - Error handling (statusCode parameter)
838
- - Response format and parsing
839
- ✅ Documented patterns: Jest + TestHelper, token auth, beforeAll/afterAll cleanup
840
- ✅ Documented prerequisites: Test users created first, then module-specific data
841
- ✅ Verified all existing tests pass (23/23 passing)
842
-
843
- ❌ Found: New Book module created but no test file exists
844
- ✅ Fixed: Created tests/modules/book.e2e-spec.ts following exact pattern
845
- - Placed in correct location: tests/modules/book.e2e-spec.ts (not tests/book/ or tests/modules/book/)
846
- - Matched imports structure
847
- - Matched beforeAll/afterAll pattern
848
- - Identified prerequisites: Book references User for borrowedBy
849
- - Created test User first in beforeAll
850
- - Matched authentication approach
851
- - Matched assertion style
852
-
853
- ❌ Found: Modified User module (added 'phone' property) but tests not updated
854
- ✅ Fixed:
855
- - Read existing tests/modules/user.e2e-spec.ts first
856
- - Ran tests before changes (all passing)
857
- - Updated test to verify 'phone' property in create/update operations
858
- - Ran tests after changes (all passing)
859
-
860
- ❌ Found: Import ordering differs from existing modules
861
- ✅ Fixed: Reordered imports to match project pattern
862
-
863
- ❌ Found: Properties not alphabetically ordered in Book model
864
- ✅ Fixed: Reordered all properties alphabetically
865
-
866
- ❌ Found: Description format inconsistent ("German only" vs "ENGLISH (DEUTSCH)")
867
- ✅ Fixed: Updated all descriptions to "ENGLISH (DEUTSCH)" format
868
-
869
- ❌ Found: Test missing required field validation
870
- ✅ Fixed: Added test case for missing required fields
871
-
872
- ❌ Found: Test cleanup not following project pattern
873
- ✅ Fixed: Updated afterAll hook to match existing test cleanup patterns
874
-
875
- ✅ All tests passing
876
- ✅ Linter passing
877
- ✅ TypeScript compiling without errors
878
-
879
- → Ready for Final Report
880
- ```
881
-
882
- **This quality review ensures**:
883
- - Generated code matches project patterns perfectly
884
- - No style inconsistencies
885
- - **TestHelper thoroughly understood before creating tests**
886
- - **TestHelper used correctly (graphQl() and rest() methods, authentication, error handling)**
887
- - **Tests in correct folder structure (tests/modules/<name>.e2e-spec.ts, tests/common.e2e-spec.ts, tests/project.e2e-spec.ts)**
888
- - **All new modules have corresponding test files**
889
- - **All modified modules have updated tests**
890
- - **All test prerequisites identified and handled correctly**
891
- - **Tests follow existing project test patterns exactly**
892
- - All tests pass before reporting
893
- - Professional, production-ready code