{"id":13798007,"url":"https://github.com/geblanco/electron-router","last_synced_at":"2026-04-06T07:35:06.640Z","repository":{"id":52164767,"uuid":"52218372","full_name":"geblanco/electron-router","owner":"geblanco","description":"Router solving Electron hell callback passing, helpfull for MVC","archived":false,"fork":false,"pushed_at":"2022-12-30T17:14:03.000Z","size":776,"stargazers_count":123,"open_issues_count":5,"forks_count":6,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-10-10T23:53:42.943Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/geblanco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-02-21T17:28:25.000Z","updated_at":"2024-03-22T19:48:14.000Z","dependencies_parsed_at":"2023-01-31T12:16:47.067Z","dependency_job_id":null,"html_url":"https://github.com/geblanco/electron-router","commit_stats":null,"previous_names":["m0n0l0c0/electron-router","m0n0l0c0/electronrouter"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/geblanco/electron-router","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geblanco%2Felectron-router","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geblanco%2Felectron-router/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geblanco%2Felectron-router/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geblanco%2Felectron-router/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/geblanco","download_url":"https://codeload.github.com/geblanco/electron-router/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geblanco%2Felectron-router/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31463160,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T21:22:52.476Z","status":"online","status_checked_at":"2026-04-06T02:00:07.287Z","response_time":112,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2024-08-04T00:00:37.776Z","updated_at":"2026-04-06T07:35:06.617Z","avatar_url":"https://github.com/geblanco.png","language":"JavaScript","funding_links":[],"categories":["Library","Tools"],"sub_categories":["IPC","For Electron"],"readme":"# ElectronRouter\n\n[![codecov](https://codecov.io/gh/m0n0l0c0/electron-router/branch/master/graph/badge.svg)](https://codecov.io/gh/m0n0l0c0/electron-router)\n[![JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)\n\nRouter solving Electron shell callback passing, helpfull for MVC\n\n# Contents\n- [Motivation](#motivation) \n- [Features](#features)\n- [API](#api)\n- [Examples](#examples)\n- [Contributing](#contributing)\n- [Future](#future)\n- [Notes](#notes)\n\n## Installation\n\n```\n// Install:\nnpm install electron-router\n\n// Test:\nnpm test\n```\n\n## Motivation\n### The problem\nWhen making an electron app I usually come down to the same problem: message passing; if you want to send a message to a window you have to keep a reference to it, whatever the module you're sending the message from, which leaves two possible solutions:\n* Pass the wanted window object to every module that needs to send a message to that window.\n\nor\n\n* Somehow send the message to the owner of the window reference (usually implies callback passing).\n\nOn the other hand, when you want to receive a message from the window you have to listen to ipc which is usually great, but forces you to have perfect tune of the variables that the callback is going to access; this does not present a problem by itself, but as the application grows it may become one.\n\nOne example of this is when you have a database and want to query it from the window renderer process, either the database is listening on the ipc and aware of the window (keeps a reference to it) for querying/retrieving data or both the window and the database route their data through the main script, becoming some sort of dummy proxy.\n\nAfter some brainstorming, the solution I came to was designing the Router, it gives similar options to [express](http://expressjs.com/). I've made a diagram to help visualize all this.\n\n![diagram explaining the problem](router.png)\n\n### The solution\nThe router just triggers the functions you register on by sending events and parameters. Allowing easy message/data passing and respecting the event/callback Electron architecture.\n\n## Features\n\n### Wildcards\nEvery sent/listened message can use wildcards\n```javascript\nrouter.on('loading::start', () =\u003e { console.log('start loading...') }\nrouter.on('loading::continue', () =\u003e { console.log('continue loading...') }\nrouter.on('loading::end', () =\u003e { console.log('end loading...') }\n\n...\n\nrouter.send('loading::start', ...) // logs \"start loading\"\nrouter.send('loading::*', ...) // logs \"start loading\", \"continue loading\", \"end loading\"\n\n```\n\n#### Simple, plain communication\nYou can send messages unidirectionally from the main process to the renderer process and viceversa (analogous to electron's ipc) (Previous example)\n\n#### Duplex communication with channels\n\n```javascript\nrouter.get('config::*')\nrouter.post('config', ( req, res ) =\u003e {\n\t// req.params contain sent parameters\n\t// res.json sends data back\n})\n...\n\nrouter.route('get', 'config::start', ( err, result ) =\u003e {\n\tconsole.log('got config', result)\n})\n```\n\n## API\n\nThe router is just a static object, there will be one router in the main process and another one on the renderer. Just 'require' it and start listening/sending events/data. What this object does is route callbacks from one side to another passing parameters, triggered by different events.\nIt can listen to ipc events and send window events too.\nHTTP Verbs are used just as different channels and for completness (equality to\nexpress). For every route/event it is possible register wildcard ('*').\n\n**You are responsible for unregistering your callbacks with\n`removeListener(listener)`, or all callbacks with `removeAllListeners()`, take\ninto account that this will also delete whatever routes where registered on IPC\noutside the router**. In order to do unregister individual callbacks, listeners\nshould not be just anonymous functions.\n\n#### Instance\n```javascript\n// Constructs the object setting its name\nlet Router = require('electron-router')\n\n// Returns the static instance\nlet router = Router( name )\n```\n\n#### Simple communication\n```javascript\n// Triggers/Sends a message on the given event name passing provided messages.\nrouter.send( event, msg1, msg2... )\n\n// Register a listener on the given event, triggering the callback when the event is sent.\n// Callback receives the messages sent on the other side\nrouter.on( event, ( msg1, msg2... ) =\u003e {})\n```\n\n#### Duplex communication\n```javascript\n// Triggers/Sends a message to the given route on the given method (channel, HTTP Verbs)\n// passing the given messages to that channel/route handler. \n// Callback is called with err/result when the handler calls res.json()\n// if the handler does not call the return function, callback is invoked with Err: Timeout\n\nrouter.route( method, route, msg1, msg2..., ( err, result ) =\u003e {})\n\n// Similar to router.routes.method( route, msg1, msg2..., ( err, result ) =\u003e {})\n\n// All handlers on all channels are called with\n// \treq { parameters: [], method: channel }\n// \tres { json: [Function] } - function to call with (err, result), triggers the route back\n\n// Registers handler on GET channel at the given route.\nrouter.get( route, ( req, res ) =\u003e {}) // must call res.json( err, result )\n\n// Registers handler on POST channel at the given route.\nrouter.post( route, ( req, res ) =\u003e {}) // must call res.json( err, result )\n\n// Registers handler on UPDATE channel at the given route.\nrouter.update( route, ( req, res ) =\u003e {}) // must call res.json( err, result )\n\n// Registers handler on DELETE channel at the given route.\nrouter.delete( route, ( req, res ) =\u003e {}) // must call res.json( err, result )\n\n```\n\n## Examples\n\n```javascript\n// On every module that uses the router\n// Import it\nlet Router = require('electron-router')\n\n// Main script\n\nconst electron = require('electron')\nconst BrowserWindow = electron.BrowserWindow\nconst app = electron.app\nconst Router = require('electron-router')\nlet router = Router('MAIN')\nlet mainWindow = null\n\n...\n\napp.on('ready', () =\u003e {\n\n\t// Create window\n\t... \n\n  // Setup DB and modules\n  ...\n\n\t// Do the rest on ready event (triggered from window, which is usaully the slowest component)\n\trouter.on('ready', () =\u003e {\n\t\trouter.on('quit', () =\u003e {\n\t\t\t// Close DB\n\t\t\t// Handle quit code\n\t\t\t...\n\t\t})\n\t})\n})\n\n...\n\n// Window script\n\nconst $ = require('jquery')\nconst Router = require('electron-router')\nlet router = Router('WINDOW')\n\n// On window ready\n$(() =\u003e {\n  // Send ready event to all registered handlers\n  router.send('ready')\n  ...\n\n  $('#updates').on('click', () =\u003e {\n  \trouter.route('POST', '/DB', $('#userData').data())\n  })\n})\n\n...\n\n// DB script\n\nconst Router = require('electron-router')\nlet router = Router('DB')\n\n...\n\nrouter.on('ready', () =\u003e { ... })\n\n// Register trigger for every route on method GET\nroute.get('*', ( req, res ) =\u003e {\n\tdb.find({ id: req.params }, ( err, results ) =\u003e {\n\t\tres.json( err, results )\n\t})\n})\n\n// Receive data on post method, route /DB\nrouter.post('/DB', ( req, res ) =\u003e {\n\tconsole.log('Received', req.params)\n\t// Save data on db\n\tdb.save( req.params, ( err, result ) =\u003e {\n\t\t// Send save result to the triggerer\n\t\tres.json( err, result )\n\t})\n})\n\n```\n\n## Contributing\nAny help is welcome, just send a pull request (please document a little what you want to do), with any ideas/code\n\n## Future\nIn the future it could be great to support:\n* ~~MVC frameworks integration (Backbone...) (Should not be too difficult, overwrite sync method on Collections)~~ [erbs](https://github.com/m0n0l0c0/erbs)\n* Template rendering (i.e.: ```res.render(data)```)\n\n## Notes\nThe diagram was made with [gliffy](https://www.gliffy.com/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeblanco%2Felectron-router","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeblanco%2Felectron-router","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeblanco%2Felectron-router/lists"}