@qazuor/claude-code-config 0.5.0 → 0.6.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 (57) hide show
  1. package/README.md +106 -41
  2. package/dist/bin.cjs +963 -84
  3. package/dist/bin.cjs.map +1 -1
  4. package/dist/bin.js +963 -84
  5. package/dist/bin.js.map +1 -1
  6. package/dist/index.cjs +73 -56
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.cts +2 -0
  9. package/dist/index.d.ts +2 -0
  10. package/dist/index.js +73 -56
  11. package/dist/index.js.map +1 -1
  12. package/package.json +23 -24
  13. package/templates/CLAUDE.md.template +60 -5
  14. package/templates/agents/README.md +58 -39
  15. package/templates/agents/_registry.json +43 -202
  16. package/templates/agents/engineering/{hono-engineer.md → api-engineer.md} +61 -70
  17. package/templates/agents/engineering/database-engineer.md +253 -0
  18. package/templates/agents/engineering/frontend-engineer.md +302 -0
  19. package/templates/hooks/on-notification.sh +0 -0
  20. package/templates/scripts/add-changelogs.sh +0 -0
  21. package/templates/scripts/generate-code-registry.ts +0 -0
  22. package/templates/scripts/health-check.sh +0 -0
  23. package/templates/scripts/sync-registry.sh +0 -0
  24. package/templates/scripts/telemetry-report.ts +0 -0
  25. package/templates/scripts/validate-docs.sh +0 -0
  26. package/templates/scripts/validate-registry.sh +0 -0
  27. package/templates/scripts/validate-structure.sh +0 -0
  28. package/templates/scripts/worktree-cleanup.sh +0 -0
  29. package/templates/scripts/worktree-create.sh +0 -0
  30. package/templates/skills/README.md +99 -90
  31. package/templates/skills/_registry.json +323 -16
  32. package/templates/skills/api-frameworks/express-patterns.md +411 -0
  33. package/templates/skills/api-frameworks/fastify-patterns.md +419 -0
  34. package/templates/skills/api-frameworks/hono-patterns.md +388 -0
  35. package/templates/skills/api-frameworks/nestjs-patterns.md +497 -0
  36. package/templates/skills/database/drizzle-patterns.md +449 -0
  37. package/templates/skills/database/mongoose-patterns.md +503 -0
  38. package/templates/skills/database/prisma-patterns.md +487 -0
  39. package/templates/skills/frontend-frameworks/astro-patterns.md +415 -0
  40. package/templates/skills/frontend-frameworks/nextjs-patterns.md +470 -0
  41. package/templates/skills/frontend-frameworks/react-patterns.md +516 -0
  42. package/templates/skills/frontend-frameworks/tanstack-start-patterns.md +469 -0
  43. package/templates/skills/patterns/atdd-methodology.md +364 -0
  44. package/templates/skills/patterns/bdd-methodology.md +281 -0
  45. package/templates/skills/patterns/clean-architecture.md +444 -0
  46. package/templates/skills/patterns/hexagonal-architecture.md +567 -0
  47. package/templates/skills/patterns/vertical-slice-architecture.md +502 -0
  48. package/templates/agents/engineering/astro-engineer.md +0 -293
  49. package/templates/agents/engineering/db-drizzle-engineer.md +0 -360
  50. package/templates/agents/engineering/express-engineer.md +0 -316
  51. package/templates/agents/engineering/fastify-engineer.md +0 -399
  52. package/templates/agents/engineering/mongoose-engineer.md +0 -473
  53. package/templates/agents/engineering/nestjs-engineer.md +0 -429
  54. package/templates/agents/engineering/nextjs-engineer.md +0 -451
  55. package/templates/agents/engineering/prisma-engineer.md +0 -432
  56. package/templates/agents/engineering/react-senior-dev.md +0 -394
  57. package/templates/agents/engineering/tanstack-start-engineer.md +0 -447
