tempalte strings & bugfixes
This commit is contained in:
+12
-19
@@ -4,7 +4,7 @@ import bsock = require('bsock');
|
|||||||
|
|
||||||
import * as T from './Types';
|
import * as T from './Types';
|
||||||
import * as I from './Interfaces';
|
import * as I from './Interfaces';
|
||||||
import { stripAfterEquals } from './Utils';
|
import { stripAfterEquals, appendComma } from './Utils';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -127,10 +127,9 @@ export class RPCSocket implements I.Socket{
|
|||||||
private callGenerator(fnName: string, fnArgs:string[], sesame?:string): T.AnyFunction{
|
private callGenerator(fnName: string, fnArgs:string[], sesame?:string): T.AnyFunction{
|
||||||
const headerArgs = fnArgs.join(",")
|
const headerArgs = fnArgs.join(",")
|
||||||
const argParams = fnArgs.map(stripAfterEquals).join(",")
|
const argParams = fnArgs.map(stripAfterEquals).join(",")
|
||||||
if(!sesame)
|
sesame = appendComma(sesame)
|
||||||
return eval( '( () => async ('+headerArgs+') => { return await this.socket.call("'+fnName+'", '+argParams+')} )()' )
|
|
||||||
else
|
return eval(`async (${headerArgs}) => { return await this.socket.call("${fnName}", ${sesame} ${argParams})}`)
|
||||||
return eval( '( () => async ('+headerArgs+') => { return await this.socket.call("'+fnName+'", "'+sesame+'", '+argParams+')} )()' )
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -140,25 +139,19 @@ export class RPCSocket implements I.Socket{
|
|||||||
*/
|
*/
|
||||||
private frontEndHookGenerator(fnName: string, fnArgs:string[], sesame?:string): T.HookFunction{
|
private frontEndHookGenerator(fnName: string, fnArgs:string[], sesame?:string): T.HookFunction{
|
||||||
fnArgs.pop()
|
fnArgs.pop()
|
||||||
const headerArgs = fnArgs.join(",")
|
let headerArgs = fnArgs.join(",")
|
||||||
const argParams = fnArgs.map(stripAfterEquals).join(",")
|
const argParams = fnArgs.map(stripAfterEquals).join(",")
|
||||||
|
sesame = appendComma(sesame)
|
||||||
|
headerArgs = appendComma(headerArgs)
|
||||||
|
|
||||||
if(!sesame){
|
return eval( `
|
||||||
return eval( `( () => async (`+headerArgs+(headerArgs.length!==0?",":"")+` callback) => {
|
async (${headerArgs} callback) => {
|
||||||
const r = await this.socket.call("`+fnName+`", `+argParams+`)
|
const r = await this.socket.call("${fnName}", ${sesame} ${argParams})
|
||||||
if(r && r.result === 'Success'){
|
if(r && r.result === 'Success'){
|
||||||
this.socket.hook(r.uuid, callback)
|
this.socket.hook(r.uuid, callback)
|
||||||
|
this.socket.on('error', e => this.socket.unhook(r.uuid))
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
} )()` )
|
}`)
|
||||||
}else{
|
|
||||||
return eval( `( () => async (`+headerArgs+(headerArgs.length!==0?",":"")+` callback) => {
|
|
||||||
const r = await this.socket.call("`+fnName+`", "`+sesame+`", `+argParams+`)
|
|
||||||
if(r && r.result === 'Success'){
|
|
||||||
this.socket.hook(r.uuid, callback)
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
} )()` )
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+23
-26
@@ -10,7 +10,7 @@ import { SubscriptionResponse } from "./Types";
|
|||||||
* @param owner The owning RPC group's name
|
* @param owner The owning RPC group's name
|
||||||
* @throws Error on RPC without name property
|
* @throws Error on RPC without name property
|
||||||
*/
|
*/
|
||||||
export const rpcToRpcinfo = <SubResT = {}>(rpc : T.RPC<any, any, SubResT>, owner: string, errorHandler: T.ErrorHandler, sesame?:T.SesameFunction):T.RpcInfo => {
|
export const rpcToRpcinfo = <SubResT = {}>(socket: I.Socket, rpc : T.RPC<any, any, SubResT>, owner: string, errorHandler: T.ErrorHandler, sesame?:T.SesameFunction):T.RpcInfo => {
|
||||||
switch (typeof rpc){
|
switch (typeof rpc){
|
||||||
case "object":
|
case "object":
|
||||||
if(rpc['call']){
|
if(rpc['call']){
|
||||||
@@ -19,7 +19,7 @@ export const rpcToRpcinfo = <SubResT = {}>(rpc : T.RPC<any, any, SubResT>, owner
|
|||||||
argNames: extractArgs(rpc['call']),
|
argNames: extractArgs(rpc['call']),
|
||||||
type: "Call",
|
type: "Call",
|
||||||
name: rpc.name,
|
name: rpc.name,
|
||||||
call: sesame?async (_sesame, ...args) => {if(sesame(_sesame)) return await rpc['call'].apply({}, args); throw makeError(rpc.name)}:rpc['call'], // check & remove sesame
|
call: sesame?async (_sesame, ...args) => {if(sesame(_sesame)) return await rpc['call'].apply({}, args); socket.destroy()}:rpc['call'], // check & remove sesame
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
const generator = hookGenerator(<T.HookRPC<any, any, any>>rpc, errorHandler, sesame)
|
const generator = hookGenerator(<T.HookRPC<any, any, any>>rpc, errorHandler, sesame)
|
||||||
@@ -37,7 +37,7 @@ RPC did not provide a name.
|
|||||||
\nUse 'funtion name(..){ .. }' syntax instead.
|
\nUse 'funtion name(..){ .. }' syntax instead.
|
||||||
\n
|
\n
|
||||||
\n<------------OFFENDING RPC:
|
\n<------------OFFENDING RPC:
|
||||||
\n`+rpc.toString()+`
|
\n${rpc.toString()}
|
||||||
\n>------------OFFENDING RPC`)
|
\n>------------OFFENDING RPC`)
|
||||||
return {
|
return {
|
||||||
owner : owner,
|
owner : owner,
|
||||||
@@ -61,7 +61,7 @@ export function rpcHooker<SubResT = {}>(socket: I.Socket, exporter:I.RPCExporter
|
|||||||
const RPCs = [...exporter.exportRPCs()]
|
const RPCs = [...exporter.exportRPCs()]
|
||||||
|
|
||||||
|
|
||||||
return RPCs.map(rpc => rpcToRpcinfo(rpc, owner, errorHandler, sesame))
|
return RPCs.map(rpc => rpcToRpcinfo(socket, rpc, owner, errorHandler, sesame))
|
||||||
.map(info => {
|
.map(info => {
|
||||||
const suffix = makeUnique?"-"+uuidv4().substr(0,4):""
|
const suffix = makeUnique?"-"+uuidv4().substr(0,4):""
|
||||||
const ret:any = info
|
const ret:any = info
|
||||||
@@ -111,41 +111,33 @@ export function stripAfterEquals(str:string):string{
|
|||||||
* @returns A {@link HookFunction}
|
* @returns A {@link HookFunction}
|
||||||
*/
|
*/
|
||||||
const hookGenerator = (rpc:T.HookRPC<any, any, any>, errorHandler: T.ErrorHandler, sesameFn?: T.SesameFunction): T.HookInfo['generator'] => {
|
const hookGenerator = (rpc:T.HookRPC<any, any, any>, errorHandler: T.ErrorHandler, sesameFn?: T.SesameFunction): T.HookInfo['generator'] => {
|
||||||
const argsArr = extractArgs(rpc.hook)
|
let argsArr = extractArgs(rpc.hook)
|
||||||
argsArr.pop() //remove 'callback' from the end
|
argsArr.pop() //remove 'callback' from the end
|
||||||
const argsStr = argsArr.join(',')
|
let callArgs = argsArr.join(',')
|
||||||
|
|
||||||
if(sesameFn){
|
const args = sesameFn?(['sesame', ...argsArr].join(','))
|
||||||
const args = ['sesame', ...argsArr].join(',')
|
:callArgs
|
||||||
return eval(`(socket) => async (`+args+`) => {
|
|
||||||
|
callArgs = appendComma(callArgs)
|
||||||
|
|
||||||
|
//note rpc.hook is the associated RPC, not a socket.hook
|
||||||
|
return eval(`
|
||||||
|
(socket) => async (${args}) => {
|
||||||
try{
|
try{
|
||||||
if(!sesameFn(sesame)) return
|
if(sesameFn && !sesameFn(sesame)) return
|
||||||
const res = await rpc.hook(`+argsStr+(argsStr.length!==0?',':'')+` (...cbargs) => {
|
const res = await rpc.hook(${callArgs} (...cbargs) => {
|
||||||
if(rpc.onCallback) rpc.onCallback.apply({}, cbargs)
|
if(rpc.onCallback) rpc.onCallback.apply({}, cbargs)
|
||||||
socket.call.apply(socket, [res.uuid, ...cbargs])
|
socket.call.apply(socket, [res.uuid, ...cbargs])
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
}catch(e){
|
}catch(e){
|
||||||
errorHandler(socket)(e, rpc.name, [`+args+`])
|
errorHandler(socket)(e, ${rpc.name}, [${args}])
|
||||||
}
|
|
||||||
}`)
|
|
||||||
}
|
|
||||||
const args = argsArr.join(',')
|
|
||||||
return eval(`(socket) => async (`+args+`) => {
|
|
||||||
try{
|
|
||||||
const res = await rpc.hook(`+args+(args.length!==0?',':'')+` (...cbargs) => {
|
|
||||||
if(rpc.onCallback) rpc.onCallback.apply({}, cbargs)
|
|
||||||
socket.call.apply(socket, [res.uuid, ...cbargs])
|
|
||||||
})
|
|
||||||
return res
|
|
||||||
}catch(e){
|
|
||||||
errorHandler(socket)(e, rpc.name, [`+args+`])
|
|
||||||
}
|
}
|
||||||
}`)
|
}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const makeError = (callName: string) => {
|
const makeError = (callName: string) => {
|
||||||
return new Error("Unhandled Promise rejection: Call not found: "+callName+". ; Zone: <root> ; Task: Promise.then ; Value: Error: Call not found: "+callName)
|
return new Error("Call not found: "+callName+". ; Zone: <root> ; Task: Promise.then ; Value: Error: Call not found: "+callName)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -179,3 +171,8 @@ export function makeSesameFunction (sesame : T.SesameFunction | string) : T.Sesa
|
|||||||
return testSesame === sesame
|
return testSesame === sesame
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function appendComma(s?:string):string{
|
||||||
|
return s?`'${s}',`:""
|
||||||
|
}
|
||||||
+25
-15
@@ -48,13 +48,12 @@ function makeServer(){
|
|||||||
describe('RPCServer', () => {
|
describe('RPCServer', () => {
|
||||||
let server: RPCServer<{ topic: string }, any>
|
let server: RPCServer<{ topic: string }, any>
|
||||||
|
|
||||||
before((done) => {
|
before(() => {
|
||||||
server = makeServer()
|
server = makeServer()
|
||||||
done()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
after(async() => {
|
after(() => {
|
||||||
await server.destroy()
|
server.destroy()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should be able to use all kinds of RPC definitions', (done) => {
|
it('should be able to use all kinds of RPC definitions', (done) => {
|
||||||
@@ -239,7 +238,7 @@ describe('Sesame should unlock the socket', () => {
|
|||||||
let server: RPCServer
|
let server: RPCServer
|
||||||
let cb = (...args) => {}
|
let cb = (...args) => {}
|
||||||
|
|
||||||
before(async() => {
|
before((done) => {
|
||||||
server = new RPCServer(21004, [{
|
server = new RPCServer(21004, [{
|
||||||
name: "test",
|
name: "test",
|
||||||
exportRPCs: () => [
|
exportRPCs: () => [
|
||||||
@@ -261,7 +260,10 @@ describe('Sesame should unlock the socket', () => {
|
|||||||
sesame: (_sesame) => _sesame === 'sesame!'
|
sesame: (_sesame) => _sesame === 'sesame!'
|
||||||
})
|
})
|
||||||
const sock = new RPCSocket(21004, "localhost")
|
const sock = new RPCSocket(21004, "localhost")
|
||||||
client = await sock.connect<SesameTestIfc>('sesame!')
|
sock.connect<SesameTestIfc>('sesame!').then(cli => {
|
||||||
|
client = cli
|
||||||
|
done()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
after(() => {
|
after(() => {
|
||||||
@@ -282,13 +284,14 @@ describe('Sesame should unlock the socket', () => {
|
|||||||
|
|
||||||
it('should not work without sesame', (done) => {
|
it('should not work without sesame', (done) => {
|
||||||
const sock = new RPCSocket(21004, "localhost")
|
const sock = new RPCSocket(21004, "localhost")
|
||||||
sock.connect<SesameTestIfc>( /* no sesame */).then(async (c) => {
|
sock.connect<SesameTestIfc>( /* no sesame */).then(async (cli) => {
|
||||||
c.test.checkCandy().then(d => {
|
cli.test.checkCandy().then(d => {
|
||||||
done()
|
done(d)
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
//console.log("EXPECTED CLIENT EXCEPTION", String(e));
|
//console.log("EXPECTED CLIENT EXCEPTION", String(e));
|
||||||
done()
|
done()
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
|
cli.destroy()
|
||||||
sock.destroy()
|
sock.destroy()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -296,14 +299,15 @@ describe('Sesame should unlock the socket', () => {
|
|||||||
|
|
||||||
it('should fail with wrong sesame', (done) => {
|
it('should fail with wrong sesame', (done) => {
|
||||||
const sock = new RPCSocket(21004, "localhost")
|
const sock = new RPCSocket(21004, "localhost")
|
||||||
sock.connect<SesameTestIfc>('abasd').then(async (c) => {
|
sock.connect<SesameTestIfc>('abasd').then(async (cli) => {
|
||||||
c.test.checkCandy().then(d => {
|
cli.test.checkCandy().then(d => {
|
||||||
done("should not be able to get candy")
|
done("should not be able to get candy")
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
//console.log("EXPECTED CLIENT EXCEPTION", String(e));
|
//console.log("EXPECTED CLIENT EXCEPTION", String(e));
|
||||||
done()
|
done()
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
sock.destroy()
|
sock.destroy()
|
||||||
|
cli.destroy()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -323,8 +327,8 @@ describe('Sesame should unlock the socket', () => {
|
|||||||
|
|
||||||
it('callback should not work without sesame', (done) => {
|
it('callback should not work without sesame', (done) => {
|
||||||
const sock = new RPCSocket(21004, "localhost")
|
const sock = new RPCSocket(21004, "localhost")
|
||||||
sock.connect<SesameTestIfc>( /* no sesame */).then(async (c) => {
|
sock.connect<SesameTestIfc>( /* no sesame */).then(async (cli) => {
|
||||||
c.test.subscribe((c) => {
|
cli.test.subscribe((c) => {
|
||||||
console.log("CALLBACK TRIGGERED UNEXPECTED");
|
console.log("CALLBACK TRIGGERED UNEXPECTED");
|
||||||
|
|
||||||
if(c === candy)
|
if(c === candy)
|
||||||
@@ -333,16 +337,17 @@ describe('Sesame should unlock the socket', () => {
|
|||||||
await client.test.checkCandy()
|
await client.test.checkCandy()
|
||||||
if(d == null){
|
if(d == null){
|
||||||
done()
|
done()
|
||||||
|
|
||||||
}else
|
}else
|
||||||
done('unexpected valid response '+(d) )
|
done('unexpected valid response '+(d) )
|
||||||
c.destroy()
|
}).finally(() => {
|
||||||
|
sock.destroy()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
describe('Error handling', ()=>{
|
describe('Error handling', ()=>{
|
||||||
|
|
||||||
let createUser = async( user: {a:any,b:any}) => {
|
let createUser = async( user: {a:any,b:any}) => {
|
||||||
@@ -374,6 +379,7 @@ describe('Error handling', ()=>{
|
|||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
cli.destroy()
|
||||||
sock.destroy()
|
sock.destroy()
|
||||||
server.destroy()
|
server.destroy()
|
||||||
})
|
})
|
||||||
@@ -407,6 +413,7 @@ describe('Error handling', ()=>{
|
|||||||
done(e)
|
done(e)
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
cli.destroy()
|
||||||
sock.destroy()
|
sock.destroy()
|
||||||
server.destroy()
|
server.destroy()
|
||||||
})
|
})
|
||||||
@@ -414,6 +421,7 @@ describe('Error handling', ()=>{
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
describe("Errorhandler functionality", ()=>{
|
describe("Errorhandler functionality", ()=>{
|
||||||
let createUser = async( user: {a:any,b:any}) => {
|
let createUser = async( user: {a:any,b:any}) => {
|
||||||
throw new Error("BAD BAD BAD")
|
throw new Error("BAD BAD BAD")
|
||||||
@@ -447,6 +455,7 @@ describe("Errorhandler functionality", ()=>{
|
|||||||
done(e)
|
done(e)
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
cli.destroy()
|
||||||
sock.destroy()
|
sock.destroy()
|
||||||
server.destroy()
|
server.destroy()
|
||||||
})
|
})
|
||||||
@@ -484,6 +493,7 @@ describe("Errorhandler functionality", ()=>{
|
|||||||
done(e)
|
done(e)
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
cli.destroy()
|
||||||
sock.destroy()
|
sock.destroy()
|
||||||
server.destroy()
|
server.destroy()
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user