# naga-audit-service

A comprehensive audit service library for NestJS applications with MongoDB support. This library provides a complete audit trail solution that can track changes to your data with full metadata support.

## Features

- 🔍 **Dynamic Schema Support**: Automatically creates audit collections based on your data structure
- 📊 **MongoDB Integration**: Built on top of Mongoose for robust database operations
- 🔗 **Inter-Service Communication**: Built-in HTTP client for communicating with other services
- 📄 **Pagination Support**: Efficient data retrieval with built-in pagination
- 🎯 **TypeScript Support**: Full TypeScript support with type definitions
- 📝 **Comprehensive Logging**: Integrated Winston logger for detailed audit logs
- 🛡️ **Error Handling**: Robust error handling with custom exceptions
- 📋 **Validation**: Built-in validation using class-validator
- 🔧 **Configurable**: Easy configuration through environment variables

## Installation

```bash
npm install naga-audit-service
```

## Quick Start

### 1. Configure and Start the Service

```typescript
import { NoukhaAuditLog } from 'naga-audit-service';

// Configure and automatically start the audit log service
await NoukhaAuditLog.configure({
  dbUrl: 'mongodb://localhost:27017/your-database',
  configServiceUrl: 'http://your-config-service:3000', // optional
  logLevel: 'info' // optional
});

// The service will automatically:
// ✅ Connect to MongoDB
// ✅ Initialize all components
// ✅ Start the audit service
// ✅ Set up graceful shutdown handlers
```

### 2. Alternative: Use Service Starter

```typescript
import { startAuditService } from 'naga-audit-service';

// Start the service with configuration
await startAuditService({
  dbUrl: 'mongodb://localhost:27017/your-database',
  configServiceUrl: 'http://your-config-service:3000',
  logLevel: 'info'
});
```

### 3. Import the Module

```typescript
import { Module } from '@nestjs/common';
import { NoukhaAuditLog } from 'naga-audit-service';

@Module({
  imports: [
    NoukhaAuditLog.getModule(),
    // ... other modules
  ],
})
export class AppModule {}
```

### 4. Use the Audit Service

```typescript
import { Injectable } from '@nestjs/common';
import { AuditService } from 'naga-audit-service';

@Injectable()
export class YourService {
  constructor(private readonly auditService: AuditService) {}

  async createAuditRecord() {
    const auditData = {
      collectionName: 'users',
      action: 'CREATE',
      userId: 'user123',
      serviceName: 'user-service',
      metaData: {
        ipAddress: '192.168.1.1',
        userAgent: 'Mozilla/5.0...',
        // ... any additional metadata
      }
    };

    return await this.auditService.transformAndInsert(auditData);
  }

  async getAuditHistory(collectionName: string) {
    return await this.auditService.getAuditByCollectionName(collectionName, {
      skip: 0,
      limit: 10,
      sort: { createdAt: -1 }
    });
  }
}
```

## API Reference

### AuditService

#### `transformAndInsert(createAuditDto: CreateAuditDto)`

Creates a new audit record in the specified collection.

**Parameters:**
- `createAuditDto`: Object containing audit data
  - `collectionName`: Name of the collection to audit
  - `action`: Action performed (CREATE, UPDATE, DELETE, etc.)
  - `userId`: ID of the user performing the action
  - `serviceName`: Name of the service
  - `metaData`: Additional metadata object

#### `getAuditByCollectionName(collectionName: string, query?: QueryOptions)`

Retrieves audit records from a specific collection with pagination support.

**Parameters:**
- `collectionName`: Name of the collection to query
- `query`: Optional query parameters
  - `skip`: Number of records to skip
  - `limit`: Number of records to return
  - `filter`: MongoDB filter object
  - `projection`: MongoDB projection object
  - `sort`: MongoDB sort object

### CreateAuditDto

```typescript
interface CreateAuditDto {
  collectionName: string;
  action: string;
  userId: string;
  serviceName: string;
  prevsState?: Record<string, any>;
  newState?: Record<string, any>;
  metaData?: Record<string, any>;
  [key: string]: any; // Additional custom fields
}
```

## Configuration & Auto-Start

### Configuration Options

| Option | Type | Required | Description | Default |
|--------|------|----------|-------------|---------|
| `dbUrl` | string | ✅ | MongoDB connection string | - |
| `configServiceUrl` | string | ❌ | Config service URL for collection validation | `http://localhost:3000` |
| `logLevel` | string | ❌ | Logging level | `info` |

> **Note**: This package is designed to be environment-agnostic. All configuration is provided programmatically through the `NoukhaAuditLog.configure()` method, ensuring no environment variables are required or included in the package.

### Automatic Service Startup

When you call `NoukhaAuditLog.configure()` or `startAuditService()`, the service automatically:

1. **Connects to MongoDB** using the provided `dbUrl`
2. **Initializes all components** (logging, HTTP client, pagination, etc.)
3. **Starts the audit service** and makes it ready for use
4. **Sets up graceful shutdown** handlers for SIGINT and SIGTERM
5. **Provides status checking** methods to verify service readiness

### Collection Configuration

The audit service validates collections against a configuration service. Make sure your config service provides collection configurations in the following format:

```typescript
interface CollectionConfig {
  serviceName: string;
  collections: string[];
  collectionsConfigId: string;
}
```

## Advanced Usage

### Custom Audit Module

```typescript
import { Module } from '@nestjs/common';
import { AuditModule } from 'naga-audit-service';

@Module({
  imports: [
    AuditModule,
    // ... other required modules
  ],
  controllers: [YourAuditController],
  providers: [YourAuditService],
})
export class CustomAuditModule {}
```

### Alternative Configuration Method

You can also configure the module directly without using the static configuration:

```typescript
import { Module } from '@nestjs/common';
import { NagaAuditServiceModule } from 'naga-audit-service';

@Module({
  imports: [
    NagaAuditServiceModule.forRoot({
      dbUrl: 'mongodb://localhost:27017/your-database',
      configServiceUrl: 'http://your-config-service:3000',
      logLevel: 'info'
    }),
    // ... other modules
  ],
})
export class AppModule {}
```

### Service Status & Control

```typescript
import { NoukhaAuditLog, startAuditService, stopAuditService } from 'naga-audit-service';

// Check if service is ready
if (NoukhaAuditLog.isServiceReady()) {
  console.log('✅ Service is ready');
}

// Wait for service to be ready
await NoukhaAuditLog.waitForReady();

// Stop the service
await stopAuditService();
```

### Using Individual Components

```typescript
import { 
  AuditService, 
  LoggerService, 
  PaginationService,
  HttpClientService 
} from 'naga-audit-service';

@Injectable()
export class CustomService {
  constructor(
    private readonly auditService: AuditService,
    private readonly logger: LoggerService,
    private readonly pagination: PaginationService,
    private readonly httpClient: HttpClientService,
  ) {}
}
```

## Error Handling

The library includes comprehensive error handling:

```typescript
import { 
  BadRequestException, 
  NotFoundException, 
  BadGatewayException 
} from '@nestjs/common';

try {
  await this.auditService.transformAndInsert(auditData);
} catch (error) {
  if (error instanceof BadRequestException) {
    // Handle validation errors
  } else if (error instanceof NotFoundException) {
    // Handle collection not found
  } else if (error instanceof BadGatewayException) {
    // Handle service communication errors
  }
}
```

## Contributing

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## Support

For support, email support@naga.com or create an issue in the GitHub repository.
