npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@viniciushrk/nestjs-audit-logger

v1.2.0

Published

NestJS library for automatic API audit logging with PostgreSQL integration

Readme

NestJS Audit Logger

Uma biblioteca completa para auditoria automática de APIs em aplicações NestJS com integração PostgreSQL via TypeORM.

🚀 Características

  • Interceptor Automático: Captura automaticamente requisições HTTP marcadas com @AuditLog
  • Tokens Customizados: Suporte a tokens não-JWT de múltiplas fontes
  • PostgreSQL Integration: Salvamento otimizado no PostgreSQL via TypeORM
  • Configuração Flexível: Configurações globais e por endpoint
  • TypeScript Completo: Tipagem completa para melhor DX
  • Performance Otimizada: Execução assíncrona não-bloqueante
  • IP Real: Captura de IP real considerando proxies
  • Estatísticas Avançadas: Relatórios e análises de uso

📦 Instalação

npm install @viniciushrk/nestjs-audit-logger

Dependências Necessárias (Peer Dependencies)

npm install @nestjs/common @nestjs/core @nestjs/typeorm typeorm pg reflect-metadata rxjs

🛠️ Configuração

1. Configuração Básica

// app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AuditLoggerModule } from '@viniciushrk/nestjs-audit-logger';

@Module({
  imports: [
    // Configuração do PostgreSQL
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: 'localhost',
      port: 5432,
      username: 'postgres',
      password: 'password',
      database: 'myapp',
      entities: [__dirname + '/**/*.entity{.ts,.js}'],
      synchronize: true, // Apenas para desenvolvimento
    }),

    // Configuração do Audit Logger
    AuditLoggerModule.forRoot({
      logRequestBody: true,
      logResponseBody: false,
      excludeRoutes: ['/health', '/metrics'],
      logLevel: 'info',
      database: {
        connection: 'default',
      },
    }),
  ],
})
export class AppModule {}

2. Configuração Assíncrona

// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { AuditLoggerModule } from '@viniciushrk/nestjs-audit-logger';

@Module({
  imports: [
    ConfigModule.forRoot(),
    AuditLoggerModule.forRootAsync({
      imports: [ConfigModule],
      useFactory: async (configService: ConfigService) => ({
        logRequestBody: configService.get('AUDIT_LOG_REQUEST_BODY', false),
        logResponseBody: configService.get('AUDIT_LOG_RESPONSE_BODY', false),
        excludeRoutes: configService.get('AUDIT_EXCLUDE_ROUTES', '').split(','),
        database: {
          connection: configService.get('AUDIT_DB_CONNECTION', 'default'),
        },
      }),
      inject: [ConfigService],
    }),
  ],
})
export class AppModule {}

3. Setup do Banco de Dados

Execute a migration para criar a tabela de auditoria:

