Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
peter 5690a572d3 v 1.2.1 5 gadus atpakaļ
src v 1.2.1 5 gadus atpakaļ
test v 1.2.1 5 gadus atpakaļ
.drone.yml push 5 gadus atpakaļ
.gitignore automate documentation 5 gadus atpakaļ
.npmignore fix 5 gadus atpakaļ
README.md v 1.2.1 5 gadus atpakaļ
package-lock.json 1.2.1 5 gadus atpakaļ
package.json v 1.2.1 5 gadus atpakaļ
tsconfig.json werks 5 gadus atpakaļ

README.md

About

rpclibrary is a websocket on steroids!

How to install

npm i rpclibrary

Quickstart

import {Backend, Frontend} from 'rpclibrary'

const echo = (x) => x

const server = new Backend.RPCServer(20000, [{
    name: 'HelloWorldRPCGroup',
    exportRPCs: ()  => [
        echo, //named function variable
        function echof(x){ return x }, //named function
        {
            name: 'echoExplicit', //describing object
            call: async (x) => x
        }
    ]
}])

const client = new Frontend.RPCSocket(20000, 'localhost')

client.connect().then(async () => {
    const r0 = await client['HelloWorldRPCGroup'].echo('Hello')
    const r1 = await client['HelloWorldRPCGroup'].echof('World')
    const r2 = await client['HelloWorldRPCGroup'].echoExplicit('RPC!')

    console.log(r0,r1,r2) //Hello World RPC!
})

Using callbacks

rpclibrary offers a special type of call that can be used with callbacks. The callback has to be the last argument and may be the only passed function.

In order to function, some metadata has to be included in the return value of hooks. On success, the function is expected to return a type SubscriptionResponse = { result: 'Success', uuid: string } or in case of errors a type ErrorResposne = { result: 'Error' }.

The uuid, as the name implies, is used to uniquely identify the callback for a given invocation and also dictates the name given to the client-side RPC which you should unhook once you’re done with it.

import {Backend, Frontend, Utils} from 'rpclibrary'

const callbacks:Map<string, Function> = new Map()

const server = new Backend.RPCServer(20000, [{
    name: 'HelloWorldRPCGroup',
    exportRPCs: ()  => [
        function  triggerCallbacks(...messages){ callbacks.forEach(cb => cb.apply({}, messages)) },
        {
            name: 'subscribe',
            hook: async (callback) => {
                const resp = Utils.makeSubResponse() //Convenience method to generate SubscriptionResponse
                callbacks.set(resp.uuid, callback); 
                return resp
            }
        },{
            name: 'unsubscribe',
            call: async (uuid) => { callbacks.delete(uuid) }
        }
    ]
}])

const client = new Frontend.RPCSocket(20000, 'localhost')
client.connect().then(async () => {
    const res = await client['HelloWorldRPCGroup'].subscribe(async (...args:any) => {
        console.log.apply(console, args)

        /* close the callbacks once you're done */
        await client['HelloWorldRPCGroup'].unsubscribe(res.uuid)
        client.unhook(res.uuid)
    })

    await client['HelloWorldRPCGroup'].triggerCallbacks("Hello", "World", "Callbacks")
})

If you need to include further response data into your SubscriptionResponse you can extend it using the server’s first generic parameter SubResType

new RPCServer<{extension: string}>({
    exportRPCs: ()  => [
        {
            name: 'subscribe',
            hook: async (callback) => {
                return {
                    result: 'Success',
                    uuid: 'very_random_string',
                    extension: 'your_data_here'
                }
            }
        }
    ]
})

Experimental typing support

It is possible to declare pseudo-interfaces for servers and clients by using server’s second generic parameter. This feature is currently still in development and considered unstable and untested. Use with caution.

type MyInterface = RPCInterface<{ 
    Group1: { 
        triggerCallbacks: (...args:any[]) => Promise<void>,
        subscribe: (param:string, callback:Function) => Promise<SubscriptionResponse<{a: string}>>,
        unsubscribe: (uuid:string) => Promise<void>
    },
    Group2: {
        echo: (x:string) => Promise<string>
    }
}>

Create a client using

RPCSocket.makeSocket<MyInterface>(port, host).then((async (client) => {
    const r = await client.Group2.echo("hee") //tsc knows about available RPCs 
}))

/* OR */

const client = new Frontend.RPCSocket(20000, 'localhost')
client.connect<MyInterface>().then((async (client) => {
    const r = await client.Group2.echo("hee") //tsc knows about available RPCs 
})) 

Create a server using

new RPCServer<{a:string}, MyInterface>(20001, 
    [{
        //...
    },{
        name: 'Group2', //Auto completion for names
        exportRPCs: () => [{
            name: 'echo', //this name too!
            call: async (x) => x+"llo World!" //the paramter and return types are known by tsc 
        }]
    }]
)

Documentation

[https://gitea.frontblock.me/fw-docs/rpclibrary]