fix
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
import * as Back from './src/backend/RPCSocketServer';
|
||||
import * as Front from './src/frontend/RPCSocket';
|
||||
|
||||
export {
|
||||
Back as Backend,
|
||||
Front as Frontend
|
||||
}
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "rpclibrary",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.3",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
+39
-20
@@ -18,17 +18,46 @@ export {
|
||||
export class Server{
|
||||
private ws = http.createServer()
|
||||
private io = bsock.createServer()
|
||||
private visibility:T.Visibility
|
||||
private closeHandler:T.CloseHandler
|
||||
private errorHandler: T.ErrorHandler
|
||||
private connectionHandler: T.ConnectionHandler
|
||||
|
||||
|
||||
constructor(
|
||||
private port:number,
|
||||
private exporters: I.Exporter[] = [],
|
||||
private conf: T.SocketConf = {
|
||||
errorHandler: (socket:I.Socket) => (error:any) => { socket.destroy(); console.error(error) },
|
||||
closeHandler: (socket:I.Socket) => () => { console.log("Socket closing") },
|
||||
connectionHandler: (socket:I.Socket) => { console.log("New websocket connection in port "+socket.port)},
|
||||
visibility: "127.0.0.1"
|
||||
}
|
||||
conf: T.SocketConf = {}
|
||||
){
|
||||
|
||||
if(!conf.visibility) this.visibility = "127.0.0.1"
|
||||
|
||||
if(!conf.errorHandler) this.errorHandler =
|
||||
(socket:I.Socket) => (error:any) => {
|
||||
socket.destroy();
|
||||
console.error(error)
|
||||
}
|
||||
|
||||
if(!conf.closeHandler) this.closeHandler =
|
||||
(socket:I.Socket) => () => {
|
||||
console.log("Socket on port "+socket.port+"closing")
|
||||
}
|
||||
|
||||
if(!conf.connectionHandler) this.connectionHandler =
|
||||
(socket:I.Socket) => {
|
||||
console.log("New websocket connection in port "+socket.port)
|
||||
}
|
||||
|
||||
let badRPC
|
||||
if(badRPC = exporters.flatMap(ex => ex.exportRPCs()).find(rpc => !rpc.name))
|
||||
throw new Error(`
|
||||
RPC did not provide a name.
|
||||
\nUse funtion name(..){ .. } syntax instead.
|
||||
\n
|
||||
\n<------------OFFENDING RPC:
|
||||
\n`+badRPC.toString()+`
|
||||
\n>------------OFFENDING RPC`)
|
||||
|
||||
this.startWebsocket()
|
||||
}
|
||||
|
||||
@@ -36,14 +65,12 @@ export class Server{
|
||||
try{
|
||||
this.io.attach(this.ws)
|
||||
this.io.on('socket', (socket:I.Socket) => {
|
||||
socket.on('error', this.conf.errorHandler(socket))
|
||||
socket.on('close', this.conf.closeHandler(socket))
|
||||
if(this.conf.visibility === "127.0.0.1")
|
||||
socket.on('error', this.errorHandler(socket))
|
||||
socket.on('close', this.closeHandler(socket))
|
||||
this.connectionHandler(socket)
|
||||
this.initRPCs(socket)
|
||||
else
|
||||
this.initPublicRPCs(socket)
|
||||
})
|
||||
this.ws.listen(this.port, this.conf.visibility)
|
||||
this.ws.listen(this.port, this.visibility)
|
||||
}catch(e){
|
||||
//@ts-ignore
|
||||
this.errorHandler(undefined)("Unable to connect to socket")
|
||||
@@ -57,12 +84,4 @@ export class Server{
|
||||
...this.exporters.flatMap(exporter => U.rpcHooker(socket, exporter))
|
||||
]
|
||||
}
|
||||
|
||||
protected initPublicRPCs(socket:I.Socket){
|
||||
socket.hook('info', () => rpcInfos)
|
||||
|
||||
const rpcInfos:T.ExtendedRpcInfo[] = [
|
||||
...this.exporters.flatMap(exporter => U.rpcHooker(socket, exporter))
|
||||
]
|
||||
}
|
||||
}
|
||||
+4
-6
@@ -1,6 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
var bsock = require('bsock')
|
||||
import bsock = require('bsock');
|
||||
|
||||
import * as T from './Types';
|
||||
import * as U from './Utils';
|
||||
@@ -26,8 +26,6 @@ export class Client implements I.Socket{
|
||||
constructor(public port:number, private server: string, private tls: boolean = false){
|
||||
}
|
||||
|
||||
|
||||
|
||||
public hook(name: T.Name, args: T.Arg){
|
||||
return this.socket.hook(name, args)
|
||||
}
|
||||
@@ -96,9 +94,9 @@ export class Client implements I.Socket{
|
||||
return eval( `( () => async (`+headerArgs+(headerArgs.length!==0?",":"")+` callback) => {
|
||||
const r = await this.socket.call("`+fnName+`", `+argParams+`)
|
||||
if(r.uid != null){
|
||||
this.socket.hook(res.uid, callback)
|
||||
this.socket.hook(r.uid, callback)
|
||||
}
|
||||
return res
|
||||
return r
|
||||
} )()` )
|
||||
}
|
||||
|
||||
@@ -111,7 +109,7 @@ export class Client implements I.Socket{
|
||||
return eval( `( () => async (`+headerArgs+`) => {
|
||||
const r = await this.socket.call("`+fnName+`", `+argParams+`)
|
||||
this.socket.unhook(`+argParams+`)
|
||||
return res
|
||||
return r
|
||||
} )()` )
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -3,8 +3,7 @@ import * as I from "./Interfaces"
|
||||
|
||||
export interface Exporter{
|
||||
name: T.Name
|
||||
localRPCs() : T.RPC[]
|
||||
publicRPCs() : T.RPC[]
|
||||
exportRPCs() : T.RPC[]
|
||||
}
|
||||
|
||||
export interface Socket {
|
||||
|
||||
+10
-8
@@ -6,12 +6,14 @@ export type Any = any
|
||||
export type Arg = string
|
||||
export type Name = Arg
|
||||
export type Owner = Name
|
||||
|
||||
export type ConnectionHandler = (socket:I.Socket) => void
|
||||
export type ErrorHandler = (socket:I.Socket) => (error:any) => void
|
||||
export type CloseHandler = (socket:I.Socket) => () => void
|
||||
export type SocketConf = {
|
||||
connectionHandler: (socket:I.Socket) => void
|
||||
errorHandler: (socket:I.Socket) => (error:any) => void
|
||||
closeHandler: (socket:I.Socket) => () => void
|
||||
visibility: Visibility
|
||||
connectionHandler?: ConnectionHandler
|
||||
errorHandler?: ErrorHandler
|
||||
closeHandler?: CloseHandler
|
||||
visibility?: Visibility
|
||||
}
|
||||
|
||||
export type RPCType = 'Hook' | 'Unhook' | 'Call'
|
||||
@@ -23,7 +25,7 @@ export type BaseRPC = {
|
||||
|
||||
export type HookRPC = BaseRPC & {
|
||||
type: 'Hook'
|
||||
clbk: CallbackFunction
|
||||
hook: CallbackFunction
|
||||
unhook: UnhookFunction
|
||||
}
|
||||
|
||||
@@ -32,10 +34,10 @@ export type UnhookRPC = BaseRPC & {
|
||||
unhook: UnhookFunction
|
||||
}
|
||||
|
||||
export type CallRPC = BaseRPC & {
|
||||
export type CallRPC = (BaseRPC & {
|
||||
type: 'Call'
|
||||
call: AsyncFunction
|
||||
}
|
||||
} ) | Function
|
||||
|
||||
export type RPC = CallRPC | UnhookRPC | HookRPC
|
||||
|
||||
|
||||
+24
-4
@@ -4,6 +4,8 @@ import * as T from "./Types";
|
||||
import * as I from "./Interfaces";
|
||||
|
||||
export const rpcToRpcinfo = (rpc : T.RPC, owner: T.Owner):T.RpcInfo => {
|
||||
switch (typeof rpc){
|
||||
case "object":
|
||||
switch(rpc.type){
|
||||
case "Call" :
|
||||
return {
|
||||
@@ -32,10 +34,29 @@ export const rpcToRpcinfo = (rpc : T.RPC, owner: T.Owner):T.RpcInfo => {
|
||||
generator: generator,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "function":
|
||||
if(!rpc.name) throw new Error(`
|
||||
RPC did not provide a name.
|
||||
\nUse funtion name(..){ .. } syntax instead.
|
||||
\n
|
||||
\n<------------OFFENDING RPC:
|
||||
\n`+rpc.toString()+`
|
||||
\n>------------OFFENDING RPC`)
|
||||
return {
|
||||
type: "Call",
|
||||
owner : owner,
|
||||
argNames: extractArgs(rpc),
|
||||
call: async(...args) => rpc.apply({}, args),
|
||||
name: rpc.name
|
||||
}
|
||||
}
|
||||
throw new Error("Bad socketIORPC type "+ typeof rpc)
|
||||
}
|
||||
|
||||
export function rpcHooker(socket: I.Socket, exporter:I.Exporter, makeUnique = true):T.ExtendedRpcInfo[]{
|
||||
const owner = exporter.name
|
||||
const RPCs = [...exporter.publicRPCs(), ...exporter.localRPCs()]
|
||||
const RPCs = [...exporter.exportRPCs()]
|
||||
const suffix = makeUnique?"-"+uuid().substr(0,4):""
|
||||
return RPCs.map(rpc => rpcToRpcinfo(rpc, owner))
|
||||
.map(info => {
|
||||
@@ -59,12 +80,12 @@ export function rpcHooker(socket: I.Socket, exporter:I.Exporter, makeUnique = tr
|
||||
}
|
||||
|
||||
const hookGenerator = (rpc:T.HookRPC): T.HookInfo['generator'] => {
|
||||
const argsArr = extractArgs(rpc.clbk)
|
||||
const argsArr = extractArgs(rpc.hook)
|
||||
argsArr.pop()
|
||||
const args = argsArr.join(',')
|
||||
|
||||
return eval(`(socket) => async (`+args+`) => {
|
||||
const res = await rpc.clbk(`+args+(args.length!==0?',':'')+` (x) => {
|
||||
const res = await rpc.hook(`+args+(args.length!==0?',':'')+` (x) => {
|
||||
socket.call(res.uid, x)
|
||||
})
|
||||
if(res.result == 'Success'){
|
||||
@@ -72,7 +93,6 @@ const hookGenerator = (rpc:T.HookRPC): T.HookInfo['generator'] => {
|
||||
const unhookRes = await rpc.unhook(res.uid)
|
||||
console.log("Specific close handler for", rpc.name, res.uid, unhookRes)
|
||||
})
|
||||
|
||||
}
|
||||
return res
|
||||
}`)
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ const frontendConf = {
|
||||
target: "web",
|
||||
entry: path.resolve(__dirname, '..', 'js', 'src', 'Frontend.js'),
|
||||
output: {
|
||||
path: path.resolve(__dirname, '..', 'js', 'src'),
|
||||
path: path.resolve(__dirname, '..', 'js', 'rpclibrary.browser.js'),
|
||||
filename: "Frontend.js",
|
||||
libraryTarget: 'commonjs',
|
||||
},
|
||||
|
||||
+28
-3
@@ -1,11 +1,36 @@
|
||||
import { Server } from '../src/Backend'
|
||||
import { SubscriptionResponse } from '../src/Responses'
|
||||
|
||||
let subcallback
|
||||
|
||||
new Server(20000, [{
|
||||
name: "HelloWorldRPCGroup",
|
||||
publicRPCs: () => [],
|
||||
localRPCs: () => [{
|
||||
exportRPCs: () => [{
|
||||
type: 'Call',
|
||||
name: 'echo',
|
||||
call: async (s:string) => s,
|
||||
}]
|
||||
},
|
||||
{
|
||||
type: 'Hook',
|
||||
name: 'subscribe',
|
||||
hook: async (callback):Promise<any> => {
|
||||
subcallback = callback
|
||||
return new SubscriptionResponse(""+Math.random())
|
||||
},
|
||||
unhook: async (uid):Promise<any> => { subcallback = null }
|
||||
},
|
||||
function add(...args:number[]):number {return args.reduce((a,b)=>a+b, 0)},
|
||||
function triggerCallback(message):number {return subcallback(message)},
|
||||
]
|
||||
}])
|
||||
|
||||
try{
|
||||
new Server(20001, [{
|
||||
name: "bad",
|
||||
exportRPCs: () => [
|
||||
(aaa,bbb,ccc) => { return aaa+bbb+ccc }
|
||||
]
|
||||
}])
|
||||
}catch(badRPCError){
|
||||
console.log("expected bad-RPC error happened: "+ !!badRPCError)
|
||||
}
|
||||
+21
-4
@@ -1,7 +1,24 @@
|
||||
import { Client } from '../src/Frontend'
|
||||
|
||||
console.log(Client)
|
||||
const client = new Client(20000, 'localhost')
|
||||
client.connect().then(_ => {
|
||||
client.info().then(console.log)
|
||||
client["HelloWorldRPCGroup"].echo("x").then(console.log)
|
||||
client.connect().then(async _ => {
|
||||
await client.info().then(console.log)
|
||||
|
||||
await client["HelloWorldRPCGroup"].echo("x")
|
||||
.then(hopefullyX => console.log("echo('x') returned x: ", hopefullyX === "x", hopefullyX))
|
||||
|
||||
await client["HelloWorldRPCGroup"].add(1,2,3)
|
||||
.then(hopefully6 => console.log("add(1,2,3) returned 6: ", hopefully6 === 6, hopefully6))
|
||||
|
||||
let counter = 0
|
||||
const handler = (s) => {
|
||||
counter++
|
||||
if(counter === 3)
|
||||
console.log("callback was called 3 times", counter === 3)
|
||||
}
|
||||
|
||||
await client["HelloWorldRPCGroup"].subscribe(handler)
|
||||
client["HelloWorldRPCGroup"].triggerCallback("test1")
|
||||
client["HelloWorldRPCGroup"].triggerCallback("test2")
|
||||
client["HelloWorldRPCGroup"].triggerCallback("test3")
|
||||
})
|
||||
@@ -0,0 +1 @@
|
||||
<script src="../lib/RPCaller.min.js"></script>
|
||||
Reference in New Issue
Block a user