autoworkflow 3.1.5 → 3.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 (124) hide show
  1. package/.claude/commands/analyze.md +19 -0
  2. package/.claude/commands/audit.md +26 -0
  3. package/.claude/commands/build.md +39 -0
  4. package/.claude/commands/commit.md +25 -0
  5. package/.claude/commands/fix.md +23 -0
  6. package/.claude/commands/plan.md +18 -0
  7. package/.claude/commands/suggest.md +23 -0
  8. package/.claude/commands/verify.md +18 -0
  9. package/.claude/hooks/post-bash-router.sh +20 -0
  10. package/.claude/hooks/post-commit.sh +140 -0
  11. package/.claude/hooks/post-edit.sh +190 -17
  12. package/.claude/hooks/pre-edit.sh +221 -0
  13. package/.claude/hooks/session-check.sh +90 -0
  14. package/.claude/settings.json +56 -6
  15. package/.claude/settings.local.json +5 -1
  16. package/.claude/skills/actix.md +337 -0
  17. package/.claude/skills/alembic.md +504 -0
  18. package/.claude/skills/angular.md +237 -0
  19. package/.claude/skills/api-design.md +187 -0
  20. package/.claude/skills/aspnet-core.md +377 -0
  21. package/.claude/skills/astro.md +245 -0
  22. package/.claude/skills/auth-clerk.md +327 -0
  23. package/.claude/skills/auth-firebase.md +367 -0
  24. package/.claude/skills/auth-nextauth.md +359 -0
  25. package/.claude/skills/auth-supabase.md +368 -0
  26. package/.claude/skills/axum.md +386 -0
  27. package/.claude/skills/blazor.md +456 -0
  28. package/.claude/skills/chi.md +348 -0
  29. package/.claude/skills/code-review.md +133 -0
  30. package/.claude/skills/csharp.md +296 -0
  31. package/.claude/skills/css-modules.md +325 -0
  32. package/.claude/skills/cypress.md +343 -0
  33. package/.claude/skills/debugging.md +133 -0
  34. package/.claude/skills/diesel.md +392 -0
  35. package/.claude/skills/django.md +301 -0
  36. package/.claude/skills/docker.md +319 -0
  37. package/.claude/skills/doctrine.md +473 -0
  38. package/.claude/skills/documentation.md +182 -0
  39. package/.claude/skills/dotnet.md +409 -0
  40. package/.claude/skills/drizzle.md +293 -0
  41. package/.claude/skills/echo.md +321 -0
  42. package/.claude/skills/eloquent.md +256 -0
  43. package/.claude/skills/emotion.md +426 -0
  44. package/.claude/skills/entity-framework.md +370 -0
  45. package/.claude/skills/express.md +316 -0
  46. package/.claude/skills/fastapi.md +329 -0
  47. package/.claude/skills/fastify.md +299 -0
  48. package/.claude/skills/fiber.md +315 -0
  49. package/.claude/skills/flask.md +322 -0
  50. package/.claude/skills/gin.md +342 -0
  51. package/.claude/skills/git.md +116 -0
  52. package/.claude/skills/github-actions.md +353 -0
  53. package/.claude/skills/go.md +377 -0
  54. package/.claude/skills/gorm.md +409 -0
  55. package/.claude/skills/graphql.md +478 -0
  56. package/.claude/skills/hibernate.md +379 -0
  57. package/.claude/skills/hono.md +306 -0
  58. package/.claude/skills/java.md +400 -0
  59. package/.claude/skills/jest.md +313 -0
  60. package/.claude/skills/jpa.md +282 -0
  61. package/.claude/skills/kotlin.md +347 -0
  62. package/.claude/skills/kubernetes.md +363 -0
  63. package/.claude/skills/laravel.md +414 -0
  64. package/.claude/skills/mcp-browser.md +320 -0
  65. package/.claude/skills/mcp-database.md +219 -0
  66. package/.claude/skills/mcp-fetch.md +241 -0
  67. package/.claude/skills/mcp-filesystem.md +204 -0
  68. package/.claude/skills/mcp-github.md +217 -0
  69. package/.claude/skills/mcp-memory.md +240 -0
  70. package/.claude/skills/mcp-search.md +218 -0
  71. package/.claude/skills/mcp-slack.md +262 -0
  72. package/.claude/skills/micronaut.md +388 -0
  73. package/.claude/skills/mongodb.md +319 -0
  74. package/.claude/skills/mongoose.md +355 -0
  75. package/.claude/skills/mysql.md +281 -0
  76. package/.claude/skills/nestjs.md +335 -0
  77. package/.claude/skills/nextjs-app-router.md +260 -0
  78. package/.claude/skills/nextjs-pages.md +172 -0
  79. package/.claude/skills/nuxt.md +202 -0
  80. package/.claude/skills/openapi.md +489 -0
  81. package/.claude/skills/performance.md +199 -0
  82. package/.claude/skills/php.md +398 -0
  83. package/.claude/skills/playwright.md +371 -0
  84. package/.claude/skills/postgresql.md +257 -0
  85. package/.claude/skills/prisma.md +293 -0
  86. package/.claude/skills/pydantic.md +304 -0
  87. package/.claude/skills/pytest.md +313 -0
  88. package/.claude/skills/python.md +272 -0
  89. package/.claude/skills/quarkus.md +377 -0
  90. package/.claude/skills/react.md +230 -0
  91. package/.claude/skills/redis.md +391 -0
  92. package/.claude/skills/refactoring.md +143 -0
  93. package/.claude/skills/remix.md +246 -0
  94. package/.claude/skills/rest-api.md +490 -0
  95. package/.claude/skills/rocket.md +366 -0
  96. package/.claude/skills/rust.md +341 -0
  97. package/.claude/skills/sass.md +380 -0
  98. package/.claude/skills/sea-orm.md +382 -0
  99. package/.claude/skills/security.md +167 -0
  100. package/.claude/skills/sequelize.md +395 -0
  101. package/.claude/skills/spring-boot.md +416 -0
  102. package/.claude/skills/sqlalchemy.md +269 -0
  103. package/.claude/skills/sqlx-rust.md +408 -0
  104. package/.claude/skills/state-jotai.md +346 -0
  105. package/.claude/skills/state-mobx.md +353 -0
  106. package/.claude/skills/state-pinia.md +431 -0
  107. package/.claude/skills/state-redux.md +337 -0
  108. package/.claude/skills/state-tanstack-query.md +434 -0
  109. package/.claude/skills/state-zustand.md +340 -0
  110. package/.claude/skills/styled-components.md +403 -0
  111. package/.claude/skills/svelte.md +238 -0
  112. package/.claude/skills/sveltekit.md +207 -0
  113. package/.claude/skills/symfony.md +437 -0
  114. package/.claude/skills/tailwind.md +279 -0
  115. package/.claude/skills/terraform.md +394 -0
  116. package/.claude/skills/testing-library.md +371 -0
  117. package/.claude/skills/trpc.md +426 -0
  118. package/.claude/skills/typeorm.md +368 -0
  119. package/.claude/skills/vitest.md +330 -0
  120. package/.claude/skills/vue.md +202 -0
  121. package/.claude/skills/warp.md +365 -0
  122. package/README.md +163 -52
  123. package/package.json +1 -1
  124. package/system/triggers.md +256 -17
