{"id":17215230,"url":"https://github.com/doctormckay/node-websocket13-jsonrpc","last_synced_at":"2025-03-25T13:20:27.108Z","repository":{"id":143928561,"uuid":"266435905","full_name":"DoctorMcKay/node-websocket13-jsonrpc","owner":"DoctorMcKay","description":"JSON-RPC 2.0 server over WebSockets","archived":false,"fork":false,"pushed_at":"2023-09-29T04:48:15.000Z","size":104,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-02T11:17:34.674Z","etag":null,"topics":["json-rpc","websocket"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/websocket13-jsonrpc","language":"TypeScript","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/DoctorMcKay.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2020-05-23T23:21:57.000Z","updated_at":"2024-10-13T15:13:12.000Z","dependencies_parsed_at":null,"dependency_job_id":"b9d1920e-a44f-45e5-852d-41eddf718c33","html_url":"https://github.com/DoctorMcKay/node-websocket13-jsonrpc","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DoctorMcKay%2Fnode-websocket13-jsonrpc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DoctorMcKay%2Fnode-websocket13-jsonrpc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DoctorMcKay%2Fnode-websocket13-jsonrpc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DoctorMcKay%2Fnode-websocket13-jsonrpc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DoctorMcKay","download_url":"https://codeload.github.com/DoctorMcKay/node-websocket13-jsonrpc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245467610,"owners_count":20620216,"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":["json-rpc","websocket"],"created_at":"2024-10-15T03:23:44.336Z","updated_at":"2025-03-25T13:20:27.050Z","avatar_url":"https://github.com/DoctorMcKay.png","language":"TypeScript","funding_links":["https://github.com/sponsors/DoctorMcKay"],"categories":[],"sub_categories":[],"readme":"# websocket13-jsonrpc\n[![npm version](https://img.shields.io/npm/v/websocket13-jsonrpc.svg)](https://npmjs.com/package/websocket13-jsonrpc)\n[![npm downloads](https://img.shields.io/npm/dm/websocket13-jsonrpc.svg)](https://npmjs.com/package/websocket13-jsonrpc)\n[![license](https://img.shields.io/npm/l/websocket13-jsonrpc.svg)](https://github.com/DoctorMcKay/node-websocket13-jsonrpc/blob/master/LICENSE)\n[![sponsors](https://img.shields.io/github/sponsors/DoctorMcKay.svg)](https://github.com/sponsors/DoctorMcKay)\n\nThis is a server implementation of [JSON-RPC 2.0](https://www.jsonrpc.org/specification) over WebSockets.\n\nA browser client implementation is available under [`browser`](https://github.com/DoctorMcKay/node-websocket13-jsonrpc/tree/master/browser).\nIf you want to write your own implementation, the only special consideration is that incoming connections **must** support\nthe subprotocol `jsonrpc-2.0`.\n\nPlease note that this server implementation does not support JSON-RPC batches, since that practically isn't useful over\na transport like WebSocket.\n\n# Exports\n\nThe module exports the following:\n\n- [`ConnectionState`](#connectionstate) - An enum indicating the state an individual connection is in\n- [`JsonRpcErrorCode`](#jsonrpcerrorcode) - An enum containing reserved JSON-RPC error codes\n- [`WebSocketStatusCode`](#websocketstatuscode) - An enum containing WebSocket closure status codes\n- [`RpcError`](#rpcerror) - An extension to `Error` used for responding to RPC calls with errors\n- [`WsRpcConnection`](#wsrpcconnection) - An object representing individual connections\n- [`WsRpcServer`](#wsrpcserver) - An object for running a server\n- [`WsRpcOutgoingConnection`](#wsrpcoutgoingconnection) - An object representing outgoing connections\n\n# ConnectionState\n\n[See enum here](https://github.com/DoctorMcKay/node-websocket13-jsonrpc/blob/master/enums/ConnectionState.ts)\n\n# JsonRpcErrorCode\n\n[See enum here](https://github.com/DoctorMcKay/node-websocket13-jsonrpc/blob/master/enums/JsonRpcErrorCode.ts)\n\nReserved JSON-RPC error codes [are defined here](https://www.jsonrpc.org/specification#error_object).\n\n# WebSocketStatusCode\n\n[See enum here](https://github.com/DoctorMcKay/node-websocket13-jsonrpc/blob/master/enums/WebSocketStatusCode.ts)\n\n# RpcError\n\nConstructed with 3 parameters:\n\n- `message` - A string containing an error message\n- `code` - A number containing an error code (MUST be an integer)\n- `data` - An optional value of any type to be sent along with the error\n\n### Example\n\n```js\nconst {RpcError} = require('websocket13-jsonrpc2');\n\nthrow new RpcError('File not found', 100, {filename: '/root/example.txt'});\n```\n\n# WsRpcConnection\n\n**This class is not to be instantiated directly.**\n\n## Properties\n\n### id\n\nA string containing a UUIDv4 assigned to this connection.\n\n### remoteAddress\n\nThe remote IP address.\n\n### server\n\nThe [`WsRpcServer`](#wsrpcserver) that spawned this connection.\n\n### state\n\nThe state of this connection. This is a value from [`ConnectionState`](#connectionstate)\n\n### handshakeData\n\nThe data object from the `handshake` event for this connection.\n\n### groups\n\nAn array containing the string name of each group that this connection is a member of.\n\n## Methods\n\n### disconnect(statusCode[, reason])\n- `statusCode` - A value from [`WebSocketStatusCode`](#websocketstatuscode)\n- `reason` - An optional string reason for the closure\n\nCloses an active connection. If the connection is already closed, does nothing.\n\n### getPeerCertificate([detailed])\n\nSame as [`tls.TLSSocket.getPeerCertificate`](https://nodejs.org/api/tls.html#tls_tlssocket_getpeercertificate_detailed).\nReturns `null` if the current connection is not secure.\n\n### getSecurityProtocol()\n\nSame as [`tls.TLSSocket.getProtocol`](https://nodejs.org/api/tls.html#tls_tlssocket_getprotocol).\nReturns `null` if the current connection is not secure.\n\n### data(key[, value])\n- `key` - String\n- `value` - Any type\n\nAssociate any arbitrary data with this connection. If `value` is undefined, returns the current value of `key`.\nIf `value` is defined, sets `key` to that `value` and returns the previous value.\n\n### ping()\n\nSends a ping frame to the remote. Returns a Promise that is resolved with the time in milliseconds that it took to\nreceive the reply.\n\n#### Example\n\n```js\nasync function pingClient() {\n    let latency = await client.ping();\n    console.log(`Client ${client.id}'s latency is ${latency} milliseconds.`);\n}\n```\n\n### joinGroup(group)\n- `group` - String group name\n\nJoins this connection to a group. Groups are used to broadcast messages to groups of connections all at once.\nFor example, you might put connections in a particular chat room into one group, or you might put connections\nauthenticated to a given user ID in a dedicated group.\n\nGroups are ad-hoc and are created or destroyed as needed.\n\nReturns `true` if this connection was joined to the group successfully, or `false` if it was already in the given group.\n\n### leaveGroup(group)\n- `group` - String group name\n\nLeaves this connection from a group. If this was the last member of the group, the group is destroyed.\n\nReturns `true` if this connection left the group successfully, or `false` if it was not in the given group.\n\n### notify(method[, params])\n- `method` - String method name\n- `params` - Any data type\n\nSends a notification to the remote. JSON-RPC notifications are messages which may not be responded to.\n\nReturns `true` if the notification was sent, or `false` if the connection was not open.\n\n### invoke(method[, params])\n- `method` - String method name\n- `params` - Any data type\n\nSends a request to the remote. Returns a Promise that will be resolved with the result of the request, or rejected with\na [`RpcError`](#rpcerror) if the request fails.\n\n## Events\n\n### latency\n- `pingTime` - Round-trip latency in milliseconds\n\nEmitted periodically (unless you've disabled pings in options) with the latency of the connection.\n\n# WsRpcServer\n\nThis class instantiates a WebSocket server.\n\nThe constructor takes a single `options` object:\n\n- `requireObjectParams` - See below\n- All other options from [`WS13.WebSocketServer`](https://github.com/DoctorMcKay/node-websocket13/wiki/WebSocketServer#options)\n  are allowed, except `protocols`.\n\n### requireObjectParams\n\nIf `requireObjectParams` is set to true, then the following will happen:\n\n- If the `params` property of incoming messages is undefined or null, it will be converted to `{}` (empty object)\n- If the `params` property of incoming messages is not an object, array, undefined, or null, then the message will be\n  rejected with error code -32602 and message `\"Invalid params\"`\n- If the `params` property of outgoing messages is undefined or null, it will be converted to `{}` (empty object)\n\nThis option is designed to allow you to do things like this without worrying about invalid incoming params causing a crash:\n\n```js\nserver.registerMethod('Add', (connection, [a, b]) =\u003e {\n\tif (typeof a != 'number' || typeof b != 'number') {\n\t\tthrow new RpcError('An operand is not a number', JsonRpcErrorCode.InvalidParams);\n    }\n\t\n    return a + b;\n});\n```\n\nThe module cannot validate that the incoming `params` object actually contains the keys you're expecting, so you still\nneed to check their types and values yourself.\n\n## Events\n\n### handshake\n- `handshakeData`\n- `reject`\n- `accept`\n\nSame as [websocket13's handshake event](https://github.com/DoctorMcKay/node-websocket13/wiki/WebSocketServer#handshake),\nwith these exceptions:\n\n- `accept()` returns a [`WsRpcConnection`](#wsrpcconnection) instead of a `WebSocket`\n- It is not possible to override `protocol` in `accept()`\n\n**This event must be handled or else all incoming connections will stall.**\n\n### connect\n- `connection` - The [`WsRpcConnection`](#wsrpcconnection) that connected\n\nEmitted when a new connection is established.\n\n### disconnect\n- `connection` - The [`WsRpcConnection`](#wsrpcconnection) that disconnected\n- `code` - A value from [`WebSocketStatusCode`](#websocketstatuscode)\n- `reason` - A string, possibly empty, describing why they disconnected\n- `initiatedByUs` - A boolean indicating whether the disconnection was initiated by the server (true) or by the client (false)\n\nEmitted when a remote disconnects.\n\n## Properties\n\n### connections\n\nAn array containing all currently-active [`WsRpcConnection`](#wsrpcconnection) objects.\n\n### groups\n\nAn array containing strings of the names of all groups that currently have members.\n\n## Methods\n\n### http(server)\n- `server` - Either an [`http.Server`](https://nodejs.org/api/http.html#http_class_http_server) or an [`https.Server`](https://nodejs.org/api/https.html#https_class_https_server)\n\nListen for WebSocket connections on this server. You can call this for more than one HTTP(S) server, but you shouldn't call it more than once per server. For example, if you're accepting both secure and insecure connections, you should call this once with an HTTP server, and once with an HTTPS server.\n\nThis binds to the server's `upgrade` event. If nothing else has bound to that event, then `node-websocket13` will respond to bad handshakes with an HTTP 400 response. Otherwise, it will do nothing. Bad handshakes are those which match any of the following criteria:\n\n- `Upgrade` header does not match the value `websocket` (case-insensitively)\n- `Connection` header does not contain the value `upgrade` (case-insensitively, interpreting the header value as a comma-separated list)\n    - For example, `Connection: keep-alive, upgrade` is valid, but `Connection: keep-alive upgrade` is not\n- Client HTTP version is not at least 1.1\n- Client request method is not `GET`\n- Client request is missing `Sec-WebSocket-Key` header or when base64-decoded, it is not 16 bytes in length\n- Client request is missing `Sec-WebSocket-Version` header or the header's value is not `13`\n\n### groupMembers(group)\n- `group` - Either a group name or an array of group names\n\nReturns an array of [`WsRpcConnection`](#wsrpcconnection) objects for the members in the given set of groups. If you\npass a single string, returns the list of members of that group. If you pass an array of strings, returns a de-duplicated\nunion of group members.\n\n### registerMethod(name, handler)\n- `name` - String method name\n- `handler` - A function to be invoked when the method is called\n\nRegisters a new method. When JSON-RPC messages invoking this method are received, the `handler` will be called with the\nsignature `(WsRpcConnection connection, any params)`.\n\nPlease note that unless the [`requireObjectParams`](#requireobjectparams) option is set, `params` can be any JSON type\n(including null or undefined).\n\nThe `handler` function must return either a response value or a `Promise` which is resolved to the response value.\nIf an error occurs while processing this method, you must throw (or reject the `Promise` with) a [`RpcError`](#rpcerror),\nwhich will be sent to the remote as an error response.\n\nBy default, if a method invocation is received that does not match any registered method, a method not found error will\nbe sent back. If you want to process unregistered methods yourself, you can use the DEFAULT_HANDLER symbol.\n\n#### Example\n\n```js\nconst {RpcError, JsonRpcErrorCode, DEFAULT_HANDLER} = require('websocket13-jsonrpc2');\n\nserver.registerMethod('Add', (connection, params) =\u003e {\n    if (typeof params != 'object' || !Array.isArray(params) || params.length != 2 || typeof params[0] != 'number' || typeof params[1] != 'number') {\n        throw new RpcError('Invalid params', JsonRpcErrorCode.InvalidParams);    \n    }\n    \n    return params[0] + params[1];\n});\n\nserver.registerMethod('AddAsync', async (connection, params) =\u003e {\n    if (typeof params != 'object' || !Array.isArray(params) || params.length != 2 || typeof params[0] != 'number' || typeof params[1] != 'number') {\n        throw new RpcError('Invalid params', JsonRpcErrorCode.InvalidParams);    \n    }\n    \n    await new Promise((resolve) =\u003e setTimeout(resolve, 1000));\n    return params[0] + params[1];\n});\n\n// This is only safe if you've enabled requireObjectParams, otherwise an incoming params value that isn't an object or\n// array will cause a crash.\nserver.registerMethod('Subtract', (connection, [a, b]) =\u003e {\n\tif (typeof a != 'number' || typeof b != 'number') {\n\t\tthrow new RpcError('Invalid params', JsonRpcErrorCode.InvalidParams);\n    }\n\t\n\treturn a - b;\n});\n\nserver.registerMethod(DEFAULT_HANDLER, (connection, method, params) =\u003e {\n\tconsole.log(`Client ${connection.id} invoked unregistered method ${method} with params ${params}`);\n\treturn 1;\n});\n```\n\n### registerNotification(name, handler)\n- `name` - String name\n- `handler` - A function to be invoked when the notification is received\n\nRegisters a new notification. When JSON-RPC messages containing this notification are received, the `handler` will be\ncalled with the signature `(WsRpcConnection connection, any params)`.\n\nPlease note that unless the [`requireObjectParams`](#requireobjectparams) option is set, `params` can be any JSON type\n(including null or undefined).\n\nAs a JSON-RPC notification requires no response, `handler` should not return anything.\n\nYou can also register a default handler for notifications in the same way as for methods.\n\n### notify(group, name[, params])\n- `group` - String name of group or array of string names of groups to send notification to.\n            Use `null` to send a notification to all active clients.\n- `name` - String name of notification to send\n- `params` - Any data type\n\nSends a JSON-RPC notification to an entire group at once. You can also pass an array of groups to send a notification\nto all members of all specified groups.\n\nReturns a number indicating how many clients received this notification.\n\n### notifyAll(name[, params])\n- `name` - String name of notification to send\n- `params` - Any data type\n\nSends a JSON-RPC notification to all connected clients.\nReturns a number indicating how many clients received this notification.\n\n# WsRpcOutgoingConnection\n\n**This class extends [`WsRpcConnection`](#wsrpcconnection). Methods, properties, and events inherited from that class\nare not listed below, so you should check those docs as well.**\n\nUsed to establish outgoing connections. You should instantiate a new instance of this class to establish a new outgoing\nconnection to a JSON-RPC server.\n\nThe constructor takes two arguments:\n\n- `url` - The WebSocket URL you want to connect to (e.g. `ws://example.com/?some=query`)\n- `options` - Optional. An object with zero or more of these properties:\n    - `requireObjectParams` - See [`requireObjectParams`](#requireobjectparams) documentation for `WsRpcServer`\n    - All other options from [`WS13.WebSocket`](https://github.com/DoctorMcKay/node-websocket13/wiki/WebSocket#options)\n      are allowed, except `protocols`.\n      \n#### Example\n\n```js\nconst {WsRpcOutgoingConnection} = require('websocket13-jsonrpc');\n\nlet conn = new WsRpcOutgoingConnection('ws://127.0.0.1:8080', {pingInterval: 30000});\n```\n\n## Properties\n\n### server\n\nAlways `null` for outgoing connections.\n\n### groups\n\nAlways `[]` (empty array) for outgoing connections.\n\n## Methods\n\n### joinGroup()\n\nOutgoing connections cannot be joined to groups, so this method throws an Error if invoked.\n\n### leaveGroup()\n\nOutgoing connections cannot be joined to groups, so this method throws an Error if invoked.\n\n### registerMethod(name, handler)\n- `name` - String\n- `handler` - Function\n\nFunctionally identical to [`WsRpcServer#registerMethod(name, handler)`](#registermethodname-handler).\nThis is how you should register methods for outgoing connections.\n\n### registerNotification(name, handler)\n- `name` - String\n- `handler` - Function\n\nFunctionally identical to [`WsRpcServer#registerNotification(name, handler)`](#registernotificationname-handler).\nThis is how you should register notifications for outgoing connections.\n\n## Events\n\n### connected\n- `details` - An object containing connection details. Identical to [`WS13.WebSocket#connected`](https://github.com/DoctorMcKay/node-websocket13/wiki/WebSocket#connected)\n\nEmitted when the connection is successfully established.\n\n### disconnected\n- `code` - A value from [`WebSocketStatusCode`](#websocketstatuscode)\n- `reason` - A string, possibly empty, describing why we disconnected\n- `initiatedByUs` - A boolean indicating whether the disconnected was initiated by us/the client (true) or by the server (false)\n\nEmitted when we disconnect from the server.\n\n### error\n- `err` - An `Error` object\n\nEmitted when a fatal error causes our connection to fail (while connecting) or be disconnected (while connected).\nUnder certain conditions, `err` may contain zero or more of these properties:\n\n- `responseCode` - The HTTP status code we received if the error occurred during the handshake\n- `responseText` - The HTTP status text we received if the error occurred during the handshake\n- `httpVersion` - The HTTP version employed by the server if the error occurred during the handshake\n- `headers` - An object containing the HTTP headers we received from the server if the error occurred during the handshake\n- `expected` - A string containing the `Sec-WebSocket-Accept` value we expected to receive, if the error occurred because we didn't\n- `actual` - A string containing the actual `Sec-WebSocket-Accept` value we received, if the error occurred because it didn't match what we expected\n- `state` - The connection state at the time of error. Always present.\n- `code` - A value from the `WS13.StatusCode` enum, if the error occurred after the WebSocket connection was established\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdoctormckay%2Fnode-websocket13-jsonrpc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdoctormckay%2Fnode-websocket13-jsonrpc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdoctormckay%2Fnode-websocket13-jsonrpc/lists"}