UNPKG

@nestjsvn/swagger-sse

Version:

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

348 lines (271 loc) 7.33 kB
# CLI Plugin Usage Guide The `@nestjsvn/swagger-sse` CLI plugin automatically detects methods decorated with `@Sse()` and adds appropriate `@ApiSse()` decorators with inferred event types from Observable return types. ## Installation ```bash npm install @nestjsvn/swagger-sse ``` ## Configuration ### NestJS CLI Integration Add the plugin to your `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, "autoGenerateOperationId": true } } ] } } ``` ### TypeScript Compiler Integration For direct TypeScript compiler integration: ```typescript // webpack.config.js or similar const { createTransformerFactory } = require('@nestjsvn/swagger-sse/plugin'); module.exports = { // ... other config module: { rules: [ { test: /\.tsx?$/, use: [ { loader: 'ts-loader', options: { getCustomTransformers: (program) => ({ before: [createTransformerFactory({ eventNamingConvention: 'kebab-case', introspectComments: true })(program)] }) } } ] } ] } }; ``` ## Plugin Options ### `eventNamingConvention` Controls how TypeScript type names are converted to event names. - `'kebab-case'` (default): `UserCreatedDto` → `user-created` - `'camelCase'`: `UserCreatedDto` → `userCreated` - `'PascalCase'`: `UserCreatedDto` → `UserCreated` ### `introspectComments` When `true` (default), the plugin extracts metadata from JSDoc comments: ```typescript /** * Streams real-time user events * @summary User event stream * @description Provides live updates for user-related activities */ @Sse('user-events') streamUserEvents(): Observable<MessageEvent<UserCreatedDto | UserUpdatedDto>> { // Implementation } ``` Generates: ```typescript @ApiSse({ summary: 'User event stream', description: 'Provides live updates for user-related activities', events: { 'user-created': UserCreatedDto, 'user-updated': UserUpdatedDto } }) ``` ### `autoGenerateOperationId` When `true` (default), automatically generates operation IDs: ```typescript @Sse('stream') streamEvents(): Observable<MessageEvent<EventDto>> { // Implementation } ``` Generates: ```typescript @ApiSse({ operationId: 'sseStreamEvents', events: { 'event': EventDto } }) ``` ## Automatic Type Detection The plugin analyzes Observable return types to extract event types: ### Single Event Type ```typescript @Sse('notifications') streamNotifications(): Observable<MessageEvent<NotificationDto>> { // Plugin generates: // @ApiSse({ // events: { // 'notification': NotificationDto // } // }) } ``` ### Union Types ```typescript @Sse('events') streamEvents(): Observable<MessageEvent<UserDto | MessageDto | OrderDto>> { // Plugin generates: // @ApiSse({ // events: { // 'user': UserDto, // 'message': MessageDto, // 'order': OrderDto // } // }) } ``` ### Complex Types ```typescript type EventTypes = | { type: 'user-created'; data: UserCreatedDto } | { type: 'user-updated'; data: UserUpdatedDto } | { type: 'user-deleted'; data: UserDeletedDto }; @Sse('user-events') streamUserEvents(): Observable<MessageEvent<EventTypes>> { // Plugin analyzes the union type and extracts event names } ``` ## Type Name Processing The plugin automatically removes common suffixes when generating event names: - `UserCreatedDto` → `user-created` - `MessageReceivedEvent` → `message-received` - `OrderData` → `order` - `NotificationPayload` → `notification` Removed suffixes: `Dto`, `Event`, `Data`, `Payload` ## Error Handling The plugin handles various edge cases gracefully: ### Methods Without Return Types ```typescript @Sse('stream') streamEvents() { // Plugin skips transformation - no return type to analyze } ``` ### Non-Observable Return Types ```typescript @Sse('stream') streamEvents(): Promise<string> { // Plugin skips transformation - not an Observable } ``` ### Observable Without MessageEvent ```typescript @Sse('stream') streamEvents(): Observable<string> { // Plugin skips transformation - not MessageEvent } ``` ## Integration with Existing Code The plugin only transforms methods that: 1. Have the `@Sse()` decorator 2. Do NOT already have the `@ApiSse()` decorator 3. Have an Observable return type 4. Are in files that import from `@nestjs/common` This ensures it doesn't interfere with manually documented endpoints. ## Debugging Enable debug logging to see what the plugin is doing: ```typescript // In your transformer configuration { name: "@nestjsvn/swagger-sse/plugin", options: { debug: true, // Enable debug logging eventNamingConvention: "kebab-case" } } ``` The plugin will log: - Which methods it's transforming - What event types it extracted - Any errors or warnings during transformation ## Best Practices ### 1. Use Explicit Return Types ```typescript // Good - explicit return type @Sse('events') streamEvents(): Observable<MessageEvent<UserDto>> { return this.eventService.stream(); } // Less ideal - inferred return type may not be detected @Sse('events') streamEvents() { return this.eventService.stream(); } ``` ### 2. Use Descriptive Type Names ```typescript // Good - descriptive names export class UserCreatedDto { userId: string; username: string; } export class MessageReceivedDto { messageId: string; content: string; } // Less ideal - generic names export class EventDto { type: string; data: any; } ``` ### 3. Add JSDoc Comments ```typescript /** * Streams real-time notifications for the authenticated user * @summary User notification stream * @description Provides live updates including messages, alerts, and system notifications */ @Sse('notifications') streamNotifications(): Observable<MessageEvent<NotificationDto>> { return this.notificationService.streamForUser(); } ``` ### 4. Group Related Events ```typescript // Group related events in union types type UserEventTypes = | UserCreatedDto | UserUpdatedDto | UserDeletedDto; @Sse('user-events') streamUserEvents(): Observable<MessageEvent<UserEventTypes>> { return this.userService.streamEvents(); } ``` ## Troubleshooting ### Plugin Not Running 1. Verify `nest-cli.json` configuration 2. Check that files import from `@nestjs/common` 3. Ensure methods have `@Sse()` decorator 4. Verify TypeScript compilation is working ### Types Not Detected 1. Check return type is `Observable<MessageEvent<T>>` 2. Verify type definitions are available 3. Ensure TypeScript can resolve the types 4. Check for circular dependencies ### Generated Names Incorrect 1. Adjust `eventNamingConvention` option 2. Consider renaming your DTOs 3. Use manual `@ApiSse()` for complex cases ### Build Performance Issues 1. The plugin adds minimal overhead (<10% build time) 2. Consider excluding test files from transformation 3. Use `include`/`exclude` patterns in TypeScript config