{"id":43727919,"url":"https://github.com/flatmax/jrpc-oo","last_synced_at":"2026-02-05T09:13:32.620Z","repository":{"id":58688165,"uuid":"533113338","full_name":"flatmax/jrpc-oo","owner":"flatmax","description":"Expose objects over the network using the JSON-RPC 2.0 protocol. This repository provides implementations in Node.js, LitElement (Web Components), and Python, allowing seamless RPC communication between different platforms.","archived":false,"fork":false,"pushed_at":"2025-12-18T03:56:59.000Z","size":303,"stargazers_count":0,"open_issues_count":2,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-12-21T13:40:21.778Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/flatmax.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-09-06T01:14:04.000Z","updated_at":"2025-12-18T03:57:03.000Z","dependencies_parsed_at":"2025-05-18T07:26:45.531Z","dependency_job_id":"6ffeb9d0-8af0-4b1a-ae0b-05b7382de089","html_url":"https://github.com/flatmax/jrpc-oo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/flatmax/jrpc-oo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flatmax%2Fjrpc-oo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flatmax%2Fjrpc-oo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flatmax%2Fjrpc-oo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flatmax%2Fjrpc-oo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/flatmax","download_url":"https://codeload.github.com/flatmax/jrpc-oo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flatmax%2Fjrpc-oo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29117921,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T05:31:32.482Z","status":"ssl_error","status_checked_at":"2026-02-05T05:31:29.075Z","response_time":65,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":"2026-02-05T09:13:31.937Z","updated_at":"2026-02-05T09:13:32.614Z","avatar_url":"https://github.com/flatmax.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# jrpc-oo\n\nExpose objects over the network using JSON-RPC 2.0 over WebSockets. Implementations for Node.js, LitElement (browser), and Python enable seamless cross-platform RPC communication.\n\n## Table of Contents\n\n- [Features](#features)\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [RPC Calling Pattern](#rpc-calling-pattern)\n- [Node.js](#nodejs)\n  - [Server](#nodejs-server)\n  - [Client](#nodejs-client)\n- [Browser (LitElement)](#browser-litelement)\n- [Python](#python)\n  - [Server](#python-server)\n  - [Client](#python-client)\n- [Bidirectional Communication](#bidirectional-communication)\n- [Running the Demos](#running-the-demos)\n- [Security (WSS)](#security-wss)\n- [License](#license)\n\n## Features\n\n- **JSON-RPC 2.0** protocol over WebSockets\n- **Bidirectional RPC**: Server can call client methods and vice versa\n- **Cross-platform**: Node.js, Browser (LitElement), and Python implementations\n- **Automatic method exposure**: Simply add a class and all its methods become callable\n- **Multiple client support**: Server can manage many connected clients\n- **Secure WebSocket (WSS)** support with certificate generation\n\n## Installation\n\n### Node.js / Browser\n\n```bash\nnpm install\n```\n\n### Python\n\n```bash\npip install -e .\n# Or install dependencies directly:\npip install websockets asyncio\n```\n\n## Quick Start\n\n### 1. Start a Server (Node.js)\n\n```bash\n./JRPCServerTest.js\n```\n\n### 2. Connect a Client (Browser)\n\n```bash\nnpm start\n# Visit https://0.0.0.0:8081\n```\n\n### 3. Or Connect a Python Client\n\n```bash\npython jrpc_oo/tests/JRPCClientTest.py ws://0.0.0.0:9000\n```\n\n## RPC Calling Pattern\n\nAll implementations use the same consistent pattern:\n\n```\nobject['ClassName.methodName'](arg1, arg2, ...)\n```\n\n| Platform | Syntax |\n|----------|--------|\n| JavaScript | `this.server['TestClass.fn2'](arg1, arg2).then(result =\u003e ...)` |\n| Python | `result = await self.server['TestClass.fn2'](arg1, arg2)` |\n\nCall all connected remotes:\n\n| Platform | Syntax |\n|----------|--------|\n| JavaScript | `this.call['ClassName.method'](args).then(results =\u003e ...)` |\n| Python | `results = await self.call['ClassName.method'](args)` |\n\nResults from `call` return a dictionary: `{uuid: result, ...}` for each connected remote.\n\n## Node.js\n\n### Node.js Server\n\n```javascript\nconst JRPCServer = require('./JRPCServer');\n\nclass Calculator {\n  add(a, b) {\n    return a + b;\n  }\n  \n  multiply(a, b) {\n    return a * b;\n  }\n}\n\nconst calc = new Calculator();\nconst server = new JRPCServer.JRPCServer(9000, 60, false); // port, timeout, ssl\nserver.addClass(calc);\n\nconsole.log('Server running on ws://0.0.0.0:9000');\n```\n\n### Node.js Client\n\n```javascript\nconst JRPCNodeClient = require('./JRPCNodeClient').JRPCNodeClient;\n\nclass ClientMethods {\n  // Methods here can be called by the server\n  notify(message) {\n    console.log('Server says:', message);\n    return 'received';\n  }\n}\n\nconst client = new JRPCNodeClient('ws://0.0.0.0:9000');\nclient.addClass(new ClientMethods());\n\n// Once connected, call server methods:\n// client.server['Calculator.add'](2, 3).then(result =\u003e console.log(result));\n```\n\n## Browser (LitElement)\n\n```javascript\nimport { JRPCClient } from './jrpc-client.js';\n\nclass MyApp extends JRPCClient {\n  constructor() {\n    super();\n    this.remoteTimeout = 60;\n  }\n\n  // Called when connection is ready\n  setupDone() {\n    // Now you can call server methods\n    this.testCalculator();\n  }\n\n  async testCalculator() {\n    try {\n      const sum = await this.server['Calculator.add'](5, 3);\n      console.log('5 + 3 =', sum);\n      \n      const product = await this.server['Calculator.multiply'](4, 7);\n      console.log('4 * 7 =', product);\n    } catch (e) {\n      console.error('RPC error:', e);\n    }\n  }\n\n  // This method can be called BY the server\n  showAlert(message) {\n    alert(message);\n    return 'alert shown';\n  }\n}\n\ncustomElements.define('my-app', MyApp);\n```\n\n```html\n\u003cmy-app serverURI=\"ws://0.0.0.0:9000\"\u003e\u003c/my-app\u003e\n```\n\n## Python\n\n### Python Server\n\n```python\nimport asyncio\nfrom jrpc_oo import JRPCServer\n\nclass Calculator:\n    def add(self, a, b):\n        return a + b\n    \n    def multiply(self, a, b):\n        return a * b\n\nasync def main():\n    server = JRPCServer(port=9000)\n    server.add_class(Calculator())\n    \n    await server.start()\n    print('Server running on ws://0.0.0.0:9000')\n    \n    # Keep running\n    await asyncio.Future()\n\nasyncio.run(main())\n```\n\n### Python Client\n\n```python\nimport asyncio\nfrom jrpc_oo import JRPCClient\n\nclass ClientMethods:\n    \"\"\"Methods the server can call on this client.\"\"\"\n    def notify(self, message):\n        print(f'Server says: {message}')\n        return 'received'\n\nasync def main():\n    client = JRPCClient('ws://0.0.0.0:9000')\n    client.add_class(ClientMethods())\n    \n    # Connect and wait for setup\n    connect_task = asyncio.create_task(client.connect())\n    \n    # Wait for connection\n    await asyncio.sleep(2)\n    \n    if client.connected:\n        # Call server methods\n        result = await client.server['Calculator.add'](10, 20)\n        print(f'10 + 20 = {result}')\n        \n        result = await client.server['Calculator.multiply'](6, 7)\n        print(f'6 * 7 = {result}')\n    \n    await connect_task\n\nasyncio.run(main())\n```\n\n## Bidirectional Communication\n\nThe server can call methods on connected clients:\n\n### Server Side (Node.js)\n\n```javascript\nclass ServerClass {\n  constructor() {\n    // get_server() is added when class is registered\n  }\n  \n  async triggerClientAlert() {\n    // Call method on connected client\n    const result = await this.getServer()['ClientMethods.showAlert']('Hello from server!');\n    console.log('Client responded:', result);\n  }\n}\n```\n\n### Server Side (Python)\n\n```python\nclass ServerClass:\n    async def trigger_client_alert(self):\n        # Call method on connected client\n        result = await self.get_server()['ClientMethods.show_alert']('Hello from server!')\n        print(f'Client responded: {result}')\n```\n\n## Running the Demos\n\n### Node.js Server + Browser Client\n\n```bash\n# Terminal 1: Start the server\n./JRPCServerTest.js\n\n# Terminal 2: Start the web server\nnpm start\n\n# Browser: Visit https://0.0.0.0:8081\n# (First visit https://0.0.0.0:9000 to accept the self-signed certificate)\n```\n\n### Node.js Server + Multiple Node.js Clients\n\n```bash\n./tests/multiTest.sh\n```\n\n### Python Server + Browser Client\n\n```bash\n# Terminal 1: Start Python server\npython jrpc_oo/tests/JRPCServerTest.py no_wss\n\n# Terminal 2: Start web server\nnpm run start:no_wss\n\n# Browser: Visit http://0.0.0.0:8081\n```\n\n### Python Server + Python Client\n\n```bash\n# Terminal 1: Start server\npython jrpc_oo/tests/JRPCServerTest.py no_wss\n\n# Terminal 2: Connect client\npython jrpc_oo/tests/JRPCClientTest.py ws://0.0.0.0:9000\n```\n\n## Security (WSS)\n\nFor secure WebSocket connections, certificates are auto-generated on first run:\n\n```bash\n# Node.js with WSS (default)\n./JRPCServerTest.js\n\n# Node.js without WSS\n./JRPCServerTest.js no_wss\n\n# Python with WSS (uses mkcert)\npython jrpc_oo/tests/JRPCServerTest.py\n\n# Python without WSS\npython jrpc_oo/tests/JRPCServerTest.py no_wss\n```\n\nWhen using WSS with self-signed certificates, visit `https://0.0.0.0:9000` in your browser first to accept the certificate.\n\n## License\n\nBSD-3-Clause. See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflatmax%2Fjrpc-oo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fflatmax%2Fjrpc-oo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflatmax%2Fjrpc-oo/lists"}