Created
July 5, 2021 04:15
-
-
Save theo-bittencourt/a674dd9f042e7294a08a98d7401fd3bc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* from: | |
* "Decoupling Logic with Domain Events [Guide] - Domain-Driven Design w/ TypeScript" | |
* https://khalilstemmler.com/articles/typescript-domain-driven-design/chain-business-logic-domain-events/ | |
*/ | |
import { UseCase } from '../../../../core/domain/UseCase'; | |
import { CreateUserDTO } from './CreateUserDTO'; | |
import { Either, Result, left, right } from '../../../../core/logic/Result'; | |
import { UserEmail } from '../../domain/userEmail'; | |
import { UserPassword } from '../../domain/userPassword'; | |
import { User } from '../../domain/user'; | |
import { IUserRepo } from '../../repos/userRepo'; | |
import { CreateUserErrors } from './CreateUserErrors'; | |
import { GenericAppError } from '../../../../core/logic/AppError'; | |
type Response = Either< | |
| GenericAppError.UnexpectedError | |
| CreateUserErrors.AccountAlreadyExists | |
| Result<any>, | |
Result<void> | |
>; | |
export class CreateUserUseCase | |
implements UseCase<CreateUserDTO, Promise<Response>> | |
{ | |
private userRepo: IUserRepo; | |
constructor(userRepo: IUserRepo) { | |
this.userRepo = userRepo; | |
} | |
async execute(req: CreateUserDTO): Promise<Response> { | |
const { firstName, lastName } = req; | |
const emailOrError = UserEmail.create(req.email); | |
const passwordOrError = UserPassword.create({ value: req.password }); | |
const combinedPropsResult = Result.combine([emailOrError, passwordOrError]); | |
if (combinedPropsResult.isFailure) { | |
return left(Result.fail<void>(combinedPropsResult.error)) as Response; | |
} | |
// Domain event gets created internally, here! | |
const userOrError = User.create({ | |
email: emailOrError.getValue(), | |
password: passwordOrError.getValue(), | |
firstName, | |
lastName, | |
isEmailVerified: false, | |
}); | |
if (userOrError.isFailure) { | |
return left(Result.fail<void>(combinedPropsResult.error)) as Response; | |
} | |
const user: User = userOrError.getValue(); | |
const userAlreadyExists = await this.userRepo.exists(user.email); | |
if (userAlreadyExists) { | |
return left( | |
new CreateUserErrors.AccountAlreadyExists(user.email.value) | |
) as Response; | |
} | |
try { | |
// If this transaction succeeds, we the afterCreate or afterUpdate hooks | |
// get called. | |
await this.userRepo.save(user); | |
} catch (err) { | |
return left(new GenericAppError.UnexpectedError(err)) as Response; | |
} | |
return right(Result.ok<void>()) as Response; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment