diff --git a/src/Backend.ts b/src/Backend.ts index 36a4d04..55a6954 100644 --- a/src/Backend.ts +++ b/src/Backend.ts @@ -27,7 +27,7 @@ export class RPCServer{ if(!conf.errorHandler) this.errorHandler = (socket:I.Socket) => (error:any) => { socket.destroy(); - console.error(error) + console.error("Caught websocket error", String(error)) } if(!conf.closeHandler) this.closeHandler = @@ -37,7 +37,7 @@ export class RPCServer{ if(!conf.connectionHandler) this.connectionHandler = (socket:I.Socket) => { - console.log("New websocket connection in port "+socket.port) + console.log("New websocket connection on port "+socket.port) } let badRPC diff --git a/src/Frontend.ts b/src/Frontend.ts index 3b0e834..6437777 100644 --- a/src/Frontend.ts +++ b/src/Frontend.ts @@ -58,9 +58,6 @@ export class RPCSocket implements I.Socket{ case 'Hook': f = this.hookGenerator(i.uniqueName, i.argNames) break - case 'Unhook': - f = this.unhookGenerator(i.uniqueName, i.argNames) - break } if(this[i.owner] == null) this[i.owner] = {} @@ -79,7 +76,7 @@ export class RPCSocket implements I.Socket{ return eval( '( () => async ('+headerArgs+') => { return await this.socket.call("'+fnName+'", '+argParams+')} )()' ) } - private hookGenerator(fnName: T.Name, fnArgs:T.Arg[]): T.CallbackFunction{ + private hookGenerator(fnName: T.Name, fnArgs:T.Arg[]): T.HookFunction{ const headerArgs = fnArgs.join(",") const argParams = fnArgs.map(stripAfterEquals).join(",") return eval( `( () => async (`+headerArgs+(headerArgs.length!==0?",":"")+` callback) => { @@ -90,18 +87,4 @@ export class RPCSocket implements I.Socket{ return r } )()` ) } - - private unhookGenerator(fnName: T.Name, fnArgs:T.Arg[]): T.UnhookFunction{ - const headerArgs = fnArgs.join(",") - const argParams = fnArgs.map(stripAfterEquals).join(",") - if(fnArgs.length != 1) - console.error("UnhookFunction", fnName, "specified more than one argument: ("+headerArgs+")") - - return eval( `( () => async (`+headerArgs+`) => { - const r = await this.socket.call("`+fnName+`", `+argParams+`) - this.socket.unhook(`+argParams+`) - return r - } )()` ) - } - } \ No newline at end of file diff --git a/src/Types.ts b/src/Types.ts index ca2cee8..7a9e12e 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -25,13 +25,9 @@ export type BaseRPC = { export type HookRPC = BaseRPC & { type: 'Hook' - hook: CallbackFunction - unhook: UnhookFunction -} - -export type UnhookRPC = BaseRPC & { - type: 'Unhook' - unhook: UnhookFunction + hook: HookFunction + onCallback?: CallbackFunction, + onClose?: HookCloseFunction } export type CallRPC = (BaseRPC & { @@ -39,7 +35,7 @@ export type CallRPC = (BaseRPC & { call: AsyncFunction } ) | Function -export type RPC = CallRPC | UnhookRPC | HookRPC +export type RPC = CallRPC | HookRPC export type BaseInfo = { owner: Name, @@ -48,13 +44,7 @@ export type BaseInfo = { export type HookInfo = BaseRPC & BaseInfo & { type: 'Hook', - generator: (socket) => CallbackFunction - unhook: UnhookFunction -} - -export type UnhookInfo = BaseRPC & BaseInfo & { - type: 'Unhook', - unhook: UnhookFunction + generator: (socket) => HookFunction } export type CallInfo = BaseRPC & BaseInfo & { @@ -62,10 +52,11 @@ export type CallInfo = BaseRPC & BaseInfo & { call: AsyncFunction } -export type RpcInfo = HookInfo | UnhookInfo | CallInfo +export type RpcInfo = HookInfo | CallInfo export type ExtendedRpcInfo = RpcInfo & { uniqueName: string } export type OnFunction = (type: 'error' | 'close', f: (e?:any)=>void) => I.Socket -export type UnhookFunction = (uid:string) => Promise -export type CallbackFunction = (...args) => Promise -export type AsyncFunction = (...args) => Promise +export type HookCloseFunction = (res:R.SubscriptionResponse) => any +export type HookFunction = (...args:any[]) => Promise +export type AsyncFunction = (...args:any[]) => Promise +export type CallbackFunction = (arg: any) => void \ No newline at end of file diff --git a/src/Utils.ts b/src/Utils.ts index fef5823..785cd1e 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -15,14 +15,6 @@ export const rpcToRpcinfo = (rpc : T.RPC, owner: T.Owner):T.RpcInfo => { name: rpc.name, call: rpc.call, } - case "Unhook" : - return { - owner: owner, - argNames: extractArgs(rpc.unhook), - type: rpc.type, - name: rpc.name, - unhook: rpc.unhook, - } case "Hook" : const generator = hookGenerator(rpc) return { @@ -30,8 +22,8 @@ export const rpcToRpcinfo = (rpc : T.RPC, owner: T.Owner):T.RpcInfo => { argNames: extractArgs(generator(undefined)), type: rpc.type, name: rpc.name, - unhook: rpc.unhook, generator: generator, + } } break; @@ -67,9 +59,6 @@ export function rpcHooker(socket: I.Socket, exporter:I.Exporter, makeUnique = tr case "Hook": socket.hook(ret.uniqueName, info.generator(socket)) break; - case "Unhook": - socket.hook(ret.uniqueName, info.unhook) - break; case "Call": socket.hook(ret.uniqueName, info.call) break; @@ -85,13 +74,14 @@ const hookGenerator = (rpc:T.HookRPC): T.HookInfo['generator'] => { const args = argsArr.join(',') return eval(`(socket) => async (`+args+`) => { - const res = await rpc.hook(`+args+(args.length!==0?',':'')+` (x) => { - socket.call(res.uid, x) + const res = await rpc.hook(`+args+(args.length!==0?',':'')+` (...cbargs) => { + if(rpc.onCallback) rpc.onCallback.apply({}, cbargs) + socket.call.apply(socket, [res.uid, ...cbargs]) }) if(res.result == 'Success'){ + if(rpc.onClose) socket.on('close', async () => { - const unhookRes = await rpc.unhook(res.uid) - console.log("Specific close handler for", rpc.name, res.uid, unhookRes) + rpc.onClose(res) }) } return res @@ -99,9 +89,6 @@ const hookGenerator = (rpc:T.HookRPC): T.HookInfo['generator'] => { } const extractArgs = (f:Function):T.Arg[] => { - let fn = String(f) - let args = fn.substr(0, fn.indexOf(")")) - args = args.substr(fn.indexOf("(")+1) - let ret = args.split(",") - return ret + let fn + return (fn = String(f)).substr(0, fn.indexOf(")")).substr(fn.indexOf("(")+1).split(",") } \ No newline at end of file diff --git a/test/TestBackend.ts b/test/TestBackend.ts index c61218b..a80ffc4 100644 --- a/test/TestBackend.ts +++ b/test/TestBackend.ts @@ -1,5 +1,6 @@ import { RPCServer } from '../src/Backend' -import { SubscriptionResponse } from '../src/Responses' +import { SubscriptionResponse, ErrorResponse, SuccessResponse } from '../src/Responses' +import { HookRPC } from '../src/Types' let subcallback @@ -17,10 +18,13 @@ new RPCServer(20000, [{ subcallback = callback return new SubscriptionResponse(""+Math.random()) }, - unhook: async (uid):Promise => { subcallback = null } + onClose: (res:SubscriptionResponse) => { + console.log("Specific close handler for", res) + subcallback = null + } }, function add(...args:number[]):number {return args.reduce((a,b)=>a+b, 0)}, - function triggerCallback(message):number {return subcallback(message)}, + function triggerCallback(...messages:any[]):number {return subcallback.apply({}, messages)}, ] }]) @@ -32,5 +36,5 @@ try{ ] }]) }catch(badRPCError){ - console.log("expected bad-RPC error happened: "+ !!badRPCError) + console.log("expected bad-RPC error happened: "+ !!badRPCError, String(badRPCError)) } \ No newline at end of file diff --git a/test/TestFrontend.ts b/test/TestFrontend.ts index d91d310..6f8866f 100644 --- a/test/TestFrontend.ts +++ b/test/TestFrontend.ts @@ -17,7 +17,7 @@ client.connect().then(async _ => { } await client["HelloWorldRPCGroup"].subscribe(handler) - client["HelloWorldRPCGroup"].triggerCallback("test1") - client["HelloWorldRPCGroup"].triggerCallback("test2") - client["HelloWorldRPCGroup"].triggerCallback("test3") + client["HelloWorldRPCGroup"].triggerCallback("test1", "test1", "test1", ) + client["HelloWorldRPCGroup"].triggerCallback("test2", "test2", "test2", ) + client["HelloWorldRPCGroup"].triggerCallback("test3", "test3", "test3", ) })