@@ -0,0 +1,281 @@
1
+ # MySQL Skill
2
+
3
+ ## Schema Design
4
+ \`\`\`sql
5
+ -- Table with constraints (MySQL 8.0+)
6
+ CREATE TABLE users (
7
+ id BINARY(16) PRIMARY KEY DEFAULT (UUID_TO_BIN(UUID())),
8
+ email VARCHAR(255) NOT NULL,
9
+ name VARCHAR(100) NOT NULL,
10
+ password_hash VARCHAR(255) NOT NULL,
11
+ role ENUM('user', 'admin', 'moderator') DEFAULT 'user',
12
+ settings JSON DEFAULT '{}',
13
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
14
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
15
+ deleted_at TIMESTAMP NULL,
16
+ UNIQUE KEY uk_email (email),
17
+ INDEX idx_role_created (role, created_at)
18
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
19
+
20
+ -- Foreign key with cascade
21
+ CREATE TABLE posts (
22
+ id BINARY(16) PRIMARY KEY DEFAULT (UUID_TO_BIN(UUID())),
23
+ title VARCHAR(255) NOT NULL,
24
+ content TEXT,
25
+ published BOOLEAN DEFAULT FALSE,
26
+ author_id BINARY(16) NOT NULL,
27
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
28
+ INDEX idx_author (author_id),
29
+ INDEX idx_published_created (published, created_at),
30
+ FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE
31
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
32
+
33
+ -- Junction table for many-to-many
34
+ CREATE TABLE post_tags (
35
+ post_id BINARY(16) NOT NULL,
36
+ tag_id BINARY(16) NOT NULL,
37
+ PRIMARY KEY (post_id, tag_id),
38
+ FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE,
39
+ FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE
40
+ ) ENGINE=InnoDB;
41
+ \`\`\`
42
+
43
+ ## Indexes
44
+ \`\`\`sql
45
+ -- B-tree index (default)
46
+ CREATE INDEX idx_users_email ON users(email);
47
+
48
+ -- Compound index (leftmost prefix rule applies)
49
+ CREATE INDEX idx_posts_author_created ON posts(author_id, created_at DESC);
50
+
51
+ -- Covering index (MySQL 8.0+ functional indexes)
52
+ CREATE INDEX idx_email_lower ON users((LOWER(email)));
53
+
54
+ -- Full-text index
55
+ ALTER TABLE posts ADD FULLTEXT INDEX ft_content (title, content);
56
+
57
+ -- Prefix index for long columns
58
+ CREATE INDEX idx_content_prefix ON posts(content(100));
59
+
60
+ -- Invisible index (for testing removal impact)
61
+ ALTER TABLE users ALTER INDEX idx_role INVISIBLE;
62
+ -- Later: ALTER TABLE users ALTER INDEX idx_role VISIBLE;
63
+ \`\`\`
64
+
65
+ ## Common Queries
66
+ \`\`\`sql
67
+ -- Pagination (offset-based)
68
+ SELECT * FROM posts
69
+ WHERE published = TRUE
70
+ ORDER BY created_at DESC
71
+ LIMIT 20 OFFSET 40;
72
+
73
+ -- Pagination (cursor-based, more efficient)
74
+ SELECT * FROM posts
75
+ WHERE published = TRUE AND created_at < '2024-01-15 10:00:00'
76
+ ORDER BY created_at DESC
77
+ LIMIT 20;
78
+
79
+ -- Upsert (INSERT ... ON DUPLICATE KEY)
80
+ INSERT INTO users (email, name, updated_at)
81
+ VALUES ('user@example.com', 'John', NOW())
82
+ ON DUPLICATE KEY UPDATE
83
+ name = VALUES(name),
84
+ updated_at = NOW();
85
+
86
+ -- Insert ignore (skip on conflict)
87
+ INSERT IGNORE INTO users (email, name) VALUES ('user@example.com', 'John');
88
+
89
+ -- Replace (delete + insert on conflict)
90
+ REPLACE INTO users (email, name) VALUES ('user@example.com', 'New Name');
91
+ \`\`\`
92
+
93
+ ## JSON Operations (MySQL 8.0+)
94
+ \`\`\`sql
95
+ -- Query JSON field
96
+ SELECT * FROM users WHERE JSON_EXTRACT(settings, '$.theme') = 'dark';
97
+ -- Shorthand: settings->>'$.theme' = 'dark'
98
+
99
+ SELECT * FROM users WHERE JSON_CONTAINS(settings, '"premium"', '$.tags');
100
+
101
+ -- Update JSON field
102
+ UPDATE users
103
+ SET settings = JSON_SET(settings, '$.theme', 'light')
104
+ WHERE id = ?;
105
+
106
+ -- Remove JSON key
107
+ UPDATE users
108
+ SET settings = JSON_REMOVE(settings, '$.oldKey')
109
+ WHERE id = ?;
110
+
111
+ -- Merge JSON objects
112
+ UPDATE users
113
+ SET settings = JSON_MERGE_PATCH(settings, '{"newKey": "value"}')
114
+ WHERE id = ?;
115
+
116
+ -- Index JSON values (generated column)
117
+ ALTER TABLE users
118
+ ADD COLUMN theme VARCHAR(50) GENERATED ALWAYS AS (settings->>'$.theme') STORED,
119
+ ADD INDEX idx_theme (theme);
120
+ \`\`\`
121
+
122
+ ## CTEs & Window Functions (MySQL 8.0+)
123
+ \`\`\`sql
124
+ -- CTE for readability
125
+ WITH active_users AS (
126
+ SELECT * FROM users WHERE deleted_at IS NULL
127
+ )
128
+ SELECT u.*, COUNT(p.id) as post_count
129
+ FROM active_users u
130
+ LEFT JOIN posts p ON u.id = p.author_id
131
+ GROUP BY u.id;
132
+
133
+ -- Recursive CTE (hierarchical data)
134
+ WITH RECURSIVE category_tree AS (
135
+ SELECT id, name, parent_id, 0 as depth
136
+ FROM categories
137
+ WHERE parent_id IS NULL
138
+
139
+ UNION ALL
140
+
141
+ SELECT c.id, c.name, c.parent_id, ct.depth + 1
142
+ FROM categories c
143
+ JOIN category_tree ct ON c.parent_id = ct.id
144
+ )
145
+ SELECT * FROM category_tree ORDER BY depth, name;
146
+
147
+ -- Window functions
148
+ SELECT
149
+ author_id,
150
+ title,
151
+ created_at,
152
+ ROW_NUMBER() OVER (PARTITION BY author_id ORDER BY created_at DESC) as post_rank,
153
+ LAG(title) OVER (ORDER BY created_at) as prev_title
154
+ FROM posts;
155
+ \`\`\`
156
+
157
+ ## Full-Text Search
158
+ \`\`\`sql
159
+ -- Natural language mode (default)
160
+ SELECT *, MATCH(title, content) AGAINST('search terms') as relevance
161
+ FROM posts
162
+ WHERE MATCH(title, content) AGAINST('search terms')
163
+ ORDER BY relevance DESC;
164
+
165
+ -- Boolean mode (more control)
166
+ SELECT * FROM posts
167
+ WHERE MATCH(title, content) AGAINST('+required -excluded "exact phrase"' IN BOOLEAN MODE);
168
+
169
+ -- Query expansion (find related)
170
+ SELECT * FROM posts
171
+ WHERE MATCH(title, content) AGAINST('database' WITH QUERY EXPANSION);
172
+ \`\`\`
173
+
174
+ ## Query Optimization
175
+ \`\`\`sql
176
+ -- Analyze query plan
177
+ EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';
178
+
179
+ -- Extended explain with more details
180
+ EXPLAIN ANALYZE SELECT * FROM posts WHERE author_id = ?;
181
+
182
+ -- Update table statistics
183
+ ANALYZE TABLE users;
184
+
185
+ -- Show index usage
186
+ SHOW INDEX FROM users;
187
+
188
+ -- Check slow queries (enable slow_query_log)
189
+ SELECT * FROM mysql.slow_log ORDER BY start_time DESC LIMIT 10;
190
+
191
+ -- Profile query execution
192
+ SET profiling = 1;
193
+ SELECT * FROM users WHERE role = 'admin';
194
+ SHOW PROFILES;
195
+ SHOW PROFILE FOR QUERY 1;
196
+ \`\`\`
197
+
198
+ ## Transactions & Locking
199
+ \`\`\`sql
200
+ -- Transaction with isolation level
201
+ SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
202
+ START TRANSACTION;
203
+ -- ... operations ...
204
+ COMMIT;
205
+ -- Or ROLLBACK;
206
+
207
+ -- Row-level lock (InnoDB)
208
+ SELECT * FROM accounts WHERE id = ? FOR UPDATE;
209
+ -- Other transactions wait
210
+
211
+ -- Shared lock (read lock)
212
+ SELECT * FROM accounts WHERE id = ? FOR SHARE;
213
+
214
+ -- Named lock (application-level)
215
+ SELECT GET_LOCK('resource_name', 10); -- 10 second timeout
216
+ -- ... do work ...
217
+ SELECT RELEASE_LOCK('resource_name');
218
+ \`\`\`
219
+
220
+ ## Prepared Statements (Node.js example)
221
+ \`\`\`typescript
222
+ import mysql from 'mysql2/promise';
223
+
224
+ const pool = mysql.createPool({
225
+ host: process.env.DB_HOST,
226
+ user: process.env.DB_USER,
227
+ password: process.env.DB_PASSWORD,
228
+ database: process.env.DB_NAME,
229
+ waitForConnections: true,
230
+ connectionLimit: 10,
231
+ queueLimit: 0,
232
+ });
233
+
234
+ // Parameterized query (prevents SQL injection)
235
+ const [rows] = await pool.execute(
236
+ 'SELECT * FROM users WHERE email = ? AND role = ?',
237
+ [email, 'user']
238
+ );
239
+
240
+ // Named placeholders
241
+ const [rows] = await pool.execute(
242
+ 'SELECT * FROM users WHERE email = :email',
243
+ { email: 'user@example.com' }
244
+ );
245
+ \`\`\`
246
+
247
+ ## Performance Tips
248
+ \`\`\`sql
249
+ -- Check InnoDB status
250
+ SHOW ENGINE INNODB STATUS;
251
+
252
+ -- Buffer pool hit ratio (should be > 99%)
253
+ SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%';
254
+
255
+ -- Table statistics
256
+ SELECT
257
+ table_name,
258
+ table_rows,
259
+ data_length / 1024 / 1024 as data_mb,
260
+ index_length / 1024 / 1024 as index_mb
261
+ FROM information_schema.tables
262
+ WHERE table_schema = DATABASE();
263
+ \`\`\`
264
+
265
+ ## ❌ DON'T
266
+ - Use MyISAM for transactional tables
267
+ - Store UUIDs as VARCHAR (use BINARY(16))
268
+ - Use SELECT * in production
269
+ - Create indexes on every column
270
+ - Use OFFSET for deep pagination
271
+ - Skip parameterized queries (SQL injection risk)
272
+
273
+ ## ✅ DO
274
+ - Use InnoDB for all tables
275
+ - Use utf8mb4 charset for proper Unicode support
276
+ - Create compound indexes matching query patterns
277
+ - Use prepared statements for all queries
278
+ - Monitor slow query log regularly
279
+ - Use connection pooling
280
+ - Prefer cursor-based pagination
281
+ - Use JSON columns for flexible schemas (MySQL 8.0+)
@@ -0,0 +1,335 @@
1
+ # NestJS Skill
2
+
3
+ ## Project Structure
4
+ \`\`\`
5
+ src/
6
+ ├── main.ts # Bootstrap
7
+ ├── app.module.ts # Root module
8
+ ├── common/
9
+ │ ├── decorators/ # Custom decorators
10
+ │ ├── guards/ # Auth guards
11
+ │ ├── interceptors/ # Response transforms
12
+ │ ├── filters/ # Exception filters
13
+ │ └── pipes/ # Validation pipes
14
+ └── modules/
15
+ └── users/
16
+ ├── users.module.ts
17
+ ├── users.controller.ts
18
+ ├── users.service.ts
19
+ ├── dto/
20
+ │ ├── create-user.dto.ts
21
+ │ └── update-user.dto.ts
22
+ └── entities/
23
+ └── user.entity.ts
24
+ \`\`\`
25
+
26
+ ## Module & Controller
27
+ \`\`\`typescript
28
+ // users.module.ts
29
+ @Module({
30
+ imports: [TypeOrmModule.forFeature([User])],
31
+ controllers: [UsersController],
32
+ providers: [UsersService],
33
+ exports: [UsersService],
34
+ })
35
+ export class UsersModule {}
36
+
37
+ // users.controller.ts
38
+ @Controller('users')
39
+ @UseGuards(JwtAuthGuard)
40
+ export class UsersController {
41
+ constructor(private readonly usersService: UsersService) {}
42
+
43
+ @Get()
44
+ findAll(@Query() query: PaginationDto) {
45
+ return this.usersService.findAll(query);
46
+ }
47
+
48
+ @Get(':id')
49
+ findOne(@Param('id', ParseUUIDPipe) id: string) {
50
+ return this.usersService.findOne(id);
51
+ }
52
+
53
+ @Post()
54
+ @HttpCode(HttpStatus.CREATED)
55
+ create(@Body() createUserDto: CreateUserDto) {
56
+ return this.usersService.create(createUserDto);
57
+ }
58
+
59
+ @Patch(':id')
60
+ update(
61
+ @Param('id', ParseUUIDPipe) id: string,
62
+ @Body() updateUserDto: UpdateUserDto,
63
+ ) {
64
+ return this.usersService.update(id, updateUserDto);
65
+ }
66
+
67
+ @Delete(':id')
68
+ @HttpCode(HttpStatus.NO_CONTENT)
69
+ remove(@Param('id', ParseUUIDPipe) id: string) {
70
+ return this.usersService.remove(id);
71
+ }
72
+ }
73
+ \`\`\`
74
+
75
+ ## DTOs with Validation
76
+ \`\`\`typescript
77
+ // dto/create-user.dto.ts
78
+ import { IsEmail, IsString, MinLength, IsOptional } from 'class-validator';
79
+
80
+ export class CreateUserDto {
81
+ @IsEmail()
82
+ email: string;
83
+
84
+ @IsString()
85
+ @MinLength(1)
86
+ name: string;
87
+
88
+ @IsString()
89
+ @MinLength(8)
90
+ password: string;
91
+ }
92
+
93
+ // dto/update-user.dto.ts
94
+ import { PartialType } from '@nestjs/mapped-types';
95
+
96
+ export class UpdateUserDto extends PartialType(CreateUserDto) {}
97
+
98
+ // Enable global validation in main.ts
99
+ app.useGlobalPipes(new ValidationPipe({
100
+ whitelist: true, // Strip unknown properties
101
+ forbidNonWhitelisted: true, // Throw on unknown properties
102
+ transform: true, // Auto-transform types
103
+ }));
104
+ \`\`\`
105
+
106
+ ## Guards
107
+ \`\`\`typescript
108
+ // guards/jwt-auth.guard.ts
109
+ @Injectable()
110
+ export class JwtAuthGuard implements CanActivate {
111
+ constructor(private jwtService: JwtService) {}
112
+
113
+ async canActivate(context: ExecutionContext): Promise<boolean> {
114
+ const request = context.switchToHttp().getRequest();
115
+ const token = this.extractToken(request);
116
+
117
+ if (!token) {
118
+ throw new UnauthorizedException();
119
+ }
120
+
121
+ try {
122
+ const payload = await this.jwtService.verifyAsync(token);
123
+ request.user = payload;
124
+ } catch {
125
+ throw new UnauthorizedException();
126
+ }
127
+
128
+ return true;
129
+ }
130
+
131
+ private extractToken(request: Request): string | undefined {
132
+ const [type, token] = request.headers.authorization?.split(' ') ?? [];
133
+ return type === 'Bearer' ? token : undefined;
134
+ }
135
+ }
136
+
137
+ // guards/roles.guard.ts
138
+ @Injectable()
139
+ export class RolesGuard implements CanActivate {
140
+ constructor(private reflector: Reflector) {}
141
+
142
+ canActivate(context: ExecutionContext): boolean {
143
+ const requiredRoles = this.reflector.getAllAndOverride<Role[]>(ROLES_KEY, [
144
+ context.getHandler(),
145
+ context.getClass(),
146
+ ]);
147
+
148
+ if (!requiredRoles) return true;
149
+
150
+ const { user } = context.switchToHttp().getRequest();
151
+ return requiredRoles.some((role) => user.roles?.includes(role));
152
+ }
153
+ }
154
+
155
+ // Usage
156
+ @Roles(Role.Admin)
157
+ @UseGuards(JwtAuthGuard, RolesGuard)
158
+ @Delete(':id')
159
+ remove(@Param('id') id: string) {}
160
+ \`\`\`
161
+
162
+ ## Custom Decorators
163
+ \`\`\`typescript
164
+ // decorators/current-user.decorator.ts
165
+ export const CurrentUser = createParamDecorator(
166
+ (data: keyof User | undefined, ctx: ExecutionContext) => {
167
+ const request = ctx.switchToHttp().getRequest();
168
+ const user = request.user;
169
+ return data ? user?.[data] : user;
170
+ },
171
+ );
172
+
173
+ // decorators/roles.decorator.ts
174
+ export const ROLES_KEY = 'roles';
175
+ export const Roles = (...roles: Role[]) => SetMetadata(ROLES_KEY, roles);
176
+
177
+ // Usage
178
+ @Get('me')
179
+ getProfile(@CurrentUser() user: User) {
180
+ return user;
181
+ }
182
+
183
+ @Get('email')
184
+ getEmail(@CurrentUser('email') email: string) {
185
+ return { email };
186
+ }
187
+ \`\`\`
188
+
189
+ ## Exception Filters
190
+ \`\`\`typescript
191
+ // filters/http-exception.filter.ts
192
+ @Catch(HttpException)
193
+ export class HttpExceptionFilter implements ExceptionFilter {
194
+ catch(exception: HttpException, host: ArgumentsHost) {
195
+ const ctx = host.switchToHttp();
196
+ const response = ctx.getResponse<Response>();
197
+ const request = ctx.getRequest<Request>();
198
+ const status = exception.getStatus();
199
+ const exceptionResponse = exception.getResponse();
200
+
201
+ response.status(status).json({
202
+ statusCode: status,
203
+ timestamp: new Date().toISOString(),
204
+ path: request.url,
205
+ message: typeof exceptionResponse === 'string'
206
+ ? exceptionResponse
207
+ : (exceptionResponse as any).message,
208
+ });
209
+ }
210
+ }
211
+
212
+ // Apply globally in main.ts
213
+ app.useGlobalFilters(new HttpExceptionFilter());
214
+ \`\`\`
215
+
216
+ ## Interceptors
217
+ \`\`\`typescript
218
+ // interceptors/transform.interceptor.ts
219
+ @Injectable()
220
+ export class TransformInterceptor<T> implements NestInterceptor<T, Response<T>> {
221
+ intercept(context: ExecutionContext, next: CallHandler): Observable<Response<T>> {
222
+ return next.handle().pipe(
223
+ map((data) => ({
224
+ success: true,
225
+ data,
226
+ timestamp: new Date().toISOString(),
227
+ })),
228
+ );
229
+ }
230
+ }
231
+
232
+ // interceptors/logging.interceptor.ts
233
+ @Injectable()
234
+ export class LoggingInterceptor implements NestInterceptor {
235
+ private readonly logger = new Logger(LoggingInterceptor.name);
236
+
237
+ intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
238
+ const request = context.switchToHttp().getRequest();
239
+ const { method, url } = request;
240
+ const now = Date.now();
241
+
242
+ return next.handle().pipe(
243
+ tap(() => {
244
+ this.logger.log(\`\${method} \${url} - \${Date.now() - now}ms\`);
245
+ }),
246
+ );
247
+ }
248
+ }
249
+ \`\`\`
250
+
251
+ ## Config Module
252
+ \`\`\`typescript
253
+ // config/configuration.ts
254
+ export default () => ({
255
+ port: parseInt(process.env.PORT, 10) || 3000,
256
+ database: {
257
+ host: process.env.DB_HOST,
258
+ port: parseInt(process.env.DB_PORT, 10) || 5432,
259
+ },
260
+ jwt: {
261
+ secret: process.env.JWT_SECRET,
262
+ expiresIn: '1h',
263
+ },
264
+ });
265
+
266
+ // app.module.ts
267
+ @Module({
268
+ imports: [
269
+ ConfigModule.forRoot({
270
+ isGlobal: true,
271
+ load: [configuration],
272
+ }),
273
+ ],
274
+ })
275
+ export class AppModule {}
276
+
277
+ // Usage
278
+ @Injectable()
279
+ export class AuthService {
280
+ constructor(private configService: ConfigService) {}
281
+
282
+ getJwtSecret() {
283
+ return this.configService.get<string>('jwt.secret');
284
+ }
285
+ }
286
+ \`\`\`
287
+
288
+ ## Testing
289
+ \`\`\`typescript
290
+ describe('UsersController', () => {
291
+ let controller: UsersController;
292
+ let service: UsersService;
293
+
294
+ beforeEach(async () => {
295
+ const module: TestingModule = await Test.createTestingModule({
296
+ controllers: [UsersController],
297
+ providers: [
298
+ {
299
+ provide: UsersService,
300
+ useValue: {
301
+ findAll: jest.fn(),
302
+ findOne: jest.fn(),
303
+ create: jest.fn(),
304
+ },
305
+ },
306
+ ],
307
+ }).compile();
308
+
309
+ controller = module.get<UsersController>(UsersController);
310
+ service = module.get<UsersService>(UsersService);
311
+ });
312
+
313
+ it('should return all users', async () => {
314
+ const result = [{ id: '1', name: 'Test' }];
315
+ jest.spyOn(service, 'findAll').mockResolvedValue(result);
316
+
317
+ expect(await controller.findAll({})).toBe(result);
318
+ });
319
+ });
320
+ \`\`\`
321
+
322
+ ## ❌ DON'T
323
+ - Put business logic in controllers
324
+ - Skip validation on DTOs
325
+ - Use any for types
326
+ - Forget to handle exceptions
327
+
328
+ ## ✅ DO
329
+ - Use DTOs for validation
330
+ - Use dependency injection
331
+ - Organize by feature modules
332
+ - Use guards for authentication
333
+ - Use interceptors for response transforms
334
+ - Use exception filters for error handling
335
+ - Write unit tests for services