@nathapp/nestjs-audit
v3.3.0
Published
Decorator-driven, storage-agnostic audit logging for NestJS applications
Downloads
62
Readme
@nathapp/nestjs-audit
Decorator-driven, storage-agnostic audit logging for NestJS applications.
Features
- Declarative capture —
@Audit({ action, resource? })on a controller/service method, picked up byAuditInterceptor - Pluggable storage —
IAuditStorageseam; shipsInMemoryAuditStorage(default) andLoggerAuditStorage; bring your own Prisma/TypeORM-backed storage - Pluggable actor resolution —
IAuditActorResolverseam; shipsDefaultActorResolver(req.user?.id ?? 'anonymous') - Never fails the request — audit storage write failures are caught and logged, not propagated to the response
- Correlation-id aware — reads
@nathapp/nestjs-logging's request-scoped correlation id automatically
Installation
npm install @nathapp/nestjs-audit @nathapp/nestjs-common @nathapp/nestjs-loggingPeer requirement:
ClockModule.AuditModuledoes not importClockModuleitself —AuditInterceptordepends on theCLOCKtoken from@nathapp/nestjs-common, and expects it to already be available in your application's module tree, the same wayLoggerAuditStorageexpectsLOGGER_SERVICEto already be available. Most apps already satisfy this if they use nestjs-common's clock seam anywhere else, sinceClockModuleisglobal: true. If yours doesn't, addClockModule.register()to your root module'simports— otherwise Nest will throw a dependency-resolution error at bootstrap.
Quick Start
import { Module } from '@nestjs/common';
import { AuditModule } from '@nathapp/nestjs-audit';
@Module({
imports: [AuditModule.register()],
})
export class AppModule {}import { Audit, AuditInterceptor } from '@nathapp/nestjs-audit';
@Controller('users')
@UseInterceptors(AuditInterceptor)
export class UsersController {
@Audit({ action: 'USER_UPDATED', resource: 'user', resourceIdParam: 'id' })
@Patch(':id')
updateUser(@Param('id') id: string, @Body() dto: UpdateUserDto) {
return this.usersService.update(id, dto);
}
}Custom storage
import { AuditModule } from '@nathapp/nestjs-audit';
@Module({
imports: [
AuditModule.registerAsync({
useFactory: (prisma: PrismaService) => ({ storage: new PrismaAuditStorage(prisma) }),
inject: [PrismaService],
}),
],
})
export class AppModule {}Scope
v1 does not include automatic before/after state diffing — pass whatever context you need through IAuditStorage directly if you need it, since AuditEntry.metadata is available to any direct storage consumer (not populated by AuditInterceptor itself, since @Audit() options are static and set at method-definition time).
Security
AuditEntry.metadata and the built-in LoggerAuditStorage write whatever is passed through verbatim (including to structured logs). Do not put secrets, API keys, passwords, or other sensitive personally-identifiable information into metadata — treat it the same way you would any other logged field.
