1
+ import { constants } from "../constants" ;
2
+ import { ConnectOpts } from 'net' ;
3
+ import { ConnectionOptions } from 'tls' ;
4
+
5
+ interface Dependency {
6
+ [ type : string ] : string ;
7
+ }
8
+
9
+ interface FnArgs {
10
+ [ type : string ] : any ;
11
+ }
12
+
13
+ interface FnMappings {
14
+ [ type : string ] : Function ;
15
+ }
16
+
17
+ interface HookMappings {
18
+ [ type : string ] : Function [ ]
19
+ }
20
+
21
+ interface ProtocolMessage {
22
+ requestId : string ;
23
+ type : string ;
24
+ }
25
+
26
+ interface RegisterModuleRequest extends ProtocolMessage {
27
+ type : 'moduleRegistration' ;
28
+ moduleId : string ;
29
+ version : string ;
30
+ dependencies : Dependency ;
31
+ }
32
+
33
+ interface RegisterModuleResponse extends ProtocolMessage {
34
+ type : 'moduleRegistered' ;
35
+ }
36
+
37
+ interface FunctionCallRequest extends ProtocolMessage {
38
+ type : 'functionCall' ;
39
+ function : string ;
40
+ arguments : FnArgs ;
41
+ }
42
+
43
+ interface FunctionCallResponse extends ProtocolMessage {
44
+ type : 'functionResponse' ;
45
+ data : FnArgs ;
46
+ }
47
+
48
+ interface RegisterHookRequest extends ProtocolMessage {
49
+ type : 'registerHook' ;
50
+ hook : string ;
51
+ }
52
+
53
+ interface ListenHookResponse extends ProtocolMessage {
54
+ type : 'hookRegistered' ;
55
+ }
56
+
57
+ interface TriggerHookRequest extends ProtocolMessage {
58
+ type : 'triggerHook' ;
59
+ hook : string ;
60
+ }
61
+
62
+ interface TriggerHookResponse extends ProtocolMessage {
63
+ type : 'hookTriggered' ;
64
+ hook : string ;
65
+ }
66
+
67
+ interface CallHookResponse extends ProtocolMessage {
68
+ type : 'hookTriggered' ;
69
+ hook : string ;
70
+ }
71
+
72
+ interface DeclareFunctionRequest extends ProtocolMessage {
73
+ type : 'declareFunction' ;
74
+ function : string ;
75
+ }
76
+
77
+ interface DeclareFunctionResponse extends ProtocolMessage {
78
+ type : 'functionDeclared' ;
79
+ function : string ;
80
+ }
81
+
82
+ export class Protocol {
83
+ private moduleId : string ;
84
+ private functions : FnMappings ;
85
+ private hookListeners : HookMappings ;
86
+ private requests : FnMappings ;
87
+
88
+ private connection : GothamConnection ;
89
+
90
+ private async sendRequest ( obj : any , cb : Function ) {
91
+ await this . connection . send ( obj ) ;
92
+ this . requests [ obj . requestId ] = cb ;
93
+ }
94
+
95
+ private generateRequestId ( ) {
96
+ return this . moduleId + Date . now ( ) ;
97
+ }
98
+
99
+ initialize ( moduleId : string , version : string , deps : Dependency ) : RegisterModuleRequest {
100
+ this . moduleId = moduleId ;
101
+ return {
102
+ requestId : this . generateRequestId ( ) ,
103
+ type : 'moduleRegistration' ,
104
+ moduleId : moduleId ,
105
+ version : version ,
106
+ dependencies : deps
107
+ }
108
+ }
109
+
110
+ registerHook ( moduleId : string , hook : string , cb : Function ) : RegisterHookRequest {
111
+ if ( this . hookListeners [ hook ] ) {
112
+ this . hookListeners [ hook ] = [ cb ] ;
113
+ } else {
114
+ this . hookListeners [ hook ] . push ( cb ) ;
115
+ }
116
+ return {
117
+ requestId : this . generateRequestId ( ) ,
118
+ type : 'registerHook' ,
119
+ hook : `${ moduleId } -${ hook } ` ,
120
+ }
121
+ }
122
+
123
+ triggerHook ( hook : string ) : TriggerHookRequest {
124
+ return {
125
+ requestId : this . generateRequestId ( ) ,
126
+ type : 'triggerHook' ,
127
+ hook : hook ,
128
+ }
129
+ }
130
+
131
+ declareFunction ( functionName : string , fn : Function ) : DeclareFunctionRequest {
132
+ this . functions [ functionName ] = fn ;
133
+ return {
134
+ requestId : this . generateRequestId ( ) ,
135
+ type : 'declareFunction' ,
136
+ function : functionName ,
137
+ }
138
+ }
139
+
140
+ callFunction ( moduleId : string , functionName : string , ...args : FnArgs [ ] ) : FunctionCallRequest {
141
+ return {
142
+ requestId : this . generateRequestId ( ) ,
143
+ type : 'functionCall' ,
144
+ function : `${ moduleId } .${ functionName } ` ,
145
+ arguments : args
146
+ }
147
+ }
148
+
149
+ hookCall ( hook : string ) {
150
+ if ( this . hookListeners [ hook ] ) {
151
+ for ( const fn of this . hookListeners [ hook ] ) {
152
+ fn ( ) ;
153
+ }
154
+ }
155
+ }
156
+
157
+ functionCall ( functionName : string , ...args : FnArgs [ ] ) {
158
+ if ( this . functions [ functionName ] ) {
159
+ this . functions [ functionName ] ( ) ;
160
+ }
161
+ }
162
+
163
+ async parseResponse ( obj : ProtocolMessage ) {
164
+ let res ;
165
+ if ( obj . type === constants . responseType . moduleRegistered ) {
166
+ res = true ;
167
+ } else if ( obj . type === constants . requestType . functionCall ) {
168
+ res = await this . parseFunctionCall ( obj as FunctionCallRequest ) ;
169
+ } else if ( obj . type === constants . responseType . functionDeclared ) {
170
+ res = true ;
171
+ } else if ( obj . type === constants . responseType . hookRegistered ) {
172
+ res = true ;
173
+ } else if ( obj . type === constants . responseType . hookTriggered ) {
174
+ res = await this . parseHookTriggered ( obj as TriggerHookRequest ) ;
175
+ } else {
176
+ res = false ;
177
+ }
178
+
179
+ // Call the callback proviced while sending the request
180
+ if ( this . requests [ obj . requestId ] ) {
181
+ this . requests [ obj . requestId ] ( res ) ;
182
+ delete this . requests [ obj . requestId ] ;
183
+ }
184
+ }
185
+
186
+ async parseFunctionCall ( obj : FunctionCallRequest ) {
187
+ if ( this . functions [ obj . function ] ) {
188
+ let res = this . functions [ obj . function ] ( ) ;
189
+ if ( res instanceof Promise ) {
190
+ res = await res ;
191
+ }
192
+ await this . sendRequest ( {
193
+ requestId : obj . requestId ,
194
+ type : 'functionResponse' ,
195
+ data : res
196
+ } , ( ) => { } ) ;
197
+ }
198
+ }
199
+
200
+ async parseHookTriggered ( obj : TriggerHookRequest ) {
201
+ if ( this . hookListeners [ obj . hook ] ) {
202
+ for ( const listener of this . hookListeners [ obj . hook ] ) {
203
+ listener ( ) ;
204
+ }
205
+ }
206
+ }
207
+ }
0 commit comments