Browse Source

before rewrite to have callbacks as FIRST parameter

master
nitowa 2 years ago
parent
commit
b2ffbbfa48
6 changed files with 182 additions and 126 deletions
  1. 16
    10
      src/Frontend.ts
  2. 2
    2
      src/Interfaces.ts
  3. 2
    1
      src/Strings.ts
  4. 50
    44
      src/Types.ts
  5. 4
    2
      src/Utils.ts
  6. 108
    67
      test/Test.ts

+ 16
- 10
src/Frontend.ts View File

4
 import * as T from './Types';
4
 import * as T from './Types';
5
 import * as I from './Interfaces';
5
 import * as I from './Interfaces';
6
 import { stripAfterEquals, appendComma } from './Utils';
6
 import { stripAfterEquals, appendComma } from './Utils';
7
-import { DESTROY_PREFIX, SOCKET_NOT_CONNECTED, UNKNOWN_RPC_IDENTIFIER, USER_DEFINED_TIMEOUT } from './Strings';
7
+import { CALLBACK_NAME, DESTROY_PREFIX, SOCKET_NOT_CONNECTED, UNKNOWN_RPC_IDENTIFIER, USER_DEFINED_TIMEOUT } from './Strings';
8
 import { DeserializerFactory } from './Decorator';
8
 import { DeserializerFactory } from './Decorator';
9
 DeserializerFactory
9
 DeserializerFactory
10
 
10
 
21
 
21
 
22
     private socket: I.Socket
22
     private socket: I.Socket
23
     private handlers: {
23
     private handlers: {
24
-        [name in string]: T.AnyFunction[]
24
+        [name in string]: T.GenericFunction[]
25
     } = {
25
     } = {
26
             error: [],
26
             error: [],
27
             close: []
27
             close: []
28
         }
28
         }
29
-    private hooks: { [name in string]: T.AnyFunction } = {}
29
+    private hooks: { [name in string]: T.GenericFunction } = {}
30
 
30
 
31
     /**
31
     /**
32
      * 
32
      * 
82
      * @param type 'error' or 'close'
82
      * @param type 'error' or 'close'
83
      * @param f The listener to attach
83
      * @param f The listener to attach
84
      */
84
      */
85
-    public on(type: string, f: T.AnyFunction) {
85
+    public on(type: string, f: T.GenericFunction) {
86
         if (!this.socket) {
86
         if (!this.socket) {
87
             if (!this.handlers[type])
87
             if (!this.handlers[type])
88
                 this.handlers[type] = []
88
                 this.handlers[type] = []
166
             v.forEach(h => this.socket.on(k, h))
166
             v.forEach(h => this.socket.on(k, h))
167
         })
167
         })
168
 
168
 
169
-        Object.entries(this.hooks).forEach((kv: [string, T.AnyFunction]) => {
169
+        Object.entries(this.hooks).forEach((kv: [string, T.GenericFunction]) => {
170
             this.socket.hook(kv[0], kv[1])
170
             this.socket.hook(kv[0], kv[1])
171
         })
171
         })
172
         const info: T.ExtendedRpcInfo[] = await this.info(sesame)
172
         const info: T.ExtendedRpcInfo[] = await this.info(sesame)
205
      * @param fnName The function name
205
      * @param fnName The function name
206
      * @param fnArgs A string-list of parameters
206
      * @param fnArgs A string-list of parameters
207
      */
207
      */
