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
Either
is either an instance ofLeft
orRight
.A common use of
Either
is as an alternative toOptional
for dealing with possible missing values. In this usage,Optional.empty
is replaced with aLeft
, which can contain useful information.Right
takes the place ofOptional.map
. Convention dictates thatLeft
is used for failure andRight
is used for success.For example,
Either<Error, number>
could be used to detect whether a received input has the expectednumber
type. If it doesn't, anError
is 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) }