Socket
Socket
Sign inDemoInstall

typeorm-auditing

Package Overview
Dependencies
10
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

typeorm-auditing

TypeORM Auditing: Create history tables and manage changes of entity automatically.


Version published
Weekly downloads
895
increased by12.16%
Maintainers
1
Created
Weekly downloads
 

Readme

Source

TypeORM Auditing(Decorator)

  • Create history tables and manage changes of entity automatically

Node.js CI NPM Version License

Install

  • NPM
$ npm install typeorm-auditing --save
  • Yarn
$ yarn add typeorm-auditing

Usage

0. Origin entity (You don't need to change your existing code)

  • This is a general entity definition. You don't need to change your existing code to add auditing feature.
export abstract class MyBase extends BaseEntity {
    @PrimaryGeneratedColumn()
    id: number;
}

@Entity()
// @Entity({ ...yourEntityOption, database: 'my-database', schema: 'my-schema' })
export class User extends MyBase {
    @Column()
    firstName: string;
    @Column()
    lastName: string;
    @Column()
    age: number;

    public get fullName(): string {
        return `${this.firstName} ${this.lastName}`;
    }
}

1. Auditing Entity

  • Define a history entity to store the changes of User entities.
    • In order to easily define columns, extended the User entity.
  • @AuditingEntity(TargetEntity) decorator automatically creates a table with _seq, _action(Create, Update, Delete) and _modifiedAt columns.
import { AuditingAction, AuditingEntity, AuditingEntityDefaultColumns } from 'typeorm-auditing'; 

@AuditingEntity(User)
// @AuditingEntity(User, { ...overrideUserEntitiesEntityOption, database: 'my-database', schema: 'my-schema' })
export class AuditingUser extends User implements AuditingEntityDefaultColumns {
    readonly _seq: number;
    readonly _action: AuditingAction;
    readonly _modifiedAt: Date;

    // Additional columns can be added. That columns must be nullable or a value must be entered via @BeforeInsert.
    // @Column({ nullable: true })
    // additionalColumn!: string;
}

2. Subscribe TypeORM event

  • You only need to configure it once for multiple entities.
  • However, if there are multiple data sources, you need to set them up for each data source.
import { AuditingSubscriber } from 'typeorm-auditing';

const dataSource = new DataSource({
    ...yourDataSourceConfig,
    entities: [User, AuditingUser],
    //entities: ['path-of-your-entities-path'],
    subscribers: [AuditingSubscriber],
})

Contributors


Example

Sample Code

import { DataSource } from 'typeorm';
import { Case1, Case1Audit } from './entity/case1';
import { AuditingSubscriber } from 'typeorm-auditing';

(async function () {
    //Data Source
    const dataSource = await new DataSource({
        type: 'sqlite',
        database: ':memory:',
        synchronize: true,
        logging: 'all',
        entities: [Case1, Case1Audit],
        subscribers: [AuditingSubscriber],
    }).initialize();

    //Create
    const entity = await dataSource.manager.save(
        Case1.create({
            firstName: 'Timber',
            lastName: 'Saw',
            age: 25,
        })
    );

    //Update
    entity.age++;
    await entity.save();

    //Delete
    await entity.remove();

    //!!!! Print history entities
    console.log(await dataSource.manager.find(Case1Audit));
})();

Sample Entity

  • Origin Entity
import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class Case1 extends BaseEntity {
    @PrimaryGeneratedColumn({ type: 'int' })
    id!: number;

    @Column()
    firstName!: string;

    @Column()
    lastName!: string;

    @Column()
    age!: number;
}
  • Audit Entity
import { AuditingAction, AuditingEntity, AuditingEntityDefaultColumns } from 'typeorm-auditing';

@AuditingEntity(Case1)
export class Case1Audit extends Case1 implements AuditingEntityDefaultColumns {
    readonly _seq!: number;
    readonly _action!: AuditingAction;
    readonly _modifiedAt!: Date;
}

Result

$ npx ts-node src/test/auditing-entity.decorator.example.ts 
creating a new table: case1
query: CREATE TABLE "case1" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "firstName" varchar NOT NULL, "lastName" varchar NOT NULL, "age" integer NOT NULL)
query: CREATE TABLE "case1_audit" ("_seq" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "_action" varchar(20) NOT NULL, "_modifiedAt" datetime NOT NULL DEFAULT (datetime('now')), "id" integer, "firstName" varchar, "lastName" varchar, "age" integer)
query: CREATE INDEX "IDX_d2fc2ad0a4f22955513bca9b1d" ON "case1_audit" ("id") 
query: COMMIT

