Inversion
The definition of the Inversion module is part of the NPM package @tmorin/ceb-messaging-inversion.
Command and Query handlers as well as Event listeners can be discovered and managed by Inversion on the container initialization.
The module MessagingModule
takes care of the discovery, registration and also disposition of handlers and listeners at the container end of life.
Discoverable Command handlers must match the DiscoverableCommandHandler
interface.
import {
Command,
Event,
MessageBuilder,
Result,
} from "@tmorin/ceb-messaging-core"
import { DiscoverableCommandHandler } from "@tmorin/ceb-messaging-inversion"
// create the handler using the "implementation" way
export class GreetSomebodyHandler
implements
DiscoverableCommandHandler<
Command<string>,
Result<string>,
Array<Event<string>>
>
{
// the type of the Command to handle
type = "GreetSomebody"
// the handler
handler(command: Command<string>) {
// create the greeting text
const result = MessageBuilder.result(command)
.body(`Hello, ${command.body}!`)
.build()
// create the event
const events = [
MessageBuilder.event("SomeoneHasBeenGreeted").body(command.body).build(),
]
// return the output
return { result, events }
}
}
Discoverable Query handlers must match the DiscoverableQueryHandler
interface.
import { MessageBuilder, Query, Result } from "@tmorin/ceb-messaging-core"
import { DiscoverableQueryHandler } from "@tmorin/ceb-messaging-inversion"
// create the handler using the "implementation" way
export class WhatTimeIsItHandler
implements DiscoverableQueryHandler<Query<void>, Result<string>>
{
// the type of the Query to handle
type = "WhatTimeIsIt"
// the handler
handler(query: Query<void>) {
return MessageBuilder.result(query).body(new Date().toISOString()).build()
}
}
Discoverable Event listeners must match the DiscoverableEventListener
interface.
import { Event } from "@tmorin/ceb-messaging-core"
import { DiscoverableEventListener } from "@tmorin/ceb-messaging-inversion"
// create the listener using the "object" way
export const SOMEONE_HAS_BEEN_GREETED_LISTENER: DiscoverableEventListener<
Event<string>
> = {
// the type of the Event to handle
type: "SomeoneHasBeenGreeted",
// the handler
listener: (event: Event<string>) => {
console.info(`${event.body} has been greeted`)
},
}
To be discoverable the handlers and listeners must be registered in the Container's Registry with the right Registry Key.
DiscoverableCommandHandlerSymbol
for the Command handlersDiscoverableQueryHandlerSymbol
for the Query handlersDiscoverableEventListenerSymbol
for the Event listeners
import { AbstractModule } from "@tmorin/ceb-inversion-core"
import { GreetSomebodyHandler } from "./inversion-discovery-command"
import { WhatTimeIsItHandler } from "./inversion-discovery-query"
import { SOMEONE_HAS_BEEN_GREETED_LISTENER } from "./inversion-discovery-event"
import {
DiscoverableCommandHandlerSymbol,
DiscoverableEventListenerSymbol,
DiscoverableQueryHandlerSymbol,
} from "@tmorin/ceb-messaging-inversion"
// define a "regular" Module
export class DiscoverableStuffModule extends AbstractModule {
async configure() {
// register the command handler
this.registry.registerValue(
DiscoverableCommandHandlerSymbol,
new GreetSomebodyHandler()
)
// register the query handler
this.registry.registerFactory(
DiscoverableQueryHandlerSymbol,
() => new WhatTimeIsItHandler()
)
// register the event listener
this.registry.registerValue(
DiscoverableEventListenerSymbol,
SOMEONE_HAS_BEEN_GREETED_LISTENER
)
}
}
Finally, the module MessagingModule
and those registering discoverable handlers and listeners must be registered as other modules.
import { ContainerBuilder } from "@tmorin/ceb-inversion-core"
import {
Gateway,
GatewaySymbol,
MessageBuilder,
} from "@tmorin/ceb-messaging-core"
import { DiscoverableStuffModule } from "./inversion-discovery-module"
import { MessagingModule } from "@tmorin/ceb-messaging-inversion"
import { SimpleModule } from "@tmorin/ceb-messaging-simple-inversion"
ContainerBuilder.get()
// register the module which discovers the handlers and listeners
.module(new MessagingModule())
// register the module which provide a Gateway instance
.module(new SimpleModule())
// register the module which contain the discoverable handlers and listeners
.module(new DiscoverableStuffModule())
.build()
.initialize()
.then(async (container) => {
// resolve the gateway
const gateway = container.registry.resolve<Gateway>(GatewaySymbol)
// register an event listener
gateway.events.subscribe("SomeoneHasBeenGreeted", (event) => {
console.info(`${event.body} has been greeted`)
})
// create and execute the GreetSomebody command
const greetSomebody = MessageBuilder.command("GreetSomebody")
.body("World")
.build()
const cmdResult = await gateway.commands.execute(greetSomebody)
console.info(`the greeting text: ${cmdResult.body}`)
// create and execute the WhatTimeIsIt query
const whatTimeIsIt = MessageBuilder.query("WhatTimeIsIt")
.body("World")
.build()
const qryResult = await gateway.queries.execute(whatTimeIsIt)
console.info(`the time: ${qryResult.body}`)
return container.dispose()
})
.catch((e) => console.error(e))