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 🙏

© 2025 – Pkg Stats / Ryan Hefner

dream_rpc

v0.2.21

Published

DreamRpc is a rpc framework for development bi-directional RPC method call between across standard JavaScript environment such as Web Browser, Node.JS and other mobile development framework using JavaScript, this is the core part of this framework that pl

Readme

What is DreamRpc?

DreamRpc is a general purpose RPC framework that primary designed for easy way to communicate and transfer realtime data across most JavaScript/TypeScript runtimes such as Web browser, Node.JS, Deno and React native like mobile development frameworks, Html5 games etc.

you can use this framework for building realtime data processing applications, Html5 based multiplayer game servers, micro services etc.

Why DreamRpc?

Advantages:

  • Written in TypeScript, object oriented design (also you can use JavaScript)
  • Bi-Directional communication between Rpc server and Rpc client
  • No magic, simple, lightweight and easy to use
  • No callback, no string event handler like "event.on("xxx", callback), event.on("yyy", callback)", all api is designed for Type Safe.

Disadvantages:

  • New so maybe has unknown (or known) bugs
  • under development progress so maybe change API in future
  • Only available on TypeScript/JavaScript at this moment

What languages are available?

  • TypeScript/JavaScript runtime (node.js, web browser, mobile devices, java script game engines)

but we have plan for implement other program languages/platforms,

here is the list of languages/platforms we are planned and future will be implemented:

  • Vala programming language server side (for making high performance game server purpose)
  • PHP server side
  • Dart server side and flutter
  • Kotlin for JVM platforms
  • .Net Core platform.

Quick start in five minutes

first of all, take a look the result of below example

Simple example

in this quick start examples we will make a simple broadcast application

development requirements:

  • Node.js of the latest version
  • TypeScript compiler (this is optional if you want to use JavaScript but we highly recommend using TypeScript for you)
  • Web browser

####feature list should be implemented:

  • some client sends a message to all clients
  • all connected clients will receive the broadcast message.

Write server side code

  1. prepare your package.json and tsconfig.json with following the command (or any methods)
  • create a directory with mkdir broadcast_server and open the dir with cd broadcast_server
  • create a packages.json with npm init (default contents of package.json is enough)
  • create a tsconfig.json with tsc --init (if you have no installed TypeScript compiler then you can install it with npm install typescript --global) the content of tsconfig file looks like this:
{
 "compilerOptions": {
   "target": "EsNext",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
   "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
   "outDir": "./bin",                        /* Redirect output structure to the directory. */
   "rootDir": "./src",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
   "strict": true,                           /* Enable all strict type-checking options. */
   "esModuleInterop": true,                  /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
   "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
   "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
   "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
   "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */
   "skipLibCheck": true,                     /* Skip type checking of declaration files. */
   "forceConsistentCasingInFileNames": true  /* Disallow inconsistently-cased references to the same file. */
 }
}
  • install necessary dependencies with npm (or yarn if you like) on terminal:
    • npm install @types/node --save-dev (for code editor auto complete node.js api)
    • npm install dream_rpc --save (core dependencies for this framework)
    • npm install dream_rpc_node_websocket --save (for websocket host support)
    • npm install ws --save and npm install @types/ws --save-dev (only required for websocket host support)
  • create a src directory for our source code with mkdir src
  • create a TypeScript file named with Shared.ts and put these code into it
    import { IStatefulClientInterface } from "dream_rpc";
    /**
     * Server side rpc methods definition
    */
    export interface IBroadcastServerInterface {
        /**
         * Return value should be return a promise object
         * IF YOU WANT TO two or more parameters then should wrap these parameters at an object like "createUser(args: {name: string, email: string}): Promise<void>" instead of createUser(name: string, email: string): Promise<void>
         */
        sendBroadcast(args: { message: string, sender: string }): Promise<void>
    }
    /**
     * Client side rpc methods definition
    */
    export interface IBroadcastClientInterface extends IStatefulClientInterface {
        onBroadcastReceived(args: { message: string, sender: string }): Promise<void>
    }
    above code is a rpc method definition of server and client, we will implement these definitions on our rpc server and rpc client later
  • create a TypeScript file named MyRpcServer.ts and put below code into it.
    import { RpcClient, RpcServer, State, StateManagerInMemory } from "dream_rpc";
    import { WebSocketServerHost } from "dream_rpc_node_websocket"
    import { IBroadcastClientInterface, IBroadcastServerInterface } from "./Shared";
    import * as Http from "http"
    import WebSocket from "ws";
       
    /**
     * State object of rpc client on server
     */
    class MyBroadcastClientState extends State {}
    /**
     * Server side rpc methods implementation
     */
    class MyBroadcastServerImplementation implements IBroadcastServerInterface {
        /**Non rpc method object names are should be start with "_", for example: "_client", "_xxNotRpcObject", for more details: please visit github (or gitee) documentation.*/
        public constructor(private _client: MyBroadcastClient) {}
        public async sendBroadcast(args: { message: string; sender: string; }): Promise<void> {
            console.log(`A broadcast message received by [${args.sender}] that content of [${args.message}]`)
            /**get all connected clients on this server and send the received message to each */
            this._client.server.clients.forEach((client) => {
                (client as MyBroadcastClient).bridge.remoteInterface.onBroadcastReceived({
                    message: args.message,
                    sender: args.sender
                })
            })
        }
    }
    class MyBroadcastClient extends RpcClient<IBroadcastServerInterface, IBroadcastClientInterface, MyBroadcastClientState> {
        protected async createState(): Promise<MyBroadcastClientState> {
            return new MyBroadcastClientState()
        }
        protected async getLocalInterfaceImplementation(): Promise<IBroadcastServerInterface> {
            return new MyBroadcastServerImplementation(this)
        }
        /**
         * This is optional lifecycle method, don't write if you don't need
         */
        protected async onConnected(): Promise<void> {
            await super.onConnected() //Must call super
            console.log("Client connected")
        }
        /**
         * This is optional lifecycle method, don't write if you don't need
         */
        protected async onReady(): Promise<void> {
            await super.onReady() //Must call super
            console.log("Connected client is now ready to use")
        }
        /**
         * This is optional lifecycle method, don't write if you don't need
         */
        protected async onDisconnected(): Promise<void> {
            await super.onDisconnected() //Must call super
            console.log("Client is disconnected")
        }
    }
    class MyBroadcastServer extends RpcServer<IBroadcastServerInterface, IBroadcastClientInterface, MyBroadcastClientState> {
        protected async createClientInstance(): Promise<RpcClient<IBroadcastServerInterface, IBroadcastClientInterface, MyBroadcastClientState>> {
            return new MyBroadcastClient()
        }
        /**
         * This is optional lifecycle method, don't write if you don't need
         */
        protected async onLaunch(): Promise<void> {
            await super.onLaunch() //Must call super
            console.log("Rpc server is start: [OK]")
        }
        protected async onShutdown(): Promise<void> {
            await super.onShutdown() //Must call super
            console.log("Rpc server is shutdown")
        }
    }
       
    async function main() {
        const httpServer = Http.createServer((request, response) => {
            response.end("Please communicate with WebSocket protocol")
        })
        httpServer.listen(8000)
       
        const myServer = new MyBroadcastServer(
            new WebSocketServerHost(async () => new WebSocket.Server({
                path: "/Broadcast",
                server: httpServer
            })),
            new StateManagerInMemory()
        )
       
        await myServer.prepareForLaunch() //Prepare for launch server, in this step, server is register internal callback for launch
        await myServer.launch() //start rpc server
    }
    main()
    now you can compile this code with tsc and start rpc server with node ./bin/MyRpcServer.js

