# 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