{"id":22545152,"url":"https://github.com/shubham-kumar-2000/protocol-registry","last_synced_at":"2025-04-04T16:17:22.544Z","repository":{"id":40443627,"uuid":"360773269","full_name":"Shubham-Kumar-2000/protocol-registry","owner":"Shubham-Kumar-2000","description":"This module allows you to set custom protocol handler for your nodejs app.","archived":false,"fork":false,"pushed_at":"2025-03-25T18:06:05.000Z","size":485,"stargazers_count":71,"open_issues_count":1,"forks_count":14,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-28T15:04:22.387Z","etag":null,"topics":["cross-platform","hacktoberfest","linux","macos","nodejs","npm-module","protocol","registry","windows"],"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/Shubham-Kumar-2000.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["Shubham-Kumar-2000"],"tidelift":"npm/protocol-registry"}},"created_at":"2021-04-23T05:31:09.000Z","updated_at":"2025-03-25T17:58:05.000Z","dependencies_parsed_at":"2023-11-10T19:30:30.940Z","dependency_job_id":"08ce4ad4-24b0-48ef-aaf3-782342c098c1","html_url":"https://github.com/Shubham-Kumar-2000/protocol-registry","commit_stats":{"total_commits":103,"total_committers":11,"mean_commits":9.363636363636363,"dds":"0.24271844660194175","last_synced_commit":"f9f5cc1e343425c87700a675ca1e07344719cb25"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shubham-Kumar-2000%2Fprotocol-registry","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shubham-Kumar-2000%2Fprotocol-registry/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shubham-Kumar-2000%2Fprotocol-registry/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shubham-Kumar-2000%2Fprotocol-registry/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Shubham-Kumar-2000","download_url":"https://codeload.github.com/Shubham-Kumar-2000/protocol-registry/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247208190,"owners_count":20901570,"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":["cross-platform","hacktoberfest","linux","macos","nodejs","npm-module","protocol","registry","windows"],"created_at":"2024-12-07T14:09:03.343Z","updated_at":"2025-04-04T16:17:22.520Z","avatar_url":"https://github.com/Shubham-Kumar-2000.png","language":"JavaScript","funding_links":["https://github.com/sponsors/Shubham-Kumar-2000","https://tidelift.com/funding/github/npm/protocol-registry"],"categories":[],"sub_categories":[],"readme":"﻿# Protocol-registry\r\n\r\n[![License](https://img.shields.io/github/license/Shubham-Kumar-2000/protocol-registry)](https://github.com/Shubham-Kumar-2000/protocol-registry)\r\n[![Latest version](https://img.shields.io/npm/v/protocol-registry)](https://www.npmjs.com/package/protocol-registry)\r\n[![Known Vulnerabilities](https://snyk.io/test/github/Shubham-Kumar-2000/protocol-registry/badge.svg)](https://snyk.io/test/github/Shubham-Kumar-2000/protocol-registry)\r\n![Nodejs workflow status](https://github.com/Shubham-Kumar-2000/protocol-registry/actions/workflows/node.js.yml/badge.svg?branch=main)\r\n[![Installs](https://img.shields.io/npm/dt/protocol-registry)](https://www.npmjs.com/package/protocol-registry)\r\n[![Node version](https://img.shields.io/node/v/protocol-registry.svg?style=flat)](https://www.npmjs.com/package/protocol-registry)\r\n\r\n\u003e Registers protocols like:- yourapp:// or myapp:// etc. to open your nodejs app from different browsers.\r\n\r\nThis is meant to be used in command-line tools and scripts, not in the browser.\r\n\r\n\u003cp align=\"center\"\u003e\r\n    \u003cbr\u003e\r\n\t\u003cimg alt=\"Coding\" width=\"500\" src=\"https://user-images.githubusercontent.com/41825906/116656011-96d46080-a9a9-11eb-9107-03b2e58f94a3.gif\" /\u003e\r\n    \u003cbr\u003e\r\n\u003c/p\u003e\r\n\r\n#### Why?\r\n\r\n- Actively maintained.\r\n- Handles Cross Platform.\r\n- Supports WSL paths to Windows apps.\r\n- Handles multi-line commands.\r\n- Works on electron.\r\n\r\n## Install\r\n\r\n```\r\n$ npm install protocol-registry\r\n```\r\n\r\n## Usage\r\n\r\n```js\r\nconst path = require(\"path\");\r\n\r\nconst ProtocolRegistry = require(\"protocol-registry\");\r\n\r\nconsole.log(\"Registering...\");\r\n\r\n// Registers the Protocol\r\nProtocolRegistry.register(\r\n    'testproto', // sets protocol for your command , testproto://**\r\n    `node \"${path.join(__dirname, './tester.js')}\" \"$_URL_\"`, // this will be executed where $_URL_ will have actual url value\r\n    {\r\n        override: true, // Use this with caution as it will destroy all previous Registrations on this protocol\r\n        terminal: true, // Use this to run your command inside a terminal\r\n        appName: 'my-custom-app-name' // Custom app name.\r\n    }\r\n).then(async () =\u003e {\r\n    console.log('Successfully registered');\r\n});\r\n```\r\n\r\n\u003cdetails\u003e\r\n    \u003csummary\u003e\r\n        \u003cb\u003e\r\n            Note : Refrain from using query to get data from the url, \u003ci\u003e click here to view some alternatives. \u003c/i\u003e \r\n        \u003c/b\u003e\r\n    \u003c/summary\u003e\r\n\u003cbr/\u003e\r\n\r\n##### Alternative 1\r\n\r\nInstead you can use routing params to get the data from the url, described in the example below:\r\n\r\n\u003cb\u003e Original Way : \u003c/b\u003e `testproto://test?a=b\u0026b=c`\r\n\r\n\u003cb\u003e Must use : \u003c/b\u003e `testproto://test/-a/b/-b/c`\r\n\u003cbr/\u003eAs it is more CLI friendly.\r\n\u003cbr/\u003e\r\n\u003cb\u003e Example : \u003c/b\u003e\r\n\r\n```js\r\nconst url = \"testProto://-l/Hindi\";\r\nconst { ArgumentParser } = require(\"argparse\");\r\nconst { version } = require(\"./package.json\");\r\n\r\nconst protocols = [\"testProto\", \"test\"];\r\nconst defaultProtocol = \"testProto\";\r\nconst parser = new ArgumentParser({\r\n  description: \"Example\",\r\n});\r\n\r\nparser.add_argument(\"-v\", \"--version\", { action: \"version\", version });\r\nparser.add_argument(\"mode\", {\r\n  type: String,\r\n  choices: protocols,\r\n  nargs: \"?\",\r\n  default: defaultProtocol,\r\n});\r\nparser.add_argument(\"-l\", \"--lang\", {\r\n  help: \"Choose the language.\",\r\n  choices: [\"Hindi\", \"English\"],\r\n});\r\nconst data = parser.parse_args(url.split(/:\\/\\/|[\\/]/g));\r\nconsole.log(JSON.stringify(data, null, 4));\r\n// {\r\n//    \"mode\": \"testProto\",\r\n//    \"lang\": \"Hindi\"\r\n// }\r\n```\r\n##### Alternative 2\r\n\r\nUse can use base64 encryption to transmit data and decode it there.\r\n\r\n```js\r\nconst encode = (str) =\u003e Buffer.from(str).toString('base64');\r\nconst decode = (str) =\u003e Buffer.from(str, 'base64').toString();\r\n\r\nconst protocol = 'testproto://';\r\nconst encoded = encode(JSON.stringify({ mode: 'testProto', lang: 'Hindi' }));\r\nconst url = `${protocol}${encoded}`;\r\nconsole.log(url);\r\n// testproto://eyJtb2RlIjoidGVzdFByb3RvIiwibGFuZyI6IkhpbmRpIn0=\r\n\r\nconst data = url.split('://')[1];\r\nconst decoded = JSON.parse(decode(data));\r\nconsole.log(decoded);\r\n// { mode: 'testProto', lang: 'Hindi' }\r\n\r\n```\r\n\r\n\u003c/details\u003e\r\n\r\n#### On Electron :\r\n\r\nOn electron, you can use the protocol-registry to open your app through custom protocols.\r\n\r\nNote : Electron's built-in `app.setAsDefaultProtocolClient` is recommended to be used in production but as it has some issues in development you can use `ProtocolRegistry.register` instead while developing.\r\n\r\n```js\r\nconst dev = require(\"electron-is-dev\");\r\nconst ProtocolRegistry = require(\"protocol-registry\")\r\n\r\nif (dev) {\r\n    ProtocolRegistry.register(\r\n        'testproto',\r\n        `\"${process.execPath}\" \"${path.resolve(process.argv[1])}\" \"$_URL_\"`,\r\n        {\r\n            override: true,\r\n            script: true,\r\n            terminal: dev\r\n        }\r\n    )\r\n        .then(() =\u003e console.log('Successfully registered'))\r\n        .catch(console.error);\r\n} else {\r\n    if (!app.isDefaultProtocolClient('testproto')) {\r\n        app.setAsDefaultProtocolClient('testproto');\r\n    }\r\n}\r\n```\r\n\r\n## API\r\n\r\nAt present it supports :\r\n\r\n### register(protocol, command, options={})\r\n\r\nRegisters a protocol and returns a promise.\r\n\r\n#### params\r\n\r\nRegister function accept the below mentioned params\r\n| name | types | default | details |\r\n| ---------------| ------------------ | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\r\n| protocol | String (required) | NA | Only alphabets allowed. Your command will be executed when any url starting with this protocol is opened i.e. \"myapp://test\",\"testproto://abcd?mode=dev\", etc. And please make sure that the protocol is unique to your application. |\r\n| command | String (required) | NA | This command will be executed when the protocol is called. **$\\_URL\\_** mentioned anywhere in your command will be replaced by the url by which it is initiated. Make sure to wrap it with double quotes for safe parsing. Avoid using single quotes as they don't allow for variable expansion. |\r\n| options.override | Boolean | false | If this is not true, then you will get an error that protocol is already being used. So, first check if the protocol exist or not then take action accordingly (Refrain from using it). |\r\n| options.terminal | Boolean | false | If this is set true, then first a terminal is opened and then your command is executed inside it.otherwise your command is executed in background and no logs appear but if your program launches any UI / webpage / file, it will be visible. |\r\n| options.appName | String | `url-${protocol}` | This is the name of the app file that will be created. |\r\n\r\n\r\n#### Example\r\n\r\n```js\r\nconst path = require(\"path\");\r\n\r\nconst ProtocolRegistry = require(\"protocol-registry\");\r\n\r\n// Registers the Protocol\r\nProtocolRegistry.register(\r\n  \"testproto\",\r\n  `node \"${path.join(__dirname, \"./tester.js\")}\" \"$_URL_\"`, \r\n  {\r\n    terminal: true,\r\n  }\r\n)\r\n  .then(() =\u003e {\r\n    // do something\r\n  })\r\n  .catch((e) =\u003e {\r\n    // do something\r\n  });\r\n// Above will run tester.js when testproto://** is called as\r\n// node .../tester.js testproto://**\r\n// you can further parse the url to run in different modes\r\n// As override is not passed true it will throw an error is protocol already exists\r\n\r\nProtocolRegistry.register(\r\n  \"testproto\",\r\n  `node \"${path.join(__dirname, \"./tester.js\")}\" \"$_URL_\"`,\r\n  {\r\n    terminal: false, // Terminal is set to false\r\n  }\r\n);\r\n// The above code will run your command in background\r\n// You wont be able to see any logs\r\n// But if your program launches any UI / webpage / file will be visible\r\n\r\nconst commands = `cd path/to/destination\r\nls\r\nnode \"${path.join(__dirname, \"./tester.js\")}\" \"$_URL_\"\r\n`;\r\n\r\nProtocolRegistry.register(\r\n  \"testproto\",\r\n  commands,\r\n  {\r\n    terminal: true, // Terminal is set to false\r\n    appName: 'My app 007' // This is the name of the app file that will be created.\r\n  }\r\n);\r\n// the above code will save your commands to a custom app file\r\n// and execute it when ever required\r\n```\r\n### checkIfExists(protocol)\r\n\r\nChecks if the provided protocol already exists or not.\r\nReturns a Promise which resolves in true or false.\r\n\r\n#### params\r\n\r\nCheckIfExists function accept the below mentioned params\r\n| name | types | default | details |\r\n| ---------------| ------------------ | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\r\n| protocol | String (required) | NA | The protocol for which default app needs to be checked. |\r\n\r\n#### Example\r\n\r\n```js\r\nconst path = require(\"path\");\r\n\r\nconst ProtocolRegistry = require(\"protocol-registry\");\r\n\r\nProtocolRegistry.checkIfExists(\"testproto\")\r\n  .then((res) =\u003e {\r\n    console.log(res); // true or false\r\n    // do something\r\n  })\r\n  .catch((e) =\u003e {\r\n    // do something\r\n  });\r\n```\r\n\r\n### getDefaultApp(protocol)\r\n\r\nFetches the path of the default registered app.\r\nReturns a Promise which resolves in String or null.\r\n\r\nNOTE: In case of windows it returns the registry path instead of app path.\r\n\r\n#### params\r\n\r\nGetDefaultApp function accept the below mentioned params\r\n| name | types | default | details |\r\n| ---------------| ------------------ | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\r\n| protocol | String (required) | NA | The protocol for which default app needs to be fetched. |\r\n\r\n#### Example\r\n\r\n```js\r\nconst path = require(\"path\");\r\n\r\nconst ProtocolRegistry = require(\"protocol-registry\");\r\n\r\nProtocolRegistry.getDefaultApp(\"testproto\")\r\n  .then((res) =\u003e {\r\n    console.log(res); // AppPath or null\r\n    // do something\r\n  })\r\n  .catch((e) =\u003e {\r\n    // do something\r\n  });\r\n```\r\n\r\n### deRegister(protocol, options={})\r\n\r\nRemoves registration of the default app associated with the given protocol.\r\n\r\n#### params\r\n\r\nDe-Register function accept the below mentioned params\r\n| name | types | default | details |\r\n| ---------------| ------------------ | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\r\n| protocol | String (required) | NA | The protocol for which default app registration needs to be removed. |\r\n| options.force | Boolean | false | In some cases just removing the registration is not possible thus removing the app itself is the only option. Thus when force is used it will remove the default app itself. **This is not required for the apps registered using this module.** Below is the more detailed explanation. |\r\n\r\n#### force : true\r\n\r\nThis is only applicable for apps that are not registered through this module.\r\nIn some cases just removing the registration is not possible thus removing the app itself is the only option. Thus when force is used it will remove the default app itself.\r\n\r\n- MacOS: Sometime in MacOS, `App Management` permission is required to modify other apps in the system. Thus without force app update may fail. But if the app is registered through this module then it directly deletes the app because we know it doesn't have any other purposes.\r\n- Windows: In windows there is no effect of this operator.\r\n- Linux: By default it only removes the mime handlers from the desktop file but if force is true or if the app is registered through this module then it deletes the registered desktop file.\r\n\r\n#### Example\r\n\r\n```js\r\nconst path = require(\"path\");\r\n\r\nconst ProtocolRegistry = require(\"protocol-registry\");\r\n\r\n// DeRegister the Protocol\r\nProtocolRegistry.deRegister('testproto', {\r\n  force: false\r\n})\r\n  .then(() =\u003e {\r\n    // do something\r\n  })\r\n  .catch((e) =\u003e {\r\n    // do something\r\n  });\r\n// Above snippet will deregister the default app associated with the protocol : testproto\r\n```\r\n\r\n## Supported platforms\r\n\r\n- [`Windows`](https://g.co/kgs/bm4Z4b) - OS - Supported\r\n- [`linux`](https://g.co/kgs/xXAi4C) - OS - Supported\r\n- [`MacOS`](https://g.co/kgs/k8yG4U) - OS - Supported\r\n\r\n## MacOS Anomalies\r\n\r\n### terminal: false\r\n\r\nIn MacOS if you don't launch the terminal it will run your command without logging in. But we still go head and log you in using your default system `SHELL` i.e. `zsh` or `bash`. Also we preserve the current `PATH` while protocol execution.\r\n\r\nBut still in some cases `PATH` added after the the registration may not work. Thus make sure all your commands are working before registering the protocol or use their absolute path.\r\n\r\n## Contributors:\r\n\r\n### Credits goes to these people: ✨\r\n\r\n\u003ctable\u003e\r\n\t\u003ctr\u003e\r\n\t\t\u003ctd\u003e\r\n            \u003ca href=\"https://github.com/Shubham-Kumar-2000/protocol-registry/graphs/contributors\"\u003e\r\n                \u003cimg src=\"https://contrib.rocks/image?repo=Shubham-Kumar-2000/protocol-registry\" /\u003e\r\n            \u003c/a\u003e\r\n\t\t\u003c/td\u003e\r\n\t\u003c/tr\u003e\r\n\u003c/table\u003e\r\n\u003cp align=\"center\"\u003e\r\n  \u003ch2 align=\"center\"\u003eVisitor's Count \u003cimg align=\"center\" src=\"https://profile-counter.glitch.me/Shubham-Kumar-2000.protocol-registry/count.svg\" alt=\"Visitor Count\" /\u003e\u003c/h2\u003e\r\n\u003c/p\u003e\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshubham-kumar-2000%2Fprotocol-registry","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshubham-kumar-2000%2Fprotocol-registry","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshubham-kumar-2000%2Fprotocol-registry/lists"}