query: BEGIN TRANSACTION
query: INSERT INTO "case1"("id", "firstName", "lastName", "age") VALUES (NULL, ?, ?, 25) -- PARAMETERS: ["Timber","Saw"]
query: INSERT INTO "case1_audit"("_seq", "_action", "_modifiedAt", "id", "firstName", "lastName", "age") VALUES (NULL, ?, datetime('now'), 1, ?, ?, 25) -- PARAMETERS: ["Create","Timber","Saw"]
query: SELECT "Case1Audit"."_seq" AS "Case1Audit__seq", "Case1Audit"."_modifiedAt" AS "Case1Audit__modifiedAt" FROM "case1_audit" "Case1Audit" WHERE "Case1Audit"."_seq" = 1
query: COMMIT
query: SELECT "Case1"."id" AS "Case1_id", "Case1"."firstName" AS "Case1_firstName", "Case1"."lastName" AS "Case1_lastName", "Case1"."age" AS "Case1_age" FROM "case1" "Case1" WHERE "Case1"."id" IN (1)

query: BEGIN TRANSACTION
query: UPDATE "case1" SET "age" = 26 WHERE "id" IN (1)
query: INSERT INTO "case1_audit"("_seq", "_action", "_modifiedAt", "id", "firstName", "lastName", "age") VALUES (NULL, ?, datetime('now'), 1, ?, ?, 26) -- PARAMETERS: ["Update","Timber","Saw"]
query: SELECT "Case1Audit"."_seq" AS "Case1Audit__seq", "Case1Audit"."_modifiedAt" AS "Case1Audit__modifiedAt" FROM "case1_audit" "Case1Audit" WHERE "Case1Audit"."_seq" = 2
query: COMMIT
query: SELECT "Case1"."id" AS "Case1_id", "Case1"."firstName" AS "Case1_firstName", "Case1"."lastName" AS "Case1_lastName", "Case1"."age" AS "Case1_age" FROM "case1" "Case1" WHERE "Case1"."id" IN (1)

query: BEGIN TRANSACTION
query: DELETE FROM "case1" WHERE "id" = 1
query: INSERT INTO "case1_audit"("_seq", "_action", "_modifiedAt", "id", "firstName", "lastName", "age") VALUES (NULL, ?, datetime('now'), 1, ?, ?, 26) -- PARAMETERS: ["Delete","Timber","Saw"]
query: SELECT "Case1Audit"."_seq" AS "Case1Audit__seq", "Case1Audit"."_modifiedAt" AS "Case1Audit__modifiedAt" FROM "case1_audit" "Case1Audit" WHERE "Case1Audit"."_seq" = 3
query: COMMIT

query: SELECT "Case1Audit"."_seq" AS "Case1Audit__seq", "Case1Audit"."_action" AS "Case1Audit__action", "Case1Audit"."_modifiedAt" AS "Case1Audit__modifiedAt", "Case1Audit"."id" AS "Case1Audit_id", "Case1Audit"."firstName" AS "Case1Audit_firstName", "Case1Audit"."lastName" AS "Case1Audit_lastName", "Case1Audit"."age" AS "Case1Audit_age" FROM "case1_audit" "Case1Audit"
[
  Case1Audit {
    _seq: 1,
    _action: 'Create',
    _modifiedAt: 2022-07-21T19:18:42.000Z,
    id: 1,
    firstName: 'Timber',
    lastName: 'Saw',
    age: 25
  },
  Case1Audit {
    _seq: 2,
    _action: 'Update',
    _modifiedAt: 2022-07-21T19:18:42.000Z,
    id: 1,
    firstName: 'Timber',
    lastName: 'Saw',
    age: 26
  },
  Case1Audit {
    _seq: 3,
    _action: 'Delete',
    _modifiedAt: 2022-07-21T19:18:42.000Z,
    id: 1,
    firstName: 'Timber',
    lastName: 'Saw',
    age: 26
  }
]

Keywords

FAQs

Last updated on 01 Dec 2022

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc