@malamute/ai-rules 1.0.0 → 1.2.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 (133) hide show
  1. package/README.md +270 -121
  2. package/bin/cli.js +5 -2
  3. package/configs/_shared/.claude/rules/conventions/documentation.md +324 -0
  4. package/configs/_shared/.claude/rules/conventions/git.md +265 -0
  5. package/configs/_shared/.claude/rules/{performance.md → conventions/performance.md} +1 -1
  6. package/configs/_shared/.claude/rules/conventions/principles.md +334 -0
  7. package/configs/_shared/.claude/rules/devops/ci-cd.md +262 -0
  8. package/configs/_shared/.claude/rules/devops/docker.md +275 -0
  9. package/configs/_shared/.claude/rules/devops/nx.md +194 -0
  10. package/configs/_shared/.claude/rules/domain/backend/api-design.md +203 -0
  11. package/configs/_shared/.claude/rules/lang/csharp/async.md +220 -0
  12. package/configs/_shared/.claude/rules/lang/csharp/csharp.md +314 -0
  13. package/configs/_shared/.claude/rules/lang/csharp/linq.md +210 -0
  14. package/configs/_shared/.claude/rules/lang/python/async.md +337 -0
  15. package/configs/_shared/.claude/rules/lang/python/celery.md +476 -0
  16. package/configs/_shared/.claude/rules/lang/python/config.md +339 -0
  17. package/configs/{python/.claude/rules → _shared/.claude/rules/lang/python}/database/sqlalchemy.md +6 -1
  18. package/configs/_shared/.claude/rules/lang/python/deployment.md +523 -0
  19. package/configs/_shared/.claude/rules/lang/python/error-handling.md +330 -0
  20. package/configs/_shared/.claude/rules/lang/python/migrations.md +421 -0
  21. package/configs/_shared/.claude/rules/lang/python/python.md +172 -0
  22. package/configs/_shared/.claude/rules/lang/python/repository.md +383 -0
  23. package/configs/{python/.claude/rules → _shared/.claude/rules/lang/python}/testing.md +2 -69
  24. package/configs/_shared/.claude/rules/lang/typescript/async.md +447 -0
  25. package/configs/_shared/.claude/rules/lang/typescript/generics.md +356 -0
  26. package/configs/_shared/.claude/rules/lang/typescript/typescript.md +212 -0
  27. package/configs/_shared/.claude/rules/quality/error-handling.md +48 -0
  28. package/configs/_shared/.claude/rules/quality/logging.md +45 -0
  29. package/configs/_shared/.claude/rules/quality/observability.md +240 -0
  30. package/configs/_shared/.claude/rules/quality/testing-patterns.md +65 -0
  31. package/configs/_shared/.claude/rules/security/secrets-management.md +222 -0
  32. package/configs/_shared/.claude/skills/analysis/explore/SKILL.md +257 -0
  33. package/configs/_shared/.claude/skills/analysis/security-audit/SKILL.md +184 -0
  34. package/configs/_shared/.claude/skills/dev/api-endpoint/SKILL.md +126 -0
  35. package/configs/_shared/.claude/{commands/generate-tests.md → skills/dev/generate-tests/SKILL.md} +6 -0
  36. package/configs/_shared/.claude/{commands/fix-issue.md → skills/git/fix-issue/SKILL.md} +6 -0
  37. package/configs/_shared/.claude/{commands/review-pr.md → skills/git/review-pr/SKILL.md} +6 -0
  38. package/configs/_shared/.claude/skills/infra/deploy/SKILL.md +139 -0
  39. package/configs/_shared/.claude/skills/infra/docker/SKILL.md +95 -0
  40. package/configs/_shared/.claude/skills/infra/migration/SKILL.md +158 -0
  41. package/configs/_shared/.claude/skills/nx/nx-affected/SKILL.md +72 -0
  42. package/configs/_shared/.claude/skills/nx/nx-lib/SKILL.md +375 -0
  43. package/configs/_shared/CLAUDE.md +52 -149
  44. package/configs/angular/.claude/rules/{components.md → core/components.md} +69 -15
  45. package/configs/angular/.claude/rules/core/resource.md +285 -0
  46. package/configs/angular/.claude/rules/core/signals.md +323 -0
  47. package/configs/angular/.claude/rules/http.md +338 -0
  48. package/configs/angular/.claude/rules/routing.md +291 -0
  49. package/configs/angular/.claude/rules/ssr.md +312 -0
  50. package/configs/angular/.claude/rules/state/signal-store.md +408 -0
  51. package/configs/angular/.claude/rules/{state.md → state/state.md} +2 -2
  52. package/configs/angular/.claude/rules/testing.md +7 -7
  53. package/configs/angular/.claude/rules/ui/aria.md +422 -0
  54. package/configs/angular/.claude/rules/ui/forms.md +424 -0
  55. package/configs/angular/.claude/rules/ui/pipes-directives.md +335 -0
  56. package/configs/angular/.claude/settings.json +1 -0
  57. package/configs/angular/.claude/skills/ngrx-slice/SKILL.md +362 -0
  58. package/configs/angular/.claude/skills/signal-store/SKILL.md +445 -0
  59. package/configs/angular/CLAUDE.md +24 -216
  60. package/configs/dotnet/.claude/rules/background-services.md +552 -0
  61. package/configs/dotnet/.claude/rules/configuration.md +426 -0
  62. package/configs/dotnet/.claude/rules/ddd.md +447 -0
  63. package/configs/dotnet/.claude/rules/dependency-injection.md +343 -0
  64. package/configs/dotnet/.claude/rules/mediatr.md +320 -0
  65. package/configs/dotnet/.claude/rules/middleware.md +489 -0
  66. package/configs/dotnet/.claude/rules/result-pattern.md +363 -0
  67. package/configs/dotnet/.claude/rules/validation.md +388 -0
  68. package/configs/dotnet/.claude/settings.json +21 -3
  69. package/configs/dotnet/CLAUDE.md +53 -286
  70. package/configs/fastapi/.claude/rules/background-tasks.md +254 -0
  71. package/configs/fastapi/.claude/rules/dependencies.md +170 -0
  72. package/configs/{python → fastapi}/.claude/rules/fastapi.md +61 -1
  73. package/configs/fastapi/.claude/rules/lifespan.md +274 -0
  74. package/configs/fastapi/.claude/rules/middleware.md +229 -0
  75. package/configs/fastapi/.claude/rules/pydantic.md +433 -0
  76. package/configs/fastapi/.claude/rules/responses.md +251 -0
  77. package/configs/fastapi/.claude/rules/routers.md +202 -0
  78. package/configs/fastapi/.claude/rules/security.md +222 -0
  79. package/configs/fastapi/.claude/rules/testing.md +251 -0
  80. package/configs/fastapi/.claude/rules/websockets.md +298 -0
  81. package/configs/fastapi/.claude/settings.json +33 -0
  82. package/configs/fastapi/CLAUDE.md +144 -0
  83. package/configs/flask/.claude/rules/blueprints.md +208 -0
  84. package/configs/flask/.claude/rules/cli.md +285 -0
  85. package/configs/flask/.claude/rules/configuration.md +281 -0
  86. package/configs/flask/.claude/rules/context.md +238 -0
  87. package/configs/flask/.claude/rules/error-handlers.md +278 -0
  88. package/configs/flask/.claude/rules/extensions.md +278 -0
  89. package/configs/flask/.claude/rules/flask.md +171 -0
  90. package/configs/flask/.claude/rules/marshmallow.md +206 -0
  91. package/configs/flask/.claude/rules/security.md +267 -0
  92. package/configs/flask/.claude/rules/testing.md +284 -0
  93. package/configs/flask/.claude/settings.json +33 -0
  94. package/configs/flask/CLAUDE.md +166 -0
  95. package/configs/nestjs/.claude/rules/common-patterns.md +300 -0
  96. package/configs/nestjs/.claude/rules/filters.md +376 -0
  97. package/configs/nestjs/.claude/rules/interceptors.md +317 -0
  98. package/configs/nestjs/.claude/rules/middleware.md +321 -0
  99. package/configs/nestjs/.claude/rules/modules.md +26 -0
  100. package/configs/nestjs/.claude/rules/pipes.md +351 -0
  101. package/configs/nestjs/.claude/rules/websockets.md +451 -0
  102. package/configs/nestjs/.claude/settings.json +16 -2
  103. package/configs/nestjs/CLAUDE.md +57 -215
  104. package/configs/nextjs/.claude/rules/api-routes.md +358 -0
  105. package/configs/nextjs/.claude/rules/authentication.md +355 -0
  106. package/configs/nextjs/.claude/rules/components.md +52 -0
  107. package/configs/nextjs/.claude/rules/data-fetching.md +249 -0
  108. package/configs/nextjs/.claude/rules/database.md +400 -0
  109. package/configs/nextjs/.claude/rules/middleware.md +303 -0
  110. package/configs/nextjs/.claude/rules/routing.md +324 -0
  111. package/configs/nextjs/.claude/rules/seo.md +350 -0
  112. package/configs/nextjs/.claude/rules/server-actions.md +353 -0
  113. package/configs/nextjs/.claude/rules/state/zustand.md +6 -6
  114. package/configs/nextjs/.claude/settings.json +5 -0
  115. package/configs/nextjs/CLAUDE.md +69 -331
  116. package/package.json +23 -9
  117. package/src/cli.js +220 -0
  118. package/src/config.js +29 -0
  119. package/src/index.js +13 -0
  120. package/src/installer.js +361 -0
  121. package/src/merge.js +116 -0
  122. package/src/tech-config.json +29 -0
  123. package/src/utils.js +96 -0
  124. package/configs/python/.claude/rules/flask.md +0 -332
  125. package/configs/python/.claude/settings.json +0 -18
  126. package/configs/python/CLAUDE.md +0 -273
  127. package/src/install.js +0 -315
  128. /package/configs/_shared/.claude/rules/{accessibility.md → domain/frontend/accessibility.md} +0 -0
  129. /package/configs/_shared/.claude/rules/{security.md → security/security.md} +0 -0
  130. /package/configs/_shared/.claude/skills/{debug → dev/debug}/SKILL.md +0 -0
  131. /package/configs/_shared/.claude/skills/{learning → dev/learning}/SKILL.md +0 -0
  132. /package/configs/_shared/.claude/skills/{spec → dev/spec}/SKILL.md +0 -0
  133. /package/configs/_shared/.claude/skills/{review → git/review}/SKILL.md +0 -0