208
-    private callGenerator(fnName: string, fnArgs: string[], sesame?: string): T.AnyFunction {
208
+    private callGenerator(fnName: string, fnArgs: string[], sesame?: string): T.GenericFunction {
209
         const headerArgs = fnArgs.join(",")
209
         const headerArgs = fnArgs.join(",")
210
         const argParams = fnArgs.map(stripAfterEquals).join(",")
210
         const argParams = fnArgs.map(stripAfterEquals).join(",")
211
         sesame = appendComma(sesame)
211
         sesame = appendComma(sesame)
221
      * @param fnName The function name
221
      * @param fnName The function name
222
      * @param fnArgs A string-list of parameters
222
      * @param fnArgs A string-list of parameters
223
      */
223
      */
224
-    private frontEndHookGenerator(fnName: string, fnArgs: string[], sesame?: string): T.HookFunction {
224
+    private frontEndHookGenerator(fnName: string, fnArgs: string[], sesame?: string): T.GenericFunction {
225
 
225
 
226
         if (sesame)
226
         if (sesame)
227
             fnArgs.shift()
227
             fnArgs.shift()
234
         const destroy_prefix = DESTROY_PREFIX
234
         const destroy_prefix = DESTROY_PREFIX
235
 
235
 
236
         const frontendHookStr = `
236
         const frontendHookStr = `
237
-        async (${headerArgs} $__callback__$) => {
237
+        async (${headerArgs} ${CALLBACK_NAME}) => {
238
             const r = await this.call("${fnName}", ${sesame} ${argParams})
238
             const r = await this.call("${fnName}", ${sesame} ${argParams})
239
             try{
239
             try{
240
                 if(r){
240
                 if(r){
241
                     if(r.uuid){
241
                     if(r.uuid){
242
-                        $__callback__$['destroy'] = () => {
242
+                        ${CALLBACK_NAME}['destroy'] = () => {
243
                             this.socket.fire(destroy_prefix+r.uuid)
243
                             this.socket.fire(destroy_prefix+r.uuid)
244
                             this.socket.unhook(r.uuid) 
244
                             this.socket.unhook(r.uuid) 
245
                         }
245
                         }
246
-                        this.socket.hook(r.uuid, $__callback__$)
246
+                        ${CALLBACK_NAME} = ${CALLBACK_NAME}.bind({
247
+                            destroy: ${CALLBACK_NAME}['destroy']
248
+                        })
249
+
250
+                        this.socket.hook(r.uuid, (...args) => {
251
+                            ${CALLBACK_NAME}.apply(${CALLBACK_NAME}, args.map(deserializer.from))
252
+                        })
247
                     }
253
                     }
248
                     return deserializer.from(r.return)
254
                     return deserializer.from(r.return)
249
                 }else{
255
                 }else{

+ 2
- 2
src/Interfaces.ts View File

15
     id?: string
15
     id?: string
16
     bind: (name: string, listener: T.PioBindListener) => void
16
     bind: (name: string, listener: T.PioBindListener) => void
17
     hook: (rpcname: string, handler: T.PioHookListener) => void
17
     hook: (rpcname: string, handler: T.PioHookListener) => void
18
-    unhook: (rpcname: string, listener?:T.AnyFunction) => void
18
+    unhook: (rpcname: string, listener?:T.GenericFunction) => void
19
     call: (rpcname: string, ...args: any[]) => Promise<any>
19
     call: (rpcname: string, ...args: any[]) => Promise<any>
20
     fire: (rpcname: string, ...args: any[]) => Promise<any>
20
     fire: (rpcname: string, ...args: any[]) => Promise<any>
21
-    on: (type: string, f: T.AnyFunction)=>any
21
+    on: (type: string, f: T.GenericFunction)=>any
22
     emit: (eventName: string, ...args: any[]) => void
22
     emit: (eventName: string, ...args: any[]) => void
23
     close(): void
23
     close(): void
24
   }
24
   }

+ 2
- 1
src/Strings.ts View File

13
 \n${name}
13
 \n${name}
14
 \n>------------OFFENDING RPC`
14
 \n>------------OFFENDING RPC`
15
 export const CLASSNAME_ATTRIBUTE = "$__CLASSNAME__$"
15
 export const CLASSNAME_ATTRIBUTE = "$__CLASSNAME__$"
16
-export const DESTROY_PREFIX = "$__DESTROY__$_"
16
+export const DESTROY_PREFIX = "$__DESTROY__$_"
17
+export const CALLBACK_NAME = "$__CALLBACK__$"

+ 50
- 44
src/Types.ts View File

1
 import * as I from "./Interfaces";
1
 import * as I from "./Interfaces";
2
 import { RPCSocket } from "./Frontend";
2
 import { RPCSocket } from "./Frontend";
3
-import { PromiseIO } from "./PromiseIO/Server";
4
 
3
 
5
 export type PioBindListener = (...args: any) => void
4
 export type PioBindListener = (...args: any) => void
6
-export type PioHookListener = AnyFunction
5
+export type PioHookListener = GenericFunction
6
+
7
+export type GenericFunction<Parameters extends any[] = any[], Result = any> = {(...args: Parameters): Result}
8
+
9
+export type BackendHook<Func extends GenericFunction> =
10
+    GenericFunction<
11
+        [
12
+            ...Head<Parameters<Func>>,
13
+            GenericFunction<
14
+                Parameters<
15
+                    AsFunction<
16
+                        Last<Parameters<Func>>
17
+                    >
18
+                >,
19
+                void
20
+            >
21
+        ],
22
+        ReturnType<Func>
23
+    >
24
+
7
 
25
 
8
-export type AnyFunction = (...args: any[]) => any
9
-export type HookFunction = AnyFunction
10
 export type AccessFilter<InterfaceT extends RPCInterface = RPCInterface> = (sesame: string | undefined, exporter: I.RPCExporter<InterfaceT, keyof InterfaceT>) => Promise<boolean> | boolean
26
 export type AccessFilter<InterfaceT extends RPCInterface = RPCInterface> = (sesame: string | undefined, exporter: I.RPCExporter<InterfaceT, keyof InterfaceT>) => Promise<boolean> | boolean
11
 export type Visibility = "127.0.0.1" | "0.0.0.0"
27
 export type Visibility = "127.0.0.1" | "0.0.0.0"
12
 export type ConnectionHandler = (socket: I.Socket) => void
28
 export type ConnectionHandler = (socket: I.Socket) => void
45
 
61
 
46
 export type RPCType = 'Hook' | 'Unhook' | 'Call'
62
 export type RPCType = 'Hook' | 'Unhook' | 'Call'
47
 
63
 
48
-export type CallRPC<Name, Func extends AnyFunction> = {
64
+export type CallRPC<Name, Func extends GenericFunction> = {
49
     name: Name
65
     name: Name
50
     call: Func
66
     call: Func
51
 }
67
 }
52
 
68
 
53
-
54
-export type HookRPC<Name, Func extends AnyFunction> = {
69
+export type HookRPC<Name, Func extends GenericFunction> = {
55
     name: Name
70
     name: Name
56
-    hook: AnyFunction
57
-    onCallback?: AnyFunction
71
+    hook: BackendHook<Func>
72
+    onCallback?: GenericFunction
58
     onDestroy?: HookCloseFunction<ReturnType<Func> extends Promise<infer T> ? T : ReturnType<Func>>
73
     onDestroy?: HookCloseFunction<ReturnType<Func> extends Promise<infer T> ? T : ReturnType<Func>>
59
 }
74
 }
60
 
75
 
61
-export type RPC<Name, Func extends AnyFunction> = HookRPC<Name, Func> | CallRPC<Name, Func> | Func
76
+export type RPC<Name, Func extends GenericFunction> = HookRPC<Name, Func> | CallRPC<Name, Func> | Func
62
 
77
 
63
 export type RPCInterface<Impl extends RPCInterface = {}> = {
78
 export type RPCInterface<Impl extends RPCInterface = {}> = {
64
     [grp in string]: {
79
     [grp in string]: {
65
-        [rpc in string]: AnyFunction
80
+        [rpc in string]: GenericFunction
66
     }
81
     }
67
 } & Impl
82
 } & Impl
68
 
83
 
71
 }
86
 }
72
 
87
 
73
 export type RPCDefinitions<Ifc extends RPCInterface> = {
88
 export type RPCDefinitions<Ifc extends RPCInterface> = {
74
-    [grp in keyof Ifc]: ({ 
75
-        [rpc in keyof Ifc[grp]]: RPC<rpc, Ifc[grp][rpc]> 
89
+    [grp in keyof Ifc]: ({
90
+        [rpc in keyof Ifc[grp]]: RPC<rpc, Ifc[grp][rpc]>
76
     }[keyof Ifc[grp]])[]
91
     }[keyof Ifc[grp]])[]
77
 }
92
 }
78
 
93
 
89
 
104
 
90
 export type CallInfo = BaseInfo & {
105
 export type CallInfo = BaseInfo & {
91
     type: 'Call',
106
     type: 'Call',
92
-    call: AnyFunction
107
+    call: GenericFunction
93
 }
108
 }
94
 
109
 
95
 export type RpcInfo = HookInfo | CallInfo
110
 export type RpcInfo = HookInfo | CallInfo
99
 export type HookCloseFunction<T> = (res: T, rpc: HookRPC<any, any>) => any
114
 export type HookCloseFunction<T> = (res: T, rpc: HookRPC<any, any>) => any
100
 
115
 
101
 
116
 
102
-export type AsyncIfc<Ifc extends RPCInterface> = { [grp in keyof Ifc]: { [rpcname in keyof Ifc[grp]]: AsyncAnyFunction<Ifc[grp][rpcname]> } }
117
+export type AsyncIfc<Ifc extends RPCInterface> = { [grp in keyof Ifc]: { [rpcname in keyof Ifc[grp]]: AsyncGenericFunction<Ifc[grp][rpcname]> } }
103
 
118
 
104
-export type AsyncAnyFunction<F extends AnyFunction = AnyFunction> = F extends (...args: Parameters<F>) => infer R
119
+export type AsyncGenericFunction<F extends GenericFunction = GenericFunction> = F extends (...args: Parameters<F>) => infer R
105
     ? ((...args: Parameters<F>) => R extends Promise<any> ? R : Promise<R>)
120
     ? ((...args: Parameters<F>) => R extends Promise<any> ? R : Promise<R>)
106
     : Promise<any>
121
     : Promise<any>
107
 
122
 
108
-type DYN_PARAM<
109
-    A = void, 
110
-    B = void,
111
-    C = void,
112
-    D = void,
113
-    E = void,
114
-    F = void,
115
-    G = void,
116
-    H = void,
117
-> = H extends void ?
118
-     G extends void ?
119
-      F extends void ?
120
-       E extends void ?
121
-        D extends void ?
122
-         C extends void ?
123
-          B extends void ?
124
-           A extends void ?
125
-            []
126
-            : [A]
127
-          : [A,B]
128
-         :[A,B,C]
129
-        :[A,B,C,D]
130
-       :[A,B,C,D,E]
131
-      :[A,B,C,D,E,F]
132
-     :[A,B,C,D,E,F,G]
133
-    :[A,B,C,D,E,F,G,H] 
134
 
123
 
135
 type Destroyable = { destroy: () => void }
124
 type Destroyable = { destroy: () => void }
136
-export type Callback<A0 = void, A1 = void, A2 = void, A3 = void, A4 = void, A5 = void, A6 = void, A7 = void> = 
137
-    (this: Destroyable, ...args: DYN_PARAM<A0, A1, A2, A3, A4, A5, A6, A7>) => void 
125
+export type Callback<Params extends any[] = []> =
126
+    (this: Destroyable, ...args: Params) => void
127
+
128
+type AsFunction<F> = F extends GenericFunction ? F : GenericFunction
129
+
130
+type Last<Tuple extends any[]> = Tuple[ Subtract<Length<Tuple>, 1> ]
131
+type Head<T extends any[]> = T extends [ ...infer Head, any ] ? Head : any[]
132
+type Tail<T extends any[]> = T extends [any, ...infer Tail] ? Tail: []
133
+
134
+type Length<T extends any[]> = 
135
+    T extends { length: infer L } ? L : never;
136
+
137
+type BuildTuple<L extends number, T extends any[] = []> = 
138
+    T extends { length: L } ? T : BuildTuple<L, [...T, any]>;
139
+
140
+type Subtract<A extends number, B extends number> = 
141
+    BuildTuple<A> extends [...(infer U), ...BuildTuple<B>]
142
+        ? Length<U>
143
+        : never;

+ 4
- 2
src/Utils.ts View File

76
  * Decorate an RPC with the error handler
76
  * Decorate an RPC with the error handler
77
  * @param rpcFunction the function to decorate
77
  * @param rpcFunction the function to decorate
78
  */
78
  */
79
-const callGenerator = (rpcName: string, $__socket__$: I.Socket, rpcFunction: T.AnyFunction, errorHandler: T.ErrorHandler): T.AnyFunction => {
79
+const callGenerator = (rpcName: string, $__socket__$: I.Socket, rpcFunction: T.GenericFunction, errorHandler: T.ErrorHandler): T.GenericFunction => {
80
     const argsArr = extractArgs(rpcFunction)
80
     const argsArr = extractArgs(rpcFunction)
81
     const args = argsArr.join(',')
81
     const args = argsArr.join(',')
82
     const argsStr = argsArr.map(stripAfterEquals).join(',')
82
     const argsStr = argsArr.map(stripAfterEquals).join(',')
108
  * @returns A {@link HookFunction}
108
  * @returns A {@link HookFunction}
109
  */
109
  */
110
 const hookGenerator = (rpc: T.HookRPC<any, any>, errorHandler: T.ErrorHandler, sesameFn?: T.SesameFunction, injectSocket?: boolean): T.HookInfo['generator'] => {
110
 const hookGenerator = (rpc: T.HookRPC<any, any>, errorHandler: T.ErrorHandler, sesameFn?: T.SesameFunction, injectSocket?: boolean): T.HookInfo['generator'] => {
111
+    const deserializer = DeserializerFactory 
111
     let argsArr = extractArgs(rpc.hook)
112
     let argsArr = extractArgs(rpc.hook)
112
     argsArr.pop() //remove callback param
113
     argsArr.pop() //remove callback param
113
 
114
 
124
             const uuid = uuidv4()
125
             const uuid = uuidv4()
125
             const res = await rpc.hook(${callArgs} (...cbargs) => {
126
             const res = await rpc.hook(${callArgs} (...cbargs) => {
126
                 ${rpc.onCallback ? `rpc.onCallback.apply({}, cbargs)` : ``}
127
                 ${rpc.onCallback ? `rpc.onCallback.apply({}, cbargs)` : ``}
128
+                cbargs = cbargs.map(deserializer.makeDeserializable)
127
                 $__socket__$.call.apply($__socket__$, [uuid, ...cbargs])
129
                 $__socket__$.call.apply($__socket__$, [uuid, ...cbargs])
128
             })
130
             })
129
             ${rpc.onDestroy ? `$__socket__$.bind(destroy_prefix+uuid, () => {
131
             ${rpc.onDestroy ? `$__socket__$.bind(destroy_prefix+uuid, () => {
247
             res(undefined)
249
             res(undefined)
248
         }),
250
         }),
249
 
251
 
250
-        unhook: (name: string, listener?: T.AnyFunction) => {
252
+        unhook: (name: string, listener?: T.GenericFunction) => {
251
             if (listener) {
253
             if (listener) {
252
                 socket.removeListener(name, listener)
254
                 socket.removeListener(name, listener)
253
             } else {
255
             } else {

+ 108
- 67
test/Test.ts View File

1
 import { describe, it } from "mocha";
1
 import { describe, it } from "mocha";
2
 import { RPCServer, RPCSocket, Serializable } from '../Index'
2
 import { RPCServer, RPCSocket, Serializable } from '../Index'
3
 import { RPCExporter, Socket } from "../src/Interfaces";
3
 import { RPCExporter, Socket } from "../src/Interfaces";
4
-import { ConnectedSocket, Callback } from "../src/Types";
4
+import { ConnectedSocket, Callback, GenericFunction } from "../src/Types";
5
 import * as log from 'why-is-node-running';
5
 import * as log from 'why-is-node-running';
6
 import * as http from 'http';
6
 import * as http from 'http';
7
 import * as express from 'express';
7
 import * as express from 'express';
9
 import { PromiseIO } from "../src/PromiseIO/Server";
9
 import { PromiseIO } from "../src/PromiseIO/Server";
10
 import { PromiseIOClient } from "../src/PromiseIO/Client";
10
 import { PromiseIOClient } from "../src/PromiseIO/Client";
11
 import { assert, expect } from 'chai';
11
 import { assert, expect } from 'chai';
12
-import { USER_DEFINED_TIMEOUT } from "../src/Strings";
12
+import { CLASSNAME_ATTRIBUTE, USER_DEFINED_TIMEOUT } from "../src/Strings";
13
 var should = require('chai').should();
13
 var should = require('chai').should();
14
 var chai = require("chai");
14
 var chai = require("chai");
15
 var chaiAsPromised = require("chai-as-promised");
15
 var chaiAsPromised = require("chai-as-promised");
16
- 
16
+
17
 chai.use(chaiAsPromised);
17
 chai.use(chaiAsPromised);
18
 const noop = (...args) => { }
18
 const noop = (...args) => { }
19
 
19
 
489
     })
489
     })
490
 
490
 
491
 
491
 
492
-    it('should have rpc echo', async() => {
492
+    it('should have rpc echo', async () => {
493
         const x = await client['test'].echo("x")
493
         const x = await client['test'].echo("x")
494
         expect(x).to.be.equal('x')
494
         expect(x).to.be.equal('x')
495
     })
495
     })
496
 
496
 
497
-    it('should add up to 6', async() => {
497
+    it('should add up to 6', async () => {
498
         const sum = await client['test'].add(1, 2, 3)
498
         const sum = await client['test'].add(1, 2, 3)
499
         expect(sum).to.be.equal(6)
499
         expect(sum).to.be.equal(6)
500
     })
500
     })
590
     let run = 0
590
     let run = 0
591
     const expected = [yesCandy, noCandy, noCandy, noCandy]
591
     const expected = [yesCandy, noCandy, noCandy, noCandy]
592
 
592
 
593
-    it('Unhook+unsubscribe should stop callbacks', async() => {
593
+    it('Unhook+unsubscribe should stop callbacks', async () => {
594
         await client['test'].subscribe(function myCallback(c) {
594
         await client['test'].subscribe(function myCallback(c) {
595
             if (run == 1)
595
             if (run == 1)
596
                 (myCallback as any).destroy()
596
                 (myCallback as any).destroy()
614
 type SesameTestIfc = {
614
 type SesameTestIfc = {
615
     test: {
615
     test: {
616
         checkCandy: () => Promise<string>
616
         checkCandy: () => Promise<string>
617
-        subscribe: (callback: Callback<string>) => Promise<topicDTO>
617
+        subscribe: (callback: Callback<[string]>) => Promise<topicDTO>
618
         manyParams: <A = string, B = number, C = boolean, D = Object>(a: A, b: B, c: C, d: D) => Promise<[A, B, C, D]>
618
         manyParams: <A = string, B = number, C = boolean, D = Object>(a: A, b: B, c: C, d: D) => Promise<[A, B, C, D]>
619
     }
619
     }
620
 }
620
 }
688
     })
688
     })
689
 
689
 
690
     it('callback should work with sesame', (done) => {
690
     it('callback should work with sesame', (done) => {
691
-        client.test.subscribe(function(c){
691
+        client.test.subscribe(function (c) {
692
             if (c === candy) {
692
             if (c === candy) {
693
                 done()
693
                 done()
694
             }
694
             }
725
                 a: 'a',
725
                 a: 'a',
726
                 b: 'b'
726
                 b: 'b'
727
             })
727
             })
728
-            .then(r => {
729
-                if (r != null)
730
-                    done(new Error("UNEXPECTED RESULT " + r))
731
-            })
732
-            .catch((e) => {
733
-                if (e.message === errtxt)
734
-                    done()
735
-                else
736
-                    done(e)
737
-            })
738
-            .finally(() => {
739
-                cli.close()
740
-                sock.close()
741
-                server.close()
742
-            })
728
+                .then(r => {
729
+                    if (r != null)
730
+                        done(new Error("UNEXPECTED RESULT " + r))
731
+                })
732
+                .catch((e) => {
733
+                    if (e.message === errtxt)
734
+                        done()
735
+                    else
736
+                        done(e)
737
+                })
738
+                .finally(() => {
739
+                    cli.close()
740
+                    sock.close()
741
+                    server.close()
742
+                })
743
         })
743
         })
744
     })
744
     })
745
 
745
 
1014
 describe("class (de-)serialization", () => {
1014
 describe("class (de-)serialization", () => {
1015
 
1015
 
1016
     @Serializable()
1016
     @Serializable()
1017
-    class SubClass{
1017
+    class SubClass {
1018
         fString = "F"
1018
         fString = "F"
1019
     }
1019
     }
1020
 
1020
 
1021
     @Serializable()
1021
     @Serializable()
1022
-    class TestClass{
1022
+    class TestClass {
1023
         aString = "A"
1023
         aString = "A"
1024
         aNumber = 46
1024
         aNumber = 46
1025
         aObject = {
1025
         aObject = {
1029
         }
1029
         }
1030
         aClassObject = new SubClass()
1030
         aClassObject = new SubClass()
1031
 
1031
 
1032
-        public returnOK(){
1032
+        public returnOK() {
1033
             return "OK"
1033
             return "OK"
1034
         }
1034
         }
1035
     }
1035
     }
1036
 
1036
 
1037
-    let myServer: RPCServer;
1038
-    let mySocket: RPCSocket;
1039
-
1040
-    before(function(done){
1041
-        myServer = new RPCServer([{
1042
-            name: "Test",
1043
-            RPCs: [
1044
-                function returnClass(){
1045
-                    return new TestClass()
1046
-                }
1047
-            ]
1048
-        }])
1049
-        myServer.listen(8084)
1050
-
1051
-        mySocket = new RPCSocket(8084, 'localhost')
1052
-        mySocket.connect().then(() => done())
1053
-    })
1054
-
1055
-    after(function(done){
1056
-        mySocket.close()
1057
-        myServer.close()
1058
-        done()
1059
-    })
1060
-
1061
-
1062
-    it("receives class in call response", async () => {
1063
-        const obj: TestClass = await mySocket['Test'].returnClass()
1064
-
1037
+    const verifyObject = (obj: any) => {
1065
         expect(obj).to.be.an.instanceOf(TestClass)
1038
         expect(obj).to.be.an.instanceOf(TestClass)
1066
         expect(obj.aString).to.be.a('string')
1039
         expect(obj.aString).to.be.a('string')
1067
         expect(obj.aNumber).to.be.a('number')
1040
         expect(obj.aNumber).to.be.a('number')
1070
         expect(obj.aObject.y).to.be.undefined
1043
         expect(obj.aObject.y).to.be.undefined
1071
         expect(obj.aObject.sub).to.be.an.instanceOf(SubClass)
1044
         expect(obj.aObject.sub).to.be.an.instanceOf(SubClass)
1072
         expect(obj.aClassObject).to.be.an.instanceOf(SubClass)
1045
         expect(obj.aClassObject).to.be.an.instanceOf(SubClass)
1073
-
1046
+        expect(obj).to.not.have.key(CLASSNAME_ATTRIBUTE)
1047
+        expect(obj.aObject.sub).to.not.have.key(CLASSNAME_ATTRIBUTE)
1048
+        expect(obj.aClassObject).to.not.have.key(CLASSNAME_ATTRIBUTE)
1074
         expect(obj.returnOK()).to.be.equal('OK')
1049
         expect(obj.returnOK()).to.be.equal('OK')
1075
-    })
1050
+    }
1076
 
1051
 
1077
-    it("receives class in hook response", async () => {
1078
-        const obj: TestClass = await mySocket['Test'].returnClass()
1052
+    describe("Responses", () => {
1053
+        type TestIfc = {
1054
+            Test: {
1055
+                returnClass: () => Promise<TestClass>
1056
+                classCallback: (callback: Callback<[TestClass]>) => Promise<TestClass>
1057
+            }
1058
+        }
1079
 
1059
 
1080
-        expect(obj).to.be.an.instanceOf(TestClass)
1081
-        expect(obj.aString).to.be.a('string')
1082
-        expect(obj.aNumber).to.be.a('number')
1083
-        expect(obj.aObject).to.be.a('object')
1084
-        expect(obj.aObject.x).to.be.a('string')
1085
-        expect(obj.aObject.y).to.be.undefined
1086
-        expect(obj.aObject.sub).to.be.an.instanceOf(SubClass)
1087
-        expect(obj.aClassObject).to.be.an.instanceOf(SubClass)
1060
+        let myServer: RPCServer<TestIfc>;
1061
+        let mySocket: ConnectedSocket<TestIfc>;
1062
+
1063
+        before(function (done) {
1064
+            myServer = new RPCServer<TestIfc>([{
1065
+                name: "Test",
1066
+                RPCs: [
1067
+                    async function returnClass() {
1068
+                        return new TestClass()
1069
+                    }, {
1070
+                        name: "classCallback",
1071
+                        hook: async function (callback) {
1072
+                            setTimeout(_ => callback(new TestClass()), 250)
1073
+                            return new TestClass()
1074
+                        }
1075
+                    }
1076
+                ]
1077
+            }])
1078
+            myServer.listen(8084)
1088
 
1079
 
1089
-        expect(obj.returnOK()).to.be.equal('OK')
1080
+            new RPCSocket<TestIfc>(8084, 'localhost').connect().then(connsock => {
1081
+                mySocket = connsock
1082
+                done()
1083
+            })
1084
+        })
1085
+
1086
+        after(function (done) {
1087
+            mySocket.close()
1088
+            myServer.close()
1089
+            done()
1090
+        })
1091
+
1092
+
1093
+        it("receives class object in call response", async () => {
1094
+            const obj: TestClass = await mySocket['Test'].returnClass()
1095
+            verifyObject(obj)
1096
+        })
1097
+
1098
+        it("receives class object in hook response", async function () {
1099
+            const obj: TestClass = await mySocket.Test.classCallback(noop)
1100
+            verifyObject(obj)
1101
+        })
1102
+
1103
+        it("receives class object in callback", function (done) {
1104
+            mySocket.Test.classCallback(function (cbValue) {
1105
+                verifyObject(cbValue)
1106
+                done()
1107
+            }).then(verifyObject)
1108
+        })
1109
+    })
1110
+    describe("Parameters", () => {
1111
+        it("Class object in call", function(done){
1112
+            const server = new RPCServer([
1113
+                {
1114
+                    name: "Test",
1115
+                    RPCs: [
1116
+                        function callWithClass(testObj: TestClass){
1117
+                            verifyObject(testObj)
1118
+                            done()
1119
+                        }
1120
+                    ]
1121
+                }
1122
+            ]).listen(8086)
1123
+
1124
+            new RPCSocket(8086, 'localhost').connect().then(sock => {
1125
+                sock['Test'].callWithClass(new TestClass()).then(_ => {
1126
+                    sock.close()
1127
+                    server.close()
1128
+                })
1129
+            })
1130
+        })
1090
     })
1131
     })
1091
 })
1132
 })

Loading…
Cancel
Save