npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@flatmax/jrpc-oo

v1.2.0

Published

Expose objects using the JRPC2 protocol.

Readme

jrpc-oo

Expose 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.

Table of Contents

Features

  • JSON-RPC 2.0 protocol over WebSockets
  • Bidirectional RPC: Server can call client methods and vice versa
  • Cross-platform: Node.js, Browser (LitElement), and Python implementations
  • Automatic method exposure: Simply add a class and all its methods become callable
  • Multiple client support: Server can manage many connected clients
  • Secure WebSocket (WSS) support with certificate generation

Installation

Node.js / Browser

npm install

Python

pip install -e .
# Or install dependencies directly:
pip install websockets asyncio

Quick Start

1. Start a Server (Node.js)

./JRPCServerTest.js

2. Connect a Client (Browser)

npm start
# Visit https://0.0.0.0:8081

3. Or Connect a Python Client

python jrpc_oo/tests/JRPCClientTest.py ws://0.0.0.0:9000

RPC Calling Pattern

All implementations use the same consistent pattern:

object['ClassName.methodName'](arg1, arg2, ...)

| Platform | Syntax | |----------|--------| | JavaScript | this.server['TestClass.fn2'](arg1, arg2).then(result => ...) | | Python | result = await self.server['TestClass.fn2'](arg1, arg2) |

Call all connected remotes:

| Platform | Syntax | |----------|--------| | JavaScript | this.call['ClassName.method'](args).then(results => ...) | | Python | results = await self.call['ClassName.method'](args) |

Results from call return a dictionary: {uuid: result, ...} for each connected remote.

Node.js

Node.js Server

const JRPCServer = require('./JRPCServer');

class Calculator {
  add(a, b) {
    return a + b;
  }
  
  multiply(a, b) {
    return a * b;
  }
}

const calc = new Calculator();
const server = new JRPCServer.JRPCServer(9000, 60, false); // port, timeout, ssl
server.addClass(calc);

console.log('Server running on ws://0.0.0.0:9000');

Node.js Client

const JRPCNodeClient = require('./JRPCNodeClient').JRPCNodeClient;

class ClientMethods {
  // Methods here can be called by the server
  notify(message) {
    console.log('Server says:', message);
    return 'received';
  }
}

const client = new JRPCNodeClient('ws://0.0.0.0:9000');
client.addClass(new ClientMethods());

// Once connected, call server methods:
// client.server['Calculator.add'](2, 3).then(result => console.log(result));

Browser (LitElement)

import { JRPCClient } from './jrpc-client.js';

class MyApp extends JRPCClient {
  constructor() {
    super();
    this.remoteTimeout = 60;
  }

  // Called when connection is ready
  setupDone() {
    // Now you can call server methods
    this.testCalculator();
  }

  async testCalculator() {
    try {
      const sum = await this.server['Calculator.add'](5, 3);
      console.log('5 + 3 =', sum);
      
      const product = await this.server['Calculator.multiply'](4, 7);
      console.log('4 * 7 =', product);
    } catch (e) {
      console.error('RPC error:', e);
    }
  }

  // This method can be called BY the server
  showAlert(message) {
    alert(message);
    return 'alert shown';
  }
}

customElements.define('my-app', MyApp);
<my-app serverURI="ws://0.0.0.0:9000"></my-app>

Python

Python Server

import asyncio
from jrpc_oo import JRPCServer

class Calculator:
    def add(self, a, b):
        return a + b
    
    def multiply(self, a, b):
        return a * b

async def main():
    server = JRPCServer(port=9000)
    server.add_class(Calculator())
    
    await server.start()
    print('Server running on ws://0.0.0.0:9000')
    
    # Keep running
    await asyncio.Future()

asyncio.run(main())

Python Client

import asyncio
from jrpc_oo import JRPCClient

class ClientMethods:
    """Methods the server can call on this client."""
    def notify(self, message):
        print(f'Server says: {message}')
        return 'received'

async def main():
    client = JRPCClient('ws://0.0.0.0:9000')
    client.add_class(ClientMethods())
    
    # Connect and wait for setup
    connect_task = asyncio.create_task(client.connect())
    
    # Wait for connection
    await asyncio.sleep(2)
    
    if client.connected:
        # Call server methods
        result = await client.server['Calculator.add'](10, 20)
        print(f'10 + 20 = {result}')
        
        result = await client.server['Calculator.multiply'](6, 7)
        print(f'6 * 7 = {result}')
    
    await connect_task

asyncio.run(main())

Bidirectional Communication

The server can call methods on connected clients:

Server Side (Node.js)

class ServerClass {
  constructor() {
    // get_server() is added when class is registered
  }
  
  async triggerClientAlert() {
    // Call method on connected client
    const result = await this.getServer()['ClientMethods.showAlert']('Hello from server!');
    console.log('Client responded:', result);
  }
}

Server Side (Python)

class ServerClass:
    async def trigger_client_alert(self):
        # Call method on connected client
        result = await self.get_server()['ClientMethods.show_alert']('Hello from server!')
        print(f'Client responded: {result}')

Running the Demos

Node.js Server + Browser Client

# Terminal 1: Start the server
./JRPCServerTest.js

# Terminal 2: Start the web server
npm start

# Browser: Visit https://0.0.0.0:8081
# (First visit https://0.0.0.0:9000 to accept the self-signed certificate)

Node.js Server + Multiple Node.js Clients

./tests/multiTest.sh

Python Server + Browser Client

# Terminal 1: Start Python server
python jrpc_oo/tests/JRPCServerTest.py no_wss

# Terminal 2: Start web server
npm run start:no_wss

# Browser: Visit http://0.0.0.0:8081

Python Server + Python Client

# Terminal 1: Start server
python jrpc_oo/tests/JRPCServerTest.py no_wss

# Terminal 2: Connect client
python jrpc_oo/tests/JRPCClientTest.py ws://0.0.0.0:9000

Security (WSS)

For secure WebSocket connections, certificates are auto-generated on first run:

# Node.js with WSS (default)
./JRPCServerTest.js

# Node.js without WSS
./JRPCServerTest.js no_wss

# Python with WSS (uses mkcert)
python jrpc_oo/tests/JRPCServerTest.py

# Python without WSS
python jrpc_oo/tests/JRPCServerTest.py no_wss

When using WSS with self-signed certificates, visit https://0.0.0.0:9000 in your browser first to accept the certificate.

License

BSD-3-Clause. See LICENSE for details.