CREATE TABLE audit_logs (
    id BIGSERIAL PRIMARY KEY,
    timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
    user_id VARCHAR(255),
    user_email VARCHAR(255),
    http_method VARCHAR(10) NOT NULL,
    endpoint TEXT NOT NULL,
    service_name VARCHAR(255),
    action_description TEXT,
    request_data JSONB,
    response_data JSONB,
    user_agent TEXT,
    ip_address INET,
    token TEXT,
    status_code INTEGER,
    execution_time_ms INTEGER,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- Índices para performance
CREATE INDEX idx_audit_logs_timestamp ON audit_logs (timestamp);
CREATE INDEX idx_audit_logs_user_id ON audit_logs (user_id);
CREATE INDEX idx_audit_logs_endpoint ON audit_logs (endpoint);
CREATE INDEX idx_audit_logs_service_name ON audit_logs (service_name);
CREATE INDEX idx_audit_logs_status_code ON audit_logs (status_code);

🎯 Uso

1. Básico - Decorador @AuditLog

// users.controller.ts
import {
  Controller,
  Post,
  Body,
  Get,
  Param,
  UseInterceptors,
} from '@nestjs/common';
import {
  AuditLog,
  AuditLoggerInterceptor,
} from '@viniciushrk/nestjs-audit-logger';

@Controller('users')
@UseInterceptors(AuditLoggerInterceptor) // Aplicar o interceptor
export class UsersController {
  @Post()
  @AuditLog({
    serviceName: 'UsersService',
    description: 'Criação de novo usuário',
    logRequestBody: true,
    logResponseBody: true,
  })
  async createUser(@Body() userData: CreateUserDto) {
    return this.usersService.create(userData);
  }

  @Get(':id')
  @AuditLog({
    serviceName: 'UsersService',
    description: 'Busca de usuário por ID',
    logRequestBody: false,
    logResponseBody: true,
  })
  async getUserById(@Param('id') id: string) {
    return this.usersService.findById(id);
  }

  @Get() // Sem @AuditLog = não será auditado
  async listUsers() {
    return this.usersService.findAll();
  }
}

2. Aplicação Global do Interceptor

// app.module.ts ou main.ts
import { APP_INTERCEPTOR } from '@nestjs/core';
import { AuditLoggerInterceptor } from '@viniciushrk/nestjs-audit-logger';

@Module({
  providers: [
    {
      provide: APP_INTERCEPTOR,
      useClass: AuditLoggerInterceptor,
    },
  ],
})
export class AppModule {}

3. Tokens Customizados

A biblioteca automaticamente captura tokens de:

  • Header Authorization: Bearer token-value
  • Headers customizados: x-api-token, x-auth-token, x-access-token
  • Query parameters: token, apikey, api_key, access_token

Extratores Customizados

AuditLoggerModule.forRoot({
  // Extrator de token customizado
  customTokenExtractor: request => {
    return request.headers['my-custom-token'];
  },

  // Extrator de user ID do token
  customUserIdExtractor: token => {
    try {
      const decoded = JSON.parse(token);
      return decoded.customUserId;
    } catch {
      return undefined;
    }
  },

  // Extrator de email do token
  customUserEmailExtractor: token => {
    try {
      const decoded = JSON.parse(token);
      return decoded.userEmail;
    } catch {
      return undefined;
    }
  },
});

📊 Consultas e Relatórios

1. Serviço de Auditoria

// my.service.ts
import { Injectable } from '@nestjs/common';
import { AuditLoggerService } from '@viniciushrk/nestjs-audit-logger';

@Injectable()
export class ReportsService {
  constructor(private readonly auditService: AuditLoggerService) {}

  async getUserActivity(userId: string) {
    const logs = await this.auditService.getAuditLogs(
      { userId },
      { page: 1, limit: 100, sortBy: 'timestamp', sortOrder: 'DESC' },
    );
    return logs;
  }

  async getServiceStats() {
    const stats = await this.auditService.getAuditStatistics({
      startDate: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000), // 30 dias
    });
    return stats;
  }
}

2. Exemplos de Consultas

// Logs de um usuário específico
const userLogs = await auditService.getAuditLogs(
  { userId: 'user-123' },
  { page: 1, limit: 50 },
);

// Logs de erro (status 4xx/5xx)
const errorLogs = await auditService.getAuditLogs(
  { statusCode: 500 },
  { sortBy: 'timestamp', sortOrder: 'DESC' },
);

// Logs de um serviço específico
const serviceLogs = await auditService.getAuditLogs(
  { serviceName: 'UsersService' },
  { page: 1, limit: 100 },
);

// Estatísticas gerais
const stats = await auditService.getAuditStatistics({
  startDate: new Date('2024-01-01'),
  endDate: new Date('2024-12-31'),
});

console.log({
  total: stats.totalRequests,
  success: stats.successfulRequests,
  errors: stats.failedRequests,
  avgTime: stats.averageExecutionTime,
  topEndpoints: stats.topEndpoints,
  topUsers: stats.topUsers,
});

⚙️ Opções de Configuração

AuditLoggerModuleOptions

