How to define an array in Mikro-ORM abstract base entity?

70 views Asked by At

I am trying have an array with domain events in my Mikro-ORM abstract entity, but after retrieving the entity from persistence (repository) it is undefined. Is there a way to make it initialized after retrieving the entity from repository?

This is the base entity

@Entity({ abstract: true })
@SoftDeletable(() => AggregateRoot, 'deletedAt', () => new Date())
export default class AggregateRoot<T extends object, P extends keyof T> extends BaseEntity<T, P> {
    private _domainEvents: Event[] = []

    constructor() {
        super()
        this.id = new UniqueEntityId().toString()
    }

    @PrimaryKey({ autoincrement: false, unique: true, type: 'varchar', length: 8, nullable: false })
    id!: string

    @Property({ fieldName: 'created_at' })
    createdAt: Date = new Date()

    @Property({ onUpdate: () => new Date(), fieldName: 'updated_at' })
    updatedAt: Date = new Date()

    @Property({ nullable: true, fieldName: 'deleted_at', type: 'datetime' })
    @Index()
    deletedAt?: Date

    get domainEvents(): Event[] {
        return this._domainEvents
    }

    protected registerEvent(domainEvent: Event): void {
        this._domainEvents.push(domainEvent) // THIS PUSH RESULTS UNDEFINED

        const thisClass = Reflect.getPrototypeOf(this)
        const domainEventClass = Reflect.getPrototypeOf(domainEvent)

        console.info('Domain Event Created:', thisClass.constructor.name, '==>', domainEventClass.constructor.name)
    }

    public clearEvents(): void {
        this._domainEvents.splice(0, this._domainEvents.length)
    }
}

and this is the entity and method in question

@Entity({
  tableName: "treatment",
  repository: () => TreatmentRepository,
})
export default class Treatment extends AggregateRoot<Treatment, "id"> {
  [EntityRepositoryType]?: TreatmentRepository;

  public endTreatment(
    treatmentEndReason: AvailableTreatmentEndReason,
    date?: Date
  ): void {
    if (!this.hasEnded()) {
      this.status = AvailableTreatmentStatuses.ENDED;
      this.endDate = date || new Date();
      this.reasonEnded = treatmentEndReason;

      this.registerEvent(
        new TreatmentEnded({
          treatmentId: this.id,
          dateEnded: this.endDate,
          endReason: treatmentEndReason,
        })
      );
    }
  }
}

Is this even possible?

1

There are 1 answers

0
Martin Adámek On

Contructors (as well as property initializers, that's technically the same) are never executed for managed entities. You have several options:

  1. use onLoad event
  2. forceConstructor option
  3. have a getter which ensures the property exists

https://mikro-orm.io/docs/entity-constructors