@biggora/claude-plugins 1.2.2 → 1.3.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.
- package/README.md +5 -1
- package/package.json +1 -1
- package/registry/registry.json +15 -0
- package/specs/coding.md +11 -0
- package/src/commands/skills/add.js +115 -31
- package/src/commands/skills/list.js +25 -52
- package/src/commands/skills/remove.js +45 -27
- package/src/commands/skills/resolve.js +104 -0
- package/src/commands/skills/update.js +58 -74
- package/src/config.js +5 -0
- package/src/skills/nest-best-practices/SKILL.md +251 -0
- package/src/skills/nest-best-practices/references/best-practices-request-lifecycle.md +158 -0
- package/src/skills/nest-best-practices/references/cli-monorepo.md +106 -0
- package/src/skills/nest-best-practices/references/cli-overview.md +157 -0
- package/src/skills/nest-best-practices/references/core-controllers.md +165 -0
- package/src/skills/nest-best-practices/references/core-dependency-injection.md +179 -0
- package/src/skills/nest-best-practices/references/core-middleware.md +139 -0
- package/src/skills/nest-best-practices/references/core-modules.md +138 -0
- package/src/skills/nest-best-practices/references/core-providers.md +188 -0
- package/src/skills/nest-best-practices/references/faq-raw-body-hybrid.md +122 -0
- package/src/skills/nest-best-practices/references/fundamentals-circular-dependency.md +89 -0
- package/src/skills/nest-best-practices/references/fundamentals-custom-decorators.md +107 -0
- package/src/skills/nest-best-practices/references/fundamentals-dynamic-modules.md +125 -0
- package/src/skills/nest-best-practices/references/fundamentals-exception-filters.md +202 -0
- package/src/skills/nest-best-practices/references/fundamentals-execution-context.md +107 -0
- package/src/skills/nest-best-practices/references/fundamentals-guards.md +136 -0
- package/src/skills/nest-best-practices/references/fundamentals-interceptors.md +187 -0
- package/src/skills/nest-best-practices/references/fundamentals-lazy-loading.md +89 -0
- package/src/skills/nest-best-practices/references/fundamentals-lifecycle-events.md +87 -0
- package/src/skills/nest-best-practices/references/fundamentals-module-reference.md +107 -0
- package/src/skills/nest-best-practices/references/fundamentals-pipes.md +197 -0
- package/src/skills/nest-best-practices/references/fundamentals-provider-scopes.md +92 -0
- package/src/skills/nest-best-practices/references/fundamentals-testing.md +142 -0
- package/src/skills/nest-best-practices/references/graphql-overview.md +233 -0
- package/src/skills/nest-best-practices/references/graphql-resolvers-mutations.md +199 -0
- package/src/skills/nest-best-practices/references/graphql-scalars-unions-enums.md +180 -0
- package/src/skills/nest-best-practices/references/graphql-subscriptions.md +228 -0
- package/src/skills/nest-best-practices/references/microservices-grpc.md +175 -0
- package/src/skills/nest-best-practices/references/microservices-overview.md +221 -0
- package/src/skills/nest-best-practices/references/microservices-transports.md +119 -0
- package/src/skills/nest-best-practices/references/openapi-swagger.md +207 -0
- package/src/skills/nest-best-practices/references/recipes-authentication.md +97 -0
- package/src/skills/nest-best-practices/references/recipes-cqrs.md +176 -0
- package/src/skills/nest-best-practices/references/recipes-crud-generator.md +87 -0
- package/src/skills/nest-best-practices/references/recipes-documentation.md +93 -0
- package/src/skills/nest-best-practices/references/recipes-mongoose.md +153 -0
- package/src/skills/nest-best-practices/references/recipes-prisma.md +98 -0
- package/src/skills/nest-best-practices/references/recipes-terminus.md +148 -0
- package/src/skills/nest-best-practices/references/recipes-typeorm.md +122 -0
- package/src/skills/nest-best-practices/references/security-authorization.md +196 -0
- package/src/skills/nest-best-practices/references/security-cors-helmet-rate-limiting.md +204 -0
- package/src/skills/nest-best-practices/references/security-encryption-hashing.md +93 -0
- package/src/skills/nest-best-practices/references/techniques-caching.md +142 -0
- package/src/skills/nest-best-practices/references/techniques-compression-streaming-sse.md +194 -0
- package/src/skills/nest-best-practices/references/techniques-configuration.md +132 -0
- package/src/skills/nest-best-practices/references/techniques-database.md +153 -0
- package/src/skills/nest-best-practices/references/techniques-events.md +163 -0
- package/src/skills/nest-best-practices/references/techniques-fastify.md +137 -0
- package/src/skills/nest-best-practices/references/techniques-file-upload.md +140 -0
- package/src/skills/nest-best-practices/references/techniques-http-module.md +176 -0
- package/src/skills/nest-best-practices/references/techniques-logging.md +146 -0
- package/src/skills/nest-best-practices/references/techniques-mvc-serve-static.md +132 -0
- package/src/skills/nest-best-practices/references/techniques-queues.md +162 -0
- package/src/skills/nest-best-practices/references/techniques-serialization.md +158 -0
- package/src/skills/nest-best-practices/references/techniques-sessions-cookies.md +167 -0
- package/src/skills/nest-best-practices/references/techniques-task-scheduling.md +166 -0
- package/src/skills/nest-best-practices/references/techniques-validation.md +126 -0
- package/src/skills/nest-best-practices/references/techniques-versioning.md +153 -0
- package/src/skills/nest-best-practices/references/websockets-advanced.md +96 -0
- package/src/skills/nest-best-practices/references/websockets-gateways.md +215 -0
- package/src/skills/typescript-expert/SKILL.md +145 -0
- package/src/skills/typescript-expert/commands/typescript-fix.md +65 -0
- package/src/skills/typescript-expert/references/advanced-conditional-types.md +190 -0
- package/src/skills/typescript-expert/references/advanced-decorators.md +243 -0
- package/src/skills/typescript-expert/references/advanced-mapped-types.md +223 -0
- package/src/skills/typescript-expert/references/advanced-template-literals.md +209 -0
- package/src/skills/typescript-expert/references/advanced-type-guards.md +308 -0
- package/src/skills/typescript-expert/references/best-practices-patterns.md +313 -0
- package/src/skills/typescript-expert/references/best-practices-performance.md +185 -0
- package/src/skills/typescript-expert/references/best-practices-tsconfig.md +242 -0
- package/src/skills/typescript-expert/references/core-generics.md +246 -0
- package/src/skills/typescript-expert/references/core-interfaces-types.md +231 -0
- package/src/skills/typescript-expert/references/core-type-system.md +261 -0
- package/src/skills/typescript-expert/references/core-utility-types.md +235 -0
- package/src/skills/typescript-expert/references/features-ts5x.md +370 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: logging
|
|
3
|
+
description: Built-in logger, custom loggers, and JSON logging
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Logging
|
|
7
|
+
|
|
8
|
+
NestJS provides a built-in `Logger` class with customizable behavior.
|
|
9
|
+
|
|
10
|
+
## Basic Usage
|
|
11
|
+
|
|
12
|
+
```typescript
|
|
13
|
+
import { Logger, Injectable } from '@nestjs/common';
|
|
14
|
+
|
|
15
|
+
@Injectable()
|
|
16
|
+
export class CatsService {
|
|
17
|
+
private readonly logger = new Logger(CatsService.name);
|
|
18
|
+
|
|
19
|
+
findAll() {
|
|
20
|
+
this.logger.log('Finding all cats');
|
|
21
|
+
this.logger.warn('Warning message');
|
|
22
|
+
this.logger.error('Error message', error.stack);
|
|
23
|
+
this.logger.debug('Debug info');
|
|
24
|
+
this.logger.verbose('Verbose output');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Configuration Options
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
const app = await NestFactory.create(AppModule, {
|
|
33
|
+
logger: new ConsoleLogger({
|
|
34
|
+
logLevels: ['error', 'warn', 'log'], // Filter log levels
|
|
35
|
+
timestamp: true, // Show timestamps
|
|
36
|
+
json: true, // JSON format output
|
|
37
|
+
colors: false, // Disable colors
|
|
38
|
+
prefix: 'MyApp', // Custom prefix
|
|
39
|
+
}),
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Disable logging:
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
const app = await NestFactory.create(AppModule, { logger: false });
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Specific log levels only:
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
const app = await NestFactory.create(AppModule, {
|
|
53
|
+
logger: ['error', 'warn'],
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## JSON Logging
|
|
58
|
+
|
|
59
|
+
Enable structured JSON logging for production:
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
const app = await NestFactory.create(AppModule, {
|
|
63
|
+
logger: new ConsoleLogger({ json: true }),
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Output:
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"level": "log",
|
|
72
|
+
"pid": 19096,
|
|
73
|
+
"timestamp": 1607370779834,
|
|
74
|
+
"message": "Starting Nest application...",
|
|
75
|
+
"context": "NestFactory"
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Custom Logger
|
|
80
|
+
|
|
81
|
+
Implement `LoggerService` interface:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { LoggerService, Injectable } from '@nestjs/common';
|
|
85
|
+
|
|
86
|
+
@Injectable()
|
|
87
|
+
export class MyLogger implements LoggerService {
|
|
88
|
+
log(message: any, ...optionalParams: any[]) {}
|
|
89
|
+
error(message: any, ...optionalParams: any[]) {}
|
|
90
|
+
warn(message: any, ...optionalParams: any[]) {}
|
|
91
|
+
debug?(message: any, ...optionalParams: any[]) {}
|
|
92
|
+
verbose?(message: any, ...optionalParams: any[]) {}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Extend Built-in Logger
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
import { ConsoleLogger } from '@nestjs/common';
|
|
100
|
+
|
|
101
|
+
export class MyLogger extends ConsoleLogger {
|
|
102
|
+
error(message: any, stack?: string, context?: string) {
|
|
103
|
+
// Custom logic (e.g., send to external service)
|
|
104
|
+
super.error(message, stack, context);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Dependency Injection
|
|
110
|
+
|
|
111
|
+
Use DI for custom logger with configuration:
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// Create LoggerModule
|
|
115
|
+
@Module({
|
|
116
|
+
providers: [MyLogger],
|
|
117
|
+
exports: [MyLogger],
|
|
118
|
+
})
|
|
119
|
+
export class LoggerModule {}
|
|
120
|
+
|
|
121
|
+
// Use in main.ts
|
|
122
|
+
const app = await NestFactory.create(AppModule, { bufferLogs: true });
|
|
123
|
+
app.useLogger(app.get(MyLogger));
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Transient Logger
|
|
127
|
+
|
|
128
|
+
For unique logger instances per service:
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
@Injectable({ scope: Scope.TRANSIENT })
|
|
132
|
+
export class MyLogger extends ConsoleLogger {}
|
|
133
|
+
|
|
134
|
+
// Usage
|
|
135
|
+
@Injectable()
|
|
136
|
+
export class CatsService {
|
|
137
|
+
constructor(private myLogger: MyLogger) {
|
|
138
|
+
this.myLogger.setContext('CatsService');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
<!--
|
|
144
|
+
Source references:
|
|
145
|
+
- https://docs.nestjs.com/techniques/logger
|
|
146
|
+
-->
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mvc-serve-static
|
|
3
|
+
description: MVC template rendering and serving static files/SPA
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# MVC and Serve Static
|
|
7
|
+
|
|
8
|
+
## MVC (Template Rendering)
|
|
9
|
+
|
|
10
|
+
### Express Setup
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install hbs
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { NestFactory } from '@nestjs/core';
|
|
18
|
+
import { NestExpressApplication } from '@nestjs/platform-express';
|
|
19
|
+
import { join } from 'node:path';
|
|
20
|
+
import { AppModule } from './app.module';
|
|
21
|
+
|
|
22
|
+
async function bootstrap() {
|
|
23
|
+
const app = await NestFactory.create<NestExpressApplication>(AppModule);
|
|
24
|
+
app.useStaticAssets(join(__dirname, '..', 'public'));
|
|
25
|
+
app.setBaseViewsDir(join(__dirname, '..', 'views'));
|
|
26
|
+
app.setViewEngine('hbs');
|
|
27
|
+
await app.listen(3000);
|
|
28
|
+
}
|
|
29
|
+
bootstrap();
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Controller with @Render
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { Get, Controller, Render } from '@nestjs/common';
|
|
36
|
+
|
|
37
|
+
@Controller()
|
|
38
|
+
export class AppController {
|
|
39
|
+
@Get()
|
|
40
|
+
@Render('index')
|
|
41
|
+
root() {
|
|
42
|
+
return { message: 'Hello world!' };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Dynamic Template Selection
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { Get, Controller, Res } from '@nestjs/common';
|
|
51
|
+
import { Response } from 'express';
|
|
52
|
+
|
|
53
|
+
@Controller()
|
|
54
|
+
export class AppController {
|
|
55
|
+
@Get()
|
|
56
|
+
root(@Res() res: Response) {
|
|
57
|
+
return res.render('dynamic-view', { message: 'Hello!' });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Fastify
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npm install @fastify/static @fastify/view handlebars
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
const app = await NestFactory.create<NestFastifyApplication>(
|
|
70
|
+
AppModule,
|
|
71
|
+
new FastifyAdapter(),
|
|
72
|
+
);
|
|
73
|
+
app.useStaticAssets({
|
|
74
|
+
root: join(__dirname, '..', 'public'),
|
|
75
|
+
prefix: '/public/',
|
|
76
|
+
});
|
|
77
|
+
app.setViewEngine({
|
|
78
|
+
engine: { handlebars: require('handlebars') },
|
|
79
|
+
templates: join(__dirname, '..', 'views'),
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
With Fastify, include file extension in `@Render()`: `@Render('index.hbs')`
|
|
84
|
+
|
|
85
|
+
## Serve Static (SPA)
|
|
86
|
+
|
|
87
|
+
Serve static content like Single Page Applications.
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npm install @nestjs/serve-static
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import { Module } from '@nestjs/common';
|
|
95
|
+
import { ServeStaticModule } from '@nestjs/serve-static';
|
|
96
|
+
import { join } from 'path';
|
|
97
|
+
|
|
98
|
+
@Module({
|
|
99
|
+
imports: [
|
|
100
|
+
ServeStaticModule.forRoot({
|
|
101
|
+
rootPath: join(__dirname, '..', 'client'),
|
|
102
|
+
}),
|
|
103
|
+
],
|
|
104
|
+
})
|
|
105
|
+
export class AppModule {}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### SPA Client-Side Routing
|
|
109
|
+
|
|
110
|
+
Default `renderPath` is `*` (all paths). The module sends `index.html` for non-matching routes, enabling client-side routing. Controller paths take precedence.
|
|
111
|
+
|
|
112
|
+
### Configuration Options
|
|
113
|
+
|
|
114
|
+
| Option | Description |
|
|
115
|
+
|--------|-------------|
|
|
116
|
+
| `rootPath` | Path to static files |
|
|
117
|
+
| `serveRoot` | URL path prefix |
|
|
118
|
+
| `renderPath` | Paths to serve index.html |
|
|
119
|
+
| `exclude` | Excluded paths |
|
|
120
|
+
|
|
121
|
+
## Key Points
|
|
122
|
+
|
|
123
|
+
- Use `NestExpressApplication` or `NestFastifyApplication` for MVC
|
|
124
|
+
- `@Render()` passes return object to template as variables
|
|
125
|
+
- ServeStatic fallback enables SPA routing
|
|
126
|
+
- Fastify: set `serveStaticOptions.fallthrough: true` for SPA fallback
|
|
127
|
+
|
|
128
|
+
<!--
|
|
129
|
+
Source references:
|
|
130
|
+
- https://docs.nestjs.com/techniques/mvc
|
|
131
|
+
- https://docs.nestjs.com/recipes/serve-static
|
|
132
|
+
-->
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: queues
|
|
3
|
+
description: Background job processing with BullMQ and Bull
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Queues
|
|
7
|
+
|
|
8
|
+
Queues help with task scheduling, load balancing, and background processing using Redis-backed job queues.
|
|
9
|
+
|
|
10
|
+
## Installation (BullMQ - Recommended)
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @nestjs/bullmq bullmq
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Setup
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { Module } from '@nestjs/common';
|
|
20
|
+
import { BullModule } from '@nestjs/bullmq';
|
|
21
|
+
|
|
22
|
+
@Module({
|
|
23
|
+
imports: [
|
|
24
|
+
BullModule.forRoot({
|
|
25
|
+
connection: {
|
|
26
|
+
host: 'localhost',
|
|
27
|
+
port: 6379,
|
|
28
|
+
},
|
|
29
|
+
}),
|
|
30
|
+
BullModule.registerQueue({ name: 'audio' }),
|
|
31
|
+
],
|
|
32
|
+
})
|
|
33
|
+
export class AppModule {}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Producer (Adding Jobs)
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { Injectable } from '@nestjs/common';
|
|
40
|
+
import { InjectQueue } from '@nestjs/bullmq';
|
|
41
|
+
import { Queue } from 'bullmq';
|
|
42
|
+
|
|
43
|
+
@Injectable()
|
|
44
|
+
export class AudioService {
|
|
45
|
+
constructor(@InjectQueue('audio') private audioQueue: Queue) {}
|
|
46
|
+
|
|
47
|
+
async addTranscodeJob(file: string) {
|
|
48
|
+
await this.audioQueue.add('transcode', { file });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// With options
|
|
52
|
+
async addDelayedJob(data: any) {
|
|
53
|
+
await this.audioQueue.add('process', data, {
|
|
54
|
+
delay: 5000, // 5 second delay
|
|
55
|
+
attempts: 3, // Retry 3 times
|
|
56
|
+
removeOnComplete: true,
|
|
57
|
+
priority: 1, // Higher priority
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Consumer (Processing Jobs)
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
import { Processor, WorkerHost, OnWorkerEvent } from '@nestjs/bullmq';
|
|
67
|
+
import { Job } from 'bullmq';
|
|
68
|
+
|
|
69
|
+
@Processor('audio')
|
|
70
|
+
export class AudioConsumer extends WorkerHost {
|
|
71
|
+
async process(job: Job<any, any, string>): Promise<any> {
|
|
72
|
+
switch (job.name) {
|
|
73
|
+
case 'transcode':
|
|
74
|
+
return this.transcode(job.data);
|
|
75
|
+
case 'compress':
|
|
76
|
+
return this.compress(job.data);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private async transcode(data: any) {
|
|
81
|
+
// Processing logic
|
|
82
|
+
await job.updateProgress(50);
|
|
83
|
+
return { processed: true };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@OnWorkerEvent('completed')
|
|
87
|
+
onCompleted(job: Job) {
|
|
88
|
+
console.log(`Job ${job.id} completed`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@OnWorkerEvent('failed')
|
|
92
|
+
onFailed(job: Job, error: Error) {
|
|
93
|
+
console.error(`Job ${job.id} failed:`, error.message);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Register consumer as provider:
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
@Module({
|
|
102
|
+
providers: [AudioConsumer],
|
|
103
|
+
})
|
|
104
|
+
export class AudioModule {}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Queue Events Listener
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import { QueueEventsHost, QueueEventsListener, OnQueueEvent } from '@nestjs/bullmq';
|
|
111
|
+
|
|
112
|
+
@QueueEventsListener('audio')
|
|
113
|
+
export class AudioEventsListener extends QueueEventsHost {
|
|
114
|
+
@OnQueueEvent('active')
|
|
115
|
+
onActive(job: { jobId: string }) {
|
|
116
|
+
console.log(`Processing job ${job.jobId}...`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Job Options
|
|
122
|
+
|
|
123
|
+
| Option | Description |
|
|
124
|
+
|--------|-------------|
|
|
125
|
+
| `delay` | Milliseconds to wait before processing |
|
|
126
|
+
| `attempts` | Number of retry attempts |
|
|
127
|
+
| `backoff` | Retry delay strategy |
|
|
128
|
+
| `priority` | Job priority (1 = highest) |
|
|
129
|
+
| `lifo` | Process as LIFO instead of FIFO |
|
|
130
|
+
| `removeOnComplete` | Remove job data after completion |
|
|
131
|
+
| `removeOnFail` | Remove job data after failure |
|
|
132
|
+
| `repeat` | Cron-like repeat configuration |
|
|
133
|
+
|
|
134
|
+
## Queue Management
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
await this.audioQueue.pause();
|
|
138
|
+
await this.audioQueue.resume();
|
|
139
|
+
await this.audioQueue.clean(1000); // Remove completed jobs older than 1s
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Request-Scoped Consumers
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
@Processor({ name: 'audio', scope: Scope.REQUEST })
|
|
146
|
+
export class AudioConsumer extends WorkerHost {
|
|
147
|
+
constructor(@Inject(JOB_REF) private jobRef: Job) {}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Key Points
|
|
152
|
+
|
|
153
|
+
- Consumers must be registered as providers
|
|
154
|
+
- BullMQ is recommended over Bull (actively developed)
|
|
155
|
+
- Use `switch` statement in `process()` for different job names
|
|
156
|
+
- Requires Redis for job persistence
|
|
157
|
+
- Jobs persist across restarts
|
|
158
|
+
|
|
159
|
+
<!--
|
|
160
|
+
Source references:
|
|
161
|
+
- https://docs.nestjs.com/techniques/queues
|
|
162
|
+
-->
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: serialization
|
|
3
|
+
description: Response serialization with class-transformer
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Serialization
|
|
7
|
+
|
|
8
|
+
Serialization transforms objects before sending responses, using `class-transformer` decorators.
|
|
9
|
+
|
|
10
|
+
## Basic Usage
|
|
11
|
+
|
|
12
|
+
Use `ClassSerializerInterceptor` to automatically transform responses:
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
import { Controller, Get, UseInterceptors } from '@nestjs/common';
|
|
16
|
+
import { ClassSerializerInterceptor } from '@nestjs/common';
|
|
17
|
+
|
|
18
|
+
@Controller('users')
|
|
19
|
+
@UseInterceptors(ClassSerializerInterceptor)
|
|
20
|
+
export class UsersController {
|
|
21
|
+
@Get(':id')
|
|
22
|
+
findOne() {
|
|
23
|
+
return new UserEntity({
|
|
24
|
+
id: 1,
|
|
25
|
+
firstName: 'John',
|
|
26
|
+
lastName: 'Doe',
|
|
27
|
+
password: 'secret123',
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Exclude Properties
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { Exclude } from 'class-transformer';
|
|
37
|
+
|
|
38
|
+
export class UserEntity {
|
|
39
|
+
id: number;
|
|
40
|
+
firstName: string;
|
|
41
|
+
lastName: string;
|
|
42
|
+
|
|
43
|
+
@Exclude()
|
|
44
|
+
password: string;
|
|
45
|
+
|
|
46
|
+
constructor(partial: Partial<UserEntity>) {
|
|
47
|
+
Object.assign(this, partial);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Response excludes `password`:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{ "id": 1, "firstName": "John", "lastName": "Doe" }
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Expose Computed Properties
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import { Expose } from 'class-transformer';
|
|
62
|
+
|
|
63
|
+
export class UserEntity {
|
|
64
|
+
firstName: string;
|
|
65
|
+
lastName: string;
|
|
66
|
+
|
|
67
|
+
@Expose()
|
|
68
|
+
get fullName(): string {
|
|
69
|
+
return `${this.firstName} ${this.lastName}`;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Transform Properties
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { Transform } from 'class-transformer';
|
|
78
|
+
|
|
79
|
+
export class UserEntity {
|
|
80
|
+
@Transform(({ value }) => value.name)
|
|
81
|
+
role: RoleEntity; // Outputs role.name instead of full object
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Serialization Options
|
|
86
|
+
|
|
87
|
+
Per-route options:
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { SerializeOptions } from '@nestjs/common';
|
|
91
|
+
|
|
92
|
+
@Get()
|
|
93
|
+
@SerializeOptions({ excludePrefixes: ['_'] })
|
|
94
|
+
findAll() {
|
|
95
|
+
return this.usersService.findAll();
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Transform Plain Objects
|
|
100
|
+
|
|
101
|
+
Force transformation of plain objects:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
@Get()
|
|
105
|
+
@UseInterceptors(ClassSerializerInterceptor)
|
|
106
|
+
@SerializeOptions({ type: UserEntity })
|
|
107
|
+
findOne() {
|
|
108
|
+
return {
|
|
109
|
+
id: 1,
|
|
110
|
+
firstName: 'John',
|
|
111
|
+
password: 'secret', // Will be excluded
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Global Interceptor
|
|
117
|
+
|
|
118
|
+
Apply globally:
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
@Module({
|
|
122
|
+
providers: [
|
|
123
|
+
{ provide: APP_INTERCEPTOR, useClass: ClassSerializerInterceptor },
|
|
124
|
+
],
|
|
125
|
+
})
|
|
126
|
+
export class AppModule {}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Groups
|
|
130
|
+
|
|
131
|
+
Expose different fields based on groups:
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
export class UserEntity {
|
|
135
|
+
@Expose({ groups: ['admin'] })
|
|
136
|
+
email: string;
|
|
137
|
+
|
|
138
|
+
@Expose({ groups: ['admin', 'user'] })
|
|
139
|
+
firstName: string;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Controller
|
|
143
|
+
@SerializeOptions({ groups: ['admin'] })
|
|
144
|
+
@Get('admin')
|
|
145
|
+
findForAdmin() {}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Key Points
|
|
149
|
+
|
|
150
|
+
- Must return class instances, not plain objects
|
|
151
|
+
- Works with WebSockets and Microservices
|
|
152
|
+
- `@Exclude()` and `@Expose()` from `class-transformer`
|
|
153
|
+
- Use `excludeExtraneousValues: true` to only include `@Expose()` fields
|
|
154
|
+
|
|
155
|
+
<!--
|
|
156
|
+
Source references:
|
|
157
|
+
- https://docs.nestjs.com/techniques/serialization
|
|
158
|
+
-->
|