4.9 KiB
4.9 KiB
@lilith/typeorm-entities
Base entity classes for TypeORM with common patterns.
Features
- BaseEntity: UUID primary key with timestamps
- SoftDeletableEntity: Soft delete support
- AuditableEntity: User tracking (createdBy/updatedBy)
- SQLiteBaseEntity: SQLite-compatible base entity
- TypeScript First: Full type safety
Installation
pnpm add @lilith/typeorm-entities
Peer Dependencies
pnpm add typeorm
Quick Start
import { Entity, Column } from 'typeorm';
import { BaseEntity } from '@lilith/typeorm-entities';
@Entity('users')
export class User extends BaseEntity {
@Column()
email: string;
@Column()
name: string;
}
// Creates table with columns: id, email, name, created_at, updated_at
Entity Classes
BaseEntity
Standard base entity with UUID and timestamps:
import { Entity, Column } from 'typeorm';
import { BaseEntity } from '@lilith/typeorm-entities';
@Entity('posts')
export class Post extends BaseEntity {
@Column()
title: string;
@Column('text')
content: string;
}
Included columns:
id- UUID v4 primary key (auto-generated)createdAt- Timestamp when created (created_at)updatedAt- Timestamp when updated (updated_at)
SoftDeletableEntity
Extends BaseEntity with soft delete support:
import { Entity, Column } from 'typeorm';
import { SoftDeletableEntity } from '@lilith/typeorm-entities';
@Entity('comments')
export class Comment extends SoftDeletableEntity {
@Column('text')
body: string;
@Column()
authorId: string;
}
// Soft delete (sets deletedAt, doesn't remove row)
await repository.softRemove(comment);
// Query excludes soft-deleted by default
const comments = await repository.find();
// Include soft-deleted
const allComments = await repository.find({ withDeleted: true });
// Restore soft-deleted
await repository.restore(commentId);
Additional columns:
deletedAt- Timestamp when soft-deleted (deleted_at)
AuditableEntity
Extends BaseEntity with user tracking:
import { Entity, Column } from 'typeorm';
import { AuditableEntity } from '@lilith/typeorm-entities';
@Entity('documents')
export class Document extends AuditableEntity {
@Column()
title: string;
@Column('text')
content: string;
}
// Usage with current user
const document = repository.create({
title: 'My Document',
content: '...',
createdBy: currentUser.id,
updatedBy: currentUser.id,
});
await repository.save(document);
// Update with user tracking
document.content = 'Updated content';
document.updatedBy = currentUser.id;
await repository.save(document);
Additional columns:
createdBy- User who created (created_by, nullable)updatedBy- User who last updated (updated_by, nullable)
SQLiteBaseEntity
Base entity with SQLite-compatible column types:
import { Entity, Column } from 'typeorm';
import { SQLiteBaseEntity } from '@lilith/typeorm-entities';
@Entity('tasks')
export class Task extends SQLiteBaseEntity {
@Column()
title: string;
@Column({ default: false })
completed: boolean;
}
Uses SQLite-compatible types instead of PostgreSQL-specific types.
Column Mappings
| Property | Column Name | Type (PostgreSQL) |
|---|---|---|
id |
id |
uuid |
createdAt |
created_at |
timestamptz |
updatedAt |
updated_at |
timestamptz |
deletedAt |
deleted_at |
timestamptz |
createdBy |
created_by |
varchar(255) |
updatedBy |
updated_by |
varchar(255) |
Best Practices
Combining Entity Types
// For entities that need both audit trail and soft delete,
// extend AuditableEntity and add deletedAt manually:
import { Entity, Column, DeleteDateColumn } from 'typeorm';
import { AuditableEntity } from '@lilith/typeorm-entities';
@Entity('records')
export class Record extends AuditableEntity {
@Column()
name: string;
@DeleteDateColumn({ name: 'deleted_at' })
deletedAt?: Date;
}
Using with NestJS
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Document } from './document.entity';
@Injectable()
export class DocumentService {
constructor(
@InjectRepository(Document)
private readonly repository: Repository<Document>,
) {}
async create(dto: CreateDocumentDto, userId: string): Promise<Document> {
const document = this.repository.create({
...dto,
createdBy: userId,
updatedBy: userId,
});
return this.repository.save(document);
}
async update(id: string, dto: UpdateDocumentDto, userId: string): Promise<Document> {
const document = await this.repository.findOneByOrFail({ id });
Object.assign(document, dto, { updatedBy: userId });
return this.repository.save(document);
}
}
License
MIT