mirror of
https://github.com/samiyev/puaros.git
synced 2025-12-27 23:06:54 +05:00
feat(core): add domain layer with clean architecture
Add domain layer components: - BaseEntity with ID, timestamps and equality checks - ValueObject for immutable value objects - IRepository interface for persistence - DomainEvent system for domain events
This commit is contained in:
44
packages/core/src/domain/entities/BaseEntity.ts
Normal file
44
packages/core/src/domain/entities/BaseEntity.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base entity class with ID and timestamps
|
||||||
|
*/
|
||||||
|
export abstract class BaseEntity {
|
||||||
|
protected readonly _id: string;
|
||||||
|
protected readonly _createdAt: Date;
|
||||||
|
protected _updatedAt: Date;
|
||||||
|
|
||||||
|
constructor(id?: string) {
|
||||||
|
this._id = id ?? uuidv4();
|
||||||
|
this._createdAt = new Date();
|
||||||
|
this._updatedAt = new Date();
|
||||||
|
}
|
||||||
|
|
||||||
|
public get id(): string {
|
||||||
|
return this._id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get createdAt(): Date {
|
||||||
|
return this._createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get updatedAt(): Date {
|
||||||
|
return this._updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected touch(): void {
|
||||||
|
this._updatedAt = new Date();
|
||||||
|
}
|
||||||
|
|
||||||
|
public equals(entity: BaseEntity): boolean {
|
||||||
|
if (entity === null || entity === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this === entity) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._id === entity._id;
|
||||||
|
}
|
||||||
|
}
|
||||||
25
packages/core/src/domain/events/DomainEvent.ts
Normal file
25
packages/core/src/domain/events/DomainEvent.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base interface for all domain events
|
||||||
|
*/
|
||||||
|
export interface IDomainEvent {
|
||||||
|
readonly eventId: string;
|
||||||
|
readonly occurredOn: Date;
|
||||||
|
readonly eventType: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for domain events
|
||||||
|
*/
|
||||||
|
export abstract class DomainEvent implements IDomainEvent {
|
||||||
|
public readonly eventId: string;
|
||||||
|
public readonly occurredOn: Date;
|
||||||
|
public readonly eventType: string;
|
||||||
|
|
||||||
|
constructor(eventType: string) {
|
||||||
|
this.eventId = uuidv4();
|
||||||
|
this.occurredOn = new Date();
|
||||||
|
this.eventType = eventType;
|
||||||
|
}
|
||||||
|
}
|
||||||
4
packages/core/src/domain/index.ts
Normal file
4
packages/core/src/domain/index.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export * from './entities/BaseEntity';
|
||||||
|
export * from './value-objects/ValueObject';
|
||||||
|
export * from './repositories/IRepository';
|
||||||
|
export * from './events/DomainEvent';
|
||||||
14
packages/core/src/domain/repositories/IRepository.ts
Normal file
14
packages/core/src/domain/repositories/IRepository.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { BaseEntity } from '../entities/BaseEntity';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic repository interface
|
||||||
|
* Defines standard CRUD operations for entities
|
||||||
|
*/
|
||||||
|
export interface IRepository<T extends BaseEntity> {
|
||||||
|
findById(id: string): Promise<T | null>;
|
||||||
|
findAll(): Promise<T[]>;
|
||||||
|
save(entity: T): Promise<T>;
|
||||||
|
update(entity: T): Promise<T>;
|
||||||
|
delete(id: string): Promise<boolean>;
|
||||||
|
exists(id: string): Promise<boolean>;
|
||||||
|
}
|
||||||
23
packages/core/src/domain/value-objects/ValueObject.ts
Normal file
23
packages/core/src/domain/value-objects/ValueObject.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* Base class for Value Objects
|
||||||
|
* Value objects are immutable and compared by value, not identity
|
||||||
|
*/
|
||||||
|
export abstract class ValueObject<T> {
|
||||||
|
protected readonly props: T;
|
||||||
|
|
||||||
|
constructor(props: T) {
|
||||||
|
this.props = Object.freeze(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
public equals(vo?: ValueObject<T>): boolean {
|
||||||
|
if (vo === null || vo === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vo.props === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSON.stringify(this.props) === JSON.stringify(vo.props);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user