@factset/frontgate-js-sdk 6.11.1 → 7.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/CHANGELOG.md +97 -40
  2. package/dist/lib/esnext/FrontgateClient.js +0 -3
  3. package/dist/lib/esnext/authentication/index.js +3 -4
  4. package/dist/lib/esnext/common/errors.js +0 -35
  5. package/dist/lib/esnext/common/functions.js +0 -84
  6. package/dist/lib/esnext/common/interfaces/index.js +0 -1
  7. package/dist/lib/esnext/compat/index.js +0 -3
  8. package/dist/lib/esnext/connection/index.js +19 -6
  9. package/dist/lib/esnext/connection/util/functions.js +0 -56
  10. package/dist/lib/esnext/index.js +0 -1
  11. package/dist/lib/esnext/message/index.js +1 -1
  12. package/dist/lib/esnext/message/interfaces/index.js +0 -1
  13. package/dist/lib/esnext/message/request/TransportLayerClientRequestHeader.js +1 -1
  14. package/dist/lib/esnext/message/request/raw/example/CreateNotationSearchRequest.js +1 -1
  15. package/dist/lib/esnext/message/request/raw/index.js +0 -1
  16. package/dist/lib/esnext/message/response/index.js +0 -5
  17. package/dist/lib/esnext/message/update/index.js +0 -1
  18. package/dist/lib/esnext/mixins/EndpointRequestMixin.js +1 -1
  19. package/dist/lib/esnext/mixins/RemoteLoggerMixin.js +29 -0
  20. package/dist/lib/esnext/mixins/auth/AppAuthMixin.js +79 -11
  21. package/dist/lib/esnext/mixins/auth/SessionAuthMixin.js +76 -36
  22. package/dist/lib/esnext/mixins/auth/UserCredentialAuthMixin.js +82 -12
  23. package/dist/lib/esnext/mixins/auth/UserPasswordAuthMixin.js +80 -13
  24. package/dist/lib/esnext/mixins/auth/index.js +0 -31
  25. package/dist/lib/esnext/mixins/index.js +1 -0
  26. package/dist/lib/esnext/mixins/subscription/EndpointSubscriptionMixin.js +149 -122
  27. package/dist/lib/esnext/version.js +1 -1
  28. package/dist/lib/node/FrontgateClient.js +0 -3
  29. package/dist/lib/node/authentication/index.js +4 -4
  30. package/dist/lib/node/common/errors.js +1 -41
  31. package/dist/lib/node/common/functions.js +0 -92
  32. package/dist/lib/node/common/interfaces/index.js +0 -1
  33. package/dist/lib/node/compat/index.js +0 -3
  34. package/dist/lib/node/connection/index.js +20 -6
  35. package/dist/lib/node/connection/util/functions.js +0 -63
  36. package/dist/lib/node/index.js +1 -3
  37. package/dist/lib/node/message/index.js +2 -1
  38. package/dist/lib/node/message/interfaces/index.js +0 -1
  39. package/dist/lib/node/message/request/TransportLayerClientRequestHeader.js +3 -3
  40. package/dist/lib/node/message/request/raw/example/CreateNotationSearchRequest.js +3 -3
  41. package/dist/lib/node/message/request/raw/index.js +0 -1
  42. package/dist/lib/node/message/response/index.js +0 -5
  43. package/dist/lib/node/message/update/index.js +0 -1
  44. package/dist/lib/node/mixins/EndpointRequestMixin.js +2 -2
  45. package/dist/lib/node/mixins/RemoteLoggerMixin.js +33 -0
  46. package/dist/lib/node/mixins/auth/AppAuthMixin.js +78 -10
  47. package/dist/lib/node/mixins/auth/SessionAuthMixin.js +75 -35
  48. package/dist/lib/node/mixins/auth/UserCredentialAuthMixin.js +80 -10
  49. package/dist/lib/node/mixins/auth/UserPasswordAuthMixin.js +78 -11
  50. package/dist/lib/node/mixins/auth/index.js +0 -33
  51. package/dist/lib/node/mixins/index.js +1 -0
  52. package/dist/lib/node/mixins/subscription/EndpointSubscriptionMixin.js +149 -122
  53. package/dist/lib/node/version.js +1 -1
  54. package/dist/lib/types/FrontgateClient.d.ts +0 -1
  55. package/dist/lib/types/authentication/index.d.ts +3 -4
  56. package/dist/lib/types/authentication/util/ChallengeResolver.d.ts +2 -1
  57. package/dist/lib/types/common/errors.d.ts +0 -21
  58. package/dist/lib/types/common/functions.d.ts +0 -8
  59. package/dist/lib/types/common/interfaces/index.d.ts +0 -1
  60. package/dist/lib/types/compat/index.d.ts +0 -3
  61. package/dist/lib/types/connection/index.d.ts +16 -6
  62. package/dist/lib/types/connection/util/functions.d.ts +0 -18
  63. package/dist/lib/types/index.d.ts +0 -1
  64. package/dist/lib/types/message/index.d.ts +1 -1
  65. package/dist/lib/types/message/interfaces/index.d.ts +0 -1
  66. package/dist/lib/types/message/request/TransportLayerClientRequestHeader.d.ts +1 -0
  67. package/dist/lib/types/message/request/raw/index.d.ts +0 -1
  68. package/dist/lib/types/message/response/index.d.ts +0 -5
  69. package/dist/lib/types/message/update/index.d.ts +0 -1
  70. package/dist/lib/types/mixins/AuthTokenRequestMixin.d.ts +1 -2
  71. package/dist/lib/types/mixins/EndpointRequestMixin.d.ts +1 -2
  72. package/dist/lib/types/mixins/HTTPProxyRequestMixin.d.ts +1 -4
  73. package/dist/lib/types/mixins/LoggerMixin.d.ts +1 -2
  74. package/dist/lib/types/mixins/MessageCompressorMixin.d.ts +1 -2
  75. package/dist/lib/types/mixins/OpenTelemetryMixin.d.ts +1 -2
  76. package/dist/lib/types/mixins/PingMixin.d.ts +1 -2
  77. package/dist/lib/types/mixins/ReconnectMixin.d.ts +1 -2
  78. package/dist/lib/types/mixins/RemoteLoggerMixin.d.ts +16 -0
  79. package/dist/lib/types/mixins/RequestMixin.d.ts +1 -2
  80. package/dist/lib/types/mixins/auth/AppAuthMixin.d.ts +15 -8
  81. package/dist/lib/types/mixins/auth/CookieTokenAuthMixin.d.ts +1 -2
  82. package/dist/lib/types/mixins/auth/FetchAuthenticationMixin.d.ts +1 -2
  83. package/dist/lib/types/mixins/auth/SessionAuthMixin.d.ts +10 -5
  84. package/dist/lib/types/mixins/auth/TokenAuthMixin.d.ts +1 -2
  85. package/dist/lib/types/mixins/auth/UserCredentialAuthMixin.d.ts +15 -8
  86. package/dist/lib/types/mixins/auth/UserPasswordAuthMixin.d.ts +15 -8
  87. package/dist/lib/types/mixins/auth/index.d.ts +0 -8
  88. package/dist/lib/types/mixins/connection/FrontgateWSMixin.d.ts +1 -2
  89. package/dist/lib/types/mixins/index.d.ts +2 -1
  90. package/dist/lib/types/mixins/subscription/EndpointSubscriptionMixin.d.ts +4 -6
  91. package/dist/lib/types/mixins/subscription/RawSubscriptionMixin.d.ts +1 -2
  92. package/dist/lib/umd/mdg2.client.min.umd.js +1 -12
  93. package/dist/lib/umd/mdg2.client.umd.js +4061 -8138
  94. package/package.json +25 -28
  95. package/dist/lib/esnext/Mdg2Client.js +0 -185
  96. package/dist/lib/esnext/authentication/AbstractAuthentication.js +0 -49
  97. package/dist/lib/esnext/authentication/AppAuthentication.js +0 -70
  98. package/dist/lib/esnext/authentication/AuthenticationInterface.js +0 -1
  99. package/dist/lib/esnext/authentication/CookieTokenAuthentication.js +0 -18
  100. package/dist/lib/esnext/authentication/TokenAuthentication.js +0 -42
  101. package/dist/lib/esnext/authentication/UserCredentialAuthentication.js +0 -73
  102. package/dist/lib/esnext/authentication/UserPasswordAuthentication.js +0 -71
  103. package/dist/lib/esnext/common/Mdg2ClientOptions.js +0 -1
  104. package/dist/lib/esnext/common/constants.js +0 -10
  105. package/dist/lib/esnext/common/interfaces/observe/ObserveOptions.js +0 -1
  106. package/dist/lib/esnext/connection/AbstractFrontgateConnection.js +0 -324
  107. package/dist/lib/esnext/connection/ConnectionInterface.js +0 -1
  108. package/dist/lib/esnext/connection/FrontgateWSConnection.js +0 -281
  109. package/dist/lib/esnext/connection/JobPromise.js +0 -2
  110. package/dist/lib/esnext/connection/LatencyHandler.js +0 -1
  111. package/dist/lib/esnext/connection/LatencyTracker.js +0 -47
  112. package/dist/lib/esnext/connection/MessageProcessor.js +0 -1
  113. package/dist/lib/esnext/connection/util/Encoding.js +0 -14
  114. package/dist/lib/esnext/core/RequestModule.js +0 -349
  115. package/dist/lib/esnext/core/SubscriptionModule.js +0 -104
  116. package/dist/lib/esnext/core/subscription/EndpointHandler.js +0 -121
  117. package/dist/lib/esnext/core/subscription/SubjectManager.js +0 -39
  118. package/dist/lib/esnext/message/MessageFactory.js +0 -36
  119. package/dist/lib/esnext/message/guards.js +0 -21
  120. package/dist/lib/esnext/message/interfaces/JobObservable.js +0 -1
  121. package/dist/lib/esnext/message/request/raw/RawRequestFactory.js +0 -18
  122. package/dist/lib/esnext/message/response/AuthenticationByTokenResponse.js +0 -1
  123. package/dist/lib/esnext/message/response/CancelSubscriptionResponse.js +0 -3
  124. package/dist/lib/esnext/message/response/LoadNotificationMessage.js +0 -1
  125. package/dist/lib/esnext/message/response/PermissionDeniedResponse.js +0 -6
  126. package/dist/lib/esnext/message/response/RejectResponse.js +0 -9
  127. package/dist/lib/esnext/message/update/SubscriptionLossMessage.js +0 -10
  128. package/dist/lib/esnext/util/TimeOutWrapper.js +0 -51
  129. package/dist/lib/node/Mdg2Client.js +0 -189
  130. package/dist/lib/node/authentication/AbstractAuthentication.js +0 -53
  131. package/dist/lib/node/authentication/AppAuthentication.js +0 -74
  132. package/dist/lib/node/authentication/AuthenticationInterface.js +0 -2
  133. package/dist/lib/node/authentication/CookieTokenAuthentication.js +0 -22
  134. package/dist/lib/node/authentication/TokenAuthentication.js +0 -46
  135. package/dist/lib/node/authentication/UserCredentialAuthentication.js +0 -77
  136. package/dist/lib/node/authentication/UserPasswordAuthentication.js +0 -75
  137. package/dist/lib/node/common/Mdg2ClientOptions.js +0 -2
  138. package/dist/lib/node/common/constants.js +0 -13
  139. package/dist/lib/node/common/interfaces/observe/ObserveOptions.js +0 -2
  140. package/dist/lib/node/connection/AbstractFrontgateConnection.js +0 -328
  141. package/dist/lib/node/connection/ConnectionInterface.js +0 -2
  142. package/dist/lib/node/connection/FrontgateWSConnection.js +0 -288
  143. package/dist/lib/node/connection/JobPromise.js +0 -6
  144. package/dist/lib/node/connection/LatencyHandler.js +0 -2
  145. package/dist/lib/node/connection/LatencyTracker.js +0 -51
  146. package/dist/lib/node/connection/MessageProcessor.js +0 -2
  147. package/dist/lib/node/connection/util/Encoding.js +0 -18
  148. package/dist/lib/node/core/RequestModule.js +0 -353
  149. package/dist/lib/node/core/SubscriptionModule.js +0 -108
  150. package/dist/lib/node/core/subscription/EndpointHandler.js +0 -125
  151. package/dist/lib/node/core/subscription/SubjectManager.js +0 -43
  152. package/dist/lib/node/message/MessageFactory.js +0 -73
  153. package/dist/lib/node/message/guards.js +0 -30
  154. package/dist/lib/node/message/interfaces/JobObservable.js +0 -2
  155. package/dist/lib/node/message/request/raw/RawRequestFactory.js +0 -22
  156. package/dist/lib/node/message/response/AuthenticationByTokenResponse.js +0 -2
  157. package/dist/lib/node/message/response/CancelSubscriptionResponse.js +0 -7
  158. package/dist/lib/node/message/response/LoadNotificationMessage.js +0 -2
  159. package/dist/lib/node/message/response/PermissionDeniedResponse.js +0 -10
  160. package/dist/lib/node/message/response/RejectResponse.js +0 -13
  161. package/dist/lib/node/message/update/SubscriptionLossMessage.js +0 -14
  162. package/dist/lib/node/util/TimeOutWrapper.js +0 -55
  163. package/dist/lib/types/Mdg2Client.d.ts +0 -52
  164. package/dist/lib/types/authentication/AbstractAuthentication.d.ts +0 -17
  165. package/dist/lib/types/authentication/AppAuthentication.d.ts +0 -12
  166. package/dist/lib/types/authentication/AuthenticationInterface.d.ts +0 -9
  167. package/dist/lib/types/authentication/CookieTokenAuthentication.d.ts +0 -6
  168. package/dist/lib/types/authentication/TokenAuthentication.d.ts +0 -14
  169. package/dist/lib/types/authentication/UserCredentialAuthentication.d.ts +0 -13
  170. package/dist/lib/types/authentication/UserPasswordAuthentication.d.ts +0 -14
  171. package/dist/lib/types/common/Mdg2ClientOptions.d.ts +0 -12
  172. package/dist/lib/types/common/constants.d.ts +0 -11
  173. package/dist/lib/types/common/interfaces/observe/ObserveOptions.d.ts +0 -5
  174. package/dist/lib/types/connection/AbstractFrontgateConnection.d.ts +0 -116
  175. package/dist/lib/types/connection/ConnectionInterface.d.ts +0 -53
  176. package/dist/lib/types/connection/FrontgateWSConnection.d.ts +0 -23
  177. package/dist/lib/types/connection/JobPromise.d.ts +0 -3
  178. package/dist/lib/types/connection/LatencyHandler.d.ts +0 -1
  179. package/dist/lib/types/connection/LatencyTracker.d.ts +0 -13
  180. package/dist/lib/types/connection/MessageProcessor.d.ts +0 -2
  181. package/dist/lib/types/connection/util/Encoding.d.ts +0 -9
  182. package/dist/lib/types/core/RequestModule.d.ts +0 -78
  183. package/dist/lib/types/core/SubscriptionModule.d.ts +0 -24
  184. package/dist/lib/types/core/subscription/EndpointHandler.d.ts +0 -37
  185. package/dist/lib/types/core/subscription/SubjectManager.d.ts +0 -21
  186. package/dist/lib/types/message/MessageFactory.d.ts +0 -29
  187. package/dist/lib/types/message/guards.d.ts +0 -11
  188. package/dist/lib/types/message/interfaces/JobObservable.d.ts +0 -4
  189. package/dist/lib/types/message/request/raw/RawRequestFactory.d.ts +0 -4
  190. package/dist/lib/types/message/response/AuthenticationByTokenResponse.d.ts +0 -20
  191. package/dist/lib/types/message/response/CancelSubscriptionResponse.d.ts +0 -3
  192. package/dist/lib/types/message/response/LoadNotificationMessage.d.ts +0 -8
  193. package/dist/lib/types/message/response/PermissionDeniedResponse.d.ts +0 -4
  194. package/dist/lib/types/message/response/RejectResponse.d.ts +0 -5
  195. package/dist/lib/types/message/update/SubscriptionLossMessage.d.ts +0 -17
  196. package/dist/lib/types/util/TimeOutWrapper.d.ts +0 -12