interface AuditLoggerModuleOptions {
  logRequestBody?: boolean; // Logar corpo da requisição (default: false)
  logResponseBody?: boolean; // Logar corpo da resposta (default: false)
  excludeRoutes?: string[]; // Rotas a excluir (supports wildcards)
  logLevel?: 'debug' | 'info' | 'warn' | 'error'; // Nível de log (default: 'info')
  database?: {
    connection?: string; // Nome da conexão TypeORM (default: 'default')
  };
  customTokenExtractor?: (request: any) => string | undefined;
  customUserIdExtractor?: (token: string) => string | undefined;
  customUserEmailExtractor?: (token: string) => string | undefined;
}

AuditLogOptions (Decorator)

interface AuditLogOptions {
  serviceName?: string; // Nome do serviço
  description?: string; // Descrição da ação
  logRequestBody?: boolean; // Override do config global
  logResponseBody?: boolean; // Override do config global
}

🛡️ Segurança

Headers Sensíveis

Os seguintes headers são automaticamente sanitizados nos logs:

  • authorization
  • cookie
  • x-api-token
  • x-auth-token
  • x-access-token
  • api-key
  • apikey

Exemplo de Log Seguro

{
  "requestData": {
    "headers": {
      "content-type": "application/json",
      "authorization": "[REDACTED]",
      "x-api-token": "[REDACTED]"
    },
    "body": { "name": "João", "email": "[email protected]" }
  }
}

🧹 Manutenção

Limpeza de Logs Antigos

// Executar limpeza (manter apenas 90 dias)
const deletedCount = await auditService.cleanupOldAuditLogs(90);
console.log(`${deletedCount} logs removidos`);

Scheduled Cleanup (usando @nestjs/schedule)

import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { AuditLoggerService } from '@viniciushrk/nestjs-audit-logger';

@Injectable()
export class CleanupService {
  constructor(private readonly auditService: AuditLoggerService) {}

  @Cron(CronExpression.EVERY_WEEK)
  async cleanupOldLogs() {
    await this.auditService.cleanupOldAuditLogs(90);
  }
}

📈 Performance

Otimizações Implementadas

  • Execução Assíncrona: Logs são salvos usando setImmediate() para não bloquear a resposta
  • Índices Otimizados: Índices PostgreSQL para consultas rápidas
  • Sanitização Eficiente: Headers sensíveis são sanitizados apenas na memória
  • Configuração Granular: Log apenas o necessário por endpoint

Benchmarks

Em testes com 1000 requisições simultâneas:

  • Overhead: < 2ms por requisição
  • Throughput: Sem impacto significativo
  • Memória: < 50MB adicional

🔧 Desenvolvimento

Estrutura do Projeto

src/
├── lib/
│   ├── audit-logger.module.ts          # Módulo principal
│   ├── audit-logger.service.ts         # Serviço de auditoria
│   ├── audit-logger.interceptor.ts     # Interceptor automático
│   ├── entities/
│   │   └── audit-log.entity.ts         # Entidade TypeORM
│   ├── interfaces/
│   │   └── audit-logger.interface.ts   # Interfaces TypeScript
│   └── decorators/
│       └── audit-log.decorator.ts      # Decorator @AuditLog
├── index.ts                            # Export principal
└── public-api.ts                       # API pública

Scripts Disponíveis

npm run build          # Build da biblioteca
npm run test           # Executar testes
npm run lint           # Linting do código
npm run format         # Formatação com Prettier

🤝 Contribuição

  1. Fork o projeto
  2. Crie uma branch para sua feature (git checkout -b feature/AmazingFeature)
  3. Commit suas mudanças (git commit -m 'Add some AmazingFeature')
  4. Push para a branch (git push origin feature/AmazingFeature)
  5. Abra um Pull Request

📄 Licença

Este projeto está sob a licença MIT. Veja o arquivo LICENSE para detalhes.

🆘 Suporte


Desenvolvido com ❤️