The Problem
Building a reliable, message‑driven microservice in Node often requires wiring a service‑bus, defining messages, handlers and workflows, and handling boiler‑plate for transports and persistence. Without a ready scaffold, teams spend time on repetitive setup rather than business logic.
What This Does
The bus‑starter repo supplies a minimal, runnable example of a @node‑ts/bus application. Core code lives under src/:
src/bus.tscreates and disposes the bus (initializeBus,disposeBus, exportedbus).- Message definitions are in
src/messages/(e.g.,siren-test-started.ts,email-maintenance-team.ts). - Handlers live in
src/handlers/and invoke the bus (start-siren-test-handler.ts,email-maintenance-team-handler.ts). - A simple workflow coordinating a siren‑test scenario is in
src/workflows/siren-test-workflow.ts.
The project is TypeScript‑first, built with npm, and includes a CircleCI pipeline (.circleci/config.yml). Tests (test/) exercise the bus and handlers.
How It Is Wired
Execution starts at src/index.ts → function runDemo (line 7). runDemo:
- Calls
initializeBusfromsrc/bus.ts(creates the bus instance). - Publishes a
StartSirenTestmessage viabus.publish. - Calls
generateUuidfromsrc/messages/uuid.tsto tag the demo run.
From there the internal call graph proceeds:
startSirenTestHandler(insrc/handlers/start-siren-test-handler.ts) receives the start message and publishesSirenTestStarted.- The workflow (
src/workflows/siren-test-workflow.ts) subscribes toSirenTestStartedand, on failure, publishesSirenTestFailed. emailMaintenanceTeamHandler(insrc/handlers/email-maintenance-team-handler.ts) reacts toSirenTestFailedand callssendEmailfromsrc/services/email-service.ts.sendEmailuses the sharedbusto emit aMaintenanceTeamEmailedevent.
The bus (src/bus.ts) is the single point of outward effect; all message traffic flows through it. The call graph shows bus invoked from seven distinct places, giving it the widest blast radius.
A circular import exists among seven modules, most notably src/bus.ts, src/services/email-service.ts, and src/handlers/email-maintenance-team-handler.ts. This creates a dependency cycle that can hinder tree‑shaking, increase build times, and make future refactoring riskier. Breaking the cycle—e.g., extracting shared types into a src/common/ module or using lazy imports—will improve modularity.
How To Use It
# Clone the starter (use the exact URL as requested)
git clone https://github.com/moses-y/bus-starter my-bus-app
cd my-bus-app
git remote set-url origin <your‑repo‑url>
# Install dependencies
npm i
# Start a local RabbitMQ instance (required transport)
docker run -d -p 8080:15672 -p 5672:5672 rabbitmq:3-management
# Run the demo in watch mode
npm run dev
The demo prints log output as the siren‑test workflow fires. Replace the message, handler, and workflow files under src/messages/, src/handlers/, and src/workflows/ with domain‑specific logic. No additional configuration files are required beyond the RabbitMQ container.
Real‑World Use
A building‑management service could adopt this scaffold to coordinate fire‑alarm tests across multiple sites. Each site publishes a StartSirenTest event; the workflow aggregates results, and on failure automatically notifies the maintenance crew via email or SMS, all without tightly coupling the test runner to the notification service.
Code Health & Issues
- High – Missing LICENSE – No license file at repository root; default is “all rights reserved”, preventing legal reuse. Fix: add an MIT or Apache‑2.0 license.
- Medium – No Dependabot – One manifest (
package.json) but no automated dependency‑update bot. Fix: add.github/dependabot.yml. - High – Import Cycle – Seven modules (e.g.,
src/bus.ts,src/services/email-service.ts,src/handlers/email-maintenance-team-handler.ts) form a circular import. Fix: extract shared types or invert dependencies to break the cycle.
Tests are present (test/), CI runs on CircleCI, and a lockfile (package-lock.json) ensures reproducible installs. No Dockerfile or committed secrets were detected.
The Bottom Line
bus-starter delivers a functional, well‑structured example of a @node‑ts/bus application, complete with a demo workflow and CI. It is suitable for teams that need a quick, TypeScript‑based entry point into message‑driven microservices, but they should address the license, dependency‑bot, and import‑cycle issues before adopting it in production.