{"_id":"@allnow/nestjs-audit-log","_rev":"2-fc1968e1b74f4b86f0b5090b8ff145d6","name":"@allnow/nestjs-audit-log","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@allnow/nestjs-audit-log","version":"0.1.0","keywords":["nestjs","audit","audit-log","typeorm","logging"],"author":"","license":"MIT","_id":"@allnow/nestjs-audit-log@0.1.0","maintainers":[{"name":"cakecpe","email":"cakecpe@gmail.com"}],"dist":{"shasum":"c6afc953f13dd494de33331eede19396bf9d47fe","tarball":"https://registry.npmjs.org/@allnow/nestjs-audit-log/-/nestjs-audit-log-0.1.0.tgz","fileCount":55,"integrity":"sha512-mWmRk9lwHUNfA5KQZOw1vf9reWtzo4a5CcrMninbgGlt47YTbuB6L9ARPOllCI2MPj2wacjFNWSV5ULlnkRqNg==","signatures":[{"sig":"MEUCIGu9LE4vgWmgIbfkS55/76oQqQ+doA7bhJI0+qRqavItAiEA/mwcKHRZ7RUUYClTPQV1cbYT7xDE3EOEV2VJOa6LzEk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":67183},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18"},"gitHead":"eab465abdb0190113537f4d5c250edb6c07c0e9a","scripts":{"build":"tsc -p tsconfig.build.json","clean":"rimraf dist","prepack":"npm run clean && npm run build","typecheck":"tsc -p tsconfig.json --noEmit"},"_npmUser":{"name":"cakecpe","email":"cakecpe@gmail.com"},"_npmVersion":"10.9.3","description":"Reusable audit log module for NestJS with request context, structured payloads, and pluggable storage.","directories":{},"_nodeVersion":"22.20.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"rxjs":"^7.8.1","rimraf":"^6.0.1","typeorm":"^0.3.20","typescript":"^5.8.0","@types/node":"^22.0.0","@nestjs/core":"^11.1.0","@nestjs/common":"^11.1.0","@types/express":"^5.0.0","reflect-metadata":"^0.2.2","@nestjs/platform-express":"^11.1.0"},"peerDependencies":{"rxjs":">=7","@nestjs/core":">=10 <12","@nestjs/common":">=10 <12","reflect-metadata":">=0.1.13 || >=0.2.0"},"peerDependenciesMeta":{"typeorm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nestjs-audit-log_0.1.0_1777967800225_0.5336912015609703","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@allnow/nestjs-audit-log","version":"0.2.0","description":"Reusable audit log module for NestJS with request context, structured payloads, and pluggable storage.","keywords":["nestjs","audit","audit-log","typeorm","logging"],"license":"MIT","author":"","main":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"tsc -p tsconfig.build.json","clean":"rimraf dist","prepack":"npm run clean && npm run build","test":"npm run test:metadata","test:metadata":"npm run build && node test/mysql-metadata.test.js","typecheck":"tsc -p tsconfig.json --noEmit"},"peerDependencies":{"@nestjs/common":">=10 <12","@nestjs/core":">=10 <12","@nestjs/typeorm":">=10 <12","reflect-metadata":">=0.1.13 || >=0.2.0","rxjs":">=7"},"peerDependenciesMeta":{"typeorm":{"optional":true},"@nestjs/typeorm":{"optional":true}},"dependencies":{},"devDependencies":{"@nestjs/common":"^11.1.0","@nestjs/core":"^11.1.0","@nestjs/platform-express":"^11.1.0","@nestjs/typeorm":"^11.0.0","@types/express":"^5.0.0","@types/node":"^22.0.0","mysql2":"^3.14.0","reflect-metadata":"^0.2.2","rimraf":"^6.0.1","rxjs":"^7.8.1","typescript":"^5.8.0","typeorm":"^0.3.20"},"publishConfig":{"access":"public"},"engines":{"node":">=18"},"_id":"@allnow/nestjs-audit-log@0.2.0","_nodeVersion":"22.20.0","_npmVersion":"10.9.3","dist":{"integrity":"sha512-JXntG7zwJ6t++NHpNmVIhTf3nCsKvUlCMVQ11mqfsPh9OKz2YT3a8ziyHUnwdKpVcGxVFhjYzxUYX2yOTvzRKA==","shasum":"1cc2ad1bb8088e4f57323f2701a4fda3e330cdf6","tarball":"https://registry.npmjs.org/@allnow/nestjs-audit-log/-/nestjs-audit-log-0.2.0.tgz","fileCount":55,"unpackedSize":88884,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDvY8KXfbVIxdGwIVAsewDPg/vi915Zh6ZN7k4HQg9RbAIhAIEaKH54b/iFaSFYhugpW5x0Dje2isgrcuMZn9F+sIsC"}]},"_npmUser":{"name":"cakecpe","email":"cakecpe@gmail.com"},"directories":{},"maintainers":[{"name":"cakecpe","email":"cakecpe@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/nestjs-audit-log_0.2.0_1778234703018_0.3808058384971067"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-05T07:56:40.129Z","modified":"2026-05-08T10:05:03.376Z","0.1.0":"2026-05-05T07:56:40.391Z","0.2.0":"2026-05-08T10:05:03.221Z"},"license":"MIT","keywords":["nestjs","audit","audit-log","typeorm","logging"],"description":"Reusable audit log module for NestJS with request context, structured payloads, and pluggable storage.","maintainers":[{"name":"cakecpe","email":"cakecpe@gmail.com"}],"readme":"# @allnow/nestjs-audit-log\n\nReusable NestJS audit log module based on the audit concept from `bms-core-service`.\n\nIt provides:\n\n- request context capture: user id, username, IP, user-agent, request id\n- structured audit payloads for `CREATE`, `UPDATE`, `DELETE`, or custom events\n- pluggable storage so logs can go to TypeORM, a queue, Kafka, RabbitMQ, HTTP, or any custom sink\n- optional `@AuditLog()` decorator and interceptor for controller-level action logs\n- TypeORM entity and storage helper for an `audit_logs` table\n\n## Install\n\n```bash\nnpm install @allnow/nestjs-audit-log\n```\n\nPeer dependencies:\n\n```bash\nnpm install @nestjs/common @nestjs/core reflect-metadata rxjs\n```\n\nFor the TypeORM helper:\n\n```bash\nnpm install typeorm @nestjs/typeorm\n```\n\n## Basic Usage\n\n```ts\nimport { Module } from '@nestjs/common';\nimport { AuditLogModule } from '@allnow/nestjs-audit-log';\n\n@Module({\n  imports: [\n    AuditLogModule.forRoot(),\n  ],\n})\nexport class AppModule {}\n```\n\nBy default logs are written through Nest `Logger`. Production applications should provide a storage adapter.\n\n## Custom Storage\n\n```ts\nimport { Injectable } from '@nestjs/common';\nimport { AuditLogPayload, AuditLogStorage } from '@allnow/nestjs-audit-log';\n\n@Injectable()\nexport class DatabaseAuditStorage implements AuditLogStorage {\n  async save(payload: AuditLogPayload): Promise<void> {\n    // insert into DB, publish to queue, etc.\n  }\n}\n```\n\n```ts\n@Module({\n  imports: [\n    AuditLogModule.forRoot({\n      storage: DatabaseAuditStorage,\n      failSilently: true,\n    }),\n  ],\n  providers: [DatabaseAuditStorage],\n})\nexport class AppModule {}\n```\n\n## Manual Logging\n\n```ts\nimport { AuditLoggerService } from '@allnow/nestjs-audit-log';\n\nexport class FuelTypeService {\n  constructor(private readonly auditLogger: AuditLoggerService) {}\n\n  async update(id: number, dto: UpdateFuelTypeDto) {\n    const before = await this.repo.findOneByOrFail({ id });\n    const saved = await this.repo.save({ ...before, ...dto });\n\n    await this.auditLogger.logUpdate({\n      before,\n      after: saved,\n      entityType: 'FuelType',\n      entityId: id,\n      action: 'updateFuelType',\n    });\n\n    return saved;\n  }\n}\n```\n\n## Controller Decorator\n\nRegister the interceptor once:\n\n```ts\nimport { APP_INTERCEPTOR } from '@nestjs/core';\nimport { AuditLogInterceptor } from '@allnow/nestjs-audit-log';\n\n@Module({\n  providers: [\n    { provide: APP_INTERCEPTOR, useClass: AuditLogInterceptor },\n  ],\n})\nexport class AppModule {}\n```\n\nUse it on handlers:\n\n```ts\nimport { AuditLog } from '@allnow/nestjs-audit-log';\n\n@Post()\n@AuditLog({ event: 'CREATE', entityType: 'FuelType', entityId: 'id', newValuesPath: 'data' })\ncreate(@Body() dto: CreateFuelTypeDto) {\n  return this.service.create(dto);\n}\n```\n\n`entityId: 'id'` reads `result.id`. Dot paths such as `data.id` are supported. `entityType`, `entityId`,\n`metadata`, and `newValues` also accept callbacks:\n\n```ts\n@AuditLog({\n  event: 'CREATE',\n  entityType: (result) => result.type,\n  entityId: (result) => result.data.id,\n  newValuesPath: 'entries.data',\n  metadata: (_result, req: any) => ({ requestBody: req.body }),\n})\n```\n\n## TypeORM Storage\n\nThe package exports `AuditLogTypeOrmModule`, `TypeOrmAuditLogEntity`, and `TypeOrmAuditLogStorage`.\nFor the common case, let the package wire `TypeOrmModule.forFeature()` and the storage provider:\n\n```ts\nimport { Module } from '@nestjs/common';\nimport {\n  AuditLogTypeOrmModule,\n} from '@allnow/nestjs-audit-log';\n\n@Module({\n  imports: [\n    AuditLogTypeOrmModule.forRoot({\n      failSilently: true,\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\nYou can also use the base module directly:\n\n```ts\nAuditLogModule.forRoot({\n  storage: 'typeorm',\n});\n```\n\nRecommended indexes are included on the entity:\n\n- `entity_type`, `entity_id`\n- `event`, `created_at`\n- `user_id`, `created_at`\n- `request_id`\n\nFor transactional manual writes, pass the active TypeORM manager:\n\n```ts\nawait this.dataSource.transaction(async (manager) => {\n  const saved = await manager.save(FuelTypeEntity, next);\n\n  await this.auditLogger.logUpdate(\n    { before, after: saved, entityType: 'FuelType', entityId: saved.id },\n    { manager },\n  );\n});\n```\n\n## Safety Options\n\nString fields are truncated before save using the entity column limits. JSON payloads are redacted recursively.\nDefault redacted keys are `password`, `token`, `authorization`, and `secret`.\n\n```ts\nAuditLogModule.forRoot({\n  redactKeys: ['password', 'token', 'authorization', 'secret', 'apiKey'],\n  truncate: {\n    userAgent: 512,\n  },\n});\n```\n\n## Request Context\n\nThe middleware reads:\n\n- request id from `x-request-id`, or generates a UUID\n- user from `request.user.id`, `request.user.userId`, or `request.user.sub`\n- username from `request.user.username`, `request.user.email`, or `request.user.name`\n- IP and user-agent from the request\n\nOverride user resolution:\n\n```ts\nAuditLogModule.forRoot({\n  userResolver: {\n    resolve: (req: any) => ({\n      id: req.auth?.accountId,\n      username: req.auth?.displayName,\n    }),\n  },\n});\n```\n\n## Publish\n\nBefore publishing, confirm `name`, `version`, and `author` in `package.json`.\n\n```bash\nnpm install\nnpm run build\nnpm pack --dry-run\nnpm publish --access public\n```\n","readmeFilename":"README.md"}