@rails/actioncable 6.0.2 → 7.1.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 +6 -6
- package/app/assets/javascripts/action_cable.js +254 -260
- package/app/assets/javascripts/actioncable.esm.js +512 -0
- package/app/assets/javascripts/actioncable.js +510 -0
- package/package.json +8 -11
- package/src/connection.js +19 -4
- package/src/connection_monitor.js +15 -16
- package/src/consumer.js +6 -1
- package/src/index.js +2 -0
- package/src/index_with_name_deprecation.js +2 -0
- package/src/internal.js +20 -0
- package/src/logger.js +12 -0
- package/src/subscription_guarantor.js +50 -0
- package/src/subscriptions.js +21 -4
- package/CHANGELOG.md +0 -179
@@ -1,154 +1,115 @@
|
|
1
1
|
(function(global, factory) {
|
2
|
-
typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define([ "exports" ], factory) :
|
3
|
-
|
2
|
+
typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define([ "exports" ], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self,
|
3
|
+
factory(global.ActionCable = {}));
|
4
|
+
})(this, (function(exports) {
|
4
5
|
"use strict";
|
5
6
|
var adapters = {
|
6
7
|
logger: self.console,
|
7
8
|
WebSocket: self.WebSocket
|
8
9
|
};
|
9
10
|
var logger = {
|
10
|
-
log
|
11
|
+
log(...messages) {
|
11
12
|
if (this.enabled) {
|
12
|
-
var _adapters$logger;
|
13
|
-
for (var _len = arguments.length, messages = Array(_len), _key = 0; _key < _len; _key++) {
|
14
|
-
messages[_key] = arguments[_key];
|
15
|
-
}
|
16
13
|
messages.push(Date.now());
|
17
|
-
|
18
|
-
}
|
19
|
-
}
|
20
|
-
};
|
21
|
-
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
|
22
|
-
return typeof obj;
|
23
|
-
} : function(obj) {
|
24
|
-
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
|
25
|
-
};
|
26
|
-
var classCallCheck = function(instance, Constructor) {
|
27
|
-
if (!(instance instanceof Constructor)) {
|
28
|
-
throw new TypeError("Cannot call a class as a function");
|
29
|
-
}
|
30
|
-
};
|
31
|
-
var createClass = function() {
|
32
|
-
function defineProperties(target, props) {
|
33
|
-
for (var i = 0; i < props.length; i++) {
|
34
|
-
var descriptor = props[i];
|
35
|
-
descriptor.enumerable = descriptor.enumerable || false;
|
36
|
-
descriptor.configurable = true;
|
37
|
-
if ("value" in descriptor) descriptor.writable = true;
|
38
|
-
Object.defineProperty(target, descriptor.key, descriptor);
|
14
|
+
adapters.logger.log("[ActionCable]", ...messages);
|
39
15
|
}
|
40
16
|
}
|
41
|
-
return function(Constructor, protoProps, staticProps) {
|
42
|
-
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
43
|
-
if (staticProps) defineProperties(Constructor, staticProps);
|
44
|
-
return Constructor;
|
45
|
-
};
|
46
|
-
}();
|
47
|
-
var now = function now() {
|
48
|
-
return new Date().getTime();
|
49
|
-
};
|
50
|
-
var secondsSince = function secondsSince(time) {
|
51
|
-
return (now() - time) / 1e3;
|
52
|
-
};
|
53
|
-
var clamp = function clamp(number, min, max) {
|
54
|
-
return Math.max(min, Math.min(max, number));
|
55
17
|
};
|
56
|
-
|
57
|
-
|
58
|
-
|
18
|
+
const now = () => (new Date).getTime();
|
19
|
+
const secondsSince = time => (now() - time) / 1e3;
|
20
|
+
class ConnectionMonitor {
|
21
|
+
constructor(connection) {
|
59
22
|
this.visibilityDidChange = this.visibilityDidChange.bind(this);
|
60
23
|
this.connection = connection;
|
61
24
|
this.reconnectAttempts = 0;
|
62
25
|
}
|
63
|
-
|
26
|
+
start() {
|
64
27
|
if (!this.isRunning()) {
|
65
28
|
this.startedAt = now();
|
66
29
|
delete this.stoppedAt;
|
67
30
|
this.startPolling();
|
68
31
|
addEventListener("visibilitychange", this.visibilityDidChange);
|
69
|
-
logger.log(
|
32
|
+
logger.log(`ConnectionMonitor started. stale threshold = ${this.constructor.staleThreshold} s`);
|
70
33
|
}
|
71
|
-
}
|
72
|
-
|
34
|
+
}
|
35
|
+
stop() {
|
73
36
|
if (this.isRunning()) {
|
74
37
|
this.stoppedAt = now();
|
75
38
|
this.stopPolling();
|
76
39
|
removeEventListener("visibilitychange", this.visibilityDidChange);
|
77
40
|
logger.log("ConnectionMonitor stopped");
|
78
41
|
}
|
79
|
-
}
|
80
|
-
|
42
|
+
}
|
43
|
+
isRunning() {
|
81
44
|
return this.startedAt && !this.stoppedAt;
|
82
|
-
}
|
83
|
-
|
45
|
+
}
|
46
|
+
recordPing() {
|
84
47
|
this.pingedAt = now();
|
85
|
-
}
|
86
|
-
|
48
|
+
}
|
49
|
+
recordConnect() {
|
87
50
|
this.reconnectAttempts = 0;
|
88
51
|
this.recordPing();
|
89
52
|
delete this.disconnectedAt;
|
90
53
|
logger.log("ConnectionMonitor recorded connect");
|
91
|
-
}
|
92
|
-
|
54
|
+
}
|
55
|
+
recordDisconnect() {
|
93
56
|
this.disconnectedAt = now();
|
94
57
|
logger.log("ConnectionMonitor recorded disconnect");
|
95
|
-
}
|
96
|
-
|
58
|
+
}
|
59
|
+
startPolling() {
|
97
60
|
this.stopPolling();
|
98
61
|
this.poll();
|
99
|
-
}
|
100
|
-
|
62
|
+
}
|
63
|
+
stopPolling() {
|
101
64
|
clearTimeout(this.pollTimeout);
|
102
|
-
}
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
65
|
+
}
|
66
|
+
poll() {
|
67
|
+
this.pollTimeout = setTimeout((() => {
|
68
|
+
this.reconnectIfStale();
|
69
|
+
this.poll();
|
70
|
+
}), this.getPollInterval());
|
71
|
+
}
|
72
|
+
getPollInterval() {
|
73
|
+
const {staleThreshold: staleThreshold, reconnectionBackoffRate: reconnectionBackoffRate} = this.constructor;
|
74
|
+
const backoff = Math.pow(1 + reconnectionBackoffRate, Math.min(this.reconnectAttempts, 10));
|
75
|
+
const jitterMax = this.reconnectAttempts === 0 ? 1 : reconnectionBackoffRate;
|
76
|
+
const jitter = jitterMax * Math.random();
|
77
|
+
return staleThreshold * 1e3 * backoff * (1 + jitter);
|
78
|
+
}
|
79
|
+
reconnectIfStale() {
|
116
80
|
if (this.connectionIsStale()) {
|
117
|
-
logger.log(
|
81
|
+
logger.log(`ConnectionMonitor detected stale connection. reconnectAttempts = ${this.reconnectAttempts}, time stale = ${secondsSince(this.refreshedAt)} s, stale threshold = ${this.constructor.staleThreshold} s`);
|
118
82
|
this.reconnectAttempts++;
|
119
83
|
if (this.disconnectedRecently()) {
|
120
|
-
logger.log(
|
84
|
+
logger.log(`ConnectionMonitor skipping reopening recent disconnect. time disconnected = ${secondsSince(this.disconnectedAt)} s`);
|
121
85
|
} else {
|
122
86
|
logger.log("ConnectionMonitor reopening");
|
123
87
|
this.connection.reopen();
|
124
88
|
}
|
125
89
|
}
|
126
|
-
}
|
127
|
-
|
128
|
-
return
|
129
|
-
}
|
130
|
-
|
90
|
+
}
|
91
|
+
get refreshedAt() {
|
92
|
+
return this.pingedAt ? this.pingedAt : this.startedAt;
|
93
|
+
}
|
94
|
+
connectionIsStale() {
|
95
|
+
return secondsSince(this.refreshedAt) > this.constructor.staleThreshold;
|
96
|
+
}
|
97
|
+
disconnectedRecently() {
|
131
98
|
return this.disconnectedAt && secondsSince(this.disconnectedAt) < this.constructor.staleThreshold;
|
132
|
-
}
|
133
|
-
|
134
|
-
var _this2 = this;
|
99
|
+
}
|
100
|
+
visibilityDidChange() {
|
135
101
|
if (document.visibilityState === "visible") {
|
136
|
-
setTimeout(
|
137
|
-
if (
|
138
|
-
logger.log(
|
139
|
-
|
102
|
+
setTimeout((() => {
|
103
|
+
if (this.connectionIsStale() || !this.connection.isOpen()) {
|
104
|
+
logger.log(`ConnectionMonitor reopening stale connection on visibilitychange. visibilityState = ${document.visibilityState}`);
|
105
|
+
this.connection.reopen();
|
140
106
|
}
|
141
|
-
}, 200);
|
107
|
+
}), 200);
|
142
108
|
}
|
143
|
-
}
|
144
|
-
|
145
|
-
}();
|
146
|
-
ConnectionMonitor.pollInterval = {
|
147
|
-
min: 3,
|
148
|
-
max: 30,
|
149
|
-
multiplier: 5
|
150
|
-
};
|
109
|
+
}
|
110
|
+
}
|
151
111
|
ConnectionMonitor.staleThreshold = 6;
|
112
|
+
ConnectionMonitor.reconnectionBackoffRate = .15;
|
152
113
|
var INTERNAL = {
|
153
114
|
message_types: {
|
154
115
|
welcome: "welcome",
|
@@ -160,129 +121,131 @@
|
|
160
121
|
disconnect_reasons: {
|
161
122
|
unauthorized: "unauthorized",
|
162
123
|
invalid_request: "invalid_request",
|
163
|
-
server_restart: "server_restart"
|
124
|
+
server_restart: "server_restart",
|
125
|
+
remote: "remote"
|
164
126
|
},
|
165
127
|
default_mount_path: "/cable",
|
166
128
|
protocols: [ "actioncable-v1-json", "actioncable-unsupported" ]
|
167
129
|
};
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
classCallCheck(this, Connection);
|
130
|
+
const {message_types: message_types, protocols: protocols} = INTERNAL;
|
131
|
+
const supportedProtocols = protocols.slice(0, protocols.length - 1);
|
132
|
+
const indexOf = [].indexOf;
|
133
|
+
class Connection {
|
134
|
+
constructor(consumer) {
|
174
135
|
this.open = this.open.bind(this);
|
175
136
|
this.consumer = consumer;
|
176
137
|
this.subscriptions = this.consumer.subscriptions;
|
177
138
|
this.monitor = new ConnectionMonitor(this);
|
178
139
|
this.disconnected = true;
|
179
140
|
}
|
180
|
-
|
141
|
+
send(data) {
|
181
142
|
if (this.isOpen()) {
|
182
143
|
this.webSocket.send(JSON.stringify(data));
|
183
144
|
return true;
|
184
145
|
} else {
|
185
146
|
return false;
|
186
147
|
}
|
187
|
-
}
|
188
|
-
|
148
|
+
}
|
149
|
+
open() {
|
189
150
|
if (this.isActive()) {
|
190
|
-
logger.log(
|
151
|
+
logger.log(`Attempted to open WebSocket, but existing socket is ${this.getState()}`);
|
191
152
|
return false;
|
192
153
|
} else {
|
193
|
-
|
154
|
+
const socketProtocols = [ ...protocols, ...this.consumer.subprotocols || [] ];
|
155
|
+
logger.log(`Opening WebSocket, current state is ${this.getState()}, subprotocols: ${socketProtocols}`);
|
194
156
|
if (this.webSocket) {
|
195
157
|
this.uninstallEventHandlers();
|
196
158
|
}
|
197
|
-
this.webSocket = new adapters.WebSocket(this.consumer.url,
|
159
|
+
this.webSocket = new adapters.WebSocket(this.consumer.url, socketProtocols);
|
198
160
|
this.installEventHandlers();
|
199
161
|
this.monitor.start();
|
200
162
|
return true;
|
201
163
|
}
|
202
|
-
}
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
}, allowReconnect = _ref.allowReconnect;
|
164
|
+
}
|
165
|
+
close({allowReconnect: allowReconnect} = {
|
166
|
+
allowReconnect: true
|
167
|
+
}) {
|
207
168
|
if (!allowReconnect) {
|
208
169
|
this.monitor.stop();
|
209
170
|
}
|
210
|
-
if (this.
|
171
|
+
if (this.isOpen()) {
|
211
172
|
return this.webSocket.close();
|
212
173
|
}
|
213
|
-
}
|
214
|
-
|
215
|
-
logger.log(
|
174
|
+
}
|
175
|
+
reopen() {
|
176
|
+
logger.log(`Reopening WebSocket, current state is ${this.getState()}`);
|
216
177
|
if (this.isActive()) {
|
217
178
|
try {
|
218
179
|
return this.close();
|
219
180
|
} catch (error) {
|
220
181
|
logger.log("Failed to reopen WebSocket", error);
|
221
182
|
} finally {
|
222
|
-
logger.log(
|
183
|
+
logger.log(`Reopening WebSocket in ${this.constructor.reopenDelay}ms`);
|
223
184
|
setTimeout(this.open, this.constructor.reopenDelay);
|
224
185
|
}
|
225
186
|
} else {
|
226
187
|
return this.open();
|
227
188
|
}
|
228
|
-
}
|
229
|
-
|
189
|
+
}
|
190
|
+
getProtocol() {
|
230
191
|
if (this.webSocket) {
|
231
192
|
return this.webSocket.protocol;
|
232
193
|
}
|
233
|
-
}
|
234
|
-
|
194
|
+
}
|
195
|
+
isOpen() {
|
235
196
|
return this.isState("open");
|
236
|
-
}
|
237
|
-
|
197
|
+
}
|
198
|
+
isActive() {
|
238
199
|
return this.isState("open", "connecting");
|
239
|
-
}
|
240
|
-
|
200
|
+
}
|
201
|
+
triedToReconnect() {
|
202
|
+
return this.monitor.reconnectAttempts > 0;
|
203
|
+
}
|
204
|
+
isProtocolSupported() {
|
241
205
|
return indexOf.call(supportedProtocols, this.getProtocol()) >= 0;
|
242
|
-
}
|
243
|
-
|
244
|
-
for (var _len = arguments.length, states = Array(_len), _key = 0; _key < _len; _key++) {
|
245
|
-
states[_key] = arguments[_key];
|
246
|
-
}
|
206
|
+
}
|
207
|
+
isState(...states) {
|
247
208
|
return indexOf.call(states, this.getState()) >= 0;
|
248
|
-
}
|
249
|
-
|
209
|
+
}
|
210
|
+
getState() {
|
250
211
|
if (this.webSocket) {
|
251
|
-
for (
|
212
|
+
for (let state in adapters.WebSocket) {
|
252
213
|
if (adapters.WebSocket[state] === this.webSocket.readyState) {
|
253
214
|
return state.toLowerCase();
|
254
215
|
}
|
255
216
|
}
|
256
217
|
}
|
257
218
|
return null;
|
258
|
-
}
|
259
|
-
|
260
|
-
for (
|
261
|
-
|
262
|
-
this.webSocket[
|
219
|
+
}
|
220
|
+
installEventHandlers() {
|
221
|
+
for (let eventName in this.events) {
|
222
|
+
const handler = this.events[eventName].bind(this);
|
223
|
+
this.webSocket[`on${eventName}`] = handler;
|
263
224
|
}
|
264
|
-
}
|
265
|
-
|
266
|
-
for (
|
267
|
-
this.webSocket[
|
225
|
+
}
|
226
|
+
uninstallEventHandlers() {
|
227
|
+
for (let eventName in this.events) {
|
228
|
+
this.webSocket[`on${eventName}`] = function() {};
|
268
229
|
}
|
269
|
-
}
|
270
|
-
|
271
|
-
}();
|
230
|
+
}
|
231
|
+
}
|
272
232
|
Connection.reopenDelay = 500;
|
273
233
|
Connection.prototype.events = {
|
274
|
-
message
|
234
|
+
message(event) {
|
275
235
|
if (!this.isProtocolSupported()) {
|
276
236
|
return;
|
277
237
|
}
|
278
|
-
|
238
|
+
const {identifier: identifier, message: message, reason: reason, reconnect: reconnect, type: type} = JSON.parse(event.data);
|
279
239
|
switch (type) {
|
280
240
|
case message_types.welcome:
|
241
|
+
if (this.triedToReconnect()) {
|
242
|
+
this.reconnectAttempted = true;
|
243
|
+
}
|
281
244
|
this.monitor.recordConnect();
|
282
245
|
return this.subscriptions.reload();
|
283
246
|
|
284
247
|
case message_types.disconnect:
|
285
|
-
logger.log(
|
248
|
+
logger.log(`Disconnecting. Reason: ${reason}`);
|
286
249
|
return this.close({
|
287
250
|
allowReconnect: reconnect
|
288
251
|
});
|
@@ -291,7 +254,17 @@
|
|
291
254
|
return this.monitor.recordPing();
|
292
255
|
|
293
256
|
case message_types.confirmation:
|
294
|
-
|
257
|
+
this.subscriptions.confirmSubscription(identifier);
|
258
|
+
if (this.reconnectAttempted) {
|
259
|
+
this.reconnectAttempted = false;
|
260
|
+
return this.subscriptions.notify(identifier, "connected", {
|
261
|
+
reconnected: true
|
262
|
+
});
|
263
|
+
} else {
|
264
|
+
return this.subscriptions.notify(identifier, "connected", {
|
265
|
+
reconnected: false
|
266
|
+
});
|
267
|
+
}
|
295
268
|
|
296
269
|
case message_types.rejection:
|
297
270
|
return this.subscriptions.reject(identifier);
|
@@ -300,8 +273,8 @@
|
|
300
273
|
return this.subscriptions.notify(identifier, "received", message);
|
301
274
|
}
|
302
275
|
},
|
303
|
-
open
|
304
|
-
logger.log(
|
276
|
+
open() {
|
277
|
+
logger.log(`WebSocket onopen event, using '${this.getProtocol()}' subprotocol`);
|
305
278
|
this.disconnected = false;
|
306
279
|
if (!this.isProtocolSupported()) {
|
307
280
|
logger.log("Protocol is unsupported. Stopping monitor and disconnecting.");
|
@@ -310,7 +283,7 @@
|
|
310
283
|
});
|
311
284
|
}
|
312
285
|
},
|
313
|
-
close
|
286
|
+
close(event) {
|
314
287
|
logger.log("WebSocket onclose event");
|
315
288
|
if (this.disconnected) {
|
316
289
|
return;
|
@@ -321,167 +294,187 @@
|
|
321
294
|
willAttemptReconnect: this.monitor.isRunning()
|
322
295
|
});
|
323
296
|
},
|
324
|
-
error
|
297
|
+
error() {
|
325
298
|
logger.log("WebSocket onerror event");
|
326
299
|
}
|
327
300
|
};
|
328
|
-
|
301
|
+
const extend = function(object, properties) {
|
329
302
|
if (properties != null) {
|
330
|
-
for (
|
331
|
-
|
303
|
+
for (let key in properties) {
|
304
|
+
const value = properties[key];
|
332
305
|
object[key] = value;
|
333
306
|
}
|
334
307
|
}
|
335
308
|
return object;
|
336
309
|
};
|
337
|
-
|
338
|
-
|
339
|
-
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
340
|
-
var mixin = arguments[2];
|
341
|
-
classCallCheck(this, Subscription);
|
310
|
+
class Subscription {
|
311
|
+
constructor(consumer, params = {}, mixin) {
|
342
312
|
this.consumer = consumer;
|
343
313
|
this.identifier = JSON.stringify(params);
|
344
314
|
extend(this, mixin);
|
345
315
|
}
|
346
|
-
|
347
|
-
var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
316
|
+
perform(action, data = {}) {
|
348
317
|
data.action = action;
|
349
318
|
return this.send(data);
|
350
|
-
}
|
351
|
-
|
319
|
+
}
|
320
|
+
send(data) {
|
352
321
|
return this.consumer.send({
|
353
322
|
command: "message",
|
354
323
|
identifier: this.identifier,
|
355
324
|
data: JSON.stringify(data)
|
356
325
|
});
|
357
|
-
}
|
358
|
-
|
326
|
+
}
|
327
|
+
unsubscribe() {
|
359
328
|
return this.consumer.subscriptions.remove(this);
|
360
|
-
}
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
329
|
+
}
|
330
|
+
}
|
331
|
+
class SubscriptionGuarantor {
|
332
|
+
constructor(subscriptions) {
|
333
|
+
this.subscriptions = subscriptions;
|
334
|
+
this.pendingSubscriptions = [];
|
335
|
+
}
|
336
|
+
guarantee(subscription) {
|
337
|
+
if (this.pendingSubscriptions.indexOf(subscription) == -1) {
|
338
|
+
logger.log(`SubscriptionGuarantor guaranteeing ${subscription.identifier}`);
|
339
|
+
this.pendingSubscriptions.push(subscription);
|
340
|
+
} else {
|
341
|
+
logger.log(`SubscriptionGuarantor already guaranteeing ${subscription.identifier}`);
|
342
|
+
}
|
343
|
+
this.startGuaranteeing();
|
344
|
+
}
|
345
|
+
forget(subscription) {
|
346
|
+
logger.log(`SubscriptionGuarantor forgetting ${subscription.identifier}`);
|
347
|
+
this.pendingSubscriptions = this.pendingSubscriptions.filter((s => s !== subscription));
|
348
|
+
}
|
349
|
+
startGuaranteeing() {
|
350
|
+
this.stopGuaranteeing();
|
351
|
+
this.retrySubscribing();
|
352
|
+
}
|
353
|
+
stopGuaranteeing() {
|
354
|
+
clearTimeout(this.retryTimeout);
|
355
|
+
}
|
356
|
+
retrySubscribing() {
|
357
|
+
this.retryTimeout = setTimeout((() => {
|
358
|
+
if (this.subscriptions && typeof this.subscriptions.subscribe === "function") {
|
359
|
+
this.pendingSubscriptions.map((subscription => {
|
360
|
+
logger.log(`SubscriptionGuarantor resubscribing ${subscription.identifier}`);
|
361
|
+
this.subscriptions.subscribe(subscription);
|
362
|
+
}));
|
363
|
+
}
|
364
|
+
}), 500);
|
365
|
+
}
|
366
|
+
}
|
367
|
+
class Subscriptions {
|
368
|
+
constructor(consumer) {
|
366
369
|
this.consumer = consumer;
|
370
|
+
this.guarantor = new SubscriptionGuarantor(this);
|
367
371
|
this.subscriptions = [];
|
368
372
|
}
|
369
|
-
|
370
|
-
|
371
|
-
|
373
|
+
create(channelName, mixin) {
|
374
|
+
const channel = channelName;
|
375
|
+
const params = typeof channel === "object" ? channel : {
|
372
376
|
channel: channel
|
373
377
|
};
|
374
|
-
|
378
|
+
const subscription = new Subscription(this.consumer, params, mixin);
|
375
379
|
return this.add(subscription);
|
376
|
-
}
|
377
|
-
|
380
|
+
}
|
381
|
+
add(subscription) {
|
378
382
|
this.subscriptions.push(subscription);
|
379
383
|
this.consumer.ensureActiveConnection();
|
380
384
|
this.notify(subscription, "initialized");
|
381
|
-
this.
|
385
|
+
this.subscribe(subscription);
|
382
386
|
return subscription;
|
383
|
-
}
|
384
|
-
|
387
|
+
}
|
388
|
+
remove(subscription) {
|
385
389
|
this.forget(subscription);
|
386
390
|
if (!this.findAll(subscription.identifier).length) {
|
387
391
|
this.sendCommand(subscription, "unsubscribe");
|
388
392
|
}
|
389
393
|
return subscription;
|
390
|
-
}
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
_this.notify(subscription, "rejected");
|
394
|
+
}
|
395
|
+
reject(identifier) {
|
396
|
+
return this.findAll(identifier).map((subscription => {
|
397
|
+
this.forget(subscription);
|
398
|
+
this.notify(subscription, "rejected");
|
396
399
|
return subscription;
|
397
|
-
});
|
398
|
-
}
|
399
|
-
|
400
|
-
this.
|
401
|
-
|
402
|
-
});
|
400
|
+
}));
|
401
|
+
}
|
402
|
+
forget(subscription) {
|
403
|
+
this.guarantor.forget(subscription);
|
404
|
+
this.subscriptions = this.subscriptions.filter((s => s !== subscription));
|
403
405
|
return subscription;
|
404
|
-
}
|
405
|
-
|
406
|
-
return this.subscriptions.filter(
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
return this.subscriptions.map(
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
Subscriptions.prototype.notifyAll = function notifyAll(callbackName) {
|
417
|
-
var _this3 = this;
|
418
|
-
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
419
|
-
args[_key - 1] = arguments[_key];
|
420
|
-
}
|
421
|
-
return this.subscriptions.map(function(subscription) {
|
422
|
-
return _this3.notify.apply(_this3, [ subscription, callbackName ].concat(args));
|
423
|
-
});
|
424
|
-
};
|
425
|
-
Subscriptions.prototype.notify = function notify(subscription, callbackName) {
|
426
|
-
for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
|
427
|
-
args[_key2 - 2] = arguments[_key2];
|
428
|
-
}
|
429
|
-
var subscriptions = void 0;
|
406
|
+
}
|
407
|
+
findAll(identifier) {
|
408
|
+
return this.subscriptions.filter((s => s.identifier === identifier));
|
409
|
+
}
|
410
|
+
reload() {
|
411
|
+
return this.subscriptions.map((subscription => this.subscribe(subscription)));
|
412
|
+
}
|
413
|
+
notifyAll(callbackName, ...args) {
|
414
|
+
return this.subscriptions.map((subscription => this.notify(subscription, callbackName, ...args)));
|
415
|
+
}
|
416
|
+
notify(subscription, callbackName, ...args) {
|
417
|
+
let subscriptions;
|
430
418
|
if (typeof subscription === "string") {
|
431
419
|
subscriptions = this.findAll(subscription);
|
432
420
|
} else {
|
433
421
|
subscriptions = [ subscription ];
|
434
422
|
}
|
435
|
-
return subscriptions.map(function(
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
423
|
+
return subscriptions.map((subscription => typeof subscription[callbackName] === "function" ? subscription[callbackName](...args) : undefined));
|
424
|
+
}
|
425
|
+
subscribe(subscription) {
|
426
|
+
if (this.sendCommand(subscription, "subscribe")) {
|
427
|
+
this.guarantor.guarantee(subscription);
|
428
|
+
}
|
429
|
+
}
|
430
|
+
confirmSubscription(identifier) {
|
431
|
+
logger.log(`Subscription confirmed ${identifier}`);
|
432
|
+
this.findAll(identifier).map((subscription => this.guarantor.forget(subscription)));
|
433
|
+
}
|
434
|
+
sendCommand(subscription, command) {
|
435
|
+
const {identifier: identifier} = subscription;
|
441
436
|
return this.consumer.send({
|
442
437
|
command: command,
|
443
438
|
identifier: identifier
|
444
439
|
});
|
445
|
-
}
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
function Consumer(url) {
|
450
|
-
classCallCheck(this, Consumer);
|
440
|
+
}
|
441
|
+
}
|
442
|
+
class Consumer {
|
443
|
+
constructor(url) {
|
451
444
|
this._url = url;
|
452
445
|
this.subscriptions = new Subscriptions(this);
|
453
446
|
this.connection = new Connection(this);
|
447
|
+
this.subprotocols = [];
|
448
|
+
}
|
449
|
+
get url() {
|
450
|
+
return createWebSocketURL(this._url);
|
454
451
|
}
|
455
|
-
|
452
|
+
send(data) {
|
456
453
|
return this.connection.send(data);
|
457
|
-
}
|
458
|
-
|
454
|
+
}
|
455
|
+
connect() {
|
459
456
|
return this.connection.open();
|
460
|
-
}
|
461
|
-
|
457
|
+
}
|
458
|
+
disconnect() {
|
462
459
|
return this.connection.close({
|
463
460
|
allowReconnect: false
|
464
461
|
});
|
465
|
-
}
|
466
|
-
|
462
|
+
}
|
463
|
+
ensureActiveConnection() {
|
467
464
|
if (!this.connection.isActive()) {
|
468
465
|
return this.connection.open();
|
469
466
|
}
|
470
|
-
}
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
}
|
476
|
-
} ]);
|
477
|
-
return Consumer;
|
478
|
-
}();
|
467
|
+
}
|
468
|
+
addSubProtocol(subprotocol) {
|
469
|
+
this.subprotocols = [ ...this.subprotocols, subprotocol ];
|
470
|
+
}
|
471
|
+
}
|
479
472
|
function createWebSocketURL(url) {
|
480
473
|
if (typeof url === "function") {
|
481
474
|
url = url();
|
482
475
|
}
|
483
476
|
if (url && !/^wss?:/i.test(url)) {
|
484
|
-
|
477
|
+
const a = document.createElement("a");
|
485
478
|
a.href = url;
|
486
479
|
a.href = a.href;
|
487
480
|
a.protocol = a.protocol.replace("http", "ws");
|
@@ -490,28 +483,29 @@
|
|
490
483
|
return url;
|
491
484
|
}
|
492
485
|
}
|
493
|
-
function createConsumer() {
|
494
|
-
var url = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getConfig("url") || INTERNAL.default_mount_path;
|
486
|
+
function createConsumer(url = getConfig("url") || INTERNAL.default_mount_path) {
|
495
487
|
return new Consumer(url);
|
496
488
|
}
|
497
489
|
function getConfig(name) {
|
498
|
-
|
490
|
+
const element = document.head.querySelector(`meta[name='action-cable-${name}']`);
|
499
491
|
if (element) {
|
500
492
|
return element.getAttribute("content");
|
501
493
|
}
|
502
494
|
}
|
495
|
+
console.log("DEPRECATION: action_cable.js has been renamed to actioncable.js – please update your reference before Rails 8");
|
503
496
|
exports.Connection = Connection;
|
504
497
|
exports.ConnectionMonitor = ConnectionMonitor;
|
505
498
|
exports.Consumer = Consumer;
|
506
499
|
exports.INTERNAL = INTERNAL;
|
507
500
|
exports.Subscription = Subscription;
|
501
|
+
exports.SubscriptionGuarantor = SubscriptionGuarantor;
|
508
502
|
exports.Subscriptions = Subscriptions;
|
509
503
|
exports.adapters = adapters;
|
510
|
-
exports.createWebSocketURL = createWebSocketURL;
|
511
|
-
exports.logger = logger;
|
512
504
|
exports.createConsumer = createConsumer;
|
505
|
+
exports.createWebSocketURL = createWebSocketURL;
|
513
506
|
exports.getConfig = getConfig;
|
507
|
+
exports.logger = logger;
|
514
508
|
Object.defineProperty(exports, "__esModule", {
|
515
509
|
value: true
|
516
510
|
});
|
517
|
-
});
|
511
|
+
}));
|