@@ -1,324 +0,0 @@
1
- import { NullLogger, LogLevel } from '../logger';
2
- import { Compressor } from './util/Compressor';
3
- import { Encoding } from './util/Encoding';
4
- import { DEFAULT_TIMEOUT_CONNECTION_IN_MS, LOGGER_NAME } from '../common/constants';
5
- import { isNodeEnvironment } from '../common/functions';
6
- import { PingRequest } from '../message/request/PingRequest';
7
- import { PingResponse } from '../message/response/PingResponse';
8
- export var ConnectionState;
9
- (function (ConnectionState) {
10
- ConnectionState[ConnectionState["DISCONNECTED"] = 0] = "DISCONNECTED";
11
- ConnectionState[ConnectionState["CONNECTING"] = 1] = "CONNECTING";
12
- ConnectionState[ConnectionState["AUTHENTICATED"] = 2] = "AUTHENTICATED";
13
- ConnectionState[ConnectionState["RECONNECTING"] = 3] = "RECONNECTING";
14
- })(ConnectionState || (ConnectionState = {}));
15
- export var DeploymentStage;
16
- (function (DeploymentStage) {
17
- DeploymentStage[DeploymentStage["production"] = 40] = "production";
18
- DeploymentStage[DeploymentStage["preproduction"] = 35] = "preproduction";
19
- DeploymentStage[DeploymentStage["show"] = 30] = "show";
20
- DeploymentStage[DeploymentStage["testing"] = 20] = "testing";
21
- })(DeploymentStage || (DeploymentStage = {}));
22
- export var DefaultHosts;
23
- (function (DefaultHosts) {
24
- DefaultHosts["production"] = "frontgate-eu.factsetdigitalsolutions.com";
25
- DefaultHosts["show"] = "frontgate-eu.show.factsetdigitalsolutions.com";
26
- })(DefaultHosts || (DefaultHosts = {}));
27
- export class AbstractFrontgateConnection {
28
- setMessageProcessor(messageName, messageProcessor) {
29
- this.messageProcessors[messageName] = messageProcessor;
30
- }
31
- removeMessageProcessor(messageName) {
32
- if (this.messageProcessors[messageName] === undefined) {
33
- return;
34
- }
35
- this.messageProcessors[messageName] = undefined;
36
- }
37
- constructor(auth, options) {
38
- this.reconnectDelays = [1000, 2000, 4000, 8000, 16000, 32000];
39
- this.reconnectCounter = 0;
40
- this.connectionCounter = 0;
41
- this.onConnect = null;
42
- this.onMessage = null;
43
- this.onClose = null;
44
- this.onError = null;
45
- this.onAuthentication = null;
46
- this.onCleanupRequests = null;
47
- this.onCleanupSubscriptions = null;
48
- this.onClearPendingSubscription = null;
49
- this.onReceiveTimeout = null;
50
- this.restartSubscriptions = null;
51
- this.options = { ...AbstractFrontgateConnection.DEFAULT_OPTIONS, ...options };
52
- this.auth = auth;
53
- this.state = ConnectionState.DISCONNECTED;
54
- if (this.options.logger) {
55
- this.logger = this.options.logger;
56
- }
57
- this.timestampOfLastMessageSent = 0;
58
- this.jobId = 0;
59
- this.peerInfo = null;
60
- this.compressor = new Compressor();
61
- this.keepAliveIntervalHandle = null;
62
- this.hasActiveSession = false;
63
- if (this.options.loglevel) {
64
- this.logger.setLevel(this.options.loglevel);
65
- }
66
- if (!Encoding.isSupportedEncoding(this.options.encoding)) {
67
- throw new Error(`Unknown or unsupported encoding: ${this.options.encoding}`);
68
- }
69
- this.messageProcessors = {};
70
- this.setMessageProcessor('Foundation::LoadNotificationMessage', this.handleLoadNotificationMessage.bind(this));
71
- this.setMessageProcessor('Foundation::KeepAliveMessage', this.handleKeepAliveMessage.bind(this));
72
- this.setMessageProcessor('Foundation::PingResponse', this.handlePingResponseMessage.bind(this));
73
- this.setMessageProcessor('Foundation::DisconnectionMessage', this.handleDisconnectionMessage.bind(this));
74
- }
75
- async close() {
76
- if (!this.isAuthenticated()) {
77
- this.logger.warn('Cannot close gracefully. Connection not open. Proceeding to handleClose.');
78
- await this.handleClose('Unauthenticated connection');
79
- return;
80
- }
81
- try {
82
- await this.sendDisconnectionMessage();
83
- }
84
- catch (error) {
85
- await this.handleClose(error.message);
86
- }
87
- }
88
- setPeerInfo(peerInfo) {
89
- this.peerInfo = { ...this.peerInfo, ...peerInfo };
90
- }
91
- isAuthenticated() {
92
- return this.state === ConnectionState.AUTHENTICATED;
93
- }
94
- isConnecting() {
95
- return this.state === ConnectionState.CONNECTING;
96
- }
97
- clearPendingConnection() {
98
- this.pendingConnection = null;
99
- }
100
- isPendingConnection() {
101
- return this.pendingConnection instanceof Promise;
102
- }
103
- handleLoadNotificationMessage(msg) {
104
- if (this.peerInfo) {
105
- this.peerInfo.loadStatus = msg.load;
106
- }
107
- return false;
108
- }
109
- handleKeepAliveMessage() {
110
- return false;
111
- }
112
- handlePingResponseMessage(msg) {
113
- const res = new PingResponse(msg);
114
- this.logger.debug(`Time in ms: Request=${res.timeOfRequest} Peer=${res.timeAtPeer} Response=${res.timeOfResponse}`);
115
- this.logger.debug(`Latency in ms: Total=${res.latencyTotal} Peer=${res.latencyAtPeer}`);
116
- return false;
117
- }
118
- async handleDisconnectionMessage(msg) {
119
- await this.handleClose(`DisconnectionMessage received: '${msg.details}`);
120
- if (this.onClose) {
121
- this.onClose(msg.details);
122
- }
123
- }
124
- handleAuthentication() {
125
- this.state = ConnectionState.AUTHENTICATED;
126
- const INTERVAL_TIMER = 1000;
127
- this.keepAliveIntervalHandle = setInterval(() => {
128
- void this.sendKeepAliveMessage();
129
- }, INTERVAL_TIMER);
130
- if (this.onAuthentication) {
131
- this.onAuthentication();
132
- }
133
- }
134
- handleReceiveTimeout() {
135
- if (this.messageReceiveTimeout) {
136
- clearTimeout(this.messageReceiveTimeout);
137
- }
138
- if (this.onReceiveTimeout) {
139
- this.onReceiveTimeout();
140
- }
141
- }
142
- resetReceiveTimeout() {
143
- if (!this.peerInfo?.maximumIdleInterval) {
144
- return;
145
- }
146
- const timeoutInMs = (this.peerInfo.maximumIdleInterval / 1000) * 2;
147
- if (this.messageReceiveTimeout) {
148
- clearTimeout(this.messageReceiveTimeout);
149
- }
150
- this.messageReceiveTimeout = setTimeout(() => {
151
- this.handleReceiveTimeout();
152
- }, timeoutInMs);
153
- }
154
- handleStandardMessage(msg) {
155
- if (this.onMessage) {
156
- this.onMessage(msg);
157
- }
158
- return true;
159
- }
160
- handleMessage(msg) {
161
- if (!msg.Message) {
162
- return undefined;
163
- }
164
- this.resetReceiveTimeout();
165
- const messageHandler = this.messageProcessors[msg.Message];
166
- if (messageHandler !== undefined) {
167
- if (!messageHandler(msg)) {
168
- return undefined;
169
- }
170
- }
171
- else {
172
- this.handleStandardMessage(msg);
173
- }
174
- return msg;
175
- }
176
- async handleClose(info) {
177
- if (typeof info === 'string') {
178
- this.logger.warn(`Handling connection close event. Reason: ${info}`);
179
- }
180
- else {
181
- const { code, reason, wasClean, type } = info;
182
- this.logger.warn('Handling connection close event.', { code, reason, wasClean, type });
183
- }
184
- if (this.onCleanupRequests) {
185
- this.onCleanupRequests();
186
- }
187
- if (!this.shouldRestartSubscriptions && this.onCleanupSubscriptions) {
188
- this.onCleanupSubscriptions();
189
- }
190
- if (this.keepAliveIntervalHandle) {
191
- clearInterval(this.keepAliveIntervalHandle);
192
- this.keepAliveIntervalHandle = null;
193
- }
194
- this.state = ConnectionState.DISCONNECTED;
195
- this.compressor.reset();
196
- this.peerInfo = null;
197
- if (this.messageReceiveTimeout) {
198
- clearTimeout(this.messageReceiveTimeout);
199
- this.messageReceiveTimeout = null;
200
- }
201
- const isDisconnectMessage = typeof info === 'string' && info.includes('DisconnectionMessage');
202
- if (isDisconnectMessage) {
203
- this.logger.debug('Disconnect message received. Preventing reconnect. Potential authentication failure.');
204
- this.options.shouldReconnectOnConnectionLoss = false;
205
- }
206
- const reconnectActivated = this.auth.reconnectable && this.options.shouldReconnectOnConnectionLoss;
207
- if (reconnectActivated) {
208
- this.onMessage = null;
209
- await this.reconnect();
210
- }
211
- else {
212
- if (this.onClose) {
213
- this.onClose(info);
214
- }
215
- this.onMessage = null;
216
- this.onClose = null;
217
- this.onError = null;
218
- }
219
- }
220
- async reconnect() {
221
- while (!this.isAuthenticated()) {
222
- this.compressor.reset();
223
- this.peerInfo = null;
224
- this.state = ConnectionState.RECONNECTING;
225
- try {
226
- const lastDelayIndex = this.reconnectDelays.length - 1;
227
- let delay = this.reconnectDelays[this.reconnectCounter] ?? this.reconnectDelays[lastDelayIndex];
228
- delay += Math.floor(Math.random() * 50);
229
- const attempts = this.reconnectCounter ? `(${this.reconnectCounter} attempts)` : '';
230
- this.logger.warn(`Trying to reconnect. Waiting ${delay} ms ${attempts}`);
231
- this.reconnectCounter++;
232
- await this.open(delay);
233
- if (this.shouldRestartSubscriptions && this.restartSubscriptions)
234
- this.restartSubscriptions();
235
- }
236
- catch (reconnectError) {
237
- this.logger.error('Failed to reconnect', reconnectError);
238
- }
239
- }
240
- this.reconnectCounter = 0;
241
- }
242
- handleWsError(handleWsError) {
243
- void this.close().then(() => {
244
- this.logger.error('Connection closed due to WebSocket error');
245
- });
246
- this.logger.error('WebSocket error: ', handleWsError);
247
- if (this.onError) {
248
- this.onError(handleWsError);
249
- }
250
- }
251
- preSubmit(msg) {
252
- if (msg.Message) {
253
- const jobId = this.returnAndAssignJobIdToMessage(msg);
254
- this.logger.trace('PreSubmit', { message: msg.Message, jobId });
255
- return jobId;
256
- }
257
- throw new TypeError('Expected message type. Must be JSON message object or Array of JSON message objects');
258
- }
259
- async sendKeepAliveMessage() {
260
- const msSinceLastMsg = Date.now() - this.timestampOfLastMessageSent;
261
- const meanIdleInterval = this.options.maximum_idle_interval / 1000 / 2;
262
- const keepAliveNeeded = this.timestampOfLastMessageSent > 0 && msSinceLastMsg > meanIdleInterval;
263
- if (!keepAliveNeeded) {
264
- return;
265
- }
266
- const request = (this.options.enablePingPongKeepalive ?? isNodeEnvironment())
267
- ? new PingRequest().getPtlMessage()
268
- : {
269
- Message: 'KeepAliveMessage',
270
- Version: 2,
271
- };
272
- await this.submit(request);
273
- }
274
- async sendDisconnectionMessage(reason = 'client shutdown', code = 64) {
275
- const request = {
276
- Message: 'Foundation::DisconnectionMessage',
277
- Version: 3,
278
- reason: {
279
- value: code,
280
- },
281
- details: reason,
282
- };
283
- await this.submit(request);
284
- await this.handleClose('Disconnected by User.');
285
- }
286
- returnAndAssignJobIdToMessage(message) {
287
- if (typeof message !== 'object') {
288
- throw new TypeError(`expected object, not ${typeof message}`);
289
- }
290
- if (typeof message.Message === 'undefined') {
291
- throw new TypeError("expected object to have a 'Message' member");
292
- }
293
- if (!/Request$/.exec(message.Message)) {
294
- return null;
295
- }
296
- if (typeof message.header === 'undefined') {
297
- return null;
298
- }
299
- if (!message.header.id_job) {
300
- this.jobId = this.jobId >= Number.MAX_SAFE_INTEGER ? 1 : this.jobId + 1;
301
- message.header.id_job = this.jobId;
302
- }
303
- return message.header.id_job;
304
- }
305
- setLogger(logger) {
306
- this.logger = logger;
307
- }
308
- }
309
- AbstractFrontgateConnection.DEFAULT_OPTIONS = {
310
- payload_content: 'foundation',
311
- deployment_stage: DeploymentStage.show,
312
- logger: NullLogger.getLogger(LOGGER_NAME),
313
- loglevel: LogLevel.WARN,
314
- maximum_idle_interval: 45000000,
315
- host: DefaultHosts.show,
316
- port: 443,
317
- tls: true,
318
- path_prefix: '',
319
- encoding: 'jsjsonc-v2',
320
- split_authentication_token_second_factor: undefined,
321
- shouldReconnectOnConnectionLoss: true,
322
- connectionTimeoutInMs: DEFAULT_TIMEOUT_CONNECTION_IN_MS,
323
- sessionHandling: false,
324
- };
@@ -1 +0,0 @@
1
- export {};
@@ -1,281 +0,0 @@
1
- import { AbstractFrontgateConnection, ConnectionState } from './AbstractFrontgateConnection';
2
- import { Encoding } from './util/Encoding';
3
- import WebSocket from 'isomorphic-ws';
4
- import { TimeoutWrapper } from '../util/TimeOutWrapper';
5
- import { delay, toUrlBase64 } from '../common/functions';
6
- import { ServiceUnavailableError, BadRequestError, InternalServerError, UnauthorizedError, TimeoutError } from '../common/errors';
7
- export class FrontgateWSConnection extends AbstractFrontgateConnection {
8
- constructor(auth, options) {
9
- if (typeof WebSocket === 'undefined') {
10
- throw new InternalServerError('WebSocketClient not supported, WebSocket() missing in JavaScript environment');
11
- }
12
- super(auth, FrontgateWSConnection.sanitizeOptions(options));
13
- this.ws = null;
14
- const { encoding } = this.options;
15
- if (!Encoding.isSupportedEncoding(encoding)) {
16
- throw new BadRequestError(`Unknown or unsupported encoding: ${encoding}`);
17
- }
18
- this.onReceiveTimeout = () => {
19
- this.logger.debug('onReceiveTimeout: Closing connection');
20
- void super.close().then(() => {
21
- this.ws?.close();
22
- });
23
- };
24
- }
25
- async openConnection() {
26
- if (this.state === ConnectionState.RECONNECTING && this.auth.onReconnect) {
27
- await this.auth.onReconnect();
28
- }
29
- this.logger.info('Opening new connection', { host: this.options.host });
30
- try {
31
- await this.openWebSocket();
32
- }
33
- catch (openWebSocketError) {
34
- this.logger.error('Problem opening connection', openWebSocketError);
35
- throw new ServiceUnavailableError(openWebSocketError.message, openWebSocketError);
36
- }
37
- this.logger.info(`Performing ${this.auth.constructor.name}`);
38
- try {
39
- await this.performAuthentication();
40
- this.logger.debug('WebSocket authenticated');
41
- }
42
- catch (authError) {
43
- this.logger.error('Authentication problem occurred:', authError);
44
- throw new UnauthorizedError(authError.message, authError);
45
- }
46
- if (this.ws) {
47
- this.ws.onclose = this.handleClose.bind(this);
48
- this.ws.onerror = this.handleWsError.bind(this);
49
- }
50
- }
51
- async performAuthentication() {
52
- await new Promise((resolve, reject) => {
53
- if (this.ws) {
54
- this.ws.onclose = () => {
55
- this.state = ConnectionState.DISCONNECTED;
56
- reject(new Error('Connection closed by server. Check credentials.'));
57
- };
58
- this.ws.onerror = (err) => {
59
- void this.close();
60
- reject(new Error(`WebSocket error during authentication: ${err.message}`));
61
- };
62
- this.auth.authenticate(this).then(resolve).catch(reject);
63
- }
64
- else {
65
- reject(new Error('WebSocket not initialized'));
66
- }
67
- });
68
- this.handleAuthentication();
69
- }
70
- async open(delayInMs) {
71
- if (this.onConnect) {
72
- this.logger.trace('onConnect()');
73
- this.onConnect();
74
- }
75
- const timeout = this.options.connectionTimeoutInMs;
76
- const reason = `Connection timeout after ${timeout} ms`;
77
- const catchHandler = async (e) => {
78
- if (e instanceof TimeoutError && !this.pendingConnection) {
79
- return Promise.resolve();
80
- }
81
- return Promise.reject(e);
82
- };
83
- if (this.isPendingConnection() && this.pendingConnection) {
84
- this.connectionCounter++;
85
- const timestamp = Date.now();
86
- this.logger.warn(`Waiting for pending connection (${this.connectionCounter}) with a timeout of ${timeout} ms`);
87
- return TimeoutWrapper.wrap(this.pendingConnection, timeout, reason)
88
- .catch(catchHandler)
89
- .then(() => {
90
- const duration = Date.now() - timestamp;
91
- this.logger.warn(`Pending connection (${this.connectionCounter}) resolved after ${duration} ms`);
92
- });
93
- }
94
- if (delayInMs) {
95
- this.logger.debug(`Opening ${delayInMs} ms delayed connection with a timeout of ${timeout} ms`);
96
- this.pendingConnection = delay(delayInMs)
97
- .then(async () => TimeoutWrapper.wrap(this.openConnection(), timeout, reason))
98
- .catch(catchHandler)
99
- .finally(() => {
100
- this.clearPendingConnection();
101
- });
102
- return this.pendingConnection;
103
- }
104
- this.logger.debug(`Opening connection with a timeout of ${timeout} ms `);
105
- this.pendingConnection = TimeoutWrapper.wrap(this.openConnection(), timeout, reason)
106
- .catch(catchHandler)
107
- .finally(() => {
108
- this.clearPendingConnection();
109
- });
110
- return this.pendingConnection;
111
- }
112
- async close(reconnect = false, logout = false) {
113
- this.logger.info('Closing connection explicitly');
114
- this.options.shouldReconnectOnConnectionLoss = reconnect;
115
- await super.close();
116
- if (this.ws) {
117
- this.clearPendingConnection();
118
- this.ws.onclose = this.handleClose.bind(this);
119
- this.ws.close();
120
- this.state = ConnectionState.DISCONNECTED;
121
- }
122
- if (logout && !reconnect && this.options.sessionHandling && this.hasActiveSession) {
123
- this.logger.info('Session logout');
124
- await this.openWebSocket(true);
125
- }
126
- }
127
- send(msg) {
128
- const idJob = this.preSubmit(msg);
129
- const promise = this.submit(msg);
130
- promise.idJob = idJob;
131
- return promise;
132
- }
133
- async submit(msg) {
134
- this.timestampOfLastMessageSent = Date.now();
135
- const promise = new Promise((resolve) => {
136
- this.logger.debug(`Sending ${msg.Message}`, { ...msg });
137
- this.sendMessage(msg);
138
- this.resolveOnMessage = resolve;
139
- switch (msg.Message) {
140
- case 'Foundation::DisconnectionMessage':
141
- case 'Foundation::KeepAliveMessage':
142
- case 'Foundation::PingRequest':
143
- resolve({ Message: 'This message does not have a response', Version: 1 });
144
- break;
145
- default:
146
- break;
147
- }
148
- });
149
- promise.catch((submitError) => {
150
- const lastMsgDate = new Date(this.timestampOfLastMessageSent);
151
- this.logger.error(`Failed sending ${msg.Message}`, submitError, { request: msg, lastMsgDate });
152
- });
153
- return promise;
154
- }
155
- sendMessage(msg) {
156
- let data = JSON.stringify(msg);
157
- if (Encoding.isCompressedJson(this.options.encoding)) {
158
- data = this.compressor.compress(data);
159
- }
160
- this.ws?.send(data);
161
- }
162
- async openWebSocket(logout = false) {
163
- this.logger.debug('Open WebSocket');
164
- return new Promise((resolve, reject) => {
165
- const { encoding, tls, host, port, path_prefix, frontgateSplitAuthenticationTokenSecondFactor, webSocketClientOptions, sessionHandling, frontgateAuthenticationToken } = this.options;
166
- const wsProtocol = tls ? 'wss' : 'ws';
167
- const wsUrl = `${wsProtocol}://${host}:${port}${path_prefix}/ws`;
168
- const [protocolVersion, protocolType] = encoding.split('-');
169
- const protocolPrefix = protocolType ? `${protocolType}.` : '';
170
- const subProtocols = [`${protocolPrefix}ws-${protocolVersion}.mdgms.com`];
171
- if (frontgateSplitAuthenticationTokenSecondFactor) {
172
- subProtocols.push(`mdg2auth-${frontgateSplitAuthenticationTokenSecondFactor}`);
173
- this.options.frontgateSplitAuthenticationTokenSecondFactor = null;
174
- }
175
- else if (sessionHandling) {
176
- if (logout) {
177
- subProtocols.push('mdg2wstoken-0');
178
- }
179
- else if (this.clientOptions.otpToken) {
180
- subProtocols.push(`mdg2wstoken-${toUrlBase64(this.clientOptions.otpToken)}`);
181
- this.clientOptions.otpToken = '';
182
- }
183
- else if (frontgateAuthenticationToken) {
184
- if (typeof window !== 'undefined') {
185
- subProtocols.push(`mdg2wstoken-${toUrlBase64(frontgateAuthenticationToken)}`);
186
- }
187
- }
188
- else {
189
- subProtocols.push('mdg2wstoken-1');
190
- }
191
- }
192
- this.state = ConnectionState.CONNECTING;
193
- if (webSocketClientOptions) {
194
- this.ws = new WebSocket(wsUrl, subProtocols, webSocketClientOptions);
195
- }
196
- else {
197
- this.ws = new WebSocket(wsUrl, subProtocols);
198
- }
199
- this.ws.binaryType = 'arraybuffer';
200
- this.ws.onopen = () => {
201
- this.logger.info('WebSocket connected', { wsUrl, subProtocols });
202
- if (logout) {
203
- this.logger.info('User logged out');
204
- if (this.ws) {
205
- this.ws.close();
206
- }
207
- }
208
- this.hasActiveSession = !logout && sessionHandling;
209
- resolve();
210
- };
211
- this.ws.onclose = (closeEvent) => {
212
- this.state = ConnectionState.DISCONNECTED;
213
- const reason = closeEvent.reason ? `: ${closeEvent.reason}` : '';
214
- reject(new Error(`Connection closed while trying to connect${reason}`));
215
- };
216
- this.ws.onerror = this.handleWsError.bind(this);
217
- this.ws.onmessage = this.onWebSocketMessage.bind(this);
218
- });
219
- }
220
- onWebSocketMessage(e) {
221
- if (this.state === ConnectionState.DISCONNECTED) {
222
- this.logger.warn('onWebSocketMessage while state is disconnected', { data: e.data });
223
- return;
224
- }
225
- const decodedMessage = this.decodeMessage(e.data);
226
- const msg = this.handleMessage(decodedMessage);
227
- this.logger.debug(`Received ${decodedMessage.Message}`, decodedMessage);
228
- if (msg) {
229
- this.resolveOnMessage(msg);
230
- }
231
- }
232
- decodeMessage(msg) {
233
- const { encoding } = this.options;
234
- try {
235
- if (msg instanceof ArrayBuffer && Encoding.isCompressedJson(encoding)) {
236
- const decoded = this.compressor.decompress(new Uint8Array(msg));
237
- return JSON.parse(decoded);
238
- }
239
- if (typeof msg === 'string' && Encoding.isPlainJson(encoding)) {
240
- return JSON.parse(msg);
241
- }
242
- }
243
- catch (decodeMessageError) {
244
- this.logger.error('Decoding message failed', decodeMessageError);
245
- }
246
- if (String(msg.constructor.name) === 'Buffer') {
247
- return msg;
248
- }
249
- this.logger.error(`Could not decode Message of type "${typeof msg}" with encoding "${encoding}".`);
250
- return { Message: `Invalid Message Type ${typeof msg}`, Version: 1 };
251
- }
252
- static sanitizeOptions(options = {}) {
253
- if (options.frontgateHost) {
254
- options.host = options.frontgateHost;
255
- }
256
- if (options.frontgatePathPrefix) {
257
- options.path_prefix = options.frontgatePathPrefix;
258
- }
259
- if (options.frontgateSplitAuthenticationTokenSecondFactor) {
260
- options.split_authentication_token_second_factor = options.frontgateSplitAuthenticationTokenSecondFactor;
261
- }
262
- if (options.frontgateWebsocketProtocol) {
263
- options.encoding = options.frontgateWebsocketProtocol;
264
- }
265
- if (options.deploymentStage) {
266
- options.deployment_stage = options.deploymentStage;
267
- }
268
- return options;
269
- }
270
- handleWsError(handleWsError) {
271
- if (typeof process !== 'undefined') {
272
- this.close(this.options.shouldReconnectOnConnectionLoss).then(() => {
273
- this.logger.error('Connection closed due to WebSocket error');
274
- });
275
- }
276
- this.logger.error('WebSocket error: ', handleWsError);
277
- if (this.onError) {
278
- this.onError(handleWsError);
279
- }
280
- }
281
- }
@@ -1,2 +0,0 @@
1
- export class JobPromise extends Promise {
2
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,47 +0,0 @@
1
- import { PingRequest, PingResponse } from '../message';
2
- export class LatencyTracker {
3
- constructor(cb, conn) {
4
- this.cb = cb;
5
- this.conn = conn;
6
- this.isRequestPending = false;
7
- this.request = new PingRequest();
8
- }
9
- start(interval) {
10
- if (this.timeout !== undefined) {
11
- throw new Error('LatencyTracker already running!');
12
- }
13
- this.conn.setMessageProcessor('Foundation::PingResponse', this.handlePingResponse.bind(this));
14
- this.timeout = setInterval(() => {
15
- if (!this.conn.isAuthenticated()) {
16
- this.cb(undefined, undefined, undefined, 'Skipping ping request, connection not authenticated!');
17
- return;
18
- }
19
- if (this.isRequestPending) {
20
- if (Date.now() - this.request.timeAtSender < LatencyTracker.MAX_RESPONSE_LATENCY_MS) {
21
- this.cb(this.request.timeAtSender, undefined, undefined, 'Skipping ping request, previous request pending!');
22
- return;
23
- }
24
- this.cb(this.request.timeAtSender, undefined, undefined, 'Clearing ping request, previous request exceeded timeout!');
25
- }
26
- this.isRequestPending = true;
27
- this.request.resetTimeAtSender();
28
- void this.conn.send(this.request.getPtlMessage());
29
- }, interval);
30
- if (typeof window === 'undefined') {
31
- this.timeout.unref();
32
- }
33
- }
34
- stop() {
35
- clearInterval(this.timeout);
36
- this.timeout = undefined;
37
- this.isRequestPending = false;
38
- this.conn.removeMessageProcessor('Foundation::PingResponse');
39
- }
40
- handlePingResponse(msg) {
41
- const resp = new PingResponse(msg);
42
- this.cb(resp.timeOfRequest, resp.latencyTotal, resp.latencyAtPeer, undefined);
43
- this.isRequestPending = false;
44
- return false;
45
- }
46
- }
47
- LatencyTracker.MAX_RESPONSE_LATENCY_MS = 60 * 1000;
@@ -1 +0,0 @@
1
- export {};
@@ -1,14 +0,0 @@
1
- export class Encoding {
2
- static isSupportedEncoding(encoding) {
3
- return Encoding.SUPPORTED_ENCODINGS.includes(encoding);
4
- }
5
- static isPlainJson(encoding) {
6
- return Encoding.PLAIN_JSON_ENCODINGS.includes(encoding);
7
- }
8
- static isCompressedJson(encoding) {
9
- return Encoding.COMPRESSED_ENCODINGS.includes(encoding);
10
- }
11
- }
12
- Encoding.SUPPORTED_ENCODINGS = ['jsjson-v2', 'jsjsonc-v2'];
13
- Encoding.PLAIN_JSON_ENCODINGS = ['jsjson-v2'];
14
- Encoding.COMPRESSED_ENCODINGS = Encoding.SUPPORTED_ENCODINGS.filter((enc) => enc.includes('jsonc'));