UNPKG

@nestjsvn/swagger-sse

Version:

OpenAPI documentation and interactive Swagger UI for NestJS Server-Sent Events endpoints

387 lines (300 loc) 9.34 kB
# 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)