import { AggregageRoot } from 'rimo'
// Create an aggregate root
class User extends AggregateRoot<{ email: string }> {
get email() {
return this.props.email
}
}
// Define inputs and/or outputs
class CreateUserInput {
@IsNotEmpty()
@IsEmail()
email!: string
static populate = (data: any) => {
return Object.assign(new CreateUserInput(), data)
}
}
// Create a use case
import { CommandHandler, Use } from 'rimo'
class CreateUserCommand implements CommandHandler<CreateUserInput, User> {
@Use(ValidateCommand)
async handle(input: CreateUserInput): Promise<User> {
const user: User = new User(input)
// persist user, do other stuff
return user
}
}
// Keep your use cases clean with the help of middlewares
// to do things like validation
import { Middleware } from 'rimo'
class ValidateCommand implements Middleware<CreateUserInput> {
async use(event: CreateUserInput) {
const errors = await validate(event)
if (errors.length > 0) {
throw new Error('validation error')
}
}
}
// Use the stupid simple, yet powerful, pub/sub mechanism that Rimo
// provides to keep your application components nicely decoupled!
import { AfterCommand, CommandRunner } from 'rimo'
class CreateUserSubscriber {
@AfterCommand(CreateUserCommand)
async afterCreateUser(user: User, runner: CommandRunner) {
// SendWelcomeEmail is another use case
await runner.run(SendWelcomeEmail, user)
}
}
Thanks goes to these wonderful people (emoji key):
Thiago Zanivan 💻 🔧 |
This project follows the all-contributors specification. Contributions of any kind are welcome!
An interface for mappers functions that converts a source type S to target type T.
the source type
the target type
Constructs a new Either holding a Left value. This usually represents a failure.
Constructs a new Either holding a Right value. This usually represents a successful value.
Generated using TypeDoc
Represents a value of one of two possible types (a disjoint union).
An instance of
Eitheris either an instance ofLeftorRight.A common use of
Eitheris as an alternative toOptionalfor dealing with possible missing values. In this usage,Optional.emptyis replaced with aLeft, which can contain useful information.Righttakes the place ofOptional.map. Convention dictates thatLeftis used for failure andRightis used for success.For example,
Either<Error, number>could be used to detect whether a received input has the expectednumbertype. If it doesn't, anErroris returned.import { Either, left, right } from 'rimo' const parse = (input: string): Either<Error, number> => { const n = parseInt(input, 10) return isNaN(n) ? left(new Error('not a number')) : right(n) }