typeorm-auditable
v1.0.4
Published
Auditing for TypeORM
Maintainers
Readme
typeorm-auditable
An audit helper for TypeORM that records audit events any time you create, update, or remove an entity. It wraps a standard TypeORM repository so every persistence operation also writes a companion event row with the change payload and the actor who performed it.
What it gives you
- Drop-in
AuditableRepositorythat mirrorssaveandremovewith audit logging AuditableEntitybase class for event rows (id, aggregate id, type, actor UUID, payload, timestamp)CreateAuditableTablemigration helper to create the audit/event table schema
Install
npm install typeorm-auditable
# or
yarn add typeorm-auditableQuick start
- Create an event entity extending
AuditableEntityand point it at your audit table name.
// src/entities/UserEvent.ts
import { Entity } from 'typeorm';
import { AuditableEntity } from 'typeorm-auditable';
@Entity('user_events')
export class UserEvent extends AuditableEntity {}- Create the audit table using the migration helper.
// migrations/1680000000000-CreateUserEventsTable.ts
import { CreateAuditableTable } from 'typeorm-auditable';
export class CreateUserEventsTable1680000000000 extends CreateAuditableTable {
tableName = 'user_events';
}- Wrap your repository with
AuditableRepository.
// src/repositories/userRepository.ts
import { DataSource } from 'typeorm';
import { AuditableRepository } from 'typeorm-auditable';
import { User } from '../entities/User';
import { UserEvent } from '../entities/UserEvent';
export const userRepository = (dataSource: DataSource) => {
const repository = dataSource.getRepository(User);
return new AuditableRepository(User, UserEvent, { repository });
};
// Or mix the auditable methods into an existing repo instance
export const userRepositoryWithExtend = (dataSource: DataSource) => {
const repository = dataSource.getRepository(User);
const auditableRepository = new AuditableRepository(User, UserEvent, { repository });
return repository.extend(auditableRepository);
};- Save or remove through the wrapper and include the
actor_uuid.
const repo = userRepository(AppDataSource);
// create
await repo.save(new User({ given_name: 'Ada' }), { actor_uuid: userUuid });
// update
const user = await repo.save(existingUser, { actor_uuid: userUuid });
user.status = 'disabled';
await repo.save(user, { actor_uuid: userUuid });
// remove
await repo.remove(user, { actor_uuid: userUuid });Each save writes the entity and then appends an event row with a JSON payload of changed fields (before/after). remove appends a removed event then deletes the record.
API
AuditableRepository
Constructor: (entityTarget, eventTarget, { repository })
save(entity | entity[], { actor_uuid })— persists and logscreatedorupdatedwith a diff payloadremove(entity | entity[], { actor_uuid })— logsremovedthen deletes
Notes:
- Arrays are handled in parallel with
Promise.all. - Changes for JSON-like columns are compared via
JSON.stringifyto catch deep equality.
AuditableEntity
Fields: id, aggregate_id, type ('created' | 'updated' | 'removed'), actor_uuid, payload, timestamp.
CreateAuditableTable
- Extend, set
tableName, and add to your migrations. Creates the audit table with the same columns asAuditableEntity.
Development
- Run tests:
npm test - Lint:
npm run lint
