import { RPCServer, RPCSocket } from './Index' import { RPCExporter } from './src/Interfaces' import { RPCInterface } from './src/Types' // TL;DR const echo = (text: string) => text const add = (a: number, b: number) : number => a + b const getAsync = async () : Promise<{topic: string, message:string}>=> await new Promise((res, _) => { setTimeout(() => { res({ topic: "Hey!!", message: "Hello World Async!" }) }, 250) }) const getCallback = (callback: Function) : string => { setTimeout(() => { try{ callback({ topic: "Hey!!", message: "Hello World Callback!" }) }catch(e){ console.log(String(e)) } }, 250) return "Please wait for a callback :)" } new RPCServer(20000, [{ name: 'MyRPCGroup1', exportRPCs: () => [ echo, add, getAsync, { name: 'getCallback', hook: getCallback, onClose: (response, rpc) => { /* ... */ }, onCallback: (...callbackArgs) => { /* ... */ } } ] }]) new RPCSocket(20000, 'localhost').connect().then(async sock => { try{ const RPCs = sock['MyRPCGroup1'] await RPCs.echo("hello!").then(console.log) await RPCs.add(1, Math.PI).then(console.log) await RPCs.getAsync().then(console.log) await RPCs.getCallback(console.log).then(console.log) }catch(e){ console.log(String(e)) } }) //Hooks and events new RPCServer(20001, [{ name: 'MyRPCGroup1', exportRPCs: () => [ echo, add, getAsync, { name: 'getCallback', hook: getCallback, onClose: (response, rpc) => { /* client disconnected */ }, onCallback: (...callbackArgs) => { /* callback triggered */ } } ], }], { visibility: '127.0.0.1', //0.0.0.0 closeHandler: (socket) => { /* global close handler */ }, connectionHandler: (socket) => { /* new connection made */ }, errorHandler: (socket, error, rpcname, argArr) => { /* An error occured inside a RPC */ }, }) const sock = new RPCSocket(20001, 'localhost') sock.on('error', (e) => { /* handle error */ }) sock.on('close', () => { /* handle close event */ }) sock.hook('RPCName', (/* arg0, arg1, ..., argN */) => { /* bind client-side RPCs */ }) //Retrieve the socket from connectionHandler (Server-side) and trigger with //socket.call('RPCName', arg0, arg1, ..., argN) sock.connect().then(_ => { /* ... */}) //Restricting access new RPCServer(20002, [{ name: 'MyRPCGroup1', exportRPCs: () => [ echo, add, getAsync, { name: 'getCallback', hook: getCallback, } ], }], { sesame: "sesame open", /* OR check sesame dynamically and refine permissioning with accessfilter (optional) */ //sesame: (sesame) => true //accessFilter: (sesame, exporter) => { return exporter.name === "MyRPCGroup1" && sesame === "sesame open" }, }) new RPCSocket(20002, 'localhost').connect("sesame open").then(async sock => { try{ const RPCs = sock['MyRPCGroup1'] await RPCs.echo("hello!").then(console.log) await RPCs.add(1, Math.PI).then(console.log) await RPCs.getAsync().then(console.log) await RPCs.getCallback(console.log).then(console.log) }catch(e){ console.log(String(e)) } }) //TypeScript and pseudo-interfaces type MyInterface = { MyRPCGroup1: { echo: (x: string) => string add: (a: number, b: number) => number getAsync: () => Promise<{ topic: string, message: string }> getCallback: (callback:Function) => string } }; /* exportRPCs is now type safe. Try swapping echo for badEcho. Sadly TSC's stack traces aren't the best, but try to scroll to the bottom of them to find useful info like Type '(x: boolean) => number' is not assignable to type '(x: string) => string' */ const badEcho = (x: boolean) : number => 3 new RPCServer(20003, [{ name: 'MyRPCGroup1', exportRPCs: () => [ //badEcho, echo, add, getAsync, { name: 'getCallback', hook: getCallback, } ], }]) new RPCSocket(20003, 'localhost').connect().then(async sock => { try{ await sock.MyRPCGroup1.echo("hello!").then(console.log) await sock.MyRPCGroup1.add(1, Math.PI).then(console.log) await sock.MyRPCGroup1.getAsync().then(console.log) await sock.MyRPCGroup1.getCallback(console.log).then(console.log) }catch(e){ console.log(String(e)) } }) //Class-based pattern interface IMyImplementation { echo: (x: string) => string add: (a: number, b: number) => number getAsync: () => Promise<{ topic: string, message: string }> getCallback: (callback:Function) => string } type IfcGenerator = { [name in Name]: { [key in keys] : Interface[key] } } type MyIfc = IfcGenerator<"MyRPCGroup1", IMyImplementation> class MyImplementation implements IMyImplementation, RPCExporter{ //"X" as "X" syntax is required to satisfy the type system (as it assumes string) name = "MyRpcGroup11" as "MyRPCGroup1" //List the functions you declared in MyIfc exportRPCs = () => [ this.echo, this.add, this.getAsync, this.getCallback ] //Write your implementations as you normally would echo = (text: string) => text add = (a: number, b: number) : number => a + b getAsync = async () : Promise<{topic: string, message:string}>=> await new Promise((res, _) => { setTimeout(() => { res({ topic: "Hey!!", message: "Hello World Async!" }) }, 250) }) getCallback = (callback: Function) : string => { setTimeout(() => { try{ callback({ topic: "Hey!!", message: "Hello World Callback!" }) }catch(e){ console.log(String(e)) } }, 250) return "Please wait for a callback :)" } } new RPCServer(20004, [new MyImplementation(), /* ... other RPCExporters */]) new RPCSocket(20004, 'localhost').connect().then(async sock => { try{ await sock.MyRPCGroup1.echo("hello!").then(console.log) await sock.MyRPCGroup1.add(1, Math.PI).then(console.log) await sock.MyRPCGroup1.getAsync().then(console.log) await sock.MyRPCGroup1.getCallback(console.log).then(console.log) }catch(e){ console.log(String(e)) } })