import { Aggregate , PersistedSnapshot , Apply } from '@centsideas/event-sourcing' ; import { PersistedEvent } from '@centsideas/models' ; import { UserId , Email , Timestamp } from '@centsideas/types' ; import * as Errors from './user.errors' ; import { PrivateUserCreated } from './private-user-created' ; import { EmailChangeRequested } from './email-change-requested' ; import { EmailChangeConfirmed } from './email-change-confirmed' ; import { PrivateUserDeleted } from './private-user-deleted' ; export interface SerializedPrivateUser { id : string ; email : string | undefined ; pendingEmail : string | undefined ; deletedAt : string | undefined ; } export class PrivateUser extends Aggregate < SerializedPrivateUser > { protected id ! : UserId ; email ! : Email | undefined ; pendingEmail : Email | undefined ; deletedAt : Timestamp | undefined ; static buildFrom ( events , snapshot ? ) { const privateUser = new PrivateUser ( ) ; if ( snapshot ) privateUser . applySnapshot ( snapshot , events ) ; else privateUser . replay ( events ) ; return privateUser ; } protected deserialize ( data ) { this . id = UserId . fromString ( data . id ) ; this . email = data . email ? Email . fromString ( data . email ) : undefined ; this . pendingEmail = data . pendingEmail ? Email . fromString ( data . pendingEmail ) : undefined ; } protected serialize ( ) { return { id : this . id . toString ( ) , email : this . email ?. toString ( ) , pendingEmail : this . pendingEmail ?. toString ( ) , deletedAt : this . deletedAt ? this . deletedAt . toString ( ) : undefined , } ; } static create ( id , email ) { const privateUser = new PrivateUser ( ) ; privateUser . raise ( new PrivateUserCreated ( id , email ) ) ; return privateUser ; } requestEmailChange ( userId , newEmail ) { this . checkGeneralConditions ( userId ) ; this . raise ( new EmailChangeRequested ( newEmail ) ) ; } confirmEmailChange ( userId ) { this . checkGeneralConditions ( userId ) ; this . raise ( new EmailChangeConfirmed ( ) ) ; } delete ( userId , deletedAt ) { this . checkGeneralConditions ( userId ) ; this . raise ( new PrivateUserDeleted ( deletedAt ) ) ; } private checkGeneralConditions ( userId ) { if ( this . deletedAt ) throw new Errors . UserAlreadyDeleted ( this . id , userId ) ; if ( ! this . id . equals ( userId ) ) throw new Errors . NoPermissionToAccessUser ( this . id , userId ) ; } @ Apply ( PrivateUserCreated ) protected created ( event ) { this . id = event . id ; this . email = event . email ; } @ Apply ( EmailChangeRequested ) protected emailChangeRequested ( event ) { this . pendingEmail = event . newEmail ; } @ Apply ( EmailChangeConfirmed ) protected emailChangeConfirmed ( ) { this . email = this . pendingEmail ! ; this . pendingEmail = undefined ; } @ Apply ( PrivateUserDeleted ) protected deleted ( event ) { this . email = undefined ; this . pendingEmail = undefined ; this . deletedAt = event . deletedAt ; } }