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