The application layer of Xeno coordinates business workflows, maps user intents
to domain entities, and enforces transactional execution boundaries. This
orchestration is anchored by the BaseHandler abstract primitive, which
standardizes message processing across commands and queries while decoupling
core domain logic from transport protocols.
Understanding the Core Role of the BaseHandler Primitive
The Xeno BaseHandler is an abstract application-layer primitive that serves as
the execution anchor for commands and queries. It encapsulates identity context
factories, facilitates runtime state evaluation, and manages asynchronous
cancellation flows natively, isolating domain logic from the underlying delivery
or infrastructure frameworks.
Operating as the processing engine behind the framework’s internal mediator bus,
BaseHandler acts as a secure boundary. It prevents the exposure of
presentation-layer parameters to your internal domain model. Every handler
execution thread runs within an isolated request boundary, utilizing an injected
user context factory to read active security tokens and multi-tenant parameters
without compromising architecture portability.
Key-Value Specification of BaseHandler Dependencies
Extending the BaseHandler requires implementing an asynchronous execution
contract bounded by strong TypeScript generic parameters. Subclasses define a
standardized handling path, receiving message packets and abort signals to
execute decoupled business rules while returning deterministic functional result
monads.
When creating custom command or query handlers, developers pass two explicit
generic parameters to the base class: TRequest (the incoming message contract
type matching ICommand or IQuery) and TResponse (the successful data model
typing returned upon execution).
The BaseHandler coordinates runtime state safety by monitoring explicit
cancellation paths and user context parameters during asynchronous execution. By
accessing localized storage variables and evaluating abort triggers early, the
processor short-circuits execution paths to prevent resource leakage or orphaned
database transactions.
To assure reliability within high-throughput concurrent systems, handlers track
execution status parameters through two cross-cutting mechanisms:
Every handler method signature receives an explicit AbortSignal propagated
down from the transport layer edge (e.g., a client disconnecting their browser
midway through a transaction). Handlers use the standard helper method
AppError.throwIfAborted(signal, context) before starting heavy input/output
procedures. This ensures that resource-intensive operations stop processing
immediately if the client disconnects, preserving database pools and thread
loops.
By querying the internal identity helper methods, a handler can read security
parameters without requiring properties to be hardcoded into incoming payload
objects:
userId — A unique Guid string identifying the authenticated actor
executing the transaction.
tenantId — A unique Guid isolating data visibility blocks within
multi-tenant keyspaces.
roles / permissions — Explicit validation arrays evaluated by
authorization strategies prior to handler invocation.
Registering Application Handlers within the AppBuilder Host Container
Registering handlers into the application host relies on explicit scoped factory
mapping chains declared inside the AppBuilder setup cycle. Binding specific
message tokens to handler implementations ensures that the mediator bus can
resolve and execute appropriate domain logic within type-safe pipeline contexts.
To support context isolation, handlers are typically registered with a Scoped
Lifetime. This guarantees that all repositories and units of work resolved
within that specific handling loop share the same database transaction state and
request context metadata.
The architectural diagram below traces an incoming application request as it
transitions through the presentation layer, passes into the mediator’s execution
pipelines, and activates the corresponding BaseHandler.
This pattern connects the delivery layer directly to the handler’s entry point
via the mediator bus, allowing you to pass the transaction down the pipeline
stack safely:
src/presentation/controllers/user.controller.ts
import { BaseController, type ResponseDto, STATUS_CODES } from'@xeno-js/core'
Every Command or Query handler within Xeno must be explicitly registered
inside your custom AppRegistry using a literal string key that matches
exactly the intent property declared on the corresponding message.
To maximize architectural clarity, maintainability, and traceability, it is an
enforced best practice that the Message Intent is identical to the Token
Name inside the registry. This guarantees that your business intentions are
tightly and predictably coupled to their specialized execution handlers,
completely avoiding loose string mismatches during the bootstrap
initialization.
Xeno is an MIT-licensed open source project. It can grow thanks to the support
of these awesome people. If you’d like to join them, please read more at
support section