ts-rpc-node

This is a simple RPC framwork.It serves a small amount services well.

Usage no npm install needed!

<script type="module">
  import tsRpcNode from 'https://cdn.skypack.dev/ts-rpc-node';
</script>

README

Build Status npm npm NpmLicense Coverage Status

ts-rpc

  • npm i ts-rpc-node
  • source code
  • See bin/test for javascript example

How it works?

Your all services connnect to a proxy server. The proxy server is responsible for forwarding data packets. If the proxy server is not connected, the client will continue to try again and again.

typescript example

// server.ts
// Create proxy server.
import { IServerOptions, createProxy, ServerHandle } from "ts-rpc-node";

const opts: IServerOptions = {
    listen: {
        host: 'localhost',
        port: 25165,
    },
    token: 'JZYKMUsG2I4t6TulbpXigKHCI2E2cC6YE84H0Los2XWL/wap+Db0xv5K/aolcQIL',
};

const proxyserver: ServerHandle = createProxy(opts);
// client1.ts
import * as rpc from 'ts-rpc-node';

class Calculate {
    public Addition(a: number, b: number, next: (err: any, ret: number) => void) {
        if (typeof a !== 'number') {
            return next('a should be number type', 0);
        }
        if (typeof b !== 'number') {
            return next('b should be number type', 0);
        }
        next(null, a + b);
    }

    public RectangleArea(data: { height: number, width: number }, next?: (err: any, ret: number) => void) {
        if (typeof data.height !== 'number' || typeof data.width !== 'number') {
            if (next) {
                next('data err', 0);
            }
            return 0;
        }
        const area = data.height * data.width;
        if (next) {
            next(null, area);
        }
        return area;
    }
}

export class MyApp {
    public calcu = new Calculate();

    public sayHello(msg: string) {
        console.log('hello,', msg);
    }
}
const app = new MyApp();

function test() {
    const OPTS: rpc.IClientOptions = {
        connect: {
            host: 'localhost',
            port: 25165,
        },
        service: 'myapp-1',
        token: 'JZYKMUsG2I4t6TulbpXigKHCI2E2cC6YE84H0Los2XWL/wap+Db0xv5K/aolcQIL',
    };
    const client: rpc.ClientHandle = rpc.createClient(OPTS, app, () => {
        console.log('registe success');
    });
    // if client has no 'on',you should npm install @types/node --save-dev
    client.on(rpc.CLIENTHANDLE_EVENT.OTHER_RIGISTED, (name: string) => {
        console.log('I find another app registed', name);
    });
}

test();
// client2.ts
import { IClientOptions, createClientSync, ClientHandle, simplerpc, promirpc } from "ts-rpc-node";
import { MyApp as Clinet1APP } from './client1';

const OPTS: IClientOptions = {
    service: 'myapp-2',
    connect: {
        host: 'localhost',
        port: 25165,
    },
    token: 'JZYKMUsG2I4t6TulbpXigKHCI2E2cC6YE84H0Los2XWL/wap+Db0xv5K/aolcQIL',
};

class MyAPP2 {
    public rpc: Clinet1APP;
    constructor(client: ClientHandle) {
        this.rpc = client.ProxyRoute();
    }
}

async function test() {
    const client = await createClientSync(OPTS);
    const app = new MyAPP2(client);
    // example for 'notice'
    simplerpc({ service: 'myapp-1' }, app.rpc.sayHello)('Peach');
    client.SetCallFuncOpts({ service: 'myapp-1' }); // set the default target service
    simplerpc(app.rpc.sayHello)('Guava');

    // example for 'request'
    simplerpc(app.rpc.calcu.Addition)(3, 3, (err: any, ret: number) => {
        console.log('Addition result', ret);
    });
    const area: number = await promirpc(app.rpc.calcu.RectangleArea)({ height: 50, width: 30 });
    console.log('Rectangle Area1 is', area);
    simplerpc({ service: 'myapp-1', timeout: 50 }, app.rpc.calcu.RectangleArea)({ height: 20, width: 40 }, (err: any, ret: number) => {
        console.log('Rectangle Area2 is', ret)
    });
}

