{"_id":"@524c/moleculer-io","_rev":"6-8f28fe2d3432216423226be1530f8808","time":{"created":"2023-12-15T14:04:40.229Z","2.3.0":"2023-12-15T13:58:11.430Z","modified":"2023-12-18T00:01:35.791Z","2.3.0-1":"2023-12-15T14:04:40.563Z","2.3.0-2":"2023-12-17T23:39:28.178Z","2.3.0-3":"2023-12-17T23:41:39.719Z","2.3.0-4":"2023-12-18T00:01:35.614Z"},"name":"@524c/moleculer-io","dist-tags":{"latest":"2.3.0-4"},"versions":{"2.3.0-1":{"name":"@524c/moleculer-io","version":"2.3.0-1","description":"An API GateWay service for Moleculer using Socket.IO","directories":{"example":"examples"},"scripts":{"dev":"nodemon --experimental-specifier-resolution=node examples/index.cjs","dev:client":"iola io ws://localhost:3000","ci":"cross-env NODE_OPTIONS=--experimental-vm-modules jest --watch","deps":"npm-check -u","test":"cross-env NODE_OPTIONS=--experimental-vm-modules jest --coverage","build":"tsup src/index.js --clean"},"repository":{"type":"git","url":"git+https://github.com/moleculerjs/moleculer-io.git"},"keywords":["socket.io","moleculer","websocket","microservice","API Gateway"],"author":{"name":"MoleculerJS"},"license":"MIT","dependencies":{"kleur":"^4.1.5","lodash":"^4.17.21","socket.io":"^4.7.2"},"devDependencies":{"eslint":"^8.51.0","eslint-config-prettier":"^8.5.0","eslint-plugin-node":"^11.1.0","eslint-plugin-prettier":"^4.2.1","eslint-plugin-promise":"^6.1.1","eslint-plugin-security":"^1.5.0","express":"^4.18.2","jest":"^29.7.0","jest-cli":"^29.7.0","moleculer":"^0.14.31","moleculer-repl":"^0.7.4","moleculer-web":"^0.10.6","nodemon":"^3.0.1","prettier":"^3.0.3","socket.io-client":"^4.7.2","socket.io-redis":"^6.1.1","tiny-glob":"^0.2.9","tsup":"^7.2.0","winston":"^3.11.0"},"peerDependencies":{"moleculer":"^0.13.0 || ^0.14.0"},"engines":{"node":">= 10.x.x"},"jest":{"testEnvironment":"node","rootDir":"./src","roots":["../test"],"coverageDirectory":"../coverage","coveragePathIgnorePatterns":["/node_modules/","/test/"]},"exports":{".":{"require":"./dist/index.js","import":"./dist/index.mjs","types":"./src/index.d.ts"}},"main":"./dist/index.mjs","module":"./dist/index.mjs","types":"./src/index.d.ts","_id":"@524c/moleculer-io@2.3.0-1","gitHead":"a56c8674a64471fee5d27ed156f3551d41678135","bugs":{"url":"https://github.com/moleculerjs/moleculer-io/issues"},"homepage":"https://github.com/moleculerjs/moleculer-io#readme","_nodeVersion":"18.19.0","_npmVersion":"10.2.3","dist":{"integrity":"sha512-DhniE6SUVpGP9nmucG6VIuRNy4BybosAB7O6qDljHcm7ma+nE04V02DzyoBx8MfYxT/DsPC0Rdt4DByW99M9hw==","shasum":"0b65814296bc1cd0918e15545c21f54038ba304d","tarball":"https://registry.npmjs.org/@524c/moleculer-io/-/moleculer-io-2.3.0-1.tgz","fileCount":5,"unpackedSize":51055,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID95YVr22hQXM/bmbkDqxvxXuLL0Cwdw6vCtHORK4sgQAiA2I/6GoTXB4KpuE5WsaUFwBuS8L3lB48aQ/TYgvhysuw=="}]},"_npmUser":{"name":"524c","email":"rogeriolucas@gmail.com"},"maintainers":[{"name":"524c","email":"rogeriolucas@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/moleculer-io_2.3.0-1_1702649080314_0.39885001972728773"},"_hasShrinkwrap":false},"2.3.0-2":{"name":"@524c/moleculer-io","version":"2.3.0-2","description":"An API GateWay service for Moleculer using Socket.IO","directories":{"example":"examples"},"scripts":{"dev":"nodemon --experimental-specifier-resolution=node examples/index.cjs","dev:client":"iola io ws://localhost:3000","ci":"cross-env NODE_OPTIONS=--experimental-vm-modules jest --watch","deps":"npm-check -u","test":"cross-env NODE_OPTIONS=--experimental-vm-modules jest --coverage","build":"tsup src/index.js --clean && cp src/index.d.ts dist/index.d.ts"},"repository":{"type":"git","url":"git+https://github.com/moleculerjs/moleculer-io.git"},"keywords":["socket.io","moleculer","websocket","microservice","API Gateway"],"author":{"name":"MoleculerJS"},"license":"MIT","dependencies":{"kleur":"^4.1.5","lodash":"^4.17.21","socket.io":"^4.7.2"},"devDependencies":{"eslint":"^8.51.0","eslint-config-prettier":"^8.5.0","eslint-plugin-node":"^11.1.0","eslint-plugin-prettier":"^4.2.1","eslint-plugin-promise":"^6.1.1","eslint-plugin-security":"^1.5.0","express":"^4.18.2","jest":"^29.7.0","jest-cli":"^29.7.0","moleculer":"^0.14.31","moleculer-repl":"^0.7.4","moleculer-web":"^0.10.6","nodemon":"^3.0.1","prettier":"^3.0.3","socket.io-client":"^4.7.2","socket.io-redis":"^6.1.1","tiny-glob":"^0.2.9","tsup":"^7.2.0","winston":"^3.11.0"},"peerDependencies":{"moleculer":"^0.13.0 || ^0.14.0"},"engines":{"node":">= 10.x.x"},"jest":{"testEnvironment":"node","rootDir":"./src","roots":["../test"],"coverageDirectory":"../coverage","coveragePathIgnorePatterns":["/node_modules/","/test/"]},"exports":{".":{"require":"./dist/index.js","import":"./dist/index.mjs","types":"./src/index.d.ts"}},"main":"./dist/index.mjs","module":"./dist/index.mjs","types":"./src/index.d.ts","_id":"@524c/moleculer-io@2.3.0-2","gitHead":"759a8c8d34ee59a228bdea6729f36e80bab5308c","bugs":{"url":"https://github.com/moleculerjs/moleculer-io/issues"},"homepage":"https://github.com/moleculerjs/moleculer-io#readme","_nodeVersion":"18.19.0","_npmVersion":"10.2.3","dist":{"integrity":"sha512-n8VCcIdbxDPCB5Q8QAc8cviiWv3wMk1RozP+If6D48BiplOsN8SHL/c5r6uHKCM48eR1jFqW0mvT3o4hL+YW7Q==","shasum":"2a2239737725b9bacb8783cc0e9ddae871787aa7","tarball":"https://registry.npmjs.org/@524c/moleculer-io/-/moleculer-io-2.3.0-2.tgz","fileCount":6,"unpackedSize":56658,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICs586VE0YqmS+Mgxix/bcwhpqWsWgeHz2QQpPcUanUVAiAL1S7Usl5rkRwpy7COXILOK7z7KBP+iu+dRedM9FJm8g=="}]},"_npmUser":{"name":"524c","email":"rogeriolucas@gmail.com"},"maintainers":[{"name":"524c","email":"rogeriolucas@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/moleculer-io_2.3.0-2_1702856367997_0.2542065638527422"},"_hasShrinkwrap":false},"2.3.0-3":{"name":"@524c/moleculer-io","version":"2.3.0-3","description":"An API GateWay service for Moleculer using Socket.IO","directories":{"example":"examples"},"scripts":{"dev":"nodemon --experimental-specifier-resolution=node examples/index.cjs","dev:client":"iola io ws://localhost:3000","ci":"cross-env NODE_OPTIONS=--experimental-vm-modules jest --watch","deps":"npm-check -u","test":"cross-env NODE_OPTIONS=--experimental-vm-modules jest --coverage","build":"tsup src/index.js --clean && cp src/index.d.ts dist/index.d.ts"},"repository":{"type":"git","url":"git+https://github.com/moleculerjs/moleculer-io.git"},"keywords":["socket.io","moleculer","websocket","microservice","API Gateway"],"author":{"name":"MoleculerJS"},"license":"MIT","dependencies":{"kleur":"^4.1.5","lodash":"^4.17.21","socket.io":"^4.7.2"},"devDependencies":{"eslint":"^8.51.0","eslint-config-prettier":"^8.5.0","eslint-plugin-node":"^11.1.0","eslint-plugin-prettier":"^4.2.1","eslint-plugin-promise":"^6.1.1","eslint-plugin-security":"^1.5.0","express":"^4.18.2","jest":"^29.7.0","jest-cli":"^29.7.0","moleculer":"^0.14.31","moleculer-repl":"^0.7.4","moleculer-web":"^0.10.6","nodemon":"^3.0.1","prettier":"^3.0.3","socket.io-client":"^4.7.2","socket.io-redis":"^6.1.1","tiny-glob":"^0.2.9","tsup":"^7.2.0","winston":"^3.11.0"},"peerDependencies":{"moleculer":"^0.13.0 || ^0.14.0"},"engines":{"node":">= 10.x.x"},"jest":{"testEnvironment":"node","rootDir":"./src","roots":["../test"],"coverageDirectory":"../coverage","coveragePathIgnorePatterns":["/node_modules/","/test/"]},"exports":{".":{"require":"./dist/index.js","import":"./dist/index.mjs","types":"./dist/index.d.ts"}},"main":"./dist/index.mjs","module":"./dist/index.mjs","types":"./dist/index.d.ts","_id":"@524c/moleculer-io@2.3.0-3","gitHead":"cc4937f7c14deb9f313486fa2bb26835feaa61f4","bugs":{"url":"https://github.com/moleculerjs/moleculer-io/issues"},"homepage":"https://github.com/moleculerjs/moleculer-io#readme","_nodeVersion":"18.19.0","_npmVersion":"10.2.3","dist":{"integrity":"sha512-G51BjTvuldiotuJxzPqz4NpOwyXop7AJ0pyDKy9uMYc8ZF2roveoxi0VYR22kUUQVvA7DFbMhVwBiDdk1tDoXw==","shasum":"bddc23ab7a1fefa5074cfd5a7993bc78ac48a365","tarball":"https://registry.npmjs.org/@524c/moleculer-io/-/moleculer-io-2.3.0-3.tgz","fileCount":6,"unpackedSize":56660,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBv75pfvjMGmZUbl2UhoGCYM71nw1y44MvV9/ALzjQ/SAiBZ6U2VuMgBJQx4UBGsde4pPGbfVpPa/XtThlrcgV4APQ=="}]},"_npmUser":{"name":"524c","email":"rogeriolucas@gmail.com"},"maintainers":[{"name":"524c","email":"rogeriolucas@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/moleculer-io_2.3.0-3_1702856499476_0.05996138684624097"},"_hasShrinkwrap":false},"2.3.0-4":{"name":"@524c/moleculer-io","version":"2.3.0-4","description":"An API GateWay service for Moleculer using Socket.IO","directories":{"example":"examples"},"scripts":{"dev":"nodemon --experimental-specifier-resolution=node examples/index.cjs","dev:client":"iola io ws://localhost:3000","ci":"cross-env NODE_OPTIONS=--experimental-vm-modules jest --watch","deps":"npm-check -u","test":"cross-env NODE_OPTIONS=--experimental-vm-modules jest --coverage","build":"tsup src/index.js --clean && cp src/index.d.ts dist/index.d.ts"},"repository":{"type":"git","url":"git+https://github.com/moleculerjs/moleculer-io.git"},"keywords":["socket.io","moleculer","websocket","microservice","API Gateway"],"author":{"name":"MoleculerJS"},"license":"MIT","dependencies":{"kleur":"^4.1.5","lodash":"^4.17.21","socket.io":"^4.7.2"},"devDependencies":{"eslint":"^8.51.0","eslint-config-prettier":"^8.5.0","eslint-plugin-node":"^11.1.0","eslint-plugin-prettier":"^4.2.1","eslint-plugin-promise":"^6.1.1","eslint-plugin-security":"^1.5.0","express":"^4.18.2","jest":"^29.7.0","jest-cli":"^29.7.0","moleculer":"^0.14.31","moleculer-repl":"^0.7.4","moleculer-web":"^0.10.6","nodemon":"^3.0.1","prettier":"^3.0.3","socket.io-client":"^4.7.2","socket.io-redis":"^6.1.1","tiny-glob":"^0.2.9","tsup":"^7.2.0","winston":"^3.11.0"},"peerDependencies":{"moleculer":"^0.13.0 || ^0.14.0"},"engines":{"node":">= 10.x.x"},"jest":{"testEnvironment":"node","rootDir":"./src","roots":["../test"],"coverageDirectory":"../coverage","coveragePathIgnorePatterns":["/node_modules/","/test/"]},"exports":{".":{"require":"./dist/index.js","import":"./dist/index.mjs","types":"./dist/index.d.ts"}},"main":"./dist/index.mjs","module":"./dist/index.mjs","types":"./dist/index.d.ts","_id":"@524c/moleculer-io@2.3.0-4","gitHead":"f60c23fa7a5e07b8d38edfffc7cd991b02a949b2","bugs":{"url":"https://github.com/moleculerjs/moleculer-io/issues"},"homepage":"https://github.com/moleculerjs/moleculer-io#readme","_nodeVersion":"18.19.0","_npmVersion":"10.2.3","dist":{"integrity":"sha512-apH9YQt/+ylfoXMWcLidIdbho5xugVzRnEnaHL/0TRlvm4Ru4qEh5+XWyTBbcK4YLn/BHfNGdjeXmHAX1oTf/w==","shasum":"618de1826523fd1b20f5a7c77d1658c00bb3cd6d","tarball":"https://registry.npmjs.org/@524c/moleculer-io/-/moleculer-io-2.3.0-4.tgz","fileCount":6,"unpackedSize":56666,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDDMekgqWYgFw1KdgW9JLKl4JM6BtFebCElXSzJ/7fNSAIgJ+apx7qdArBYCy2uIvmdFg9lGKOaSAKdYqhHWlIDik0="}]},"_npmUser":{"name":"524c","email":"rogeriolucas@gmail.com"},"maintainers":[{"name":"524c","email":"rogeriolucas@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/moleculer-io_2.3.0-4_1702857695461_0.8249444094051215"},"_hasShrinkwrap":false}},"maintainers":[{"name":"524c","email":"rogeriolucas@gmail.com"}],"description":"An API GateWay service for Moleculer using Socket.IO","homepage":"https://github.com/moleculerjs/moleculer-io#readme","keywords":["socket.io","moleculer","websocket","microservice","API Gateway"],"repository":{"type":"git","url":"git+https://github.com/moleculerjs/moleculer-io.git"},"author":{"name":"MoleculerJS"},"bugs":{"url":"https://github.com/moleculerjs/moleculer-io/issues"},"license":"MIT","readme":"[![Moleculer logo](http://moleculer.services/images/banner.png)](https://github.com/moleculerjs/moleculer)\n\n[![CI test](https://github.com/moleculerjs/moleculer-io/actions/workflows/ci.yml/badge.svg)](https://github.com/moleculerjs/moleculer-io/actions/workflows/ci.yml)\n[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/moleculerjs/moleculer-io/master/LICENSE)\n[![npm](https://img.shields.io/npm/v/moleculer-io.svg)](https://www.npmjs.com/package/moleculer-io)\n[![Known Vulnerabilities](https://snyk.io/test/github/moleculerjs/moleculer-io/badge.svg)](https://snyk.io/test/github/moleculerjs/moleculer-io)\n[![Downloads](https://img.shields.io/npm/dm/moleculer-io.svg)](https://www.npmjs.com/package/moleculer-io)\n\n<h1>Moleculer-io</h1>\n\nThis is a fork of moleculer-io converted to ESM.\n\nThe `moleculer-io` is a Websocket gateway service for [Moleculer](https://github.com/moleculerjs/moleculer) using `socket.io`.\n\n<h1>Features</h1>\n- Call moleculer actions by emiting Socket.io events.\n- Support Socket.io authorization (Default: `socket.client.user` => moleculer `ctx.meta.user`)\n- Whitelist.\n- Middlewares.\n- Broadcast events.\n- Joining and leaving rooms.\n\n<h1>Install</h1>\n\n```shell\n$ npm install @524c/moleculer-io\n```\n\n<h1>Table of contents</h1>\n<!-- TOC depthFrom:1 depthTo:6 withLinks:1 updateOnSave:1 orderedList:0 -->\n\n-   [Usage](#usage)\n    -   [Init server](#init-server)\n    -   [Handle socket events](#handle-socket-events)\n    -   [Handle multiple events](#handle-multiple-events)\n    -   [Aliases](#aliases)\n        -   [Mapping policy](#mapping-policy)\n    -   [Custom handler](#custom-handler)\n    -   [Handler hooks](#handler-hooks)\n    -   [Calling options](#calling-options)\n    -   [Middlewares](#middlewares)\n    -   [Authorization](#authorization)\n    -   [Joining and leaving rooms](#joining-and-leaving-rooms)\n    -   [Broadcast](#broadcast)\n    -   [CORS](#cors)\n    -   [Using multiple instances](#using-multiple-instances)\n    -   [Logging settings](#logging-settings)\n    -   [Full settings](#full-settings)\n    -   [License](#license)\n    -   [Contact](#contact)\n\n<!-- /TOC -->\n\n# Usage\n\n## Init server\n\nUsing with Node http server:\n\n```javascript\nconst server = require(\"http\").Server(app);\nconst SocketIOService = require(\"moleculer-io\");\nconst ioService = broker.createService({\n\tname: \"io\",\n\tmixins: [SocketIOService]\n});\n\nioService.initSocketIO(server);\n\n// Once the initSocketIO() was called, you can access the io object from ioService.io\nbroker.start();\nserver.listen(3000);\n```\n\nOr let moleculer-io create a server for you:\n\n```javascript\nbroker.createService({\n\tname: \"io\",\n\tmixins: [SocketIOService],\n\tsettings: {\n\t\tport: 3000 //will call initSocketIO() on broker.start()\n\t}\n});\nbroker.start();\n```\n\nOr maybe you want to use it with `moleculer-web`\n\n```js\nconst ApiService = require(\"moleculer-web\");\nconst SocketIOService = require(\"moleculer-io\");\nbroker.createService({\n\tname: \"gateway\",\n\tmixins: [ApiService, SocketIOService], //Should after moleculer-web\n\tsettings: {\n\t\tport: 3000\n\t}\n});\nbroker.start();\n```\n\nIn this case, `moleculer-io` will use the server created by `moleculer-web` .\n\n## Handle socket events\n\nServer:\n\n```javascript\nconst IO = require(\"socket.io\");\nconst { ServiceBroker } = require(\"moleculer\");\nconst SocketIOService = require(\"moleculer-io\");\n\nconst broker = new ServiceBroker();\n\nbroker.createService({\n\tname: \"math\",\n\tactions: {\n\t\tadd(ctx) {\n\t\t\treturn Number(ctx.params.a) + Number(ctx.params.b);\n\t\t}\n\t}\n});\n\nconst ioService = broker.createService({\n\tname: \"io\",\n\tmixins: [SocketIOService],\n\tsettings: {\n\t\tport: 3000\n\t}\n});\n\nbroker.start();\n```\n\nBy default, `moleculer-io` handle the `call` event which will proxy to moleculer's `broker.call`\n\nExamples:\n\n-   Call `test.hello` action without params: `socket.emit('call','test.hello', callback)`\n-   Call `math.add` action with params: `socket.emit('call','math.add', {a:25, b:13}, callback)`\n-   Get health info of node: `socket.emit('call','$node.health', callback)`\n-   List all actions: `socket.emit('call', '$node.actions', callback)`\n\n**Example client:**\n\n```javascript\nconst io = require(\"socket.io-client\");\nconst socket = io(\"http://localhost:3000\");\nsocket.emit(\"call\", \"math.add\", { a: 123, b: 456 }, function (err, res) {\n\tif (err) {\n\t\tconsole.error(err);\n\t} else {\n\t\tconsole.log(\"call success:\", res);\n\t}\n});\n```\n\n## Handle multiple events\n\nYou can create multiple routes with different whitelist, calling options & authorization.\n\n```javascript\nbroker.createService({\n\tname: \"io\",\n\tmixins: [SocketIOService],\n\tsettings: {\n\t\tport: 3000,\n\t\tio: {\n\t\t\tnamespaces: {\n\t\t\t\t\"/\": {\n\t\t\t\t\tevents: {\n\t\t\t\t\t\tcall: {\n\t\t\t\t\t\t\twhitelist: [\"math.add\"],\n\t\t\t\t\t\t\tcallOptions: {}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tadminCall: {\n\t\t\t\t\t\t\twhitelist: [\"users.*\", \"$node.*\"]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\n```\n\n## Aliases\n\nYou can use alias names instead of action names.\n\n```javascript\nbroker.createService({\n\tname: \"io\",\n\tmixins: [SocketIOService],\n\tsettings: {\n\t\tport: 3000,\n\t\tio: {\n\t\t\tnamespaces: {\n\t\t\t\t\"/\": {\n\t\t\t\t\tevents: {\n\t\t\t\t\t\tcall: {\n\t\t\t\t\t\t\taliases: {\n\t\t\t\t\t\t\t\tadd: \"math.add\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\twhitelist: [\"math.add\"],\n\t\t\t\t\t\t\tcallOptions: {}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\n```\n\nThen doing `socket.emit('call','math.add', {a:25, b:13}, callback)` on the client side will be equivalent to `socket.emit('call','add', {a:25, b:13}, callback)`.\n\n### Mapping policy\n\nThe `event` has a `mappingPolicy` property to handle events without aliases.\n\n_Available options:_\n\n-   `all` - enable to handle all actions with or without aliases (default)\n-   `restrict` - enable to handle only the actions with aliases\n\n```javascript\nbroker.createService({\n\tname: \"io\",\n\tmixins: [SocketIOService],\n\tsettings: {\n\t\tport: 3000,\n\t\tio: {\n\t\t\tnamespaces: {\n\t\t\t\t\"/\": {\n\t\t\t\t\tevents: {\n\t\t\t\t\t\tcall: {\n\t\t\t\t\t\t\tmappingPolicy: \"restrict\",\n\t\t\t\t\t\t\taliases: {\n\t\t\t\t\t\t\t\tadd: \"math.add\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tcallOptions: {}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\n```\n\n## Custom handler\n\nYou can make use of custom functions within the declaration of an event handler.\n\n```javascript\nbroker.createService({\n\tname: \"io\",\n\tmixins: [SocketIOService],\n\tsettings: {\n\t\tport: 3000,\n\t\tio: {\n\t\t\tnamespaces: {\n\t\t\t\t\"/\": {\n\t\t\t\t\tevents: {\n\t\t\t\t\t\tcall: {},\n\t\t\t\t\t\tmyCustomEventHandler: function (data, ack) {\n\t\t\t\t\t\t\t// write your handler function here.\n\t\t\t\t\t\t\tlet socket = this;\n\t\t\t\t\t\t\tsocket.emit(\"hello\", \"world\");\n\t\t\t\t\t\t\tsocket.$service.broker.call(\"math.add\", {\n\t\t\t\t\t\t\t\ta: 123,\n\t\t\t\t\t\t\t\tb: 456\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\n```\n\nThere is an internal pointer in socket objects:\n\n-   `socket.$service` is pointed to this service instance.\n\n## Handler hooks\n\nThe event handler has before & after call hooks. You can use it to set ctx.meta, access socket object or modify the response data.\n\n```javascript\nbroker.createService({\n\tname: \"io\",\n\tmixins: [SocketIOService],\n\tsettings: {\n\t\tio: {\n\t\t\tnamespaces: {\n\t\t\t\t\"/\": {\n\t\t\t\t\tevents: {\n\t\t\t\t\t\tcall: {\n\t\t\t\t\t\t\twhitelist: [\"math.*\"],\n\t\t\t\t\t\t\tonBeforeCall: async function (\n\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t\tsocket,\n\t\t\t\t\t\t\t\taction,\n\t\t\t\t\t\t\t\tparams,\n\t\t\t\t\t\t\t\tcallOptions\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t//before hook\n\t\t\t\t\t\t\t\tconsole.log(\"before hook:\", params);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tonAfterCall: async function (ctx, socket, res) {\n\t\t\t\t\t\t\t\t//after hook\n\t\t\t\t\t\t\t\tconsole.log(\"after hook\", res);\n\t\t\t\t\t\t\t\t// res: The respose data.\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\n```\n\n## Calling options\n\nThe handler has a callOptions property which is passed to broker.call. So you can set timeout, retryCount or fallbackResponse options for routes.\n\n```javascript\nbroker.createService({\n  name: 'io',\n  mixins: [SocketIOService],\n  settings: {\n    io: {\n      namespaces: {\n        '/': {\n          events: {\n            'call': {\n              callOptions: {\n                timeout: 500,\n                retryCount: 0,\n                fallbackResponse(ctx, err) { ...\n                }\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n})\n```\n\nNote: If you provide a meta field here, it replaces the socketGetMeta method's result.\n\n## Middlewares\n\nRegister middlewares. Both namespace middlewares and packet middlewares are supported.\n\n```javascript\nbroker.createService({\n\tname: \"io\",\n\tmixins: [SocketIOService],\n\tsettings: {\n\t\tio: {\n\t\t\tnamespaces: {\n\t\t\t\t\"/\": {\n\t\t\t\t\tmiddlewares: [\n\t\t\t\t\t\t//Namespace level middlewares, equipment to namespace.use()\n\t\t\t\t\t\tfunction (socket, next) {\n\t\t\t\t\t\t\tif (socket.request.headers.cookie) return next();\n\t\t\t\t\t\t\tnext(new Error(\"Authentication error\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t\t\tpacketMiddlewares: [\n\t\t\t\t\t\t// equipment to socket.use()\n\t\t\t\t\t\tfunction (packet, next) {\n\t\t\t\t\t\t\tif (packet.doge === true) return next();\n\t\t\t\t\t\t\tnext(new Error(\"Not a doge error\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t\t\tevents: {\n\t\t\t\t\t\tcall: {}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\n```\n\n**Note:** In middlewares the `this` is always pointed to the Service instance.\n\n## Authorization\n\nYou can implement authorization. Do 2 things to enable it.\n\n-   Set `authorization: true` in your namespace\n-   Define the `socketAuthorize` method in service.\n\n```javascript\nbroker.createService({\n\tname: \"io\",\n\tmixins: [SocketIOService],\n\tsettings: {\n\t\tio: {\n\t\t\tnamespaces: {\n\t\t\t\t\"/\": {\n\t\t\t\t\tauthorization: true, // First thing\n\t\t\t\t\tevents: {\n\t\t\t\t\t\tcall: {\n\t\t\t\t\t\t\twhitelist: [\"math.*\", \"accounts.*\"]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tmethods: {\n\t\t// Second thing\n\t\tasync socketAuthorize(socket, eventHandler) {\n\t\t\tlet accessToken = socket.handshake.query.token;\n\t\t\tif (accessToken) {\n\t\t\t\ttry {\n\t\t\t\t\tlet user = await this.broker.call(\"user.verifyToken\", { accessToken });\n\t\t\t\t\treturn { id: user.id, email: user.email, token: accessToken }; // valid credential, return the user\n\t\t\t\t} catch (err) {\n\t\t\t\t\tthrow new UnAuthorizedError(); // invalid credentials\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// anonymous user\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n});\n```\n\nClient:\n\n```javascript\nconst socket = io({\n\tquery: {\n\t\ttoken: \"12345\"\n\t}\n});\n```\n\nSee [`examples/full`](examples/full)\n\nAlso you could overwrite the `socketGetMeta` method to add more addition meta info. The default `socketGetMeta` method is:\n\n```javascript\nsocketGetMeta(socket){\n  return {\n    user: socket.client.user,\n    $rooms: Object.keys(socket.rooms)\n  }\n}\n```\n\nExample to add more additional info:\n\n```javascript\nbroker.createService({\n\tname: \"io\",\n\tmixins: [SocketIOService],\n\tmethods: {\n\t\tsocketGetMeta(socket) {\n\t\t\t//construct the meta object.\n\t\t\treturn {\n\t\t\t\tuser: socket.client.user,\n\t\t\t\t$rooms: Object.keys(socket.rooms),\n\t\t\t\tsocketId: socket.id\n\t\t\t};\n\t\t},\n\t\t// In addition, you can also customize the place where user is stored.\n\t\t// Here is the default method the save user:\n\t\tsocketSaveMeta(socket, ctx) {\n\t\t\tsocket.client.user = ctx.meta.user;\n\t\t}\n\t}\n});\n```\n\nIf you want to authorize a user after socket connected, you can write an action to do it.\n\n```js\nbroker.createService({\n\tname: \"accounts\",\n\tactions: {\n\t\tlogin(ctx) {\n\t\t\tif (ctx.params.user == \"tiaod\" && ctx.params.password == \"pass\") {\n\t\t\t\tctx.meta.user = { id: \"tiaod\" };\n\t\t\t}\n\t\t},\n\t\tgetUserInfo(ctx) {\n\t\t\treturn ctx.meta.user;\n\t\t}\n\t}\n});\n```\n\n## Joining and leaving rooms\n\nIn your action, set `ctx.meta.$join` or `ctx.meta.$leave` to the rooms you want to join or leave.\n\neg.\n\n```javascript\nctx.meta.$join = \"room1\"; //Join room1\nctx.meta.$join = [\"room1\", \"room2\"]; // Join room1 and room2\n\nctx.meta.$leave = \"room1\"; //Leave room1\nctx.meta.$leave = [\"room1\", \"room2\"]; // Leave room1 and room2\n```\n\nAfter the action is finished, `moleculer-io` will join or leave the room you specified.\n\n**Example room management service:**\n\n```javascript\nbroker.createService({\n\tname: \"rooms\",\n\tactions: {\n\t\tjoin(ctx) {\n\t\t\tctx.meta.$join = ctx.params.room;\n\t\t},\n\t\tleave(ctx) {\n\t\t\tctx.meta.$leave = ctx.params.room;\n\t\t},\n\t\tlist(ctx) {\n\t\t\treturn ctx.meta.$rooms;\n\t\t}\n\t}\n});\n```\n\n## Broadcast\n\nIf you want to broadcast event to socket.io from moleculer service:\n\n```javascript\nbroker.call(\"io.broadcast\", {\n\tnamespace: \"/\", //optional\n\tevent: \"hello\",\n\targs: [\"my\", \"friends\", \"!\"], //optional\n\tvolatile: true, //optional\n\tlocal: true, //optional\n\trooms: [\"room1\", \"room2\"] //optional\n});\n```\n\n_Note: You should change the 'io' to the service name you created._\n\n## CORS\n\n`moleculer-io` will pick the `settings.cors.origin` option and use it to validate the request. (Which is also compatible with `moleculer-web`! )\n\n```js\nbroker.createService({\n\tname: \"io\",\n\tmixins: [ApiGateway, SocketIOService],\n\tsettings: {\n\t\tcors: {\n\t\t\torigin: [\"http://example.com\"], //Moleculer-io only pick up this option and set it to io.origins()\n\t\t\tmethods: [\"GET\", \"OPTIONS\", \"POST\", \"PUT\", \"DELETE\"],\n\t\t\tallowedHeaders: [],\n\t\t\texposedHeaders: [],\n\t\t\tcredentials: false,\n\t\t\tmaxAge: 3600\n\t\t}\n\t}\n});\n```\n\nFor detail see https://socket.io/docs/server-api/#server-origins-fn\n\n## Using multiple instances\n\nIf you plan for a highly available setup (launching multiple instances of this service behind a Load Balancer),\nyou will have to take some extra steps. Due to the nature of WebSockets these instances will need a PubSub capable broker\nto connect to, in order to broadcast messages to sockets that are connected to other instances. For a more\nin depth explanation of this concept, and additional steps that have to be taken (such as Load Balancer configuration), refer to the [Socket.io Documentation](https://socket.io/docs/using-multiple-nodes/).\n\nIn order to interconnect this service with other services, start the service with an adapter:\n\n```javascript\nconst broker = new ServiceBroker({\n\ttransporter: \"redis://redis:6379\"\n});\nbroker.createService({\n\tname: \"io\",\n\tmixins: [SocketIOService],\n\tsettings: {\n\t\tport: 3000,\n\t\tio: {\n\t\t\toptions: {\n\t\t\t\tadapter: require(\"socket.io-redis\")(\"redis://redis:6379\")\n\t\t\t}\n\t\t}\n\t}\n});\n```\n\n## Logging settings\n\nIf you want to keep clean your project console or have a more deep way to debug the data sent over the socket you can just change some settings in your service to add/remove logs:\n\n-   **logRequest**: Log all the incoming request through the socket\n-   **logRequestParams**: Log the request params\n-   **logResponse**: Log response data\n-   **logBroadcastRequest**: Log the request to forward to the sockets\n-   **logClientConnection**: Log when a client gets connected\n\nTo start logging something indicate whatever logging level you want:\n\n```javascript\nconst broker = new ServiceBroker({\n    transporter: \"redis://redis:6379\"\n})\nbroker.createService({\n  name: 'io',\n  mixins: [SocketIOService],\n  settings: {\n    logClientConnection: 'info'\n    port: 3000,\n    io: {\n      options: {\n        adapter: require(\"socket.io-redis\")(\"redis://redis:6379\")\n      }\n    }\n  }\n})\n```\n\nlogRequest, logRequestParams, logResponse are adopted from the API gateway, the other ones are managed only in this one and by default they are disabled\n\n## Full settings\n\n```javascript\nsettings: {\n  port: 3000,\n  io: {\n    options: {}, //socket.io options\n    namespaces: {\n      '/':{\n        authorization: false,\n        middlewares: [],\n        packetMiddlewares:[],\n        events: {\n          call: {\n            mappingPolicy: 'all',\n            aliases: {\n              'add': 'math.add'\n            },\n            whitelist: [\n              'math.*'\n            ],\n            callOptions:{},\n            onBeforeCall: async function(ctx, socket, action, params, callOptions){\n              ctx.meta.socketid = socket.id\n            },\n            onAfterCall:async function(ctx, socket, res){\n             socket.emit('afterCall', res)\n            }\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n## License\n\nThe project is available under the [MIT license](https://tldrlegal.com/license/mit-license).\n\n## Contact\n\nCopyright (c) 2021 MoleculerJS\n\n[![@MoleculerJS](https://img.shields.io/badge/github-moleculerjs-green.svg)](https://github.com/moleculerjs) [![@MoleculerJS](https://img.shields.io/badge/twitter-MoleculerJS-blue.svg)](https://twitter.com/MoleculerJS)\n","readmeFilename":"README.md"}