{"id":20619200,"url":"https://github.com/shalvah/burns","last_synced_at":"2025-04-15T11:52:46.742Z","repository":{"id":52118939,"uuid":"107014528","full_name":"shalvah/burns","owner":"shalvah","description":"Manage your application's events without writing spaghetti code","archived":false,"fork":false,"pushed_at":"2021-05-07T08:23:56.000Z","size":1744,"stargazers_count":91,"open_issues_count":0,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-28T19:44:59.314Z","etag":null,"topics":["event-broadcasting","event-driven","event-handlers","events","handlers","listeners","nodejs","npm"],"latest_commit_sha":null,"homepage":"http://shalvah.me/burns/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shalvah.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-15T13:27:59.000Z","updated_at":"2024-11-30T05:46:21.000Z","dependencies_parsed_at":"2022-09-01T03:23:06.729Z","dependency_job_id":null,"html_url":"https://github.com/shalvah/burns","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shalvah%2Fburns","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shalvah%2Fburns/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shalvah%2Fburns/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shalvah%2Fburns/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shalvah","download_url":"https://codeload.github.com/shalvah/burns/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248766757,"owners_count":21158301,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["event-broadcasting","event-driven","event-handlers","events","handlers","listeners","nodejs","npm"],"created_at":"2024-11-16T12:11:00.096Z","updated_at":"2025-04-15T11:52:46.724Z","avatar_url":"https://github.com/shalvah.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eBurns\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"burns.gif\"\u003e\u003cbr\u003e\n  \u003cem\u003eExcellent\u003c/em\u003e\n\u003c/p\u003e\n\n[![npm version](https://badge.fury.io/js/burns.svg)](https://badge.fury.io/js/burns)\n[![Build Status](https://travis-ci.org/shalvah/burns.svg?branch=master)](https://travis-ci.org/shalvah/burns)\n[![Dependabot Status](https://api.dependabot.com/badges/status?host=github\u0026repo=shalvah/burns)](https://dependabot.com)\n[![npm](https://img.shields.io/npm/dt/burns)](https://www.npmjs.com/package/burns)\n\nBurns is a lightweight (no dependencies!) Node.js module for managing application events elegantly. Define your events and handlers in one place and dispatch them when you need to.\n\nInspired by Laravel's [events](https://laravel.com/docs/master/events) and [broadcasting](https://laravel.com/docs/master/broadcasting) systems.\n\n## What you get\n- Easy visibility of all application events\n- Default handler to catch generic events\n- Attaching event handlers at multiple places\n- Asynchronous handling of events\n- Inbuilt event broadcasting\n\n## Installation\n```bash\nnpm install burns\n```\n\n## How to use\n\n```js\nconst burns = require('burns');\n```\n\nDefine an event handler:\n\n```js\n// handlers/order.js\n\nfunction sendOrderShippedEmail(data)\n{\n    mailer.sendEmail(`Hi ${data.userName}, Your order ${data.orderId} has been shipped`);\n}\n```\n\nRegister the event and attach the handler:\n```js\nlet { sendOrderShippedEmail } = require('./handlers/order');\nburns.registerEvents({\n  orderShipped: sendOrderShippedEmail\n});\n```\n\nDispatch the event when you're ready! 🚀\n```js\nburns.dispatch('orderShipped', {\n    orderId: order.id,\n    userName: user.name\n});\n```\n\n### Registering events\nRegister events by calling ` registerEvents` with a single object. The names of your events should be the keys of this object and their handlers the values:\n\n```js\nburns.registerEvents({\n  newPurchase: sendInvoice,\n  orderShipped: notifyUser\n});\n```\nYou can also attach multiple handlers to a single event:\n\n```js\nburns.registerEvents({\n  userSignUp: [\n    userListener.sendEmail,\n    userListener.congratulateReferrer\n  ]\n})\n```\nBurns allows you to register events at multiple locations. This means that for a large application, you can have each application component define its own events and handlers by calling `registerEvents` wherever it needs to.\n\n### Defining handlers\nA handler is a function that responds to an event. A handler takes a single parameter, the event payload which you pass when dispatching the event:\n\n```js\nfunction sendInvoice(data)\n{\n    let invoice = createInvoice(data.order, data.user);\n    mailer.sendEmail('Here is your order invoice', invoice);\n}\n\nburns.registerEvents({\n  newPurchase: sendInvoice,\n});\n\n// this will call sendInvoice with data = {}\nburns.dispatch('newPurchase');\n\n// this will call sendInvoice with data containing order and user\nburns.dispatch('newPurchase', {\n    order: getOrder(),\n    user: findUser()\n});\n```\n\n\n#### Stopping event propagation\nSuppose you're running a subscription service (like Netflix) where you bill users every month. Your app can fire a `newBillingPeriod` event and perform multiple actions when this event is fired: charge the customer's card, extend their subscription, send them a invoice. Burns allows you to register multiple handlers for the event, and will call them in the order in which they were registered:\n\n```js\nburns.registerEvents({\n  newBillingPeriod: [\n      chargeCustomerCard,\n      extendCustomerSubscription,\n      sendCustomerInvoice,\n   ]\n})\n```\n\nIf the process of charging the customer's card fails, you probably wouldn't want to go through with the other actions. In such a situation, you can prevent the subsequent handlers from being called by returning `false` from the current handler:\n\n```js\nfunction chargeCustomerCard(customer) {\n  if (!PaymentProcessor.chargeCard(customer)) {\n      // bonus: dispatch a 'chargeCardFailed` event. Cool, huh?\n    burns.dispatch('chargeCardFailed', customer);\n    return false;\n  }\n\n}\n```\n\n#### Using a default handler\nYou may specify a `defaultHandler`. Burns will pass a dispatched event to this handler if no handlers are registered for it:\n\n```js\nfunction handleEverything (data) {}\n\nburns.configure({\n    defaultHandler: handleEverything\n});\n\n// this will call handleEverything\nburns.dispatch('unregisteredEvent', somePayload);\n```\n\n### Dispatching events\nTo dispatch an event, call ` dispatch` with the name of the event:\n\n```js\nburns.dispatch('postLiked');\n```\n\nYou may also pass in a payload containing data to be transmitted with the event:\n\n```js\nburns.dispatch('postLiked', {\n    postId: 69,\n    likedBy: 42,\n});\n```\nThis object will be passed as an argument to the handler.\n\n## Broadcasting events\nSupposing you have an `orderStatusUpdated` event that is fired when the status of an order is updated, and you wish to update the order status on your frontend in realtime. Burns handles this for you via event broadcasting.\n\n### Configuring broadcasting\nYou'll need to specify a `broadcaster`. For now, broadcasting is only supported to the console log (broadcaster: 'log') and [Pusher](http://pusher.com) (broadcaster: 'pusher'). The default broadcaster is `log`, which will log all broadcasts to the Node console. (You can disable broadcasting by setting `broadcaster: null`.)\n\nIf you're broadcasting with Pusher, pass in your credentials as a `pusher` object:\n\n```js\nburns.configure({\n  broadcaster: 'pusher',\n  pusher: {\n    appId: 'APP_ID',\n    key: 'APP_KEY',\n    secret: 'SECRET_KEY',\n    cluster: 'CLUSTER',\n  }\n})\n```\n\n\u003e ⚠ To use the `pusher` broadcaster, you need to install the Pusher Node.js SDK: `npm install pusher`\n\n### Broadcasting an event\nThen register the `orderStatusUpdated` using the \"advanced\" configuration format:\n\n```js\nburns.registerEvents({\n  orderStatusUpdated: {\n      handlers: [\n          notifyUser\n      ],\n      broadcastOn: 'orderStatusUpdates' // or an array of channels\n  }\n});\n```\n\nThe `broadcastOn` key specifies the name of the channel on which the event will be broadcast. It can be a string or a function that takes in the event payload and returns a channel name.\n\nNow when you call\n\n```js\nburns.dispatch('orderStatusUpdated', order);\n```\n\nBurns will automatically publish a message on the channel `orderStatusUpdates` with the `order` object as the payload. All that's left is for you to listen for this event on the frontend.\n\nIf you'd like to exclude the client that triggered the event from receiving the broadcast, you can pass in an object as the third parameter to `dispatch()`. The 'exclude' key should contain the socket ID of the client to exclude:\n\n```js\nburns.dispatch('orderStatusUpdated', order, { exclude: socketId });\n```\n\n### Conditional broadcasting\nYou can also have conditional broadcasting by using the `broadcastIf` property.\n\n```js\nburns.registerEvents({\n  orderStatusUpdated: {\n      handlers: [\n          notifyUser\n      ],\n      broadcastOn: 'orderStatusUpdates',\n      broadcastIf: process.env.NODE_ENV === 'production'\n  }\n});\n```\n\nYou may specify a function that takes the event payload and should return true or false:\n\n```js\n({\n    broadcastIf: (data) =\u003e data.user.notifications.enabled === true,\n    // your function can return a promise too. Burns will await the result\n    // broadcastIf: (data) =\u003e data.user.getSettings()\n    //   .then(settings =\u003e settings.notifications.enabled === true),\n})\n```\n`\n## But Node already supports events natively!\nYes, and that's a great thing for handling events at lower levels in your code base (for instance, on `open` of a file, on `data` of a stream). When dealing with events at a higher level (such as a new user signing up), Burns is perfect for helping you keep your code clean and organized.\n\n## Asynchronous vs. Synchronous\nUnlike [Node.js' inbuilt events system](https://nodejs.org/api/events.html#events_asynchronous_vs_synchronous), Burns calls your event handlers asynchronously in the order in which they were registered. This means that the functions are queued behind whatever I/O event callbacks that are already in the event queue, thus enabling you to send a response to your user immediately, while your event gets handled in the background.\n\nThis also means that if you dispatch one event from a handler for another event, all of the original event's handlers will be executed first, before moving on to those for the newly-dispatched event.\n\n## Like it?\nStar and share, and give me a shout out [on Twitter](http://twitter.com/theshalvah)\n\n## Contributing\nIf you have an bugfix, idea or feature you'd like to implement, you're welcome to send in a PR!\n\n(Requires Node v8 or above)\n- Clone the repo\n\n```bash\ngit clone https://github.com/shalvah/burns.git\n```\n\n- Create a branch for your fix/feature:\n\n```bash\ngit checkout -b my-patch\n```\n\n- Write your code. Add tests too, if you know how. If you're not sure how, just send in the PR anyway.\n\n- Make sure all tests are passing\n\n```bash\nnpm run test\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshalvah%2Fburns","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshalvah%2Fburns","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshalvah%2Fburns/lists"}