@nestjsvn/swagger-sse
Version:
OpenAPI documentation and interactive Swagger UI for NestJS Server-Sent Events endpoints
387 lines (300 loc) • 9.34 kB
Markdown
# Getting Started with @nestjsvn/swagger-sse
This guide will help you get up and running with `@nestjsvn/swagger-sse` in your NestJS application.
## Table of Contents
1. [Installation](#installation)
2. [Basic Setup](#basic-setup)
3. [Creating Your First SSE Endpoint](#creating-your-first-sse-endpoint)
4. [Using the CLI Plugin](#using-the-cli-plugin)
5. [Swagger UI Integration](#swagger-ui-integration)
6. [Advanced Configuration](#advanced-configuration)
7. [Testing Your Implementation](#testing-your-implementation)
8. [Troubleshooting](#troubleshooting)
## Installation
Install the package using npm or yarn:
```bash
npm install @nestjsvn/swagger-sse
# or
yarn add @nestjsvn/swagger-sse
```
### Peer Dependencies
Make sure you have the required peer dependencies installed:
```bash
npm install @nestjs/common @nestjs/swagger
# or
yarn add @nestjs/common @nestjs/swagger
```
## Basic Setup
### 1. Update Your Main Application File
Replace the standard `SwaggerModule.setup()` with `setupSsePlugin()`:
```typescript
// main.ts
import { NestFactory } from '@nestjs/core';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { setupSsePlugin } from '@nestjsvn/swagger-sse';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const config = new DocumentBuilder()
.setTitle('My API')
.setDescription('API with SSE support')
.setVersion('1.0')
.build();
const document = SwaggerModule.createDocument(app, config);
// Use setupSsePlugin instead of SwaggerModule.setup
setupSsePlugin(app, document, 'api-docs');
await app.listen(3000);
}
bootstrap();
```
### 2. Enable CORS (if needed)
If your frontend is on a different domain, enable CORS:
```typescript
// main.ts
app.enableCors({
origin: ['http://localhost:3000', 'https://yourdomain.com'],
credentials: true,
});
```
## Creating Your First SSE Endpoint
### 1. Define Your Event DTOs
Create TypeScript classes for your event data:
```typescript
// events/dto/user-events.dto.ts
export class UserCreatedDto {
userId: string;
username: string;
email: string;
createdAt: Date;
}
export class UserUpdatedDto {
userId: string;
username: string;
email: string;
updatedAt: Date;
}
```
### 2. Create Your SSE Controller
```typescript
// events/events.controller.ts
import { Controller, Sse } from '@nestjs/common';
import { Observable, interval, map } from 'rxjs';
import { ApiSse } from '@nestjsvn/swagger-sse';
import { UserCreatedDto, UserUpdatedDto } from './dto/user-events.dto';
@Controller('events')
export class EventsController {
@Sse('user-stream')
@ApiSse({
summary: 'User events stream',
description: 'Real-time stream of user-related events',
events: {
'user-created': UserCreatedDto,
'user-updated': UserUpdatedDto,
},
})
streamUserEvents(): Observable<MessageEvent> {
return interval(2000).pipe(
map((i) => ({
data: JSON.stringify({
userId: `user-${i}`,
username: `User${i}`,
email: `user${i}@example.com`,
createdAt: new Date(),
}),
type: 'user-created',
} as MessageEvent))
);
}
}
```
### 3. Register Your Controller
```typescript
// app.module.ts
import { Module } from '@nestjs/common';
import { EventsController } from './events/events.controller';
@Module({
controllers: [EventsController],
})
export class AppModule {}
```
## Using the CLI Plugin
For automatic documentation generation, enable the CLI plugin:
### 1. Update nest-cli.json
```json
{
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"deleteOutDir": true,
"plugins": [
"@nestjs/swagger",
{
"name": "@nestjsvn/swagger-sse/plugin",
"options": {
"eventNamingConvention": "kebab-case",
"introspectComments": true
}
}
]
}
}
```
### 2. Use Zero-Configuration Endpoints
With the plugin enabled, you can create SSE endpoints without explicit `@ApiSse` decorators:
```typescript
@Controller('notifications')
export class NotificationsController {
/**
* Streams notification events
* @summary Real-time notification stream
* @description Provides live updates for user notifications
*/
@Sse('updates')
streamNotifications(): Observable<MessageEvent<NotificationDto>> {
// The plugin will automatically generate documentation
// based on the return type and JSDoc comments
return this.notificationService.getStream();
}
}
```
## Swagger UI Integration
### 1. Access Your Documentation
Navigate to `http://localhost:3000/api-docs` to see your Swagger UI with SSE support.
### 2. Using the SSE Interface
1. **Find your SSE endpoint** in the Swagger UI
2. **Expand the endpoint** to see the SSE-specific interface
3. **Click "Connect"** to establish the SSE connection
4. **View real-time events** in the event log
5. **Disconnect** when finished
### 3. SSE-Specific UI Elements
The enhanced Swagger UI includes:
- **Connection Status Indicator**: Shows connected/disconnected/error states
- **Connect/Disconnect Buttons**: Control SSE connection
- **Real-time Event Log**: Displays incoming events with timestamps
- **Event Type Filtering**: Filter events by type
- **Clear Log Button**: Clear the event history
- **JSON Formatting**: Pretty-printed event data
## Advanced Configuration
### 1. Custom Event Types
Handle complex event scenarios:
```typescript
@ApiSse({
summary: 'Multi-type event stream',
events: {
'user-created': UserCreatedDto,
'user-updated': UserUpdatedDto,
'user-deleted': { userId: string },
'system-alert': SystemAlertDto,
},
defaultEvent: GenericEventDto,
})
streamEvents(): Observable<MessageEvent> {
return merge(
this.userEvents$,
this.systemEvents$,
this.alertEvents$
);
}
```
### 2. Authentication
Secure your SSE endpoints:
```typescript
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiSse({
summary: 'Authenticated event stream',
security: [{ bearer: [] }],
events: {
'private-event': PrivateEventDto,
},
})
streamPrivateEvents(@Request() req): Observable<MessageEvent> {
return this.eventService.getPrivateEvents(req.user.id);
}
```
### 3. Query Parameters
Filter events based on parameters:
```typescript
@ApiSse({
summary: 'Filtered event stream',
events: {
'filtered-event': FilteredEventDto,
},
})
streamFilteredEvents(
@Query('userId') userId?: string,
@Query('eventType') eventType?: string,
): Observable<MessageEvent> {
return this.eventService.getFilteredEvents({ userId, eventType });
}
```
### 4. Error Handling
Include error events in your stream:
```typescript
@ApiSse({
events: {
'data-update': DataUpdateDto,
'error': ErrorEventDto,
},
})
streamWithErrorHandling(): Observable<MessageEvent> {
return this.dataService.watchData().pipe(
map(data => ({ type: 'data-update', data: JSON.stringify(data) })),
catchError(error => of({
type: 'error',
data: JSON.stringify({ message: error.message, code: error.code })
}))
);
}
```
## Testing Your Implementation
### 1. Manual Testing
1. Start your application: `npm run start:dev`
2. Open Swagger UI: `http://localhost:3000/api-docs`
3. Test SSE endpoints using the interactive interface
### 2. Automated Testing
Run the included test suites:
```bash
# Unit tests
npm run test
# Unit tests with watch mode
npm run test:watch
# Test coverage
npm run test:coverage
```
**Note**: E2E and performance testing infrastructure is planned but not yet implemented in the current package.json scripts. The project currently focuses on comprehensive unit testing.
## Troubleshooting
### Common Issues
#### 1. SSE Connection Fails
**Problem**: Connection button shows error state immediately.
**Solutions**:
- Check that your SSE endpoint is accessible
- Verify CORS configuration if frontend is on different domain
- Ensure the endpoint returns proper `text/event-stream` content type
#### 2. Events Not Appearing
**Problem**: Connection succeeds but no events are displayed.
**Solutions**:
- Verify your Observable is emitting MessageEvent objects
- Check that event data is properly JSON stringified
- Ensure event types match those defined in `@ApiSse`
#### 3. Plugin Not Working
**Problem**: Automatic documentation generation isn't working.
**Solutions**:
- Verify `nest-cli.json` configuration
- Ensure plugin is listed after `@nestjs/swagger`
- Check TypeScript compilation for errors
#### 4. Performance Issues
**Problem**: UI becomes slow with many events.
**Solutions**:
- Implement event log size limits
- Use event filtering
- Consider pagination for historical events
### Getting Help
- **Documentation**: Check the [API Reference](./api-reference.md)
- **Examples**: See the [examples directory](../examples/)
- **Issues**: Report bugs on [GitHub Issues](https://github.com/nestjsx/swagger-sse/issues)
- **Discussions**: Join [GitHub Discussions](https://github.com/nestjsx/swagger-sse/discussions)
## Next Steps
- Explore [Advanced Usage Patterns](./advanced-usage.md)
- Learn about [Performance Optimization](./performance.md)
- Check out [Real-world Examples](../examples/)
- Read the [API Reference](./api-reference.md)