Write client side code (Node.js as client)

  • Create a TypeScript file in src directory named with MyRpcClient.ts and put following content:
    import { IBroadcastClientInterface, IBroadcastServerInterface } from "./Shared";
    import { IStateModule, RpcBridge, StateModuleInMemoryImplementation } from "dream_rpc";
    import WebSocket from "ws";
    import { WebSocketBridgeHost } from "dream_rpc_node_websocket";
       
    class MyBroadcastClientImplementation implements IBroadcastClientInterface {
        /**
         * Related state management, please visit github (or gitee) documentation
         */
        stateModule: IStateModule = new StateModuleInMemoryImplementation()
        /**
         * Calling when server side occur events related this client.
         * @param error error
         */
        public async sendErrorMessage(error: string): Promise<void> {
            console.error(error)
        }
       
        public async onBroadcastReceived(args: { message: string; sender: string; }): Promise<void> {
            console.log(`A message received by [${args.sender}] with the following content:`)
            console.log(args.message)
        }
    }
       
    async function main() {
        const client = new RpcBridge<IBroadcastClientInterface, IBroadcastServerInterface>(
            new WebSocketBridgeHost(async () => new WebSocket("ws://127.0.0.1:8000/Broadcast")),
            new MyBroadcastClientImplementation()
        )
        await client.connect()
        await client.remoteInterface.sendBroadcast({
            sender: "مۇختەرجان",
            message: "Hello there, I'm coming..."
        })
    }
    main()
  • compile with tsc and run with node ./bin/MyRpcClient.js

Write client code(Web browser version)

actually the client code can be run directly on web browser, but there some a little difference:

  • For older version of browsers, we should use some techniques like babel for support ES6 features
  • Web browsers are not support ES6 style module import/export statements, so we should change our code to browser compatible code, of course we can use some techniques likewebpack.

this framework provided browser compatible versions of necessary libraries.

