Browse Source

v0.1.4 sesame sockets

master
peter 5 years ago
parent
commit
4087a12a87
8 changed files with 603 additions and 756 deletions
  1. 524
    726
      package-lock.json
  2. 1
    1
      package.json
  3. 2
    2
      src/Backend.ts
  4. 30
    17
      src/Frontend.ts
  5. 2
    2
      src/Interfaces.ts
  6. 8
    1
      src/Types.ts
  7. 15
    6
      src/Utils.ts
  8. 21
    1
      test/devtest.ts

+ 524
- 726
package-lock.json
File diff suppressed because it is too large
View File


+ 1
- 1
package.json View File

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

+ 2
- 2
src/Backend.ts View File

30
     constructor(
30
     constructor(
31
         private port:number,
31
         private port:number,
32
         private exporters: I.RPCExporter<T.RPCInterface<InterfaceT>, keyof InterfaceT, SubResType>[] = [],
32
         private exporters: I.RPCExporter<T.RPCInterface<InterfaceT>, keyof InterfaceT, SubResType>[] = [],
33
-        conf: T.SocketConf =  {}
33
+        private conf: T.ServerConf =  {}
34
     ){
34
     ){
35
         
35
         
36
         if(!conf.visibility) this.visibility = "127.0.0.1"        
36
         if(!conf.visibility) this.visibility = "127.0.0.1"        
82
     protected initRPCs(socket:I.Socket){
82
     protected initRPCs(socket:I.Socket){
83
         socket.hook('info', () => rpcInfos)
83
         socket.hook('info', () => rpcInfos)
84
         const rpcInfos:T.ExtendedRpcInfo[] = [
84
         const rpcInfos:T.ExtendedRpcInfo[] = [
85
-            ...this.exporters.flatMap(exporter => U.rpcHooker(socket, exporter))
85
+            ...this.exporters.flatMap(exporter => U.rpcHooker(socket, exporter, this.conf.sesame))
86
         ]
86
         ]
87
     }
87
     }
88
 
88
 

+ 30
- 17
src/Frontend.ts View File

17
  * A websocket-on-steroids with built-in RPC capabilities
17
  * A websocket-on-steroids with built-in RPC capabilities
18
  */
18
  */
19
 export class RPCSocket implements I.Socket{
19
 export class RPCSocket implements I.Socket{
20
-    static async makeSocket<T extends T.RPCInterface= T.RPCInterface>(port:number, server: string, tls: boolean = false): Promise<RPCSocket & T.RPCInterface<T>> {
21
-        const socket = <RPCSocket & T> new RPCSocket(port, server, tls)
20
+    static async makeSocket<T extends T.RPCInterface= T.RPCInterface>(port:number, server: string, conf?:T.SocketConf): Promise<RPCSocket & T.RPCInterface<T>> {
21
+        const socket = <RPCSocket & T> new RPCSocket(port, server, conf)
22
         return await socket.connect<T>()
22
         return await socket.connect<T>()
23
     }
23
     }
24
 
24
 
30
      * @param server Server address
30
      * @param server Server address
31
      * @param tls @default false use TLS
31
      * @param tls @default false use TLS
32
      */
32
      */
33
-    constructor(public port:number, private server: string, private tls: boolean = false){
33
+    constructor(public port:number, private server: string, private conf:T.SocketConf = { tls: false }){
34
         Object.defineProperty(this, 'socket', {value: undefined, writable: true})
34
         Object.defineProperty(this, 'socket', {value: undefined, writable: true})
35
     }
35
     }
36
 
36
 
95
     /**
95
     /**
96
      * Connects to the server and attaches available RPCs to this object
96
      * Connects to the server and attaches available RPCs to this object
97
      */
97
      */
98
-    public async connect<T extends T.RPCInterface= T.RPCInterface>() : Promise<RPCSocket & T.RPCInterface<T>>{
99
-        this.socket = await bsock.connect(this.port, this.server, this.tls)
98
+    public async connect<T extends T.RPCInterface= T.RPCInterface>( sesame?: string ) : Promise<RPCSocket & T.RPCInterface<T>>{
99
+        this.socket = await bsock.connect(this.port, this.server, this.conf.tls?this.conf.tls:false)
100
 
100
 
101
         const info:T.ExtendedRpcInfo[] = await this.info()
101
         const info:T.ExtendedRpcInfo[] = await this.info()
102
         info.forEach(i => {
102
         info.forEach(i => {
103
             let f: any
103
             let f: any
104
             switch (i.type) {
104
             switch (i.type) {
105
                 case 'Call':
105
                 case 'Call':
106
-                    f = this.callGenerator(i.uniqueName, i.argNames)    
106
+                    f = this.callGenerator(i.uniqueName, i.argNames, sesame)    
107
                     break                
107
                     break                
108
                 case 'Hook':
108
                 case 'Hook':
109
-                    f = this.hookGenerator(i.uniqueName, i.argNames)                    
109
+                    f = this.hookGenerator(i.uniqueName, i.argNames, sesame)                    
110
                     break
110
                     break
111
             }
111
             }
112
             if(this[i.owner] == null)
112
             if(this[i.owner] == null)
129
      * @param fnName The function name
129
      * @param fnName The function name
130
      * @param fnArgs A string-list of parameters
130
      * @param fnArgs A string-list of parameters
131
      */
131
      */
132
-    private callGenerator(fnName: string, fnArgs:string[]): T.AnyFunction{
132
+    private callGenerator(fnName: string, fnArgs:string[], sesame?:string): T.AnyFunction{
133
         const headerArgs = fnArgs.join(",")
133
         const headerArgs = fnArgs.join(",")
134
         const argParams = fnArgs.map(stripAfterEquals).join(",")
134
         const argParams = fnArgs.map(stripAfterEquals).join(",")
135
-        return eval( '( () => async ('+headerArgs+') => { return await this.socket.call("'+fnName+'", '+argParams+')} )()' )
135
+        if(!sesame)
136
+            return eval( '( () => async ('+headerArgs+') => { return await this.socket.call("'+fnName+'", '+argParams+')} )()' )
137
+        else   
138
+            return eval( '( () => async ('+headerArgs+') => { return await this.socket.call("'+fnName+'", "'+sesame+'", '+argParams+')} )()' )
136
     }
139
     }
137
 
140
 
138
     /**
141
     /**
140
      * @param fnName The function name
143
      * @param fnName The function name
141
      * @param fnArgs A string-list of parameters
144
      * @param fnArgs A string-list of parameters
142
      */
145
      */
143
-    private hookGenerator(fnName: string, fnArgs:string[]): T.HookFunction{
146
+    private hookGenerator(fnName: string, fnArgs:string[], sesame?:string): T.HookFunction{
144
         const headerArgs = fnArgs.join(",")
147
         const headerArgs = fnArgs.join(",")
145
         const argParams = fnArgs.map(stripAfterEquals).join(",")
148
         const argParams = fnArgs.map(stripAfterEquals).join(",")
146
-        return eval( `( () => async (`+headerArgs+(headerArgs.length!==0?",":"")+` callback) => {
147
-                            const r = await this.socket.call("`+fnName+`", `+argParams+`)
148
-                            if(r.result === 'Success'){
149
-                                this.socket.hook(r.uuid, callback)
150
-                            }
151
-                            return r
152
-                        } )()` )
149
+        if(!sesame){
150
+            return eval( `( () => async (`+headerArgs+(headerArgs.length!==0?",":"")+` callback) => {
151
+                const r = await this.socket.call("`+fnName+`", `+argParams+`)
152
+                if(r.result === 'Success'){
153
+                    this.socket.hook(r.uuid, callback)
154
+                }
155
+                return r
156
+            } )()` )
157
+        }else{
158
+            return eval( `( () => async (`+headerArgs+(headerArgs.length!==0?",":"")+` callback) => {
159
+                const r = await this.socket.call("`+fnName+`", "`+sesame+`", `+argParams+`)
160
+                if(r.result === 'Success'){
161
+                    this.socket.hook(r.uuid, callback)
162
+                }
163
+                return r
164
+            } )()` )
165
+        }
153
     }
166
     }
154
 }
167
 }

+ 2
- 2
src/Interfaces.ts View File

5
  * Interface for all classes that export RPCs
5
  * Interface for all classes that export RPCs
6
  */
6
  */
7
 export interface RPCExporter<
7
 export interface RPCExporter<
8
-    Ifc extends T.RPCInterface,
9
-    Name extends keyof Ifc,
8
+    Ifc extends T.RPCInterface = T.RPCInterface,
9
+    Name extends keyof Ifc = keyof Ifc,
10
     SubresT = {}
10
     SubresT = {}
11
 >{
11
 >{
12
     name: Name
12
     name: Name

+ 8
- 1
src/Types.ts View File

7
 export type ConnectionHandler = (socket:I.Socket) => void
7
 export type ConnectionHandler = (socket:I.Socket) => void
8
 export type ErrorHandler = (socket:I.Socket, error:any) => void
8
 export type ErrorHandler = (socket:I.Socket, error:any) => void
9
 export type CloseHandler = (socket:I.Socket) =>  void
9
 export type CloseHandler = (socket:I.Socket) =>  void
10
-export type SocketConf = {
10
+export type SesameConf = {
11
+    sesame?: string
12
+}
13
+export type ServerConf = {
11
     connectionHandler?: ConnectionHandler
14
     connectionHandler?: ConnectionHandler
12
     errorHandler?: ErrorHandler
15
     errorHandler?: ErrorHandler
13
     closeHandler?: CloseHandler
16
     closeHandler?: CloseHandler
14
     visibility?: Visibility
17
     visibility?: Visibility
18
+} & SesameConf
19
+
20
+export type SocketConf = {
21
+    tls:boolean
15
 }
22
 }
16
 
23
 
17
 export type ResponseType = "Subscribe" | "Success" | "Error"
24
 export type ResponseType = "Subscribe" | "Success" | "Error"

+ 15
- 6
src/Utils.ts View File

10
  * @param owner The owning RPC group's name
10
  * @param owner The owning RPC group's name
11
  * @throws Error on RPC without name property
11
  * @throws Error on RPC without name property
12
  */
12
  */
13
-export const rpcToRpcinfo = <SubResT = {}>(rpc : T.RPC<any, any, SubResT>, owner: string):T.RpcInfo => {
13
+export const rpcToRpcinfo = <SubResT = {}>(rpc : T.RPC<any, any, SubResT>, owner: string, sesame?:string):T.RpcInfo => {
14
     switch (typeof rpc){
14
     switch (typeof rpc){
15
         case  "object":
15
         case  "object":
16
             if(rpc['call']){
16
             if(rpc['call']){
19
                     argNames: extractArgs(rpc['call']),
19
                     argNames: extractArgs(rpc['call']),
20
                     type: "Call",
20
                     type: "Call",
21
                     name: rpc.name,
21
                     name: rpc.name,
22
-                    call: rpc['call'],
22
+                    call: sesame?async (_sesame, ...args) => {if(sesame === _sesame) return await rpc['call'].apply({}, args)}:rpc['call'],
23
                 }
23
                 }
24
             }else{
24
             }else{
25
-                const generator = hookGenerator(<T.HookRPC<any, any, any>>rpc)
25
+                const generator = hookGenerator(<T.HookRPC<any, any, any>>rpc, sesame)
26
                 return {
26
                 return {
27
                     owner: owner,
27
                     owner: owner,
28
                     argNames: extractArgs(generator(undefined)),
28
                     argNames: extractArgs(generator(undefined)),
56
  * @param exporter The exporter
56
  * @param exporter The exporter
57
  * @param makeUnique @default true Attach a suffix to RPC names
57
  * @param makeUnique @default true Attach a suffix to RPC names
58
  */
58
  */
59
-export function rpcHooker<SubResT = {}>(socket: I.Socket, exporter:I.RPCExporter<any, any, SubResT>, makeUnique = true):T.ExtendedRpcInfo[]{
59
+export function rpcHooker<SubResT = {}>(socket: I.Socket, exporter:I.RPCExporter<any, any, SubResT>, sesame?:string, makeUnique = true):T.ExtendedRpcInfo[]{
60
     const owner = exporter.name
60
     const owner = exporter.name
61
     const RPCs = [...exporter.exportRPCs()]
61
     const RPCs = [...exporter.exportRPCs()]
62
+
63
+
62
     const suffix = makeUnique?"-"+uuidv4().substr(0,4):""
64
     const suffix = makeUnique?"-"+uuidv4().substr(0,4):""
63
-    return RPCs.map(rpc => rpcToRpcinfo(rpc, owner))
65
+    return RPCs.map(rpc => rpcToRpcinfo(rpc, owner, sesame))
64
     .map(info => {
66
     .map(info => {
65
         const ret:any = info
67
         const ret:any = info
66
         ret.uniqueName = info.name+suffix
68
         ret.uniqueName = info.name+suffix
67
 
69
 
70
+
68
         switch(info.type){
71
         switch(info.type){
69
             case "Hook":
72
             case "Hook":
70
                 socket.hook(ret.uniqueName, info.generator(socket))
73
                 socket.hook(ret.uniqueName, info.generator(socket))
82
  * @param rpc The RPC to transform
85
  * @param rpc The RPC to transform
83
  * @returns A {@link HookFunction}
86
  * @returns A {@link HookFunction}
84
  */
87
  */
85
-const hookGenerator = (rpc:T.HookRPC<any, any, any>): T.HookInfo['generator'] => { 
88
+const hookGenerator = (rpc:T.HookRPC<any, any, any>, sesame?:string): T.HookInfo['generator'] => { 
86
     const argsArr = extractArgs(rpc.hook)
89
     const argsArr = extractArgs(rpc.hook)
90
+    if(sesame){
91
+        const _sesame = argsArr.shift()
92
+        if(sesame !== _sesame){
93
+            throw new Error('Bad sesame')
94
+        }
95
+    }
87
     argsArr.pop()
96
     argsArr.pop()
88
     const args = argsArr.join(',')
97
     const args = argsArr.join(',')
89
 
98
 

+ 21
- 1
test/devtest.ts View File

50
     })
50
     })
51
 
51
 
52
     await client.Group1.triggerCallbacks("Hello", "World", "Callbacks")
52
     await client.Group1.triggerCallbacks("Hello", "World", "Callbacks")
53
-}))
53
+}))
54
+
55
+const srv = new RPCServer(30000, [{
56
+    name: 'Group2',
57
+    exportRPCs: () => [{
58
+        name: 'echo',
59
+        call: async (x) => x
60
+    }]
61
+}], {
62
+    sesame: 'open'
63
+})
64
+
65
+const s = new RPCSocket(30000, 'localhost')
66
+s.connect("open").then(async() => {
67
+    s['Group2']['echo']('open', 'dfgfg').then(console.log)
68
+    s['Group2']['echo']('dfgfg').then(console.log)
69
+
70
+    s['Group2']['echo']('dfgfg').then(console.log)
71
+
72
+})
73
+

Loading…
Cancel
Save