oorja 1.5.0 → 1.6.2
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.
- package/README.md +10 -4
- package/bin/oorja +5 -0
- package/lib/commands/signout.js +2 -2
- package/lib/commands/teletype/index.js +3 -3
- package/lib/lib/config.d.ts +5 -6
- package/lib/lib/config.js +12 -7
- package/lib/lib/encryption.d.ts +1 -1
- package/lib/lib/encryption.js +12 -7
- package/lib/lib/index.js +1 -0
- package/lib/lib/oorja/index.js +14 -13
- package/lib/lib/oorja/preflight.d.ts +1 -1
- package/lib/lib/oorja/preflight.js +17 -11
- package/lib/lib/surya/index.d.ts +2 -2
- package/lib/lib/surya/index.js +15 -13
- package/lib/lib/surya/types.d.ts +10 -10
- package/lib/lib/surya/vendor/phoenix/ajax.d.ts +8 -0
- package/lib/lib/surya/vendor/phoenix/ajax.js +85 -0
- package/lib/lib/surya/vendor/phoenix/channel.d.ts +154 -0
- package/lib/lib/surya/vendor/phoenix/channel.js +311 -0
- package/lib/lib/surya/vendor/phoenix/constants.d.ts +33 -0
- package/lib/lib/surya/vendor/phoenix/constants.js +32 -0
- package/lib/lib/surya/vendor/phoenix/index.d.ts +199 -0
- package/lib/lib/surya/vendor/phoenix/index.js +207 -0
- package/lib/lib/surya/vendor/phoenix/longpoll.d.ts +12 -0
- package/lib/lib/surya/vendor/phoenix/longpoll.js +129 -0
- package/lib/lib/surya/vendor/phoenix/presence.d.ts +44 -0
- package/lib/lib/surya/vendor/phoenix/presence.js +155 -0
- package/lib/lib/surya/vendor/phoenix/push.d.ts +57 -0
- package/lib/lib/surya/vendor/phoenix/push.js +125 -0
- package/lib/lib/surya/vendor/phoenix/serializer.d.ts +53 -0
- package/lib/lib/surya/vendor/phoenix/serializer.js +102 -0
- package/lib/lib/surya/vendor/phoenix/socket.d.ts +222 -0
- package/lib/lib/surya/vendor/phoenix/socket.js +544 -0
- package/lib/lib/surya/vendor/phoenix/timer.d.ts +25 -0
- package/lib/lib/surya/vendor/phoenix/timer.js +43 -0
- package/lib/lib/surya/vendor/phoenix/utils.d.ts +1 -0
- package/lib/lib/surya/vendor/phoenix/utils.js +15 -0
- package/lib/lib/teletype/auxiliary.d.ts +1 -1
- package/lib/lib/teletype/auxiliary.js +8 -4
- package/lib/lib/teletype/index.d.ts +1 -1
- package/lib/lib/teletype/index.js +13 -12
- package/lib/lib/utils.js +2 -1
- package/oclif.manifest.json +1 -1
- package/package.json +10 -9
- package/lib/lib/surya/vendor/phoenix.d.ts +0 -486
- package/lib/lib/surya/vendor/phoenix.js +0 -1299
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
// @ts-nocheck
|
|
4
|
+
const constants_1 = require("./constants");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
6
|
+
const ajax_1 = require("./ajax");
|
|
7
|
+
const channel_1 = require("./channel");
|
|
8
|
+
const longpoll_1 = require("./longpoll");
|
|
9
|
+
const serializer_1 = require("./serializer");
|
|
10
|
+
const timer_1 = require("./timer");
|
|
11
|
+
const ws_1 = require("ws");
|
|
12
|
+
/** Initializes the Socket *
|
|
13
|
+
*
|
|
14
|
+
* For IE8 support use an ES5-shim (https://github.com/es-shims/es5-shim)
|
|
15
|
+
*
|
|
16
|
+
* @param {string} endPoint - The string WebSocket endpoint, ie, `"ws://example.com/socket"`,
|
|
17
|
+
* `"wss://example.com"`
|
|
18
|
+
* `"/socket"` (inherited host & protocol)
|
|
19
|
+
* @param {Object} [opts] - Optional configuration
|
|
20
|
+
* @param {Function} [opts.transport] - The Websocket Transport, for example WebSocket or Phoenix.LongPoll.
|
|
21
|
+
*
|
|
22
|
+
* Defaults to WebSocket with automatic LongPoll fallback.
|
|
23
|
+
* @param {Function} [opts.encode] - The function to encode outgoing messages.
|
|
24
|
+
*
|
|
25
|
+
* Defaults to JSON encoder.
|
|
26
|
+
*
|
|
27
|
+
* @param {Function} [opts.decode] - The function to decode incoming messages.
|
|
28
|
+
*
|
|
29
|
+
* Defaults to JSON:
|
|
30
|
+
*
|
|
31
|
+
* ```javascript
|
|
32
|
+
* (payload, callback) => callback(JSON.parse(payload))
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @param {number} [opts.timeout] - The default timeout in milliseconds to trigger push timeouts.
|
|
36
|
+
*
|
|
37
|
+
* Defaults `DEFAULT_TIMEOUT`
|
|
38
|
+
* @param {number} [opts.heartbeatIntervalMs] - The millisec interval to send a heartbeat message
|
|
39
|
+
* @param {number} [opts.reconnectAfterMs] - The optional function that returns the millisec
|
|
40
|
+
* socket reconnect interval.
|
|
41
|
+
*
|
|
42
|
+
* Defaults to stepped backoff of:
|
|
43
|
+
*
|
|
44
|
+
* ```javascript
|
|
45
|
+
* function(tries){
|
|
46
|
+
* return [10, 50, 100, 150, 200, 250, 500, 1000, 2000][tries - 1] || 5000
|
|
47
|
+
* }
|
|
48
|
+
* ````
|
|
49
|
+
*
|
|
50
|
+
* @param {number} [opts.rejoinAfterMs] - The optional function that returns the millisec
|
|
51
|
+
* rejoin interval for individual channels.
|
|
52
|
+
*
|
|
53
|
+
* ```javascript
|
|
54
|
+
* function(tries){
|
|
55
|
+
* return [1000, 2000, 5000][tries - 1] || 10000
|
|
56
|
+
* }
|
|
57
|
+
* ````
|
|
58
|
+
*
|
|
59
|
+
* @param {Function} [opts.logger] - The optional function for specialized logging, ie:
|
|
60
|
+
*
|
|
61
|
+
* ```javascript
|
|
62
|
+
* function(kind, msg, data) {
|
|
63
|
+
* console.log(`${kind}: ${msg}`, data)
|
|
64
|
+
* }
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* @param {number} [opts.longpollerTimeout] - The maximum timeout of a long poll AJAX request.
|
|
68
|
+
*
|
|
69
|
+
* Defaults to 20s (double the server long poll timer).
|
|
70
|
+
*
|
|
71
|
+
* @param {(Object|function)} [opts.params] - The optional params to pass when connecting
|
|
72
|
+
* @param {string} [opts.binaryType] - The binary type to use for binary WebSocket frames.
|
|
73
|
+
*
|
|
74
|
+
* Defaults to "arraybuffer"
|
|
75
|
+
*
|
|
76
|
+
* @param {vsn} [opts.vsn] - The serializer's protocol version to send on connect.
|
|
77
|
+
*
|
|
78
|
+
* Defaults to DEFAULT_VSN.
|
|
79
|
+
*/
|
|
80
|
+
class Socket {
|
|
81
|
+
constructor(endPoint, opts = {}) {
|
|
82
|
+
this.stateChangeCallbacks = { open: [], close: [], error: [], message: [] };
|
|
83
|
+
this.channels = [];
|
|
84
|
+
this.sendBuffer = [];
|
|
85
|
+
this.ref = 0;
|
|
86
|
+
this.timeout = opts.timeout || constants_1.DEFAULT_TIMEOUT;
|
|
87
|
+
this.transport = ws_1.WebSocket;
|
|
88
|
+
this.establishedConnections = 0;
|
|
89
|
+
this.defaultEncoder = serializer_1.default.encode.bind(serializer_1.default);
|
|
90
|
+
this.defaultDecoder = serializer_1.default.decode.bind(serializer_1.default);
|
|
91
|
+
this.closeWasClean = false;
|
|
92
|
+
this.binaryType = opts.binaryType || "arraybuffer";
|
|
93
|
+
this.connectClock = 1;
|
|
94
|
+
if (this.transport !== longpoll_1.default) {
|
|
95
|
+
this.encode = opts.encode || this.defaultEncoder;
|
|
96
|
+
this.decode = opts.decode || this.defaultDecoder;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
this.encode = this.defaultEncoder;
|
|
100
|
+
this.decode = this.defaultDecoder;
|
|
101
|
+
}
|
|
102
|
+
let awaitingConnectionOnPageShow = null;
|
|
103
|
+
if (constants_1.phxWindow && constants_1.phxWindow.addEventListener) {
|
|
104
|
+
constants_1.phxWindow.addEventListener("pagehide", _e => {
|
|
105
|
+
if (this.conn) {
|
|
106
|
+
this.disconnect();
|
|
107
|
+
awaitingConnectionOnPageShow = this.connectClock;
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
constants_1.phxWindow.addEventListener("pageshow", _e => {
|
|
111
|
+
if (awaitingConnectionOnPageShow === this.connectClock) {
|
|
112
|
+
awaitingConnectionOnPageShow = null;
|
|
113
|
+
this.connect();
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
this.heartbeatIntervalMs = opts.heartbeatIntervalMs || 30000;
|
|
118
|
+
this.rejoinAfterMs = (tries) => {
|
|
119
|
+
if (opts.rejoinAfterMs) {
|
|
120
|
+
return opts.rejoinAfterMs(tries);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
return [1000, 2000, 5000][tries - 1] || 10000;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
this.reconnectAfterMs = (tries) => {
|
|
127
|
+
if (opts.reconnectAfterMs) {
|
|
128
|
+
return opts.reconnectAfterMs(tries);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
return [10, 50, 100, 150, 200, 250, 500, 1000, 2000][tries - 1] || 5000;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
this.logger = opts.logger || null;
|
|
135
|
+
this.longpollerTimeout = opts.longpollerTimeout || 20000;
|
|
136
|
+
this.params = (0, utils_1.closure)(opts.params || {});
|
|
137
|
+
this.endPoint = `${endPoint}/${constants_1.TRANSPORTS.websocket}`;
|
|
138
|
+
this.vsn = opts.vsn || constants_1.DEFAULT_VSN;
|
|
139
|
+
this.heartbeatTimeoutTimer = null;
|
|
140
|
+
this.heartbeatTimer = null;
|
|
141
|
+
this.pendingHeartbeatRef = null;
|
|
142
|
+
this.reconnectTimer = new timer_1.default(() => {
|
|
143
|
+
this.teardown(() => this.connect());
|
|
144
|
+
}, this.reconnectAfterMs);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Returns the LongPoll transport reference
|
|
148
|
+
*/
|
|
149
|
+
getLongPollTransport() { return longpoll_1.default; }
|
|
150
|
+
/**
|
|
151
|
+
* Disconnects and replaces the active transport
|
|
152
|
+
*
|
|
153
|
+
* @param {Function} newTransport - The new transport class to instantiate
|
|
154
|
+
*
|
|
155
|
+
*/
|
|
156
|
+
replaceTransport(newTransport) {
|
|
157
|
+
this.connectClock++;
|
|
158
|
+
this.closeWasClean = true;
|
|
159
|
+
this.reconnectTimer.reset();
|
|
160
|
+
this.sendBuffer = [];
|
|
161
|
+
if (this.conn) {
|
|
162
|
+
this.conn.close();
|
|
163
|
+
this.conn = null;
|
|
164
|
+
}
|
|
165
|
+
this.transport = newTransport;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Returns the socket protocol
|
|
169
|
+
*
|
|
170
|
+
* @returns {string}
|
|
171
|
+
*/
|
|
172
|
+
protocol() { return location.protocol.match(/^https/) ? "wss" : "ws"; }
|
|
173
|
+
/**
|
|
174
|
+
* The fully qualified socket url
|
|
175
|
+
*
|
|
176
|
+
* @returns {string}
|
|
177
|
+
*/
|
|
178
|
+
endPointURL() {
|
|
179
|
+
let uri = ajax_1.default.appendParams(ajax_1.default.appendParams(this.endPoint, this.params()), { vsn: this.vsn });
|
|
180
|
+
if (uri.charAt(0) !== "/") {
|
|
181
|
+
return uri;
|
|
182
|
+
}
|
|
183
|
+
if (uri.charAt(1) === "/") {
|
|
184
|
+
return `${this.protocol()}:${uri}`;
|
|
185
|
+
}
|
|
186
|
+
return `${this.protocol()}://${location.host}${uri}`;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Disconnects the socket
|
|
190
|
+
*
|
|
191
|
+
* See https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes for valid status codes.
|
|
192
|
+
*
|
|
193
|
+
* @param {Function} callback - Optional callback which is called after socket is disconnected.
|
|
194
|
+
* @param {integer} code - A status code for disconnection (Optional).
|
|
195
|
+
* @param {string} reason - A textual description of the reason to disconnect. (Optional)
|
|
196
|
+
*/
|
|
197
|
+
disconnect(callback, code, reason) {
|
|
198
|
+
this.connectClock++;
|
|
199
|
+
this.closeWasClean = true;
|
|
200
|
+
this.reconnectTimer.reset();
|
|
201
|
+
this.teardown(callback, code, reason);
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
*
|
|
205
|
+
* @param {Object} params - The params to send when connecting, for example `{user_id: userToken}`
|
|
206
|
+
*
|
|
207
|
+
* Passing params to connect is deprecated; pass them in the Socket constructor instead:
|
|
208
|
+
* `new Socket("/socket", {params: {user_id: userToken}})`.
|
|
209
|
+
*/
|
|
210
|
+
connect(params) {
|
|
211
|
+
if (params) {
|
|
212
|
+
console && console.log("passing params to connect is deprecated. Instead pass :params to the Socket constructor");
|
|
213
|
+
this.params = (0, utils_1.closure)(params);
|
|
214
|
+
}
|
|
215
|
+
if (this.conn) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
this.connectClock++;
|
|
219
|
+
this.closeWasClean = false;
|
|
220
|
+
this.conn = new ws_1.WebSocket(this.endPointURL());
|
|
221
|
+
this.conn.binaryType = this.binaryType;
|
|
222
|
+
this.conn.timeout = this.longpollerTimeout;
|
|
223
|
+
this.conn.onopen = () => this.onConnOpen();
|
|
224
|
+
this.conn.onerror = error => this.onConnError(error);
|
|
225
|
+
this.conn.onmessage = event => this.onConnMessage(event);
|
|
226
|
+
this.conn.onclose = event => this.onConnClose(event);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Logs the message. Override `this.logger` for specialized logging. noops by default
|
|
230
|
+
* @param {string} kind
|
|
231
|
+
* @param {string} msg
|
|
232
|
+
* @param {Object} data
|
|
233
|
+
*/
|
|
234
|
+
log(kind, msg, data) { this.logger(kind, msg, data); }
|
|
235
|
+
/**
|
|
236
|
+
* Returns true if a logger has been set on this socket.
|
|
237
|
+
*/
|
|
238
|
+
hasLogger() { return this.logger !== null; }
|
|
239
|
+
/**
|
|
240
|
+
* Registers callbacks for connection open events
|
|
241
|
+
*
|
|
242
|
+
* @example socket.onOpen(function(){ console.info("the socket was opened") })
|
|
243
|
+
*
|
|
244
|
+
* @param {Function} callback
|
|
245
|
+
*/
|
|
246
|
+
onOpen(callback) {
|
|
247
|
+
let ref = this.makeRef();
|
|
248
|
+
this.stateChangeCallbacks.open.push([ref, callback]);
|
|
249
|
+
return ref;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Registers callbacks for connection close events
|
|
253
|
+
* @param {Function} callback
|
|
254
|
+
*/
|
|
255
|
+
onClose(callback) {
|
|
256
|
+
let ref = this.makeRef();
|
|
257
|
+
this.stateChangeCallbacks.close.push([ref, callback]);
|
|
258
|
+
return ref;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Registers callbacks for connection error events
|
|
262
|
+
*
|
|
263
|
+
* @example socket.onError(function(error){ alert("An error occurred") })
|
|
264
|
+
*
|
|
265
|
+
* @param {Function} callback
|
|
266
|
+
*/
|
|
267
|
+
onError(callback) {
|
|
268
|
+
let ref = this.makeRef();
|
|
269
|
+
this.stateChangeCallbacks.error.push([ref, callback]);
|
|
270
|
+
return ref;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Registers callbacks for connection message events
|
|
274
|
+
* @param {Function} callback
|
|
275
|
+
*/
|
|
276
|
+
onMessage(callback) {
|
|
277
|
+
let ref = this.makeRef();
|
|
278
|
+
this.stateChangeCallbacks.message.push([ref, callback]);
|
|
279
|
+
return ref;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Pings the server and invokes the callback with the RTT in milliseconds
|
|
283
|
+
* @param {Function} callback
|
|
284
|
+
*
|
|
285
|
+
* Returns true if the ping was pushed or false if unable to be pushed.
|
|
286
|
+
*/
|
|
287
|
+
ping(callback) {
|
|
288
|
+
if (!this.isConnected()) {
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
let ref = this.makeRef();
|
|
292
|
+
let startTime = Date.now();
|
|
293
|
+
this.push({ topic: "phoenix", event: "heartbeat", payload: {}, ref: ref });
|
|
294
|
+
let onMsgRef = this.onMessage(msg => {
|
|
295
|
+
if (msg.ref === ref) {
|
|
296
|
+
this.off([onMsgRef]);
|
|
297
|
+
callback(Date.now() - startTime);
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* @private
|
|
304
|
+
*/
|
|
305
|
+
clearHeartbeats() {
|
|
306
|
+
clearTimeout(this.heartbeatTimer);
|
|
307
|
+
clearTimeout(this.heartbeatTimeoutTimer);
|
|
308
|
+
}
|
|
309
|
+
onConnOpen() {
|
|
310
|
+
if (this.hasLogger())
|
|
311
|
+
this.log("transport", `connected to ${this.endPointURL()}`);
|
|
312
|
+
this.closeWasClean = false;
|
|
313
|
+
this.establishedConnections++;
|
|
314
|
+
this.flushSendBuffer();
|
|
315
|
+
this.reconnectTimer.reset();
|
|
316
|
+
this.resetHeartbeat();
|
|
317
|
+
this.stateChangeCallbacks.open.forEach(([, callback]) => callback());
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* @private
|
|
321
|
+
*/
|
|
322
|
+
heartbeatTimeout() {
|
|
323
|
+
if (this.pendingHeartbeatRef) {
|
|
324
|
+
this.pendingHeartbeatRef = null;
|
|
325
|
+
if (this.hasLogger()) {
|
|
326
|
+
this.log("transport", "heartbeat timeout. Attempting to re-establish connection");
|
|
327
|
+
}
|
|
328
|
+
this.triggerChanError();
|
|
329
|
+
this.closeWasClean = false;
|
|
330
|
+
this.teardown(() => this.reconnectTimer.scheduleTimeout(), constants_1.WS_CLOSE_NORMAL, "heartbeat timeout");
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
resetHeartbeat() {
|
|
334
|
+
if (this.conn && this.conn.skipHeartbeat) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
this.pendingHeartbeatRef = null;
|
|
338
|
+
this.clearHeartbeats();
|
|
339
|
+
this.heartbeatTimer = setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs);
|
|
340
|
+
}
|
|
341
|
+
teardown(callback, code, reason) {
|
|
342
|
+
if (!this.conn) {
|
|
343
|
+
return callback && callback();
|
|
344
|
+
}
|
|
345
|
+
this.waitForBufferDone(() => {
|
|
346
|
+
if (this.conn) {
|
|
347
|
+
if (code) {
|
|
348
|
+
this.conn.close(code, reason || "");
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
this.conn.close();
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
this.waitForSocketClosed(() => {
|
|
355
|
+
if (this.conn) {
|
|
356
|
+
this.conn.onopen = function () { }; // noop
|
|
357
|
+
this.conn.onerror = function () { }; // noop
|
|
358
|
+
this.conn.onmessage = function () { }; // noop
|
|
359
|
+
this.conn.onclose = function () { }; // noop
|
|
360
|
+
this.conn = null;
|
|
361
|
+
}
|
|
362
|
+
callback && callback();
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
waitForBufferDone(callback, tries = 1) {
|
|
367
|
+
if (tries === 5 || !this.conn || !this.conn.bufferedAmount) {
|
|
368
|
+
callback();
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
setTimeout(() => {
|
|
372
|
+
this.waitForBufferDone(callback, tries + 1);
|
|
373
|
+
}, 150 * tries);
|
|
374
|
+
}
|
|
375
|
+
waitForSocketClosed(callback, tries = 1) {
|
|
376
|
+
if (tries === 5 || !this.conn || this.conn.readyState === constants_1.SOCKET_STATES.closed) {
|
|
377
|
+
callback();
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
setTimeout(() => {
|
|
381
|
+
this.waitForSocketClosed(callback, tries + 1);
|
|
382
|
+
}, 150 * tries);
|
|
383
|
+
}
|
|
384
|
+
onConnClose(event) {
|
|
385
|
+
let closeCode = event && event.code;
|
|
386
|
+
if (this.hasLogger())
|
|
387
|
+
this.log("transport", "close", event);
|
|
388
|
+
this.triggerChanError();
|
|
389
|
+
this.clearHeartbeats();
|
|
390
|
+
if (!this.closeWasClean && closeCode !== 1000) {
|
|
391
|
+
this.reconnectTimer.scheduleTimeout();
|
|
392
|
+
}
|
|
393
|
+
this.stateChangeCallbacks.close.forEach(([, callback]) => callback(event));
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* @private
|
|
397
|
+
*/
|
|
398
|
+
onConnError(error) {
|
|
399
|
+
if (this.hasLogger())
|
|
400
|
+
this.log("transport", error);
|
|
401
|
+
let transportBefore = this.transport;
|
|
402
|
+
let establishedBefore = this.establishedConnections;
|
|
403
|
+
this.stateChangeCallbacks.error.forEach(([, callback]) => {
|
|
404
|
+
callback(error, transportBefore, establishedBefore);
|
|
405
|
+
});
|
|
406
|
+
if (transportBefore === this.transport || establishedBefore > 0) {
|
|
407
|
+
this.triggerChanError();
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* @private
|
|
412
|
+
*/
|
|
413
|
+
triggerChanError() {
|
|
414
|
+
this.channels.forEach(channel => {
|
|
415
|
+
if (!(channel.isErrored() || channel.isLeaving() || channel.isClosed())) {
|
|
416
|
+
channel.trigger(constants_1.CHANNEL_EVENTS.error);
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* @returns {string}
|
|
422
|
+
*/
|
|
423
|
+
connectionState() {
|
|
424
|
+
switch (this.conn && this.conn.readyState) {
|
|
425
|
+
case constants_1.SOCKET_STATES.connecting: return "connecting";
|
|
426
|
+
case constants_1.SOCKET_STATES.open: return "open";
|
|
427
|
+
case constants_1.SOCKET_STATES.closing: return "closing";
|
|
428
|
+
default: return "closed";
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* @returns {boolean}
|
|
433
|
+
*/
|
|
434
|
+
isConnected() { return this.connectionState() === "open"; }
|
|
435
|
+
/**
|
|
436
|
+
* @private
|
|
437
|
+
*
|
|
438
|
+
* @param {Channel}
|
|
439
|
+
*/
|
|
440
|
+
remove(channel) {
|
|
441
|
+
this.off(channel.stateChangeRefs);
|
|
442
|
+
this.channels = this.channels.filter(c => c.joinRef() !== channel.joinRef());
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Removes `onOpen`, `onClose`, `onError,` and `onMessage` registrations.
|
|
446
|
+
*
|
|
447
|
+
* @param {refs} - list of refs returned by calls to
|
|
448
|
+
* `onOpen`, `onClose`, `onError,` and `onMessage`
|
|
449
|
+
*/
|
|
450
|
+
off(refs) {
|
|
451
|
+
for (let key in this.stateChangeCallbacks) {
|
|
452
|
+
this.stateChangeCallbacks[key] = this.stateChangeCallbacks[key].filter(([ref]) => {
|
|
453
|
+
return refs.indexOf(ref) === -1;
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Initiates a new channel for the given topic
|
|
459
|
+
*
|
|
460
|
+
* @param {string} topic
|
|
461
|
+
* @param {Object} chanParams - Parameters for the channel
|
|
462
|
+
* @returns {Channel}
|
|
463
|
+
*/
|
|
464
|
+
channel(topic, chanParams = {}) {
|
|
465
|
+
let chan = new channel_1.default(topic, chanParams, this);
|
|
466
|
+
this.channels.push(chan);
|
|
467
|
+
return chan;
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* @param {Object} data
|
|
471
|
+
*/
|
|
472
|
+
push(data) {
|
|
473
|
+
if (this.hasLogger()) {
|
|
474
|
+
let { topic, event, payload, ref, join_ref } = data;
|
|
475
|
+
this.log("push", `${topic} ${event} (${join_ref}, ${ref})`, payload);
|
|
476
|
+
}
|
|
477
|
+
if (this.isConnected()) {
|
|
478
|
+
this.encode(data, result => this.conn.send(result));
|
|
479
|
+
}
|
|
480
|
+
else {
|
|
481
|
+
this.sendBuffer.push(() => this.encode(data, result => this.conn.send(result)));
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Return the next message ref, accounting for overflows
|
|
486
|
+
* @returns {string}
|
|
487
|
+
*/
|
|
488
|
+
makeRef() {
|
|
489
|
+
let newRef = this.ref + 1;
|
|
490
|
+
if (newRef === this.ref) {
|
|
491
|
+
this.ref = 0;
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
this.ref = newRef;
|
|
495
|
+
}
|
|
496
|
+
return this.ref.toString();
|
|
497
|
+
}
|
|
498
|
+
sendHeartbeat() {
|
|
499
|
+
if (this.pendingHeartbeatRef && !this.isConnected()) {
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
this.pendingHeartbeatRef = this.makeRef();
|
|
503
|
+
this.push({ topic: "phoenix", event: "heartbeat", payload: {}, ref: this.pendingHeartbeatRef });
|
|
504
|
+
this.heartbeatTimeoutTimer = setTimeout(() => this.heartbeatTimeout(), this.heartbeatIntervalMs);
|
|
505
|
+
}
|
|
506
|
+
flushSendBuffer() {
|
|
507
|
+
if (this.isConnected() && this.sendBuffer.length > 0) {
|
|
508
|
+
this.sendBuffer.forEach(callback => callback());
|
|
509
|
+
this.sendBuffer = [];
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
onConnMessage(rawMessage) {
|
|
513
|
+
this.decode(rawMessage.data, msg => {
|
|
514
|
+
let { topic, event, payload, ref, join_ref } = msg;
|
|
515
|
+
if (ref && ref === this.pendingHeartbeatRef) {
|
|
516
|
+
this.clearHeartbeats();
|
|
517
|
+
this.pendingHeartbeatRef = null;
|
|
518
|
+
this.heartbeatTimer = setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs);
|
|
519
|
+
}
|
|
520
|
+
if (this.hasLogger())
|
|
521
|
+
this.log("receive", `${payload.status || ""} ${topic} ${event} ${ref && "(" + ref + ")" || ""}`, payload);
|
|
522
|
+
for (let i = 0; i < this.channels.length; i++) {
|
|
523
|
+
const channel = this.channels[i];
|
|
524
|
+
if (!channel.isMember(topic, event, payload, join_ref)) {
|
|
525
|
+
continue;
|
|
526
|
+
}
|
|
527
|
+
channel.trigger(event, payload, ref, join_ref);
|
|
528
|
+
}
|
|
529
|
+
for (let i = 0; i < this.stateChangeCallbacks.message.length; i++) {
|
|
530
|
+
let [, callback] = this.stateChangeCallbacks.message[i];
|
|
531
|
+
callback(msg);
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
leaveOpenTopic(topic) {
|
|
536
|
+
let dupChannel = this.channels.find(c => c.topic === topic && (c.isJoined() || c.isJoining()));
|
|
537
|
+
if (dupChannel) {
|
|
538
|
+
if (this.hasLogger())
|
|
539
|
+
this.log("transport", `leaving duplicate topic "${topic}"`);
|
|
540
|
+
dupChannel.leave();
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
exports.default = Socket;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Creates a timer that accepts a `timerCalc` function to perform
|
|
4
|
+
* calculated timeout retries, such as exponential backoff.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* let reconnectTimer = new Timer(() => this.connect(), function(tries){
|
|
8
|
+
* return [1000, 5000, 10000][tries - 1] || 10000
|
|
9
|
+
* })
|
|
10
|
+
* reconnectTimer.scheduleTimeout() // fires after 1000
|
|
11
|
+
* reconnectTimer.scheduleTimeout() // fires after 5000
|
|
12
|
+
* reconnectTimer.reset()
|
|
13
|
+
* reconnectTimer.scheduleTimeout() // fires after 1000
|
|
14
|
+
*
|
|
15
|
+
* @param {Function} callback
|
|
16
|
+
* @param {Function} timerCalc
|
|
17
|
+
*/
|
|
18
|
+
export default class Timer {
|
|
19
|
+
constructor(callback: any, timerCalc: any);
|
|
20
|
+
reset(): void;
|
|
21
|
+
/**
|
|
22
|
+
* Cancels any previous scheduleTimeout and schedules callback
|
|
23
|
+
*/
|
|
24
|
+
scheduleTimeout(): void;
|
|
25
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
// @ts-nocheck
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* Creates a timer that accepts a `timerCalc` function to perform
|
|
7
|
+
* calculated timeout retries, such as exponential backoff.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* let reconnectTimer = new Timer(() => this.connect(), function(tries){
|
|
11
|
+
* return [1000, 5000, 10000][tries - 1] || 10000
|
|
12
|
+
* })
|
|
13
|
+
* reconnectTimer.scheduleTimeout() // fires after 1000
|
|
14
|
+
* reconnectTimer.scheduleTimeout() // fires after 5000
|
|
15
|
+
* reconnectTimer.reset()
|
|
16
|
+
* reconnectTimer.scheduleTimeout() // fires after 1000
|
|
17
|
+
*
|
|
18
|
+
* @param {Function} callback
|
|
19
|
+
* @param {Function} timerCalc
|
|
20
|
+
*/
|
|
21
|
+
class Timer {
|
|
22
|
+
constructor(callback, timerCalc) {
|
|
23
|
+
this.callback = callback;
|
|
24
|
+
this.timerCalc = timerCalc;
|
|
25
|
+
this.timer = null;
|
|
26
|
+
this.tries = 0;
|
|
27
|
+
}
|
|
28
|
+
reset() {
|
|
29
|
+
this.tries = 0;
|
|
30
|
+
clearTimeout(this.timer);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Cancels any previous scheduleTimeout and schedules callback
|
|
34
|
+
*/
|
|
35
|
+
scheduleTimeout() {
|
|
36
|
+
clearTimeout(this.timer);
|
|
37
|
+
this.timer = setTimeout(() => {
|
|
38
|
+
this.tries = this.tries + 1;
|
|
39
|
+
this.callback();
|
|
40
|
+
}, this.timerCalc(this.tries + 1));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.default = Timer;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare let closure: (value: any) => any;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.closure = void 0;
|
|
4
|
+
// @ts-nocheck
|
|
5
|
+
// wraps value in closure or returns closure
|
|
6
|
+
let closure = (value) => {
|
|
7
|
+
if (typeof value === "function") {
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
let closure = function () { return value; };
|
|
12
|
+
return closure;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
exports.closure = closure;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { IPty } from "node-pty";
|
|
2
2
|
import { Hash } from "../surya/types";
|
|
3
3
|
export declare const initScreen: (username: string, hostname: string, shell: string, multiplexed: boolean) => void;
|
|
4
|
-
export
|
|
4
|
+
export type dimensions = {
|
|
5
5
|
rows: number;
|
|
6
6
|
cols: number;
|
|
7
7
|
};
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.resizeBestFit = exports.areDimensionEqual = exports.getDimensions = exports.initScreen = void 0;
|
|
4
4
|
const chalk = require("chalk");
|
|
5
5
|
const termSize = require("term-size");
|
|
6
|
-
|
|
6
|
+
const initScreen = (username, hostname, shell, multiplexed) => {
|
|
7
7
|
console.log(chalk.bold(chalk.blueBright("TeleType")));
|
|
8
8
|
if (multiplexed) {
|
|
9
9
|
console.log(chalk.yellowBright("You have allowed room participants to write to your shell"));
|
|
@@ -13,16 +13,20 @@ exports.initScreen = (username, hostname, shell, multiplexed) => {
|
|
|
13
13
|
This session is end-to-end encrypted.
|
|
14
14
|
To terminate stream run ${chalk.yellowBright("exit")} or press ${chalk.yellowBright("ctrl-d")} \n`);
|
|
15
15
|
};
|
|
16
|
-
exports.
|
|
16
|
+
exports.initScreen = initScreen;
|
|
17
|
+
const getDimensions = () => {
|
|
17
18
|
const { rows, columns } = termSize();
|
|
18
19
|
return { rows, cols: columns };
|
|
19
20
|
};
|
|
20
|
-
exports.
|
|
21
|
+
exports.getDimensions = getDimensions;
|
|
22
|
+
const areDimensionEqual = (a, b) => {
|
|
21
23
|
return a.rows === b.rows && a.cols === b.cols;
|
|
22
24
|
};
|
|
23
|
-
exports.
|
|
25
|
+
exports.areDimensionEqual = areDimensionEqual;
|
|
26
|
+
const resizeBestFit = (term, userDimensions) => {
|
|
24
27
|
const allViewports = Object.values(userDimensions);
|
|
25
28
|
const minrows = Math.min(...allViewports.map((d) => d.rows));
|
|
26
29
|
const mincols = Math.min(...allViewports.map((d) => d.cols));
|
|
27
30
|
term.resize(mincols, minrows);
|
|
28
31
|
};
|
|
32
|
+
exports.resizeBestFit = resizeBestFit;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { RoomKey } from "../surya/types";
|
|
3
3
|
import { JoinChannelOptions } from "../surya";
|
|
4
4
|
import { Channel } from "../surya/vendor/phoenix";
|
|
5
|
-
export
|
|
5
|
+
export type TeletypeOptions = {
|
|
6
6
|
userId: string;
|
|
7
7
|
roomKey: RoomKey;
|
|
8
8
|
shell: string;
|