so where I find it? actually npm packages of this framework is contain browser compatible versions in its directory.

  • Get necessary dependency files
    • node_modules/dream_rpc/bin/dream_rpc_browser.development.js or node_modules/dream_rpc/bin/dream_rpc_browser.production.js
    • node_modules/dream_rpc_node_websocket/bin/dream_rpc.websocket_bridge_host.development.js or node_modules/dream_rpc_node_websocket/bin/dream_rpc.websocket_bridge_host.production.js
  • browser compatible version of the client code, for this, create a new html file under src folder named with MyRpcClient.html and put the following code:
    <html>
        <script src="../node_modules/dream_rpc/bin/dream_rpc_browser.production.js"></script>
        <script src="../node_modules/dream_rpc_node_websocket/bin/dream_rpc.websocket_bridge_host.production.js"></script>
            <div style="position: absolute; top: 0; right: 0; bottom: 0; left: 0; display: flex; flex-direction: column;">
                <div style="flex-grow: 1; overflow: auto;" id="screen"></div>
                <div style="display: flex; height: 150px;">
                    <textarea id="content" style="flex-grow: 1;"></textarea>
                </div>
                <div style="display: flex; flex-direction: row;">
                    <input type="text" id="sender">
                    <button onclick="sendBroadcast()">Send</button>
                </div>
            </div>
        <script>
            const display = document.getElementById("screen")
            const content = document.getElementById("content")
            const sender = document.getElementById("sender")
       
            let client
            class MyBroadcastClientImplementation {
                constructor() {
                    /**
                     * Related state management, please visit github (or gitee) documentation
                     */
                    this.stateModule = new dream_rpc.StateModuleInMemoryImplementation();
                }
                /**
                 * Calling when server side occur events related this client.
                 * @param error error
                 */
                async sendErrorMessage(error) {
                    console.error(error);
                }
                async onBroadcastReceived(args) {
                    let content = `A message received by [${args.sender}] with the following content: [${args.message}]`
                    console.log(content)
                    display.innerText += content + "\n"
                }
            }
            async function main() {
                client = new dream_rpc.RpcBridge(new dream_rpc_node_websocket.WebSocketBridgeHost(async () => new WebSocket("ws://127.0.0.1:8000/Broadcast")), new MyBroadcastClientImplementation());
                await client.connect();
                display.innerText += "Connect to RPC server: [OK]\n"
            }
            async function sendBroadcast() {
                await client.remoteInterface.sendBroadcast({
                    sender: sender.value,
                    message: content.value
                })
            }
            main();
        </script>
    </html>

Open this file with your web browser that support ES6 features like Chrome, FireFox, Vivaldi, Microsoft edge chromium etc.

Also you can get full code at: https://gitee.com/yeganaaa/dream-rpc-core-examples

Fundamentals

Architecture

Architecture

Lifecycle

Lifecycle

this framework consists some basic concepts that:

  • Rpc server, this is corresponds Http server in http frameworks but Rpc server is not stateless
  • Rpc client, this is corresponds Http client, but rpc client is not stateless
  • State management, maybe this is corresponding session in http servers but also has some difference, state management is responsible to save/restore user state when rpc client is connecting/disconnecting
  • Transport layer, Rpc server has no any transport functionality, so it is dependent on transport layer like Tcp socket, Web socket, Http long pooling etc.

Detailed explains

first of all, this framework is fully bi-directional (of course, this is optional if you don't need this). so we need to define a set of rpc methods on both server side and client side, we can directly call these rpc methods from anther way.

for example: we want to make a chat room application

on the server side, we will define some methods like "createRoom", "deleteRoom", "joinToRoom", "leaveFromRoom", "sendMessageToRoom"

client side we will need to define some methods like "onRoomCreated", "onRoomDeleted", "onUserJoin", "onUserLeave", "onMessageReceived" etc.

on the server side, we can directly call client side methods, and on the client side, directly call server side methods.

Rpc server

Rpc server is a high abstraction of socket server, it has its own lifecycle and management methods such as "start", "stop".

it's responsible to manage rpc client connections, for example: accept and create, hold rpc client instance, manage clients state through StateManager.

all rpc client instances are holds by rpc server, we can get all connected client instances using "someRpcServer.clients" property, and foreach them, call each client rpc methods.

Rpc client

rpc client is high abstraction of socket client, also rpc client has its own lifecycles and management methods, this is correspond a user, a client, rpc client holds a state object that save the client state, a bridge object consists server side rpc methods implementation object and client side rpc methods implementation delegate object, we can make actual rpc call through these implementation objects. they are will details on below example.

State management

State management is a concept that if a user disconnects from server then server will save the client state, if client is reconnect, server restore the client state into rpc client instance object. rpc client instance has a property called state, this state object is corresponds "session" in http server.

for example: we make a simple game, user has score in the game, if the user connection is lost and reconnect after 5 second, then server should be save and restore the score of the user.

State object of rpc client is can do this. we can save client temporary data to the state object in client instance like user has login or not.

Transport layer

both rpc server and rpc client is a high level abstraction of socket server and socket client, but they are no have actual communication functionality.

so we need a actual transport layer like TcpSocket, WebSocket or other

so we need to supply some actual transport layer to Rpc server and rpc client, maybe this transport layer is tcp socket or web socket or other.

at the moment, we have done some popular transport layers implementation, TcpSocket and WebSocket.

we can customize our own transport layers for security needs or other requirements

for example, we need to encrypt and decrypt the data before/after sending or compress and decompress the data before/after sending. also for these requirements, we can make our custom transport layer on top of another already existing transport layers, this is very easy.