@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,221 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: microservices
|
|
3
|
+
description: Building microservices with various transport layers
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Microservices
|
|
7
|
+
|
|
8
|
+
NestJS supports microservice architecture with multiple transport protocols.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @nestjs/microservices
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Available Transporters
|
|
17
|
+
|
|
18
|
+
| Transport | Package |
|
|
19
|
+
|-----------|---------|
|
|
20
|
+
| TCP | Built-in |
|
|
21
|
+
| Redis | `redis` |
|
|
22
|
+
| MQTT | `mqtt` |
|
|
23
|
+
| NATS | `nats` |
|
|
24
|
+
| RabbitMQ | `amqplib` |
|
|
25
|
+
| Kafka | `kafkajs` |
|
|
26
|
+
| gRPC | `@grpc/grpc-js` |
|
|
27
|
+
|
|
28
|
+
## Creating a Microservice
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
// main.ts
|
|
32
|
+
import { NestFactory } from '@nestjs/core';
|
|
33
|
+
import { Transport, MicroserviceOptions } from '@nestjs/microservices';
|
|
34
|
+
import { AppModule } from './app.module';
|
|
35
|
+
|
|
36
|
+
async function bootstrap() {
|
|
37
|
+
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
|
|
38
|
+
AppModule,
|
|
39
|
+
{
|
|
40
|
+
transport: Transport.TCP,
|
|
41
|
+
options: { host: 'localhost', port: 3001 },
|
|
42
|
+
},
|
|
43
|
+
);
|
|
44
|
+
await app.listen();
|
|
45
|
+
}
|
|
46
|
+
bootstrap();
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Hybrid Application
|
|
50
|
+
|
|
51
|
+
Combine HTTP and microservice:
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
const app = await NestFactory.create(AppModule);
|
|
55
|
+
app.connectMicroservice<MicroserviceOptions>({
|
|
56
|
+
transport: Transport.TCP,
|
|
57
|
+
options: { port: 3001 },
|
|
58
|
+
});
|
|
59
|
+
await app.startAllMicroservices();
|
|
60
|
+
await app.listen(3000);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Request-Response Pattern
|
|
64
|
+
|
|
65
|
+
### Handler (Microservice)
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import { Controller } from '@nestjs/common';
|
|
69
|
+
import { MessagePattern, Payload } from '@nestjs/microservices';
|
|
70
|
+
|
|
71
|
+
@Controller()
|
|
72
|
+
export class MathController {
|
|
73
|
+
@MessagePattern({ cmd: 'sum' })
|
|
74
|
+
sum(@Payload() data: number[]): number {
|
|
75
|
+
return data.reduce((a, b) => a + b, 0);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Client (Producer)
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import { Module } from '@nestjs/common';
|
|
84
|
+
import { ClientsModule, Transport } from '@nestjs/microservices';
|
|
85
|
+
|
|
86
|
+
@Module({
|
|
87
|
+
imports: [
|
|
88
|
+
ClientsModule.register([
|
|
89
|
+
{
|
|
90
|
+
name: 'MATH_SERVICE',
|
|
91
|
+
transport: Transport.TCP,
|
|
92
|
+
options: { host: 'localhost', port: 3001 },
|
|
93
|
+
},
|
|
94
|
+
]),
|
|
95
|
+
],
|
|
96
|
+
})
|
|
97
|
+
export class AppModule {}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import { Injectable, Inject } from '@nestjs/common';
|
|
102
|
+
import { ClientProxy } from '@nestjs/microservices';
|
|
103
|
+
import { firstValueFrom } from 'rxjs';
|
|
104
|
+
|
|
105
|
+
@Injectable()
|
|
106
|
+
export class AppService {
|
|
107
|
+
constructor(@Inject('MATH_SERVICE') private client: ClientProxy) {}
|
|
108
|
+
|
|
109
|
+
async calculate(): Promise<number> {
|
|
110
|
+
const pattern = { cmd: 'sum' };
|
|
111
|
+
const payload = [1, 2, 3, 4, 5];
|
|
112
|
+
return firstValueFrom(this.client.send<number>(pattern, payload));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Event-Based Pattern
|
|
118
|
+
|
|
119
|
+
### Handler
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
@EventPattern('user_created')
|
|
123
|
+
async handleUserCreated(@Payload() data: CreateUserEvent) {
|
|
124
|
+
await this.usersService.processNewUser(data);
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Emitter
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
async createUser(dto: CreateUserDto) {
|
|
132
|
+
const user = await this.usersRepository.create(dto);
|
|
133
|
+
this.client.emit('user_created', new CreateUserEvent(user));
|
|
134
|
+
return user;
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Accessing Context
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
import { Ctx, Payload, NatsContext } from '@nestjs/microservices';
|
|
142
|
+
|
|
143
|
+
@MessagePattern('time.us.*')
|
|
144
|
+
getDate(@Payload() data: any, @Ctx() context: NatsContext) {
|
|
145
|
+
console.log(`Subject: ${context.getSubject()}`);
|
|
146
|
+
return new Date().toISOString();
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Async Configuration
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
ClientsModule.registerAsync([
|
|
154
|
+
{
|
|
155
|
+
name: 'MATH_SERVICE',
|
|
156
|
+
imports: [ConfigModule],
|
|
157
|
+
useFactory: async (configService: ConfigService) => ({
|
|
158
|
+
transport: Transport.TCP,
|
|
159
|
+
options: {
|
|
160
|
+
host: configService.get('MATH_HOST'),
|
|
161
|
+
port: configService.get('MATH_PORT'),
|
|
162
|
+
},
|
|
163
|
+
}),
|
|
164
|
+
inject: [ConfigService],
|
|
165
|
+
},
|
|
166
|
+
]);
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Timeout Handling
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
import { timeout } from 'rxjs/operators';
|
|
173
|
+
|
|
174
|
+
this.client
|
|
175
|
+
.send<number>({ cmd: 'sum' }, [1, 2, 3])
|
|
176
|
+
.pipe(timeout(5000));
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## TLS Support
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
// Server
|
|
183
|
+
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
|
|
184
|
+
AppModule,
|
|
185
|
+
{
|
|
186
|
+
transport: Transport.TCP,
|
|
187
|
+
options: {
|
|
188
|
+
tlsOptions: {
|
|
189
|
+
key: fs.readFileSync('key.pem'),
|
|
190
|
+
cert: fs.readFileSync('cert.pem'),
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
// Client
|
|
197
|
+
ClientsModule.register([
|
|
198
|
+
{
|
|
199
|
+
name: 'SERVICE',
|
|
200
|
+
transport: Transport.TCP,
|
|
201
|
+
options: {
|
|
202
|
+
tlsOptions: {
|
|
203
|
+
ca: [fs.readFileSync('ca.pem')],
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
]);
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Key Points
|
|
211
|
+
|
|
212
|
+
- `@MessagePattern()` for request-response (requires reply)
|
|
213
|
+
- `@EventPattern()` for fire-and-forget events
|
|
214
|
+
- Client connection is lazy (connects on first call)
|
|
215
|
+
- Use `firstValueFrom` to convert Observable to Promise
|
|
216
|
+
- TCP is the default transport
|
|
217
|
+
|
|
218
|
+
<!--
|
|
219
|
+
Source references:
|
|
220
|
+
- https://docs.nestjs.com/microservices/basics
|
|
221
|
+
-->
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: microservices-transports
|
|
3
|
+
description: Redis, Kafka, NATS, RabbitMQ transport configuration
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Microservice Transports
|
|
7
|
+
|
|
8
|
+
## Redis
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm i ioredis
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
{
|
|
16
|
+
transport: Transport.REDIS,
|
|
17
|
+
options: {
|
|
18
|
+
host: 'localhost',
|
|
19
|
+
port: 6379,
|
|
20
|
+
password: 'secret',
|
|
21
|
+
retryAttempts: 3,
|
|
22
|
+
retryDelay: 1000,
|
|
23
|
+
wildcards: true, // psubscribe for pattern matching
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Client: `ClientsModule.register([{ name: 'MATH_SERVICE', transport: Transport.REDIS, options: {...} }])`
|
|
29
|
+
|
|
30
|
+
## Kafka
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm i kafkajs
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
{
|
|
38
|
+
transport: Transport.KAFKA,
|
|
39
|
+
options: {
|
|
40
|
+
client: {
|
|
41
|
+
clientId: 'my-app',
|
|
42
|
+
brokers: ['localhost:9092'],
|
|
43
|
+
},
|
|
44
|
+
consumer: {
|
|
45
|
+
groupId: 'my-consumer',
|
|
46
|
+
},
|
|
47
|
+
producer: {
|
|
48
|
+
allowAutoTopicCreation: true,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Use `@MessagePattern('topic')` for Kafka topics. Event-based (fire-and-forget) by default.
|
|
55
|
+
|
|
56
|
+
## NATS
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm i nats
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
{
|
|
64
|
+
transport: Transport.NATS,
|
|
65
|
+
options: {
|
|
66
|
+
servers: ['nats://localhost:4222'],
|
|
67
|
+
queue: 'my-queue', // queue group
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Supports wildcards: `@MessagePattern('time.us.*')` — `*` and `>` (multi-level).
|
|
73
|
+
|
|
74
|
+
## RabbitMQ
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npm i amqplib
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
{
|
|
82
|
+
transport: Transport.RMQ,
|
|
83
|
+
options: {
|
|
84
|
+
urls: ['amqp://localhost:5672'],
|
|
85
|
+
queue: 'my_queue',
|
|
86
|
+
queueOptions: {
|
|
87
|
+
durable: true,
|
|
88
|
+
},
|
|
89
|
+
noAck: false,
|
|
90
|
+
prefetchCount: 1,
|
|
91
|
+
},
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Transport Comparison
|
|
96
|
+
|
|
97
|
+
| Transport | Pattern | Use Case |
|
|
98
|
+
|-----------|---------|----------|
|
|
99
|
+
| TCP | Request-Response | Internal RPC |
|
|
100
|
+
| Redis | Pub/Sub, Request-Response | Caching, queues |
|
|
101
|
+
| Kafka | Event-based | Event streaming |
|
|
102
|
+
| NATS | Pub/Sub, Request-Response | Lightweight messaging |
|
|
103
|
+
| RabbitMQ | Pub/Sub, Request-Response | Enterprise messaging |
|
|
104
|
+
| gRPC | Request-Response, Streaming | Performance, typed APIs |
|
|
105
|
+
|
|
106
|
+
## Key Points
|
|
107
|
+
|
|
108
|
+
- Redis: fire-and-forget, no delivery guarantee
|
|
109
|
+
- Kafka: persistent events, consumer groups
|
|
110
|
+
- NATS: wildcards (`*`, `>`), queue groups
|
|
111
|
+
- RabbitMQ: durable queues, ack required for reliability
|
|
112
|
+
|
|
113
|
+
<!--
|
|
114
|
+
Source references:
|
|
115
|
+
- https://docs.nestjs.com/microservices/redis
|
|
116
|
+
- https://docs.nestjs.com/microservices/kafka
|
|
117
|
+
- https://docs.nestjs.com/microservices/nats
|
|
118
|
+
- https://docs.nestjs.com/microservices/rabbitmq
|
|
119
|
+
-->
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: openapi-swagger
|
|
3
|
+
description: OpenAPI/Swagger documentation generation
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# OpenAPI (Swagger)
|
|
7
|
+
|
|
8
|
+
Generate interactive API documentation using the OpenAPI specification.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @nestjs/swagger
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Basic Setup
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { NestFactory } from '@nestjs/core';
|
|
20
|
+
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
|
|
21
|
+
import { AppModule } from './app.module';
|
|
22
|
+
|
|
23
|
+
async function bootstrap() {
|
|
24
|
+
const app = await NestFactory.create(AppModule);
|
|
25
|
+
|
|
26
|
+
const config = new DocumentBuilder()
|
|
27
|
+
.setTitle('Cats API')
|
|
28
|
+
.setDescription('The cats API description')
|
|
29
|
+
.setVersion('1.0')
|
|
30
|
+
.addTag('cats')
|
|
31
|
+
.addBearerAuth()
|
|
32
|
+
.build();
|
|
33
|
+
|
|
34
|
+
const documentFactory = () => SwaggerModule.createDocument(app, config);
|
|
35
|
+
SwaggerModule.setup('api', app, documentFactory);
|
|
36
|
+
|
|
37
|
+
await app.listen(3000);
|
|
38
|
+
}
|
|
39
|
+
bootstrap();
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Access Swagger UI at `http://localhost:3000/api`
|
|
43
|
+
|
|
44
|
+
## DTO Documentation
|
|
45
|
+
|
|
46
|
+
Use `@ApiProperty()` to document DTO properties:
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
|
50
|
+
|
|
51
|
+
export class CreateCatDto {
|
|
52
|
+
@ApiProperty({ description: 'The name of the cat' })
|
|
53
|
+
name: string;
|
|
54
|
+
|
|
55
|
+
@ApiProperty({ minimum: 0, maximum: 30, default: 1 })
|
|
56
|
+
age: number;
|
|
57
|
+
|
|
58
|
+
@ApiPropertyOptional({ example: 'Persian' })
|
|
59
|
+
breed?: string;
|
|
60
|
+
|
|
61
|
+
@ApiProperty({ enum: ['male', 'female'] })
|
|
62
|
+
gender: string;
|
|
63
|
+
|
|
64
|
+
@ApiProperty({ type: [String] })
|
|
65
|
+
tags: string[];
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Common Decorators
|
|
70
|
+
|
|
71
|
+
| Decorator | Level | Purpose |
|
|
72
|
+
|-----------|-------|---------|
|
|
73
|
+
| `@ApiTags()` | Controller/Method | Group endpoints |
|
|
74
|
+
| `@ApiOperation()` | Method | Describe operation |
|
|
75
|
+
| `@ApiResponse()` | Method/Controller | Document responses |
|
|
76
|
+
| `@ApiParam()` | Method | Document URL params |
|
|
77
|
+
| `@ApiQuery()` | Method | Document query params |
|
|
78
|
+
| `@ApiBody()` | Method | Document request body |
|
|
79
|
+
| `@ApiBearerAuth()` | Method/Controller | Mark as authenticated |
|
|
80
|
+
| `@ApiProperty()` | Model | Document property |
|
|
81
|
+
| `@ApiHideProperty()` | Model | Hide property |
|
|
82
|
+
| `@ApiExcludeEndpoint()` | Method | Exclude from docs |
|
|
83
|
+
|
|
84
|
+
## Controller Documentation
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
import {
|
|
88
|
+
ApiTags,
|
|
89
|
+
ApiOperation,
|
|
90
|
+
ApiResponse,
|
|
91
|
+
ApiBearerAuth,
|
|
92
|
+
} from '@nestjs/swagger';
|
|
93
|
+
|
|
94
|
+
@ApiTags('cats')
|
|
95
|
+
@ApiBearerAuth()
|
|
96
|
+
@Controller('cats')
|
|
97
|
+
export class CatsController {
|
|
98
|
+
@Post()
|
|
99
|
+
@ApiOperation({ summary: 'Create a cat' })
|
|
100
|
+
@ApiResponse({ status: 201, description: 'Cat created successfully' })
|
|
101
|
+
@ApiResponse({ status: 400, description: 'Invalid input' })
|
|
102
|
+
create(@Body() dto: CreateCatDto) {
|
|
103
|
+
return this.catsService.create(dto);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@Get(':id')
|
|
107
|
+
@ApiOperation({ summary: 'Get a cat by ID' })
|
|
108
|
+
@ApiParam({ name: 'id', description: 'Cat ID' })
|
|
109
|
+
@ApiResponse({ status: 200, type: Cat })
|
|
110
|
+
@ApiResponse({ status: 404, description: 'Cat not found' })
|
|
111
|
+
findOne(@Param('id') id: string) {
|
|
112
|
+
return this.catsService.findOne(id);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Enums
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
export enum CatStatus {
|
|
121
|
+
Available = 'available',
|
|
122
|
+
Pending = 'pending',
|
|
123
|
+
Sold = 'sold',
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@ApiProperty({
|
|
127
|
+
enum: CatStatus,
|
|
128
|
+
enumName: 'CatStatus'
|
|
129
|
+
})
|
|
130
|
+
status: CatStatus;
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Authentication
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
const config = new DocumentBuilder()
|
|
137
|
+
.addBearerAuth()
|
|
138
|
+
.addApiKey({ type: 'apiKey', name: 'X-API-Key', in: 'header' }, 'api-key')
|
|
139
|
+
.addOAuth2()
|
|
140
|
+
.build();
|
|
141
|
+
|
|
142
|
+
// Apply to endpoints
|
|
143
|
+
@ApiBearerAuth()
|
|
144
|
+
@UseGuards(AuthGuard('jwt'))
|
|
145
|
+
@Get('profile')
|
|
146
|
+
getProfile() {}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## CLI Plugin
|
|
150
|
+
|
|
151
|
+
Auto-document DTOs by adding to `nest-cli.json`:
|
|
152
|
+
|
|
153
|
+
```json
|
|
154
|
+
{
|
|
155
|
+
"compilerOptions": {
|
|
156
|
+
"plugins": ["@nestjs/swagger"]
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
With options:
|
|
162
|
+
|
|
163
|
+
```json
|
|
164
|
+
{
|
|
165
|
+
"plugins": [
|
|
166
|
+
{
|
|
167
|
+
"name": "@nestjs/swagger",
|
|
168
|
+
"options": {
|
|
169
|
+
"classValidatorShim": true,
|
|
170
|
+
"introspectComments": true
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
]
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Document Options
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
const documentFactory = () => SwaggerModule.createDocument(app, config, {
|
|
181
|
+
include: [CatsModule], // Only include specific modules
|
|
182
|
+
extraModels: [ExtraModel], // Add extra models
|
|
183
|
+
ignoreGlobalPrefix: false, // Include global prefix
|
|
184
|
+
deepScanRoutes: true, // Scan imported modules
|
|
185
|
+
});
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Setup Options
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
SwaggerModule.setup('api', app, documentFactory, {
|
|
192
|
+
jsonDocumentUrl: '/api-json',
|
|
193
|
+
yamlDocumentUrl: '/api-yaml',
|
|
194
|
+
customSiteTitle: 'My API Docs',
|
|
195
|
+
customCss: '.swagger-ui .topbar { display: none }',
|
|
196
|
+
swaggerOptions: {
|
|
197
|
+
persistAuthorization: true,
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
<!--
|
|
203
|
+
Source references:
|
|
204
|
+
- https://docs.nestjs.com/openapi/introduction
|
|
205
|
+
- https://docs.nestjs.com/openapi/types-and-parameters
|
|
206
|
+
- https://docs.nestjs.com/openapi/decorators
|
|
207
|
+
-->
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: recipes-authentication
|
|
3
|
+
description: Authentication with Passport in NestJS
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Authentication
|
|
7
|
+
|
|
8
|
+
NestJS integrates with Passport for authentication strategies.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install --save @nestjs/passport passport passport-local
|
|
14
|
+
npm install --save-dev @types/passport-local
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Local Strategy
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
|
21
|
+
import { PassportStrategy } from '@nestjs/passport';
|
|
22
|
+
import { Strategy } from 'passport-local';
|
|
23
|
+
import { AuthService } from './auth.service';
|
|
24
|
+
|
|
25
|
+
@Injectable()
|
|
26
|
+
export class LocalStrategy extends PassportStrategy(Strategy) {
|
|
27
|
+
constructor(private authService: AuthService) {
|
|
28
|
+
super();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async validate(username: string, password: string): Promise<any> {
|
|
32
|
+
const user = await this.authService.validateUser(username, password);
|
|
33
|
+
if (!user) {
|
|
34
|
+
throw new UnauthorizedException();
|
|
35
|
+
}
|
|
36
|
+
return user;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## JWT Strategy
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm install --save @nestjs/jwt passport-jwt
|
|
45
|
+
npm install --save-dev @types/passport-jwt
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import { Injectable } from '@nestjs/common';
|
|
50
|
+
import { PassportStrategy } from '@nestjs/passport';
|
|
51
|
+
import { ExtractJwt, Strategy } from 'passport-jwt';
|
|
52
|
+
|
|
53
|
+
@Injectable()
|
|
54
|
+
export class JwtStrategy extends PassportStrategy(Strategy) {
|
|
55
|
+
constructor() {
|
|
56
|
+
super({
|
|
57
|
+
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
|
58
|
+
ignoreExpiration: false,
|
|
59
|
+
secretOrKey: 'secret',
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async validate(payload: any) {
|
|
64
|
+
return { userId: payload.sub, username: payload.username };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Using Guards
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
@UseGuards(AuthGuard('local'))
|
|
73
|
+
@Post('auth/login')
|
|
74
|
+
async login(@Request() req) {
|
|
75
|
+
return req.user;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@UseGuards(AuthGuard('jwt'))
|
|
79
|
+
@Get('profile')
|
|
80
|
+
getProfile(@Request() req) {
|
|
81
|
+
return req.user;
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Key Points
|
|
86
|
+
|
|
87
|
+
- Use `@nestjs/passport` for Passport integration
|
|
88
|
+
- Create strategies extending `PassportStrategy`
|
|
89
|
+
- Use `AuthGuard` with strategy name
|
|
90
|
+
- JWT tokens for stateless authentication
|
|
91
|
+
- Local strategy for username/password
|
|
92
|
+
- User object available in `request.user`
|
|
93
|
+
|
|
94
|
+
<!--
|
|
95
|
+
Source references:
|
|
96
|
+
- https://docs.nestjs.com/security/authentication
|
|
97
|
+
-->
|