Hoppity 🚨
A middleware pipeline for Rascal broker configuration that enables modular, composable broker setup.
Features
- Middleware Pipeline: Chain multiple middleware functions to build complex broker configurations
- Context Sharing: Share state between middleware via context objects
- Type Safety: Full TypeScript support with generic broker extensions
- Post-Creation Callbacks: Execute setup code after broker creation
- Error Handling: Enhanced error messages with pipeline context
- Debugging: Internal execution logging and introspection capabilities
- Logging: Built-in logger interface with console implementation
Installation
npm install @apogeelabs/hoppity
Basic Usage
import hoppity from "@apogeelabs/hoppity";
import { BrokerConfig } from "rascal";
const baseTopology: BrokerConfig = {
vhosts: {
"/": {
connection: {
url: "amqp://localhost",
},
},
},
};
const broker = await hoppity
.withTopology(baseTopology)
.use(myMiddleware1)
.use(myMiddleware2)
.build();
Middleware Context
The middleware pattern supports context sharing between middleware functions. Each middleware receives a context object that can be used to share data with downstream middleware.
Context Interface
interface MiddlewareContext {
data: Record<string, any>;
middlewareNames: string[];
logger: Logger;
}
Example: Context Usage
import { MiddlewareFunction, MiddlewareContext } from "@apogeelabs/hoppity";
const exchangeSetupMiddleware: MiddlewareFunction = (topology, context) => {
context.logger.info("Setting up exchanges...");
const modifiedTopology = { ...topology };
context.data.exchangeNames = ["user-events", "order-events"];
context.data.serviceName = "user-service";
context.logger.debug("Exchanges configured", { exchangeNames: context.data.exchangeNames });
return { topology: modifiedTopology };
};
const queueSetupMiddleware: MiddlewareFunction = (topology, context) => {
const exchangeNames = context.data.exchangeNames || [];
const serviceName = context.data.serviceName;
context.logger.info("Setting up queues for service", { serviceName, exchangeNames });
if (!context.middlewareNames.includes("exchangeSetupMiddleware")) {
throw new Error("exchangeSetupMiddleware must run before queueSetupMiddleware");
}
const modifiedTopology = { ...topology };
return { topology: modifiedTopology };
};
API Reference
Main Interface
hoppity.withTopology(topology)
- Start with an existing topology
hoppity.use(middleware)
- Start with empty topology and add middleware
Builder Interface
builder.use(middleware)
- Add middleware to the pipeline
builder.build()
- Create the broker and execute the pipeline
Types
MiddlewareFunction
- Function signature for middleware
MiddlewareContext
- Context object for sharing state
MiddlewareResult
- Return type for middleware functions
BrokerCreatedCallback
- Callback for post-creation setup
BrokerWithExtensions<T>
- Utility type for combining broker extensions
Logger
- Logger interface for middleware logging
BuilderInterface
- Interface for the builder pattern
Logger
ConsoleLogger
- Console-based logger implementation
defaultLogger
- Default logger instance
Examples
See the examples/
directory for complete working examples demonstrating:
- Basic middleware usage
- Context sharing between middleware
- Service-to-service messaging
- Logging and monitoring plugins
For RPC communication patterns, see the separate @apogeelabs/hoppity-rpc
package.
Dependencies
This package depends on:
rascal
- The underlying RabbitMQ library
lodash
- For deep cloning and utility functions
License
ISC