@@ -0,0 +1,351 @@
1
+ ---
2
+ paths:
3
+ - "**/*.pipe.ts"
4
+ - "**/pipes/**/*.ts"
5
+ ---
6
+
7
+ # NestJS Pipes
8
+
9
+ ## Built-in Pipes
10
+
11
+ ```typescript
12
+ import {
13
+ ValidationPipe,
14
+ ParseIntPipe,
15
+ ParseBoolPipe,
16
+ ParseArrayPipe,
17
+ ParseUUIDPipe,
18
+ ParseEnumPipe,
19
+ DefaultValuePipe,
20
+ } from '@nestjs/common';
21
+
22
+ @Controller('users')
23
+ export class UsersController {
24
+ // ParseIntPipe
25
+ @Get(':id')
26
+ findOne(@Param('id', ParseIntPipe) id: number) {
27
+ return this.usersService.findOne(id);
28
+ }
29
+
30
+ // ParseUUIDPipe with version
31
+ @Get(':uuid')
32
+ findByUuid(@Param('uuid', new ParseUUIDPipe({ version: '4' })) uuid: string) {
33
+ return this.usersService.findByUuid(uuid);
34
+ }
35
+
36
+ // ParseEnumPipe
37
+ @Get()
38
+ findByStatus(
39
+ @Query('status', new ParseEnumPipe(UserStatus)) status: UserStatus,
40
+ ) {
41
+ return this.usersService.findByStatus(status);
42
+ }
43
+
44
+ // DefaultValuePipe
45
+ @Get()
46
+ findAll(
47
+ @Query('page', new DefaultValuePipe(1), ParseIntPipe) page: number,
48
+ @Query('limit', new DefaultValuePipe(10), ParseIntPipe) limit: number,
49
+ ) {
50
+ return this.usersService.findAll({ page, limit });
51
+ }
52
+
53
+ // ParseArrayPipe
54
+ @Get()
55
+ findByIds(
56
+ @Query('ids', new ParseArrayPipe({ items: Number, separator: ',' }))
57
+ ids: number[],
58
+ ) {
59
+ return this.usersService.findByIds(ids);
60
+ }
61
+ }
62
+ ```
63
+
64
+ ## Global Validation Pipe
65
+
66
+ ```typescript
67
+ // main.ts
68
+ import { ValidationPipe } from '@nestjs/common';
69
+
70
+ async function bootstrap() {
71
+ const app = await NestFactory.create(AppModule);
72
+
73
+ app.useGlobalPipes(
74
+ new ValidationPipe({
75
+ whitelist: true, // Strip non-decorated properties
76
+ forbidNonWhitelisted: true, // Throw on extra properties
77
+ transform: true, // Transform payloads to DTO types
78
+ transformOptions: {
79
+ enableImplicitConversion: true,
80
+ },
81
+ exceptionFactory: (errors) => {
82
+ const messages = errors.map((error) => ({
83
+ field: error.property,
84
+ constraints: Object.values(error.constraints || {}),
85
+ }));
86
+ return new BadRequestException({ errors: messages });
87
+ },
88
+ }),
89
+ );
90
+
91
+ await app.listen(3000);
92
+ }
93
+ ```
94
+
95
+ ## Custom Pipes
96
+
97
+ ### Transform Pipe
98
+
99
+ ```typescript
100
+ // pipes/parse-date.pipe.ts
101
+ import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common';
102
+
103
+ @Injectable()
104
+ export class ParseDatePipe implements PipeTransform<string, Date> {
105
+ transform(value: string): Date {
106
+ const date = new Date(value);
107
+
108
+ if (isNaN(date.getTime())) {
109
+ throw new BadRequestException(`Invalid date format: ${value}`);
110
+ }
111
+
112
+ return date;
113
+ }
114
+ }
115
+
116
+ // Usage
117
+ @Get()
118
+ findByDate(@Query('date', ParseDatePipe) date: Date) {
119
+ return this.service.findByDate(date);
120
+ }
121
+ ```
122
+
123
+ ### Validation Pipe with Schema
124
+
125
+ ```typescript
126
+ // pipes/zod-validation.pipe.ts
127
+ import { PipeTransform, BadRequestException } from '@nestjs/common';
128
+ import { ZodSchema, ZodError } from 'zod';
129
+
130
+ export class ZodValidationPipe implements PipeTransform {
131
+ constructor(private readonly schema: ZodSchema) {}
132
+
133
+ transform(value: unknown) {
134
+ try {
135
+ return this.schema.parse(value);
136
+ } catch (error) {
137
+ if (error instanceof ZodError) {
138
+ throw new BadRequestException({
139
+ message: 'Validation failed',
140
+ errors: error.errors.map((e) => ({
141
+ path: e.path.join('.'),
142
+ message: e.message,
143
+ })),
144
+ });
145
+ }
146
+ throw error;
147
+ }
148
+ }
149
+ }
150
+
151
+ // Usage
152
+ const createUserSchema = z.object({
153
+ email: z.string().email(),
154
+ name: z.string().min(2),
155
+ });
156
+
157
+ @Post()
158
+ create(@Body(new ZodValidationPipe(createUserSchema)) dto: CreateUserDto) {
159
+ return this.usersService.create(dto);
160
+ }
161
+ ```
162
+
163
+ ### Async Pipe
164
+
165
+ ```typescript
166
+ // pipes/user-exists.pipe.ts
167
+ import {
168
+ PipeTransform,
169
+ Injectable,
170
+ NotFoundException,
171
+ } from '@nestjs/common';
172
+ import { UsersService } from '../users.service';
173
+
174
+ @Injectable()
175
+ export class UserExistsPipe implements PipeTransform<string, Promise<User>> {
176
+ constructor(private readonly usersService: UsersService) {}
177
+
178
+ async transform(id: string): Promise<User> {
179
+ const user = await this.usersService.findOne(id);
180
+
181
+ if (!user) {
182
+ throw new NotFoundException(`User with ID ${id} not found`);
183
+ }
184
+
185
+ return user;
186
+ }
187
+ }
188
+
189
+ // Usage - returns User directly, not ID
190
+ @Get(':id')
191
+ findOne(@Param('id', UserExistsPipe) user: User) {
192
+ return user;
193
+ }
194
+ ```
195
+
196
+ ### Trim and Sanitize
197
+
198
+ ```typescript
199
+ // pipes/trim.pipe.ts
200
+ import { PipeTransform, Injectable } from '@nestjs/common';
201
+
202
+ @Injectable()
203
+ export class TrimPipe implements PipeTransform {
204
+ transform(value: unknown) {
205
+ if (typeof value === 'string') {
206
+ return value.trim();
207
+ }
208
+
209
+ if (typeof value === 'object' && value !== null) {
210
+ return this.trimObject(value);
211
+ }
212
+
213
+ return value;
214
+ }
215
+
216
+ private trimObject(obj: Record<string, unknown>): Record<string, unknown> {
217
+ const trimmed: Record<string, unknown> = {};
218
+
219
+ for (const [key, val] of Object.entries(obj)) {
220
+ trimmed[key] = typeof val === 'string' ? val.trim() : val;
221
+ }
222
+
223
+ return trimmed;
224
+ }
225
+ }
226
+ ```
227
+
228
+ ### File Validation Pipe
229
+
230
+ ```typescript
231
+ // pipes/file-validation.pipe.ts
232
+ import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common';
233
+
234
+ interface FileValidationOptions {
235
+ maxSize: number;
236
+ allowedMimeTypes: string[];
237
+ }
238
+
239
+ @Injectable()
240
+ export class FileValidationPipe implements PipeTransform {
241
+ constructor(private readonly options: FileValidationOptions) {}
242
+
243
+ transform(file: Express.Multer.File) {
244
+ if (!file) {
245
+ throw new BadRequestException('File is required');
246
+ }
247
+
248
+ if (file.size > this.options.maxSize) {
249
+ throw new BadRequestException(
250
+ `File size exceeds ${this.options.maxSize / 1024 / 1024}MB`,
251
+ );
252
+ }
253
+
254
+ if (!this.options.allowedMimeTypes.includes(file.mimetype)) {
255
+ throw new BadRequestException(
256
+ `File type ${file.mimetype} is not allowed`,
257
+ );
258
+ }
259
+
260
+ return file;
261
+ }
262
+ }
263
+
264
+ // Usage
265
+ @Post('upload')
266
+ @UseInterceptors(FileInterceptor('file'))
267
+ upload(
268
+ @UploadedFile(
269
+ new FileValidationPipe({
270
+ maxSize: 5 * 1024 * 1024,
271
+ allowedMimeTypes: ['image/jpeg', 'image/png'],
272
+ }),
273
+ )
274
+ file: Express.Multer.File,
275
+ ) {
276
+ return this.uploadService.upload(file);
277
+ }
278
+ ```
279
+
280
+ ## Pipe Binding Scopes
281
+
282
+ ```typescript
283
+ // Parameter level
284
+ @Get(':id')
285
+ findOne(@Param('id', ParseIntPipe) id: number) {}
286
+
287
+ // Method level
288
+ @Post()
289
+ @UsePipes(ValidationPipe)
290
+ create(@Body() dto: CreateDto) {}
291
+
292
+ // Controller level
293
+ @Controller('users')
294
+ @UsePipes(TrimPipe)
295
+ export class UsersController {}
296
+
297
+ // Global level (main.ts)
298
+ app.useGlobalPipes(new ValidationPipe());
299
+
300
+ // Global with DI
301
+ @Module({
302
+ providers: [
303
+ {
304
+ provide: APP_PIPE,
305
+ useClass: ValidationPipe,
306
+ },
307
+ ],
308
+ })
309
+ export class AppModule {}
310
+ ```
311
+
312
+ ## Anti-patterns
313
+
314
+ ```typescript
315
+ // BAD: Pipe with side effects
316
+ @Injectable()
317
+ export class LoggingPipe implements PipeTransform {
318
+ transform(value: unknown) {
319
+ console.log(value); // Use interceptor instead
320
+ this.analyticsService.track(value); // Side effect!
321
+ return value;
322
+ }
323
+ }
324
+
325
+ // GOOD: Pipes are for transformation/validation only
326
+
327
+ // BAD: Heavy async operations in pipe
328
+ @Injectable()
329
+ export class HeavyPipe implements PipeTransform {
330
+ async transform(value: string) {
331
+ await this.externalApi.validate(value); // Too slow
332
+ return value;
333
+ }
334
+ }
335
+
336
+ // GOOD: Keep pipes lightweight, use guards for auth checks
337
+
338
+ // BAD: Not handling validation errors properly
339
+ transform(value: string) {
340
+ return new Date(value); // Crashes on invalid input
341
+ }
342
+
343
+ // GOOD: Proper error handling
344
+ transform(value: string) {
345
+ const date = new Date(value);
346
+ if (isNaN(date.getTime())) {
347
+ throw new BadRequestException('Invalid date');
348
+ }
349
+ return date;
350
+ }
351
+ ```