@theoptimalpartner/nestjs-optiaudit
v0.1.7
Published
NestJS module for OptiAudit event tracking
Maintainers
Readme
@theoptimalpartner/nestjs-optiaudit
NestJS module for OptiAudit event tracking. Zero-config integration with automatic request tracking.
Features
- Zero-config: Reads
OPTIAUDIT_URLandOPTIAUDIT_WRITE_KEYfrom environment - Decorators:
@TrackEvent()and@TrackPageView()for declarative tracking - Auto context extraction: Extracts
actor_idfromreq.contextorreq.user - Silent fallback: Disabled automatically in tests or when env vars are missing
- Request ID propagation: Middleware for
X-Request-IDheader
Installation
npm install @theoptimalpartner/nestjs-optiauditQuick Start
1. Environment Variables
OPTIAUDIT_URL=https://some-url.optiaudit.com/api/v1
OPTIAUDIT_WRITE_KEY=your_write_key2. Import Module
// app.module.ts
import { Module } from '@nestjs/common';
import { OptiauditModule } from '@theoptimalpartner/nestjs-optiaudit';
@Module({
imports: [
OptiauditModule.forRoot(), // That's it!
],
})
export class AppModule {}3. Use Decorators
import { Controller, Get, Post } from '@nestjs/common';
import { TrackEvent, TrackPageView } from '@theoptimalpartner/nestjs-optiaudit';
@Controller('documents')
export class DocumentsController {
@Get()
@TrackPageView('documents')
findAll() {
return this.documentsService.findAll();
}
@Post()
@TrackEvent('document_created', 'documents')
create(@Body() dto: CreateDocumentDto) {
return this.documentsService.create(dto);
}
@Delete(':id')
@TrackEvent('document_deleted', 'documents')
remove(@Param('id') id: string) {
return this.documentsService.remove(id);
}
}Manual Tracking
For custom events outside of HTTP requests:
import { Injectable } from '@nestjs/common';
import { OptiauditService } from '@theoptimalpartner/nestjs-optiaudit';
@Injectable()
export class PaymentsService {
constructor(private readonly optiaudit: OptiauditService) {}
async processPayment(userId: string, amount: number) {
// ... process payment ...
await this.optiaudit.track({
event_type: 'payment_processed',
actor_id: userId,
metadata: { amount, currency: 'USD' },
});
}
}Context Extraction
The interceptor automatically extracts user info from the request:
| Priority | Source | Fields |
|----------|--------|--------|
| 1 | req.context | user_id, organization_id, email, username, sub |
| 2 | req.user | user_id or id, organization_id, email, user_email, username, sub |
| 3 | Fallback | 'anonymous' |
Extracted fields:
user_id/id→actor_id(required)organization_id→organization_id(optional)email/user_email→metadata.email(optional)username→metadata.username(optional, for Cognito login with username)sub→metadata.sub(optional, for Cognito integration)
This works with:
- Custom
x-encrypted-contextmiddleware (TheOptimal backends) - Passport.js / JWT strategies (
req.user) - AWS Cognito (
subfield) - Any middleware that sets
req.contextorreq.user
Note: The context extraction logic may need updates as new projects adopt this library. If your project uses a different structure (e.g.,
req.session.userId), please open a PR to add support or use manual tracking instead.
Compatibility
| Dependency | Versions |
|------------|----------|
| @nestjs/common | ^10.0.0, ^11.0.0 |
| @nestjs/core | ^10.0.0, ^11.0.0 |
| @nestjs/axios | ^3.0.0, ^4.0.0 |
| rxjs | ^7.0.0 |
| Node.js | >= 18 |
Note: If your project uses a different version of these dependencies, please open a PR to add compatibility or report an issue.
Advanced Configuration
OptiauditModule.forRoot({
url: 'https://custom-url.com/api/v1', // Override env var
writeKey: 'custom-key', // Override env var
timeout: 5000, // Request timeout (default: 3000ms)
enabled: false, // Force disable
logErrors: false, // Disable warning logs on failure
})Request ID Middleware
Propagates X-Request-ID header for request correlation:
// main.ts
import { RequestIdMiddleware } from '@theoptimalpartner/nestjs-optiaudit';
// Apply globally
app.use(new RequestIdMiddleware().use);Or in a module:
import { MiddlewareConsumer, Module } from '@nestjs/common';
import { RequestIdMiddleware } from '@theoptimalpartner/nestjs-optiaudit';
@Module({})
export class AppModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(RequestIdMiddleware).forRoutes('*');
}
}Track Params
Full interface for optiaudit.track():
interface TrackParams {
event_type: string; // Required: event name
actor_id: string; // Required: user/actor ID
organization_id?: number; // Optional: org ID
resource_path?: string; // Optional: endpoint path
ip_address?: string; // Optional: client IP
user_agent?: string; // Optional: browser/client
session_id?: string; // Optional: session ID
metadata?: Record<string, unknown>; // Optional: custom data
}Behavior
| Condition | Behavior |
|-----------|----------|
| No env vars | Silently disabled |
| NODE_ENV=test | Silently disabled |
| HTTP error | Logs warning, doesn't throw |
| Timeout (3s) | Logs warning, doesn't throw |
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
MIT
