Browse Source

fix subscribe+sesame

master
peter 4 years ago
parent
commit
ae843d341e
5 changed files with 90 additions and 33 deletions
  1. 1
    1
      package.json
  2. 0
    1
      src/Backend.ts
  3. 12
    5
      src/Frontend.ts
  4. 20
    18
      src/Utils.ts
  5. 57
    8
      test/Test.ts

+ 1
- 1
package.json View File

@@ -1,6 +1,6 @@
1 1
 {
2 2
   "name": "rpclibrary",
3
-  "version": "1.5.1",
3
+  "version": "1.5.2",
4 4
   "description": "rpclibrary is a websocket on steroids!",
5 5
   "main": "./js/Index.js",
6 6
   "repository": {

+ 0
- 1
src/Backend.ts View File

@@ -37,7 +37,6 @@ export class RPCServer<
37 37
         if(!conf.visibility) this.visibility = "127.0.0.1"        
38 38
         
39 39
         if(conf.sesame){
40
-            console.log("Setting Sesame")
41 40
             this.sesame = U.makeSesameFunction(conf.sesame)
42 41
         }
43 42
 

+ 12
- 5
src/Frontend.ts View File

@@ -106,7 +106,7 @@ export class RPCSocket implements I.Socket{
106 106
                     f = this.callGenerator(i.uniqueName, i.argNames, sesame)    
107 107
                     break                
108 108
                 case 'Hook':
109
-                    f = this.hookGenerator(i.uniqueName, i.argNames, sesame)                    
109
+                    f = this.frontEndHookGenerator(i.uniqueName, i.argNames, sesame)                    
110 110
                     break
111 111
             }
112 112
             if(this[i.owner] == null)
@@ -143,21 +143,28 @@ export class RPCSocket implements I.Socket{
143 143
      * @param fnName The function name
144 144
      * @param fnArgs A string-list of parameters
145 145
      */
146
-    private hookGenerator(fnName: string, fnArgs:string[], sesame?:string): T.HookFunction{
146
+    private frontEndHookGenerator(fnName: string, fnArgs:string[], sesame?:string): T.HookFunction{
147
+        fnArgs.pop()
147 148
         const headerArgs = fnArgs.join(",")
148 149
         const argParams = fnArgs.map(stripAfterEquals).join(",")
150
+
149 151
         if(!sesame){
150
-            return eval( `( () => async (`+headerArgs+(headerArgs.length!==0?",":"")+` callback) => {
152
+            const headerArgs = fnArgs.join(",")
153
+            const argParams = fnArgs.map(stripAfterEquals).join(",")
154
+
155
+            const f = eval( `( () => async (`+headerArgs+(headerArgs.length!==0?",":"")+` callback) => {
151 156
                 const r = await this.socket.call("`+fnName+`", `+argParams+`)
152
-                if(r.result === 'Success'){
157
+                if(r && r.result === 'Success'){
153 158
                     this.socket.hook(r.uuid, callback)
154 159
                 }
155 160
                 return r
156 161
             } )()` )
162
+            return f
157 163
         }else{
164
+
158 165
             return eval( `( () => async (`+headerArgs+(headerArgs.length!==0?",":"")+` callback) => {
159 166
                 const r = await this.socket.call("`+fnName+`", "`+sesame+`", `+argParams+`)
160
-                if(r.result === 'Success'){
167
+                if(r && r.result === 'Success'){
161 168
                     this.socket.hook(r.uuid, callback)
162 169
                 }
163 170
                 return r

+ 20
- 18
src/Utils.ts View File

@@ -82,37 +82,38 @@ export function rpcHooker<SubResT = {}>(socket: I.Socket, exporter:I.RPCExporter
82 82
     })
83 83
 }
84 84
 /**
85
- * Utility function to generate {@link HookFunction} from a RPC
85
+ * Utility function to generate {@link HookFunction} from a RPC for backend
86 86
  * @param rpc The RPC to transform
87 87
  * @returns A {@link HookFunction}
88 88
  */
89
-const hookGenerator = (rpc:T.HookRPC<any, any, any>, sesame?:T.SesameFunction): T.HookInfo['generator'] => { 
89
+const hookGenerator = (rpc:T.HookRPC<any, any, any>, sesameFn?: T.SesameFunction): T.HookInfo['generator'] => { 
90 90
     const argsArr = extractArgs(rpc.hook)
91
-    if(sesame){
92
-        const _sesame = argsArr.shift()
93
-        if(!sesame(_sesame!)){
94
-            throw new Error('Bad sesame')
95
-        }
96
-    }
97 91
     argsArr.pop() //remove 'callback' from the end
98
-    const args = argsArr.join(',')
92
+    const argsStr = argsArr.join(',')
99 93
 
100
-    return eval(`(socket) => async (`+args+`) => { 
94
+    if(sesameFn){
95
+        const args = ['sesame', ...argsArr].join(',')
96
+        const f =  eval(`(socket) => async (`+args+`) => {
97
+            if(!sesameFn(sesame)) return
98
+            const res = await rpc.hook(`+argsStr+(argsStr.length!==0?',':'')+` (...cbargs) => {
99
+                if(rpc.onCallback) rpc.onCallback.apply({}, cbargs)
100
+                socket.call.apply(socket, [res.uuid, ...cbargs])
101
+            })
102
+            return res
103
+        }`)
104
+        return f
105
+    }
106
+    const args = argsArr.join(',')
107
+    return eval(`(socket) => async (`+args+`) => {
101 108
         const res = await rpc.hook(`+args+(args.length!==0?',':'')+` (...cbargs) => {
102 109
             if(rpc.onCallback) rpc.onCallback.apply({}, cbargs)
103 110
             socket.call.apply(socket, [res.uuid, ...cbargs])
104 111
         })
105
-        if(res.result === 'Success'){
106
-            if(rpc.onClose){
107
-                socket.on('close', async () => {
108
-                    rpc.onClose(res, rpc)
109
-                })
110
-            }
111
-        }
112 112
         return res
113 113
     }`)
114 114
 }
115 115
 
116
+
116 117
 /**
117 118
  * Extract a string list of parameters from a function
118 119
  * @param f The source function
@@ -134,6 +135,7 @@ export function makeSubResponse<T extends {} = {}>(extension:T):SubscriptionResp
134 135
     }
135 136
 }
136 137
 
138
+
137 139
 export function makeSesameFunction (sesame : T.SesameFunction | string) : T.SesameFunction {
138 140
     if(typeof sesame === 'function'){
139 141
         return sesame
@@ -142,4 +144,4 @@ export function makeSesameFunction (sesame : T.SesameFunction | string) : T.Sesa
142 144
     return (testSesame : string) => {
143 145
         return testSesame === sesame 
144 146
     }
145
-}
147
+}

+ 57
- 8
test/Test.ts View File

@@ -1,4 +1,4 @@
1
-import { describe, it } from "mocha";
1
+import { describe, it, Func } from "mocha";
2 2
 
3 3
 import { RPCServer, RPCSocket, SubscriptionResponse, makeSubResponse } from '../Index'
4 4
 import * as uuidv4 from "uuid/v4"
@@ -226,18 +226,35 @@ describe('It should do unhook', () => {
226 226
 })
227 227
 
228 228
 
229
-type SesameTestIfc = { test: { checkCandy: ()=>Promise<string>} }
229
+type SesameTestIfc = { 
230
+    test: { 
231
+        checkCandy: ()=>Promise<string>
232
+        subscribe: (callback) => Promise<SubscriptionResponse<{ topic: string; }>>
233
+    } 
234
+}
230 235
 
231 236
 describe('Sesame should unlock the socket', () => {
232 237
     let candy = "OK"
233 238
     let client: RPCSocket & SesameTestIfc
234
-    let server: RPCServer<{topic: string}, SesameTestIfc> 
239
+    let server: RPCServer 
240
+    let cb = (...args) => {}
235 241
 
236 242
     before(async() => {
237
-        server = new RPCServer<{ topic: string }, SesameTestIfc>(20004, [{
243
+        server = new RPCServer(20004, [{
238 244
             name: "test",
239 245
             exportRPCs: () => [
240
-                async function checkCandy():Promise<string> { return candy },
246
+                {
247
+                    name: 'subscribe',
248
+                    hook: async(callback) => {
249
+                        cb = callback
250
+                        return <SubscriptionResponse>{
251
+                            result: "Success",
252
+                            uuid: uuidv4(),
253
+                            topic: 'test'
254
+                        }
255
+                    }
256
+                },
257
+                async function checkCandy():Promise<string> { cb(candy); cb=()=>{}; return candy },
241 258
             ]}
242 259
         ],{
243 260
             sesame: (_sesame) => _sesame === 'sesame!' 
@@ -251,6 +268,10 @@ describe('Sesame should unlock the socket', () => {
251 268
         server.destroy()
252 269
     })
253 270
 
271
+    it('should work with sesame', (done) => {
272
+        client.test.checkCandy().then(c => done())
273
+    })
274
+
254 275
     it('should not work without sesame', (done) => {
255 276
         const sock = new RPCSocket(20004, "localhost")
256 277
         sock.connect<SesameTestIfc>( /* no sesame */).then(async (c) => {
@@ -264,7 +285,35 @@ describe('Sesame should unlock the socket', () => {
264 285
         })
265 286
     })
266 287
 
267
-    it('should work with sesame', (done) => {
268
-        client.test.checkCandy().then(c => done())
288
+    it('callback should work with sesame', (done) => {
289
+        client.test.subscribe((c) => {
290
+            if(c === candy){
291
+                done()
292
+            }
293
+        }).then(d => {
294
+            if(d.result !== 'Success')
295
+                done('expected valid response')
296
+
297
+            client.test.checkCandy()
298
+        })
299
+    })
300
+
301
+    it('callback should not work without sesame', (done) => {
302
+        const sock = new RPCSocket(20004, "localhost")
303
+        sock.connect<SesameTestIfc>( /* no sesame */).then(async (c) => {
304
+            c.test.subscribe((c) => {
305
+                console.log("CALLBACK TRIGGERED UNEXPECTED");
306
+                
307
+                if(c === candy)
308
+                    done("super not")
309
+            }).then(async d => {
310
+                await client.test.checkCandy()
311
+                if(d == null){
312
+                    done()
313
+                }else
314
+                    done('unexpected valid response '+(d) )
315
+                c.destroy()
316
+            })
317
+        })
269 318
     })
270
-})
319
+})

Loading…
Cancel
Save