@biggora/claude-plugins 1.2.2 → 1.3.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.
- package/README.md +2 -0
- package/package.json +1 -1
- package/registry/registry.json +15 -0
- package/specs/coding.md +6 -0
- package/src/commands/skills/add.js +63 -7
- package/src/commands/skills/list.js +23 -52
- package/src/commands/skills/remove.js +26 -27
- package/src/commands/skills/resolve.js +155 -0
- package/src/commands/skills/update.js +58 -74
- 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,137 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: fastify
|
|
3
|
+
description: Using Fastify as the HTTP adapter for better performance
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Fastify (Performance)
|
|
7
|
+
|
|
8
|
+
Fastify is a high-performance alternative to Express, achieving nearly 2x better benchmark results.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @nestjs/platform-fastify
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Setup
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { NestFactory } from '@nestjs/core';
|
|
20
|
+
import {
|
|
21
|
+
FastifyAdapter,
|
|
22
|
+
NestFastifyApplication,
|
|
23
|
+
} from '@nestjs/platform-fastify';
|
|
24
|
+
import { AppModule } from './app.module';
|
|
25
|
+
|
|
26
|
+
async function bootstrap() {
|
|
27
|
+
const app = await NestFactory.create<NestFastifyApplication>(
|
|
28
|
+
AppModule,
|
|
29
|
+
new FastifyAdapter(),
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
// Fastify listens only on localhost by default
|
|
33
|
+
await app.listen(3000, '0.0.0.0');
|
|
34
|
+
}
|
|
35
|
+
bootstrap();
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Fastify Options
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
new FastifyAdapter({
|
|
42
|
+
logger: true,
|
|
43
|
+
trustProxy: true,
|
|
44
|
+
});
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Middleware Differences
|
|
48
|
+
|
|
49
|
+
Fastify middleware receives raw `req` and `res` objects:
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { Injectable, NestMiddleware } from '@nestjs/common';
|
|
53
|
+
import { FastifyRequest, FastifyReply } from 'fastify';
|
|
54
|
+
|
|
55
|
+
@Injectable()
|
|
56
|
+
export class LoggerMiddleware implements NestMiddleware {
|
|
57
|
+
use(req: FastifyRequest['raw'], res: FastifyReply['raw'], next: () => void) {
|
|
58
|
+
console.log('Request...');
|
|
59
|
+
next();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Redirect Response
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
@Get()
|
|
68
|
+
redirect(@Res() res: FastifyReply) {
|
|
69
|
+
res.status(302).redirect('/login');
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Route Config
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { RouteConfig } from '@nestjs/platform-fastify';
|
|
77
|
+
|
|
78
|
+
@RouteConfig({ output: 'hello world' })
|
|
79
|
+
@Get()
|
|
80
|
+
index(@Req() req: FastifyRequest) {
|
|
81
|
+
return req.routeConfig.output;
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Route Constraints
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { RouteConstraints } from '@nestjs/platform-fastify';
|
|
89
|
+
|
|
90
|
+
@RouteConstraints({ version: '1.2.x' })
|
|
91
|
+
@Get()
|
|
92
|
+
newFeature() {
|
|
93
|
+
return 'Works only for version >= 1.2.x';
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Registering Plugins
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
import compression from '@fastify/compress';
|
|
101
|
+
import helmet from '@fastify/helmet';
|
|
102
|
+
import fastifyCookie from '@fastify/cookie';
|
|
103
|
+
|
|
104
|
+
const app = await NestFactory.create<NestFastifyApplication>(
|
|
105
|
+
AppModule,
|
|
106
|
+
new FastifyAdapter(),
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
await app.register(compression);
|
|
110
|
+
await app.register(helmet);
|
|
111
|
+
await app.register(fastifyCookie, { secret: 'my-secret' });
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Platform-Specific Packages
|
|
115
|
+
|
|
116
|
+
When using Fastify, replace Express packages with Fastify equivalents:
|
|
117
|
+
|
|
118
|
+
| Express | Fastify |
|
|
119
|
+
|---------|---------|
|
|
120
|
+
| `express-session` | `@fastify/secure-session` |
|
|
121
|
+
| `cookie-parser` | `@fastify/cookie` |
|
|
122
|
+
| `compression` | `@fastify/compress` |
|
|
123
|
+
| `helmet` | `@fastify/helmet` |
|
|
124
|
+
| `multer` | Not compatible |
|
|
125
|
+
|
|
126
|
+
## Key Points
|
|
127
|
+
|
|
128
|
+
- Provides significant performance improvements
|
|
129
|
+
- Not all Express middleware is compatible
|
|
130
|
+
- Use `NestFastifyApplication` type for proper typings
|
|
131
|
+
- Default listener is `localhost` only (specify `0.0.0.0` for external access)
|
|
132
|
+
- File upload (multer) is not compatible with Fastify
|
|
133
|
+
|
|
134
|
+
<!--
|
|
135
|
+
Source references:
|
|
136
|
+
- https://docs.nestjs.com/techniques/performance
|
|
137
|
+
-->
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: file-upload
|
|
3
|
+
description: File upload handling with multer integration
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# File Upload
|
|
7
|
+
|
|
8
|
+
NestJS uses [multer](https://github.com/expressjs/multer) middleware for handling `multipart/form-data` file uploads.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm i -D @types/multer
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Single File Upload
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { Controller, Post, UseInterceptors, UploadedFile } from '@nestjs/common';
|
|
20
|
+
import { FileInterceptor } from '@nestjs/platform-express';
|
|
21
|
+
import { Express } from 'express';
|
|
22
|
+
|
|
23
|
+
@Controller('upload')
|
|
24
|
+
export class UploadController {
|
|
25
|
+
@Post()
|
|
26
|
+
@UseInterceptors(FileInterceptor('file'))
|
|
27
|
+
uploadFile(@UploadedFile() file: Express.Multer.File) {
|
|
28
|
+
console.log(file);
|
|
29
|
+
return { filename: file.originalname };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## File Validation
|
|
35
|
+
|
|
36
|
+
Use `ParseFilePipe` with built-in validators:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
@Post()
|
|
40
|
+
uploadFile(
|
|
41
|
+
@UploadedFile(
|
|
42
|
+
new ParseFilePipe({
|
|
43
|
+
validators: [
|
|
44
|
+
new MaxFileSizeValidator({ maxSize: 1000000 }), // 1MB
|
|
45
|
+
new FileTypeValidator({ fileType: 'image/jpeg' }),
|
|
46
|
+
],
|
|
47
|
+
}),
|
|
48
|
+
)
|
|
49
|
+
file: Express.Multer.File,
|
|
50
|
+
) {
|
|
51
|
+
return { filename: file.originalname };
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Using builder pattern:
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
@UploadedFile(
|
|
59
|
+
new ParseFilePipeBuilder()
|
|
60
|
+
.addFileTypeValidator({ fileType: 'jpeg' })
|
|
61
|
+
.addMaxSizeValidator({ maxSize: 1000000 })
|
|
62
|
+
.build({ errorHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY }),
|
|
63
|
+
)
|
|
64
|
+
file: Express.Multer.File,
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Multiple Files (Same Field)
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
@Post('uploads')
|
|
71
|
+
@UseInterceptors(FilesInterceptor('files', 10)) // max 10 files
|
|
72
|
+
uploadFiles(@UploadedFiles() files: Array<Express.Multer.File>) {
|
|
73
|
+
return files.map(f => f.originalname);
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Multiple Files (Different Fields)
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
@Post('uploads')
|
|
81
|
+
@UseInterceptors(FileFieldsInterceptor([
|
|
82
|
+
{ name: 'avatar', maxCount: 1 },
|
|
83
|
+
{ name: 'background', maxCount: 1 },
|
|
84
|
+
]))
|
|
85
|
+
uploadFiles(
|
|
86
|
+
@UploadedFiles() files: {
|
|
87
|
+
avatar?: Express.Multer.File[],
|
|
88
|
+
background?: Express.Multer.File[]
|
|
89
|
+
},
|
|
90
|
+
) {
|
|
91
|
+
return { avatar: files.avatar?.[0], background: files.background?.[0] };
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Any Files
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
@Post('any')
|
|
99
|
+
@UseInterceptors(AnyFilesInterceptor())
|
|
100
|
+
uploadAny(@UploadedFiles() files: Array<Express.Multer.File>) {
|
|
101
|
+
return files;
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Configure Destination
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
import { MulterModule } from '@nestjs/platform-express';
|
|
109
|
+
|
|
110
|
+
@Module({
|
|
111
|
+
imports: [
|
|
112
|
+
MulterModule.register({ dest: './uploads' }),
|
|
113
|
+
],
|
|
114
|
+
})
|
|
115
|
+
export class UploadModule {}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Async configuration:
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
MulterModule.registerAsync({
|
|
122
|
+
imports: [ConfigModule],
|
|
123
|
+
useFactory: async (configService: ConfigService) => ({
|
|
124
|
+
dest: configService.get('UPLOAD_DEST'),
|
|
125
|
+
}),
|
|
126
|
+
inject: [ConfigService],
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Key Points
|
|
131
|
+
|
|
132
|
+
- `FileInterceptor` field name must match form field name
|
|
133
|
+
- Not compatible with Fastify adapter
|
|
134
|
+
- Use `fileIsRequired: false` for optional files
|
|
135
|
+
- Multer only processes `multipart/form-data`
|
|
136
|
+
|
|
137
|
+
<!--
|
|
138
|
+
Source references:
|
|
139
|
+
- https://docs.nestjs.com/techniques/file-upload
|
|
140
|
+
-->
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: http-module
|
|
3
|
+
description: Making HTTP requests with @nestjs/axios
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# HTTP Module
|
|
7
|
+
|
|
8
|
+
NestJS wraps Axios for making HTTP requests to external services.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @nestjs/axios axios
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Setup
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { Module } from '@nestjs/common';
|
|
20
|
+
import { HttpModule } from '@nestjs/axios';
|
|
21
|
+
|
|
22
|
+
@Module({
|
|
23
|
+
imports: [HttpModule],
|
|
24
|
+
providers: [CatsService],
|
|
25
|
+
})
|
|
26
|
+
export class CatsModule {}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Basic Usage
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { Injectable } from '@nestjs/common';
|
|
33
|
+
import { HttpService } from '@nestjs/axios';
|
|
34
|
+
import { firstValueFrom } from 'rxjs';
|
|
35
|
+
import { AxiosResponse } from 'axios';
|
|
36
|
+
|
|
37
|
+
@Injectable()
|
|
38
|
+
export class CatsService {
|
|
39
|
+
constructor(private readonly httpService: HttpService) {}
|
|
40
|
+
|
|
41
|
+
// Using Observable
|
|
42
|
+
findAll(): Observable<AxiosResponse<Cat[]>> {
|
|
43
|
+
return this.httpService.get('https://api.example.com/cats');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Using Promise
|
|
47
|
+
async findAllAsync(): Promise<Cat[]> {
|
|
48
|
+
const { data } = await firstValueFrom(
|
|
49
|
+
this.httpService.get<Cat[]>('https://api.example.com/cats'),
|
|
50
|
+
);
|
|
51
|
+
return data;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## HTTP Methods
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
// GET
|
|
60
|
+
this.httpService.get('/users');
|
|
61
|
+
|
|
62
|
+
// POST
|
|
63
|
+
this.httpService.post('/users', { name: 'John' });
|
|
64
|
+
|
|
65
|
+
// PUT
|
|
66
|
+
this.httpService.put('/users/1', { name: 'Jane' });
|
|
67
|
+
|
|
68
|
+
// PATCH
|
|
69
|
+
this.httpService.patch('/users/1', { name: 'Jane' });
|
|
70
|
+
|
|
71
|
+
// DELETE
|
|
72
|
+
this.httpService.delete('/users/1');
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Configuration
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
HttpModule.register({
|
|
79
|
+
timeout: 5000,
|
|
80
|
+
maxRedirects: 5,
|
|
81
|
+
baseURL: 'https://api.example.com',
|
|
82
|
+
headers: {
|
|
83
|
+
'Authorization': 'Bearer token',
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Async Configuration
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
HttpModule.registerAsync({
|
|
92
|
+
imports: [ConfigModule],
|
|
93
|
+
useFactory: async (configService: ConfigService) => ({
|
|
94
|
+
timeout: configService.get('HTTP_TIMEOUT'),
|
|
95
|
+
maxRedirects: configService.get('HTTP_MAX_REDIRECTS'),
|
|
96
|
+
baseURL: configService.get('API_URL'),
|
|
97
|
+
}),
|
|
98
|
+
inject: [ConfigService],
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Error Handling
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
import { catchError, firstValueFrom } from 'rxjs';
|
|
106
|
+
import { AxiosError } from 'axios';
|
|
107
|
+
|
|
108
|
+
async findAll(): Promise<Cat[]> {
|
|
109
|
+
const { data } = await firstValueFrom(
|
|
110
|
+
this.httpService.get<Cat[]>('/cats').pipe(
|
|
111
|
+
catchError((error: AxiosError) => {
|
|
112
|
+
this.logger.error(error.response?.data);
|
|
113
|
+
throw new HttpException(
|
|
114
|
+
'External API error',
|
|
115
|
+
HttpStatus.BAD_GATEWAY,
|
|
116
|
+
);
|
|
117
|
+
}),
|
|
118
|
+
),
|
|
119
|
+
);
|
|
120
|
+
return data;
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Direct Axios Access
|
|
125
|
+
|
|
126
|
+
Access the underlying Axios instance:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
@Injectable()
|
|
130
|
+
export class CatsService {
|
|
131
|
+
constructor(private readonly httpService: HttpService) {}
|
|
132
|
+
|
|
133
|
+
async findAll(): Promise<Cat[]> {
|
|
134
|
+
const { data } = await this.httpService.axiosRef.get('/cats');
|
|
135
|
+
return data;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Interceptors
|
|
141
|
+
|
|
142
|
+
Add Axios interceptors:
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
@Injectable()
|
|
146
|
+
export class CatsService implements OnModuleInit {
|
|
147
|
+
constructor(private readonly httpService: HttpService) {}
|
|
148
|
+
|
|
149
|
+
onModuleInit() {
|
|
150
|
+
this.httpService.axiosRef.interceptors.request.use((config) => {
|
|
151
|
+
config.headers['X-Request-Id'] = uuid();
|
|
152
|
+
return config;
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
this.httpService.axiosRef.interceptors.response.use(
|
|
156
|
+
(response) => response,
|
|
157
|
+
(error) => {
|
|
158
|
+
// Log error
|
|
159
|
+
return Promise.reject(error);
|
|
160
|
+
},
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Key Points
|
|
167
|
+
|
|
168
|
+
- Returns RxJS Observables by default
|
|
169
|
+
- Use `firstValueFrom` or `lastValueFrom` for Promises
|
|
170
|
+
- `AxiosResponse` is from `axios` package
|
|
171
|
+
- Configuration passed directly to Axios constructor
|
|
172
|
+
|
|
173
|
+
<!--
|
|
174
|
+
Source references:
|
|
175
|
+
- https://docs.nestjs.com/techniques/http-module
|
|
176
|
+
-->
|
|
@@ -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
|
+
-->
|