Skip to content

ganesanarun/type-audit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

@snow-tzu/audit

Transparent audit tracking for object field changes in TypeScript applications. Non-intrusive proxy-based tracking that preserves original object behavior while passively collecting audit information.

npm License: MIT build.yml

Table of Contents

Features

✨ Field-level tracking - @AuditField() decorator for selective field monitoring
🎯 Class-level tracking - @Auditable() decorator for comprehensive audit coverage
🚫 Field exclusion - @AuditIgnore() decorator to exclude sensitive fields
πŸ” Non-intrusive proxies - Preserve original object behavior and method context
πŸ›‘οΈ Type safety - Full TypeScript support with strong typing
πŸ“Š Change history - Retrieve all tracked changes with changes()
πŸ”„ Reset functionality - Clear audit history without affecting object state
⚑ Robust error handling - Never disrupts business logic execution
πŸ› Optional logging - Built-in debugging utilities

Installation

yarn add @snow-tzu/audit
# or
npm install @snow-tzu/audit

Quick Start

1. Field-Level Tracking

import { Audit, AuditField } from '@snow-tzu/audit';

class User {
  @AuditField()
  email: string = '';
  
  name: string = ''; // Not tracked
}

const user = new User();
const audited = Audit(user);

audited.email = 'john@example.com';
audited.name = 'John Doe';

console.log(audited.changes());
// [{ field: 'email', oldValue: '', newValue: 'john@example.com' }]

2. Class-Level Tracking

import { Audit, Auditable, AuditIgnore } from '@snow-tzu/audit';

@Auditable()
class Product {
  id: number = 0;
  name: string = '';
  
  @AuditIgnore()
  internalCode: string = ''; // Excluded from tracking
}

const product = new Product();
const audited = Audit(product);

audited.id = 123;
audited.name = 'Widget';
audited.internalCode = 'X123';

console.log(audited.changes());
// [
//   { field: 'id', oldValue: 0, newValue: 123 },
//   { field: 'name', oldValue: '', newValue: 'Widget' }
// ]

3. Reset Audit History

const audited = Audit(new User());
audited.email = 'test@example.com';

console.log(audited.changes().length); // 1

audited.resetAudit?.();
console.log(audited.changes().length); // 0

API Reference

Main Function

Audit<T>(target: T): T & AuditHandle

Wraps an object for audit tracking while preserving all original behavior.

Parameters:

  • target - The object to wrap with audit tracking

Returns: A wrapped object that behaves identically to the original while tracking changes

Decorators

@AuditField()

Property decorator that marks individual fields for audit tracking.

class Example {
  @AuditField()
  trackedField: string = '';
}

@Auditable()

Class decorator that marks all fields in a class for audit tracking.

@Auditable()
class Example {
  field1: string = ''; // Tracked
  field2: number = 0;  // Tracked
}

@AuditIgnore()

Property decorator that excludes specific fields from tracking when used with @Auditable().

@Auditable()
class Example {
  tracked: string = '';
  
  @AuditIgnore()
  ignored: string = ''; // Not tracked
}

Interfaces

AuditHandle

interface AuditHandle {
  changes(): ChangeRecord[];
  resetAudit?(): void;
}

ChangeRecord

interface ChangeRecord {
  readonly field: string;
  readonly oldValue: unknown;
  readonly newValue: unknown;
}

Utilities

enableAuditLogging(level?: LogLevel)

Enable debug logging for audit operations.

disableAuditLogging()

Disable audit logging.

LogLevel

enum LogLevel {
  ERROR = 'ERROR',
  WARN = 'WARN',
  DEBUG = 'DEBUG'
}

Examples

πŸ‘‰ NestJS + TypeORM Example - Complete audit tracking with PostgreSQL

Complex Object Tracking

@Auditable()
class Order {
  id: number = 0;
  items: string[] = [];
  
  @AuditIgnore()
  internalNotes: string = '';
  
  calculateTotal(): number {
    return this.items.length * 10;
  }
}

const order = new Order();
const audited = Audit(order);

// Method calls work normally
console.log(audited.calculateTotal()); // 0

// Field changes are tracked
audited.id = 123;
audited.items = ['item1', 'item2'];
audited.internalNotes = 'secret'; // Not tracked

console.log(audited.changes());
console.log(audited.calculateTotal()); // 20
// [
//   { field: 'id', oldValue: 0, newValue: 123 },
//   { field: 'items', oldValue: [], newValue: ['item1', 'item2'] }
// ]

Inheritance Support

@Auditable()
class BaseEntity {
  id: number = 0;
  createdAt: Date = new Date();
}

class User extends BaseEntity {
  @AuditField()
  email: string = '';
  
  name: string = ''; // Tracked via inheritance
}

const user = new User();
const audited = Audit(user);

audited.id = 1;
audited.email = 'user@example.com';
audited.name = 'John';

console.log(audited.changes().length); // 3 changes tracked

Performance

@snow-tzu/audit is designed for production use with minimal overhead:

  • ⚑ Fast proxy creation - Efficient object wrapping
  • πŸš€ Negligible field access overhead - Transparent property access
  • πŸ“Š Efficient change detection - Smart change tracking and collapsing
  • πŸ”‹ Minimal memory footprint - ~0.2KB per tracked object

Benchmarks

The library includes comprehensive benchmarks to measure real-world performance impact:

Latest Results (Node.js v24.5.0, macOS ARM64)

Metric Unwrapped Wrapped Overhead
Assignment Performance 1.34M ops/sec 0.59M ops/sec +56.1%
Memory Usage ~0 KB 0.21 KB +0.21 KB per object

The optimized implementation provides excellent performance with minimal memory overhead.

Why @snow-tzu/audit?

vs. Manual Change Tracking

Feature @snow-tzu/audit Manual Tracking
Setup complexity βœ… Decorator-based ❌ Boilerplate code
Type safety βœ… Full TypeScript ⚠️ Manual typing
Non-intrusive βœ… Transparent proxies ❌ Code modification
Error handling βœ… Built-in resilience ❌ Manual implementation
Performance βœ… Optimized proxies ⚠️ Varies

vs. Object.observe() (Deprecated)

Feature @snow-tzu/audit Object.observe
Browser support βœ… All modern browsers ❌ Deprecated
Selective tracking βœ… Decorator-based ❌ All properties
TypeScript support βœ… Native ❌ No types
Change collapsing βœ… Smart merging ❌ Raw events

Requirements

  • Node.js 16+ or modern browsers
  • TypeScript 4.5+ (for decorator support)
  • experimentalDecorators: true in tsconfig.json

Contributing

We welcome contributions!

License

MIT Β© Ganesan Arunachalam

Complete Examples

Check out the examples directory for fully working projects:

Each example includes:

  • πŸš€ Ready-to-run setup with Docker
  • πŸ“Š Database schema and migrations
  • πŸ”„ Transaction-based audit logging
  • 🎯 Real-world usage patterns
  • πŸ“ API examples and documentation

Support

About

Transparent audit tracking for object field changes in TypeScript applications

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published