{"id":46847944,"url":"https://github.com/boringnode/bus","last_synced_at":"2026-03-10T15:32:24.949Z","repository":{"id":224834885,"uuid":"752818729","full_name":"boringnode/bus","owner":"boringnode","description":"A simple and lean service bus implementation for Node.js","archived":false,"fork":false,"pushed_at":"2026-03-01T15:00:35.000Z","size":1967,"stargazers_count":38,"open_issues_count":5,"forks_count":5,"subscribers_count":3,"default_branch":"0.x","last_synced_at":"2026-03-01T18:18:59.999Z","etag":null,"topics":["bus","framework-agnostic","nodejs"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/boringnode.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-02-04T21:58:39.000Z","updated_at":"2026-02-16T14:18:21.000Z","dependencies_parsed_at":"2026-03-01T17:06:50.736Z","dependency_job_id":null,"html_url":"https://github.com/boringnode/bus","commit_stats":null,"previous_names":["romainlanz/bus","boringnode/bus"],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/boringnode/bus","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boringnode%2Fbus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boringnode%2Fbus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boringnode%2Fbus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boringnode%2Fbus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/boringnode","download_url":"https://codeload.github.com/boringnode/bus/tar.gz/refs/heads/0.x","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boringnode%2Fbus/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30340117,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T15:03:31.997Z","status":"ssl_error","status_checked_at":"2026-03-10T15:01:30.431Z","response_time":106,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bus","framework-agnostic","nodejs"],"created_at":"2026-03-10T15:32:24.074Z","updated_at":"2026-03-10T15:32:24.931Z","avatar_url":"https://github.com/boringnode.png","language":"TypeScript","readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/user-attachments/assets/04d2c9b7-9b36-4e17-8bd6-ab8fe85dadbf\" alt=\"@boringnode/bus\"\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n[![typescript-image]][typescript-url]\n[![gh-workflow-image]][gh-workflow-url]\n[![npm-image]][npm-url]\n[![npm-download-image]][npm-download-url]\n[![license-image]][license-url]\n\n\u003c/div\u003e\n\n\u003chr /\u003e\n\n`@boringnode/bus` is a service bus implementation for Node.js. It is designed to be simple and easy to use.\n\nCurrently, it supports the following transports:\n\n\u003cp\u003e\n👉 \u003cstrong\u003eMemory:\u003c/strong\u003e A simple in-memory transport for testing purposes.\u003cbr /\u003e\n👉 \u003cstrong\u003eRedis:\u003c/strong\u003e A Redis transport for production usage.\u003cbr /\u003e\n👉 \u003cstrong\u003eMqtt:\u003c/strong\u003e A Mqtt transport for production usage.\n\u003c/p\u003e\n\n## Table of Contents\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\n- [Installation](#installation)\n- [Usage](#usage)\n- [Retry Queue](#retry-queue)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n## Installation\n\n```bash\nnpm install @boringnode/bus\n```\n\n## Usage\n\nThe module exposes a manager that can be used to register buses.\n\n```typescript\nimport { BusManager } from '@boringnode/bus'\nimport { redis } from '@boringnode/bus/transports/redis'\nimport { mqtt } from '@boringnode/bus/transports/mqtt'\nimport { memory } from '@boringnode/bus/transports/memory'\n\nconst manager = new BusManager({\n  default: 'main',\n  transports: {\n    main: {\n      transport: memory(),\n    },\n    redis: {\n      transport: redis({\n        host: 'localhost',\n        port: 6379,\n      }),\n    },\n    mqtt: {\n      transport: mqtt({\n        host: 'localhost',\n        port: 1883,\n      }),\n    },\n  }\n})\n```\n\nOnce the manager is created, you can subscribe to channels and publish messages.\n\n```typescript\nmanager.subscribe('channel', (message) =\u003e {\n  console.log('Received message', message)\n})\n\nmanager.publish('channel', 'Hello world')\n```\n\nBy default, the bus will use the `default` transport. You can specify different transport by using the `use` method.\n\n```typescript\nmanager.use('redis').publish('channel', 'Hello world')\nmanager.use('mqtt').publish('channel', 'Hello world')\n```\n\n### Without the manager\n\nIf you don't need multiple buses, you can create a single bus directly by importing the transports and the Bus class.\n\n```typescript\nimport { Bus } from '@boringnode/bus'\nimport { RedisTransport } from '@boringnode/bus/transports/redis'\n\nconst transport = new RedisTransport({\n  host: 'localhost',\n  port: 6379,\n})\n\nconst bus = new Bus(transport, {\n  retryQueue: {\n    retryInterval: '100ms'\n  }\n})\n```\n\n## Retry Queue\n\nThe bus also supports a retry queue. When a message fails to be published, it will be moved to the retry queue.\n\nFor example, your Redis server is down.\n\n```typescript\nconst manager = new BusManager({\n  default: 'main',\n  transports: {\n    main: {\n      transport: redis({\n        host: 'localhost',\n        port: 6379,\n      }),\n      retryQueue: {\n        retryInterval: '100ms'\n      }\n    },\n  }\n})\n\nmanager.use('redis').publish('channel', 'Hello World')\n```\n\nThe message will be moved to the retry queue and will be retried every 100ms.\n\nYou have multiple options to configure the retry queue.\n\n```typescript\nexport interface RetryQueueOptions {\n  // Enable the retry queue (default: true)\n  enabled?: boolean\n  \n  // Defines if we allow duplicates messages in the retry queue (default: true)\n  removeDuplicates?: boolean\n  \n  // The maximum size of the retry queue (default: null)\n  maxSize?: number | null\n  \n  // The interval between each retry (default: false)\n  retryInterval?: Duration | false\n}\n```\n\n## Test helpers\n\nThe module also provides some test helpers to make it easier to test the code that relies on the bus. First, you can use the `MemoryTransport` to create a bus that uses an in-memory transport.\n\nYou can also use the `ChaosTransport` to simulate a transport that fails randomly, in order to test the resilience of your code.\n\n```ts\nimport { Bus } from '@boringnode/bus'\nimport { ChaosTransport } from '@boringnode/bus/test_helpers'\n\nconst buggyTransport = new ChaosTransport(new MemoryTransport())\nconst bus = new Bus(buggyTransport)\n\n/**\n * Now, every time you will try to publish a message, the transport \n * will throw an error.\n */\nbuggyTransport.alwaysThrow()\n```\n\n[gh-workflow-image]: https://img.shields.io/github/actions/workflow/status/boringnode/bus/checks.yml?branch=0.x\u0026style=for-the-badge\n[gh-workflow-url]: https://github.com/boringnode/bus/actions/workflows/checks.yml\n[npm-image]: https://img.shields.io/npm/v/@boringnode/bus.svg?style=for-the-badge\u0026logo=npm\n[npm-url]: https://www.npmjs.com/package/@boringnode/bus\n[npm-download-image]: https://img.shields.io/npm/dm/@boringnode/bus?style=for-the-badge\n[npm-download-url]: https://www.npmjs.com/package/@boringnode/bus\n[typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge\u0026logo=typescript\n[typescript-url]: https://www.typescriptlang.org\n[license-image]: https://img.shields.io/npm/l/@boringnode/bus?color=blueviolet\u0026style=for-the-badge\n[license-url]: LICENSE.md\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboringnode%2Fbus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fboringnode%2Fbus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboringnode%2Fbus/lists"}