@@ -0,0 +1,497 @@
1
+ # NestJS Framework Patterns
2
+
3
+ ## Overview
4
+
5
+ NestJS is a progressive Node.js framework for building efficient, scalable server-side applications. This skill provides patterns for implementing APIs with NestJS.
6
+
7
+ ---
8
+
9
+ ## Module Structure
10
+
11
+ **Pattern**: Feature-based modules with clear boundaries
12
+
13
+ ```typescript
14
+ // items/items.module.ts
15
+ import { Module } from '@nestjs/common';
16
+ import { TypeOrmModule } from '@nestjs/typeorm';
17
+ import { ItemsController } from './items.controller';
18
+ import { ItemsService } from './items.service';
19
+ import { Item } from './entities/item.entity';
20
+
21
+ @Module({
22
+ imports: [TypeOrmModule.forFeature([Item])],
23
+ controllers: [ItemsController],
24
+ providers: [ItemsService],
25
+ exports: [ItemsService],
26
+ })
27
+ export class ItemsModule {}
28
+ ```
29
+
30
+ ### App Module
31
+
32
+ ```typescript
33
+ // app.module.ts
34
+ import { Module } from '@nestjs/common';
35
+ import { ConfigModule } from '@nestjs/config';
36
+ import { TypeOrmModule } from '@nestjs/typeorm';
37
+ import { ItemsModule } from './items/items.module';
38
+ import { UsersModule } from './users/users.module';
39
+ import { AuthModule } from './auth/auth.module';
40
+
41
+ @Module({
42
+ imports: [
43
+ ConfigModule.forRoot({ isGlobal: true }),
44
+ TypeOrmModule.forRoot({
45
+ type: 'postgres',
46
+ url: process.env.DATABASE_URL,
47
+ autoLoadEntities: true,
48
+ synchronize: process.env.NODE_ENV === 'development',
49
+ }),
50
+ AuthModule,
51
+ ItemsModule,
52
+ UsersModule,
53
+ ],
54
+ })
55
+ export class AppModule {}
56
+ ```
57
+
58
+ ---
59
+
60
+ ## Controller Pattern
61
+
62
+ ```typescript
63
+ // items/items.controller.ts
64
+ import {
65
+ Controller,
66
+ Get,
67
+ Post,
68
+ Put,
69
+ Delete,
70
+ Body,
71
+ Param,
72
+ Query,
73
+ UseGuards,
74
+ HttpCode,
75
+ HttpStatus,
76
+ ParseUUIDPipe,
77
+ } from '@nestjs/common';
78
+ import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
79
+ import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
80
+ import { CurrentUser } from '../auth/decorators/current-user.decorator';
81
+ import { ItemsService } from './items.service';
82
+ import { CreateItemDto } from './dto/create-item.dto';
83
+ import { UpdateItemDto } from './dto/update-item.dto';
84
+ import { QueryItemDto } from './dto/query-item.dto';
85
+
86
+ @ApiTags('items')
87
+ @Controller('items')
88
+ export class ItemsController {
89
+ constructor(private readonly itemsService: ItemsService) {}
90
+
91
+ @Get()
92
+ @ApiOperation({ summary: 'Get all items' })
93
+ async findAll(@Query() query: QueryItemDto) {
94
+ return this.itemsService.findAll(query);
95
+ }
96
+
97
+ @Get(':id')
98
+ @ApiOperation({ summary: 'Get item by ID' })
99
+ async findOne(@Param('id', ParseUUIDPipe) id: string) {
100
+ return this.itemsService.findOne(id);
101
+ }
102
+
103
+ @Post()
104
+ @UseGuards(JwtAuthGuard)
105
+ @ApiBearerAuth()
106
+ @ApiOperation({ summary: 'Create new item' })
107
+ async create(
108
+ @Body() createItemDto: CreateItemDto,
109
+ @CurrentUser() user: User,
110
+ ) {
111
+ return this.itemsService.create(createItemDto, user);
112
+ }
113
+
114
+ @Put(':id')
115
+ @UseGuards(JwtAuthGuard)
116
+ @ApiBearerAuth()
117
+ @ApiOperation({ summary: 'Update item' })
118
+ async update(
119
+ @Param('id', ParseUUIDPipe) id: string,
120
+ @Body() updateItemDto: UpdateItemDto,
121
+ @CurrentUser() user: User,
122
+ ) {
123
+ return this.itemsService.update(id, updateItemDto, user);
124
+ }
125
+
126
+ @Delete(':id')
127
+ @UseGuards(JwtAuthGuard)
128
+ @ApiBearerAuth()
129
+ @HttpCode(HttpStatus.NO_CONTENT)
130
+ @ApiOperation({ summary: 'Delete item' })
131
+ async remove(
132
+ @Param('id', ParseUUIDPipe) id: string,
133
+ @CurrentUser() user: User,
134
+ ) {
135
+ return this.itemsService.remove(id, user);
136
+ }
137
+ }
138
+ ```
139
+
140
+ ---
141
+
142
+ ## Service Pattern
143
+
144
+ ```typescript
145
+ // items/items.service.ts
146
+ import { Injectable, NotFoundException, ForbiddenException } from '@nestjs/common';
147
+ import { InjectRepository } from '@nestjs/typeorm';
148
+ import { Repository } from 'typeorm';
149
+ import { Item } from './entities/item.entity';
150
+ import { CreateItemDto } from './dto/create-item.dto';
151
+ import { UpdateItemDto } from './dto/update-item.dto';
152
+ import { QueryItemDto } from './dto/query-item.dto';
153
+
154
+ @Injectable()
155
+ export class ItemsService {
156
+ constructor(
157
+ @InjectRepository(Item)
158
+ private readonly itemRepository: Repository<Item>,
159
+ ) {}
160
+
161
+ async findAll(query: QueryItemDto) {
162
+ const { page = 1, limit = 10, status } = query;
163
+
164
+ const [items, total] = await this.itemRepository.findAndCount({
165
+ where: status ? { status } : {},
166
+ take: limit,
167
+ skip: (page - 1) * limit,
168
+ order: { createdAt: 'DESC' },
169
+ relations: ['author'],
170
+ });
171
+
172
+ return {
173
+ data: items,
174
+ pagination: {
175
+ total,
176
+ page,
177
+ limit,
178
+ totalPages: Math.ceil(total / limit),
179
+ },
180
+ };
181
+ }
182
+
183
+ async findOne(id: string) {
184
+ const item = await this.itemRepository.findOne({
185
+ where: { id },
186
+ relations: ['author'],
187
+ });
188
+
189
+ if (!item) {
190
+ throw new NotFoundException(`Item #${id} not found`);
191
+ }
192
+
193
+ return item;
194
+ }
195
+
196
+ async create(createItemDto: CreateItemDto, user: User) {
197
+ const item = this.itemRepository.create({
198
+ ...createItemDto,
199
+ authorId: user.id,
200
+ });
201
+
202
+ return this.itemRepository.save(item);
203
+ }
204
+
205
+ async update(id: string, updateItemDto: UpdateItemDto, user: User) {
206
+ const item = await this.findOne(id);
207
+
208
+ if (item.authorId !== user.id) {
209
+ throw new ForbiddenException('You can only update your own items');
210
+ }
211
+
212
+ Object.assign(item, updateItemDto);
213
+ return this.itemRepository.save(item);
214
+ }
215
+
216
+ async remove(id: string, user: User) {
217
+ const item = await this.findOne(id);
218
+
219
+ if (item.authorId !== user.id) {
220
+ throw new ForbiddenException('You can only delete your own items');
221
+ }
222
+
223
+ await this.itemRepository.remove(item);
224
+ }
225
+ }
226
+ ```
227
+
228
+ ---
229
+
230
+ ## DTOs with Validation
231
+
232
+ ```typescript
233
+ // items/dto/create-item.dto.ts
234
+ import { IsString, IsNotEmpty, IsOptional, MaxLength } from 'class-validator';
235
+ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
236
+
237
+ export class CreateItemDto {
238
+ @ApiProperty({ description: 'Item title', maxLength: 255 })
239
+ @IsString()
240
+ @IsNotEmpty()
241
+ @MaxLength(255)
242
+ title: string;
243
+
244
+ @ApiPropertyOptional({ description: 'Item description' })
245
+ @IsString()
246
+ @IsOptional()
247
+ description?: string;
248
+ }
249
+
250
+ // items/dto/update-item.dto.ts
251
+ import { PartialType } from '@nestjs/swagger';
252
+ import { CreateItemDto } from './create-item.dto';
253
+
254
+ export class UpdateItemDto extends PartialType(CreateItemDto) {}
255
+
256
+ // items/dto/query-item.dto.ts
257
+ import { IsOptional, IsInt, Min, IsEnum } from 'class-validator';
258
+ import { Type } from 'class-transformer';
259
+ import { ApiPropertyOptional } from '@nestjs/swagger';
260
+
261
+ export class QueryItemDto {
262
+ @ApiPropertyOptional({ default: 1 })
263
+ @IsOptional()
264
+ @Type(() => Number)
265
+ @IsInt()
266
+ @Min(1)
267
+ page?: number = 1;
268
+
269
+ @ApiPropertyOptional({ default: 10 })
270
+ @IsOptional()
271
+ @Type(() => Number)
272
+ @IsInt()
273
+ @Min(1)
274
+ limit?: number = 10;
275
+
276
+ @ApiPropertyOptional({ enum: ['active', 'archived'] })
277
+ @IsOptional()
278
+ @IsEnum(['active', 'archived'])
279
+ status?: string;
280
+ }
281
+ ```
282
+
283
+ ---
284
+
285
+ ## Guards and Decorators
286
+
287
+ ### JWT Auth Guard
288
+
289
+ ```typescript
290
+ // auth/guards/jwt-auth.guard.ts
291
+ import { Injectable, ExecutionContext } from '@nestjs/common';
292
+ import { AuthGuard } from '@nestjs/passport';
293
+
294
+ @Injectable()
295
+ export class JwtAuthGuard extends AuthGuard('jwt') {
296
+ canActivate(context: ExecutionContext) {
297
+ return super.canActivate(context);
298
+ }
299
+ }
300
+ ```
301
+
302
+ ### Current User Decorator
303
+
304
+ ```typescript
305
+ // auth/decorators/current-user.decorator.ts
306
+ import { createParamDecorator, ExecutionContext } from '@nestjs/common';
307
+
308
+ export const CurrentUser = createParamDecorator(
309
+ (data: unknown, ctx: ExecutionContext) => {
310
+ const request = ctx.switchToHttp().getRequest();
311
+ return request.user;
312
+ },
313
+ );
314
+ ```
315
+
316
+ ### Roles Guard
317
+
318
+ ```typescript
319
+ // auth/guards/roles.guard.ts
320
+ import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
321
+ import { Reflector } from '@nestjs/core';
322
+ import { ROLES_KEY } from '../decorators/roles.decorator';
323
+
324
+ @Injectable()
325
+ export class RolesGuard implements CanActivate {
326
+ constructor(private reflector: Reflector) {}
327
+
328
+ canActivate(context: ExecutionContext): boolean {
329
+ const requiredRoles = this.reflector.getAllAndOverride<string[]>(ROLES_KEY, [
330
+ context.getHandler(),
331
+ context.getClass(),
332
+ ]);
333
+
334
+ if (!requiredRoles) {
335
+ return true;
336
+ }
337
+
338
+ const { user } = context.switchToHttp().getRequest();
339
+ return requiredRoles.some((role) => user.roles?.includes(role));
340
+ }
341
+ }
342
+ ```
343
+
344
+ ---
345
+
346
+ ## Exception Filters
347
+
348
+ ```typescript
349
+ // common/filters/http-exception.filter.ts
350
+ import {
351
+ ExceptionFilter,
352
+ Catch,
353
+ ArgumentsHost,
354
+ HttpException,
355
+ HttpStatus,
356
+ } from '@nestjs/common';
357
+ import { Response } from 'express';
358
+
359
+ @Catch()
360
+ export class AllExceptionsFilter implements ExceptionFilter {
361
+ catch(exception: unknown, host: ArgumentsHost) {
362
+ const ctx = host.switchToHttp();
363
+ const response = ctx.getResponse<Response>();
364
+
365
+ const status =
366
+ exception instanceof HttpException
367
+ ? exception.getStatus()
368
+ : HttpStatus.INTERNAL_SERVER_ERROR;
369
+
370
+ const message =
371
+ exception instanceof HttpException
372
+ ? exception.getResponse()
373
+ : 'Internal server error';
374
+
375
+ response.status(status).json({
376
+ success: false,
377
+ statusCode: status,
378
+ error: typeof message === 'string' ? { message } : message,
379
+ timestamp: new Date().toISOString(),
380
+ });
381
+ }
382
+ }
383
+ ```
384
+
385
+ ---
386
+
387
+ ## Testing
388
+
389
+ ```typescript
390
+ // items/items.controller.spec.ts
391
+ import { Test, TestingModule } from '@nestjs/testing';
392
+ import { ItemsController } from './items.controller';
393
+ import { ItemsService } from './items.service';
394
+
395
+ describe('ItemsController', () => {
396
+ let controller: ItemsController;
397
+ let service: ItemsService;
398
+
399
+ const mockItemsService = {
400
+ findAll: jest.fn(),
401
+ findOne: jest.fn(),
402
+ create: jest.fn(),
403
+ update: jest.fn(),
404
+ remove: jest.fn(),
405
+ };
406
+
407
+ beforeEach(async () => {
408
+ const module: TestingModule = await Test.createTestingModule({
409
+ controllers: [ItemsController],
410
+ providers: [
411
+ {
412
+ provide: ItemsService,
413
+ useValue: mockItemsService,
414
+ },
415
+ ],
416
+ }).compile();
417
+
418
+ controller = module.get<ItemsController>(ItemsController);
419
+ service = module.get<ItemsService>(ItemsService);
420
+ });
421
+
422
+ it('should be defined', () => {
423
+ expect(controller).toBeDefined();
424
+ });
425
+
426
+ describe('findAll', () => {
427
+ it('should return array of items', async () => {
428
+ const result = { data: [], pagination: {} };
429
+ mockItemsService.findAll.mockResolvedValue(result);
430
+
431
+ expect(await controller.findAll({})).toBe(result);
432
+ });
433
+ });
434
+
435
+ describe('create', () => {
436
+ it('should create item', async () => {
437
+ const dto = { title: 'Test' };
438
+ const user = { id: '1' };
439
+ const item = { id: '1', ...dto };
440
+
441
+ mockItemsService.create.mockResolvedValue(item);
442
+
443
+ expect(await controller.create(dto, user as any)).toBe(item);
444
+ expect(mockItemsService.create).toHaveBeenCalledWith(dto, user);
445
+ });
446
+ });
447
+ });
448
+ ```
449
+
450
+ ---
451
+
452
+ ## Project Structure
453
+
454
+ ```
455
+ {API_PATH}/
456
+ ├── src/
457
+ │ ├── main.ts
458
+ │ ├── app.module.ts
459
+ │ ├── common/
460
+ │ │ ├── filters/
461
+ │ │ ├── guards/
462
+ │ │ ├── interceptors/
463
+ │ │ └── pipes/
464
+ │ ├── auth/
465
+ │ │ ├── auth.module.ts
466
+ │ │ ├── auth.service.ts
467
+ │ │ ├── guards/
468
+ │ │ └── decorators/
469
+ │ └── items/
470
+ │ ├── items.module.ts
471
+ │ ├── items.controller.ts
472
+ │ ├── items.service.ts
473
+ │ ├── dto/
474
+ │ └── entities/
475
+ └── test/
476
+ └── items.e2e-spec.ts
477
+ ```
478
+
479
+ ---
480
+
481
+ ## Best Practices
482
+
483
+ ### Good
484
+
485
+ - Use modules for feature encapsulation
486
+ - Use DTOs for validation with class-validator
487
+ - Use guards for authentication/authorization
488
+ - Use interceptors for response transformation
489
+ - Use dependency injection consistently
490
+
491
+ ### Bad
492
+
493
+ - Circular dependencies between modules
494
+ - Business logic in controllers
495
+ - Skipping validation
496
+ - Not using pipes for transformation
497
+ - Hardcoded values instead of ConfigService