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

@hiennc24/audit

v2.1.0

Published

Audit trail client SDK for BISO24 services

Readme

@hiennc24/audit

Audit trail client SDK for BISO24 microservices.

Installation

npm install @hiennc24/audit

Usage

import { AuditClient, sanitize } from '@hiennc24/audit'

// Initialize client (once per service)
const audit = new AuditClient({
  redisUrl: process.env.REDIS_URL,
  serviceName: 'svc-inventory',
  enabled: process.env.NODE_ENV !== 'test'
})

// Log audit event
await audit.log({
  action: 'UPDATE',
  entity: 'Product',
  entityId: productId,
  userId: meta.userId,
  orgIds: meta.orgIds,
  before: sanitize(originalProduct, ['password']),
  after: sanitize(updatedProduct, ['password']),
  metadata: { reason: 'Price adjustment' }
})

Repository Interceptor (v2.1+)

Zero-code audit integration - Automatically audit all repository operations without manual logging.

Quick Start

import { AuditClient } from '@hiennc24/audit'

// 1. Initialize client
const auditClient = new AuditClient({
  redisUrl: process.env.REDIS_URL,
  serviceName: 'svc-inventory'
})

// 2. Wrap repository with interceptor (setup once)
const productRepo = auditClient.intercept(baseProductRepo, {
  entity: 'Product',
  extractContext: (meta) => ({
    userId: meta.userId,
    orgIds: meta.orgIds,
    domain: meta.domain
  })
})

// 3. Use normally - audit is automatic!
await productRepo.create(data, meta)              // ✅ Auto audited (CREATE)
await productRepo.update(id, updates, meta)       // ✅ Auto audited (UPDATE)
await productRepo.delete(id, meta)                // ✅ Auto audited (DELETE)
await productRepo.findByIdAndUpdate(id, data, meta) // ✅ Auto audited (UPDATE)

// Non-auditable methods pass through unchanged
const products = await productRepo.findAll()     // No audit
const count = await productRepo.count()          // No audit

Supported Methods

| Method | Action | Before State Fetched | |--------|--------|---------------------| | create, insertOne | CREATE | No | | update, updateById, findByIdAndUpdate, findOneAndUpdate | UPDATE | Yes | | delete, deleteById, remove, findByIdAndDelete, findByIdAndRemove | DELETE | Yes |

Configuration Options

interface InterceptConfig<TMeta> {
  // Required
  entity: string                              // Entity name (e.g., 'Product')
  extractContext: (meta: TMeta) => AuditContext  // Extract userId, orgIds, domain

  // Optional
  idExtractor?: (args: any[], methodName: string) => string  // Custom ID extraction
  sensitiveFields?: string[]                  // Fields to sanitize (default: SENSITIVE_FIELDS)
  findByIdMethod?: string                     // Method to fetch before state (default: 'findById')
  methods?: Record<string, MethodConfig>      // Custom method configurations
  debug?: boolean                             // Enable verbose logging
}

Advanced Example

// Custom configuration
const orderRepo = auditClient.intercept(baseOrderRepo, {
  entity: 'Order',
  extractContext: (meta) => ({
    userId: meta.user?._id || 'system',
    orgIds: meta.orgIds || [],
    domain: meta.domain
  }),

  // Custom ID extraction for non-standard patterns
  idExtractor: (args, methodName) => {
    if (methodName === 'updateByOrderNumber') {
      return args[0].orderNumber
    }
    return args[0]
  },

  // Additional sensitive fields
  sensitiveFields: ['creditCard', 'cvv', 'apiKey'],

  // Use custom findById method
  findByIdMethod: 'findOne',

  // Debug mode for troubleshooting
  debug: process.env.DEBUG === 'true'
})

Benefits

  • 87% Code Reduction: From 15 lines per operation to 2 lines one-time setup
  • Consistency: Impossible to forget audit logging
  • Type-Safe: Full TypeScript support with generics
  • Performance: <50ms overhead per operation
  • Fire-and-Forget: Audit failures don't break business logic

API

AuditClient

  • constructor(config) - Initialize client
  • log(event) - Publish audit event (async, fire-and-forget)
  • intercept(repository, config) - Create intercepted repository with auto-audit (v2.1+)
  • close() - Close Redis connection

sanitize(obj, fields)

Remove sensitive fields from object before logging.

autoSanitize(obj)

Auto-sanitize using common sensitive fields (password, apiKey, creditCard, etc.).

Configuration

| Option | Type | Default | Description | |--------|------|---------|-------------| | redisUrl | string | required | Redis connection URL | | serviceName | string | required | Service name (e.g., 'svc-inventory') | | enabled | boolean | true | Enable/disable auditing | | streamName | string | 'audit:events' | Redis Stream name |

Features

  • Fire-and-forget: Non-blocking, doesn't throw on errors
  • Idempotency: Unique eventId for each event
  • Sanitizer: Remove sensitive fields before logging
  • Lightweight: Zero dependencies on svc-audit service
  • Type-safe: Full TypeScript support

Example: Sanitizing Data

import { sanitize, autoSanitize, SENSITIVE_FIELDS } from '@hiennc24/audit'

// Manual sanitization
const sanitized = sanitize(user, ['password', 'ssn'])

// Auto-sanitize common fields
const sanitized = autoSanitize(user)

// Custom sensitive fields
const customSanitized = sanitize(data, [...SENSITIVE_FIELDS, 'customSecret'])

Error Handling

The SDK follows a fire-and-forget pattern. Errors are logged to console but never thrown, ensuring audit logging doesn't impact application flow.

License

MIT