test();

simplerpc()

Wrapper of RPC function

Possible signatures:

  • simplerpc(rpcFunc)
  • simplerpc(options,rpcFunc)

simplerpc(rpcFunc)

Parameters:

  • rpcFunc «Function»

Returns:

  • «Function»

simplerpc(options,rpcFunc)

Parameters:

Returns:

  • «Function»

promirpc()

Wrapper of RPC function, return by promise.

Possible signatures:

  • promirpc(rpcFunc)
  • promirpc(options,rpcFunc)

promirpc(rpcFunc)

Parameters:

  • rpcFunc «Function»

Returns:

  • «Promise<T>» T is rpcFunc's return type.

promirpc(rpcFunc)

Parameters:

Returns:

  • «Promise<T>» T is rpcFunc's return type.

Class:ClientHandle

Event:CLIENTHANDLE_EVENT.REGISTED

  • key «string» My service's name.
  • others «string[]»Name Array of other services.

Emitted when the client successfully registe in proxy server.

Event:CLIENTHANDLE_EVENT.CLOSE

  • error «any»

Emitted when the connection between client and proxy server is disconnected.

Event:CLIENTHANDLE_EVENT.OTHER_RIGISTED

  • key «string» Other service's name.

Emitted when other service successfully registe in proxy server.

Event:CLIENTHANDLE_EVENT.OTHER_CLOSE

  • key «string» Other service's name.

Emitted when the connection between a service and proxy server is disconnected.

client.SetEnv

  • app «any» the context

Set the context for other app's rpc

client.Remove

Disconnect from proxy server and release all references.

client.ProxyRoute

  • [attr] «string»

Proxy attribute.

// client1.ts
app.rpc=client.ProxyRoute('recv') as TestA;
simplerpc({service:'client2'},app.rpc.print)('everybody');
// client2.ts
class TestA{
    print(msg){
        console.log('hello',msg);
    }
}
app.recv=new TestA();

client.SetCallFuncOpts

simplerpc or promirpc will use this opts if you do not give a ICallFuncOption. client.SetCallFuncOpts(undefined) will clear opts you set before.

client.setEncodeDecode

  • encode «Function»
  • decode «Function»

The default encode:JSON.stringify,decode:JSON.parse. Call this method to set your own encode,decode for rpc's arguments.

createClient

Parameters:

Returns:

createClientSync

Parameters:

Returns:

Class:ServerHandle

Properties:

  • tokencheck «boolean»Open tokencheck by setting true, close by false. True is Default.If it's false, checking will not effect either client sends token or not.
  • newtoken «string»You can Update token string. It will be priority before IServerOptions.token.

server.Remove

Close proxy server and release all references.

createProxy

Parameters:

Returns:

interface

ICallFuncOption

  • service «string|string[]» The target service's name.This name is the unique identifier for each service.Giving a string array means the rpc will be broadcast to these services as a notice.
  • [timeout] «number»
  • [ignorecb] «boolean» Default false. When you use simplerpc, if the last argument is Function type, it means a notice, not a request. Set the option true to force the rpc to be a notice.And The last argument will be encode even it is a Function.
  • [bytes] «number» The default size of a pack is 1MB. And the head of pack may take tens of bytes.You can set a right number by this option.

IClientOptions

  • service «string» The unique string different from ench service.
  • connect «Object»
    • host «string»
    • port «number»
  • [logger] «any» You can set console or log4js to print logs.
  • [coding] «string»
  • [callback_timeout] «number»
  • [token] «string»

IServerOptions

  • listen «Object»
    • host «string»
    • port «number»
    • [exclusive] «boolean»
  • [logger] «any» You can set console or log4js to print logs.
  • [coding] «string»
  • [token] «string»