actioncable 6.1.3.2 → 7.0.8
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +140 -31
- data/MIT-LICENSE +1 -1
- data/README.md +1 -1
- data/app/assets/javascripts/action_cable.js +230 -257
- data/app/assets/javascripts/actioncable.esm.js +491 -0
- data/app/assets/javascripts/actioncable.js +489 -0
- data/lib/action_cable/channel/base.rb +1 -1
- data/lib/action_cable/channel/broadcasting.rb +1 -1
- data/lib/action_cable/channel/naming.rb +1 -1
- data/lib/action_cable/channel/streams.rb +5 -7
- data/lib/action_cable/channel/test_case.rb +16 -1
- data/lib/action_cable/connection/base.rb +5 -5
- data/lib/action_cable/connection/identification.rb +1 -1
- data/lib/action_cable/connection/subscriptions.rb +1 -1
- data/lib/action_cable/connection/tagged_logger_proxy.rb +3 -3
- data/lib/action_cable/connection/test_case.rb +1 -1
- data/lib/action_cable/engine.rb +10 -1
- data/lib/action_cable/gem_version.rb +5 -5
- data/lib/action_cable/helpers/action_cable_helper.rb +3 -2
- data/lib/action_cable/remote_connections.rb +1 -1
- data/lib/action_cable/server/broadcasting.rb +1 -1
- data/lib/action_cable/server/configuration.rb +1 -0
- data/lib/action_cable/server/worker/active_record_connection_management.rb +2 -2
- data/lib/action_cable/server/worker.rb +3 -4
- data/lib/action_cable/subscription_adapter/postgresql.rb +2 -2
- data/lib/action_cable/subscription_adapter/redis.rb +98 -22
- data/lib/action_cable/subscription_adapter/test.rb +1 -1
- data/lib/action_cable/test_helper.rb +2 -2
- data/lib/action_cable/version.rb +1 -1
- data/lib/action_cable.rb +1 -1
- data/lib/rails/generators/channel/USAGE +1 -1
- data/lib/rails/generators/channel/channel_generator.rb +79 -20
- data/lib/rails/generators/channel/templates/javascript/index.js.tt +1 -5
- metadata +16 -13
- /data/lib/rails/generators/channel/templates/application_cable/{channel.rb.tt → channel.rb} +0 -0
- /data/lib/rails/generators/channel/templates/application_cable/{connection.rb.tt → connection.rb} +0 -0
@@ -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",
|
@@ -165,32 +126,31 @@
|
|
165
126
|
default_mount_path: "/cable",
|
166
127
|
protocols: [ "actioncable-v1-json", "actioncable-unsupported" ]
|
167
128
|
};
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
classCallCheck(this, Connection);
|
129
|
+
const {message_types: message_types, protocols: protocols} = INTERNAL;
|
130
|
+
const supportedProtocols = protocols.slice(0, protocols.length - 1);
|
131
|
+
const indexOf = [].indexOf;
|
132
|
+
class Connection {
|
133
|
+
constructor(consumer) {
|
174
134
|
this.open = this.open.bind(this);
|
175
135
|
this.consumer = consumer;
|
176
136
|
this.subscriptions = this.consumer.subscriptions;
|
177
137
|
this.monitor = new ConnectionMonitor(this);
|
178
138
|
this.disconnected = true;
|
179
139
|
}
|
180
|
-
|
140
|
+
send(data) {
|
181
141
|
if (this.isOpen()) {
|
182
142
|
this.webSocket.send(JSON.stringify(data));
|
183
143
|
return true;
|
184
144
|
} else {
|
185
145
|
return false;
|
186
146
|
}
|
187
|
-
}
|
188
|
-
|
147
|
+
}
|
148
|
+
open() {
|
189
149
|
if (this.isActive()) {
|
190
|
-
logger.log(
|
150
|
+
logger.log(`Attempted to open WebSocket, but existing socket is ${this.getState()}`);
|
191
151
|
return false;
|
192
152
|
} else {
|
193
|
-
logger.log(
|
153
|
+
logger.log(`Opening WebSocket, current state is ${this.getState()}, subprotocols: ${protocols}`);
|
194
154
|
if (this.webSocket) {
|
195
155
|
this.uninstallEventHandlers();
|
196
156
|
}
|
@@ -199,90 +159,85 @@
|
|
199
159
|
this.monitor.start();
|
200
160
|
return true;
|
201
161
|
}
|
202
|
-
}
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
}, allowReconnect = _ref.allowReconnect;
|
162
|
+
}
|
163
|
+
close({allowReconnect: allowReconnect} = {
|
164
|
+
allowReconnect: true
|
165
|
+
}) {
|
207
166
|
if (!allowReconnect) {
|
208
167
|
this.monitor.stop();
|
209
168
|
}
|
210
|
-
if (this.
|
169
|
+
if (this.isOpen()) {
|
211
170
|
return this.webSocket.close();
|
212
171
|
}
|
213
|
-
}
|
214
|
-
|
215
|
-
logger.log(
|
172
|
+
}
|
173
|
+
reopen() {
|
174
|
+
logger.log(`Reopening WebSocket, current state is ${this.getState()}`);
|
216
175
|
if (this.isActive()) {
|
217
176
|
try {
|
218
177
|
return this.close();
|
219
178
|
} catch (error) {
|
220
179
|
logger.log("Failed to reopen WebSocket", error);
|
221
180
|
} finally {
|
222
|
-
logger.log(
|
181
|
+
logger.log(`Reopening WebSocket in ${this.constructor.reopenDelay}ms`);
|
223
182
|
setTimeout(this.open, this.constructor.reopenDelay);
|
224
183
|
}
|
225
184
|
} else {
|
226
185
|
return this.open();
|
227
186
|
}
|
228
|
-
}
|
229
|
-
|
187
|
+
}
|
188
|
+
getProtocol() {
|
230
189
|
if (this.webSocket) {
|
231
190
|
return this.webSocket.protocol;
|
232
191
|
}
|
233
|
-
}
|
234
|
-
|
192
|
+
}
|
193
|
+
isOpen() {
|
235
194
|
return this.isState("open");
|
236
|
-
}
|
237
|
-
|
195
|
+
}
|
196
|
+
isActive() {
|
238
197
|
return this.isState("open", "connecting");
|
239
|
-
}
|
240
|
-
|
198
|
+
}
|
199
|
+
isProtocolSupported() {
|
241
200
|
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
|
-
}
|
201
|
+
}
|
202
|
+
isState(...states) {
|
247
203
|
return indexOf.call(states, this.getState()) >= 0;
|
248
|
-
}
|
249
|
-
|
204
|
+
}
|
205
|
+
getState() {
|
250
206
|
if (this.webSocket) {
|
251
|
-
for (
|
207
|
+
for (let state in adapters.WebSocket) {
|
252
208
|
if (adapters.WebSocket[state] === this.webSocket.readyState) {
|
253
209
|
return state.toLowerCase();
|
254
210
|
}
|
255
211
|
}
|
256
212
|
}
|
257
213
|
return null;
|
258
|
-
}
|
259
|
-
|
260
|
-
for (
|
261
|
-
|
262
|
-
this.webSocket[
|
214
|
+
}
|
215
|
+
installEventHandlers() {
|
216
|
+
for (let eventName in this.events) {
|
217
|
+
const handler = this.events[eventName].bind(this);
|
218
|
+
this.webSocket[`on${eventName}`] = handler;
|
263
219
|
}
|
264
|
-
}
|
265
|
-
|
266
|
-
for (
|
267
|
-
this.webSocket[
|
220
|
+
}
|
221
|
+
uninstallEventHandlers() {
|
222
|
+
for (let eventName in this.events) {
|
223
|
+
this.webSocket[`on${eventName}`] = function() {};
|
268
224
|
}
|
269
|
-
}
|
270
|
-
|
271
|
-
}();
|
225
|
+
}
|
226
|
+
}
|
272
227
|
Connection.reopenDelay = 500;
|
273
228
|
Connection.prototype.events = {
|
274
|
-
message
|
229
|
+
message(event) {
|
275
230
|
if (!this.isProtocolSupported()) {
|
276
231
|
return;
|
277
232
|
}
|
278
|
-
|
233
|
+
const {identifier: identifier, message: message, reason: reason, reconnect: reconnect, type: type} = JSON.parse(event.data);
|
279
234
|
switch (type) {
|
280
235
|
case message_types.welcome:
|
281
236
|
this.monitor.recordConnect();
|
282
237
|
return this.subscriptions.reload();
|
283
238
|
|
284
239
|
case message_types.disconnect:
|
285
|
-
logger.log(
|
240
|
+
logger.log(`Disconnecting. Reason: ${reason}`);
|
286
241
|
return this.close({
|
287
242
|
allowReconnect: reconnect
|
288
243
|
});
|
@@ -291,6 +246,7 @@
|
|
291
246
|
return this.monitor.recordPing();
|
292
247
|
|
293
248
|
case message_types.confirmation:
|
249
|
+
this.subscriptions.confirmSubscription(identifier);
|
294
250
|
return this.subscriptions.notify(identifier, "connected");
|
295
251
|
|
296
252
|
case message_types.rejection:
|
@@ -300,8 +256,8 @@
|
|
300
256
|
return this.subscriptions.notify(identifier, "received", message);
|
301
257
|
}
|
302
258
|
},
|
303
|
-
open
|
304
|
-
logger.log(
|
259
|
+
open() {
|
260
|
+
logger.log(`WebSocket onopen event, using '${this.getProtocol()}' subprotocol`);
|
305
261
|
this.disconnected = false;
|
306
262
|
if (!this.isProtocolSupported()) {
|
307
263
|
logger.log("Protocol is unsupported. Stopping monitor and disconnecting.");
|
@@ -310,7 +266,7 @@
|
|
310
266
|
});
|
311
267
|
}
|
312
268
|
},
|
313
|
-
close
|
269
|
+
close(event) {
|
314
270
|
logger.log("WebSocket onclose event");
|
315
271
|
if (this.disconnected) {
|
316
272
|
return;
|
@@ -321,167 +277,183 @@
|
|
321
277
|
willAttemptReconnect: this.monitor.isRunning()
|
322
278
|
});
|
323
279
|
},
|
324
|
-
error
|
280
|
+
error() {
|
325
281
|
logger.log("WebSocket onerror event");
|
326
282
|
}
|
327
283
|
};
|
328
|
-
|
284
|
+
const extend = function(object, properties) {
|
329
285
|
if (properties != null) {
|
330
|
-
for (
|
331
|
-
|
286
|
+
for (let key in properties) {
|
287
|
+
const value = properties[key];
|
332
288
|
object[key] = value;
|
333
289
|
}
|
334
290
|
}
|
335
291
|
return object;
|
336
292
|
};
|
337
|
-
|
338
|
-
|
339
|
-
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
340
|
-
var mixin = arguments[2];
|
341
|
-
classCallCheck(this, Subscription);
|
293
|
+
class Subscription {
|
294
|
+
constructor(consumer, params = {}, mixin) {
|
342
295
|
this.consumer = consumer;
|
343
296
|
this.identifier = JSON.stringify(params);
|
344
297
|
extend(this, mixin);
|
345
298
|
}
|
346
|
-
|
347
|
-
var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
299
|
+
perform(action, data = {}) {
|
348
300
|
data.action = action;
|
349
301
|
return this.send(data);
|
350
|
-
}
|
351
|
-
|
302
|
+
}
|
303
|
+
send(data) {
|
352
304
|
return this.consumer.send({
|
353
305
|
command: "message",
|
354
306
|
identifier: this.identifier,
|
355
307
|
data: JSON.stringify(data)
|
356
308
|
});
|
357
|
-
}
|
358
|
-
|
309
|
+
}
|
310
|
+
unsubscribe() {
|
359
311
|
return this.consumer.subscriptions.remove(this);
|
360
|
-
}
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
312
|
+
}
|
313
|
+
}
|
314
|
+
class SubscriptionGuarantor {
|
315
|
+
constructor(subscriptions) {
|
316
|
+
this.subscriptions = subscriptions;
|
317
|
+
this.pendingSubscriptions = [];
|
318
|
+
}
|
319
|
+
guarantee(subscription) {
|
320
|
+
if (this.pendingSubscriptions.indexOf(subscription) == -1) {
|
321
|
+
logger.log(`SubscriptionGuarantor guaranteeing ${subscription.identifier}`);
|
322
|
+
this.pendingSubscriptions.push(subscription);
|
323
|
+
} else {
|
324
|
+
logger.log(`SubscriptionGuarantor already guaranteeing ${subscription.identifier}`);
|
325
|
+
}
|
326
|
+
this.startGuaranteeing();
|
327
|
+
}
|
328
|
+
forget(subscription) {
|
329
|
+
logger.log(`SubscriptionGuarantor forgetting ${subscription.identifier}`);
|
330
|
+
this.pendingSubscriptions = this.pendingSubscriptions.filter((s => s !== subscription));
|
331
|
+
}
|
332
|
+
startGuaranteeing() {
|
333
|
+
this.stopGuaranteeing();
|
334
|
+
this.retrySubscribing();
|
335
|
+
}
|
336
|
+
stopGuaranteeing() {
|
337
|
+
clearTimeout(this.retryTimeout);
|
338
|
+
}
|
339
|
+
retrySubscribing() {
|
340
|
+
this.retryTimeout = setTimeout((() => {
|
341
|
+
if (this.subscriptions && typeof this.subscriptions.subscribe === "function") {
|
342
|
+
this.pendingSubscriptions.map((subscription => {
|
343
|
+
logger.log(`SubscriptionGuarantor resubscribing ${subscription.identifier}`);
|
344
|
+
this.subscriptions.subscribe(subscription);
|
345
|
+
}));
|
346
|
+
}
|
347
|
+
}), 500);
|
348
|
+
}
|
349
|
+
}
|
350
|
+
class Subscriptions {
|
351
|
+
constructor(consumer) {
|
366
352
|
this.consumer = consumer;
|
353
|
+
this.guarantor = new SubscriptionGuarantor(this);
|
367
354
|
this.subscriptions = [];
|
368
355
|
}
|
369
|
-
|
370
|
-
|
371
|
-
|
356
|
+
create(channelName, mixin) {
|
357
|
+
const channel = channelName;
|
358
|
+
const params = typeof channel === "object" ? channel : {
|
372
359
|
channel: channel
|
373
360
|
};
|
374
|
-
|
361
|
+
const subscription = new Subscription(this.consumer, params, mixin);
|
375
362
|
return this.add(subscription);
|
376
|
-
}
|
377
|
-
|
363
|
+
}
|
364
|
+
add(subscription) {
|
378
365
|
this.subscriptions.push(subscription);
|
379
366
|
this.consumer.ensureActiveConnection();
|
380
367
|
this.notify(subscription, "initialized");
|
381
|
-
this.
|
368
|
+
this.subscribe(subscription);
|
382
369
|
return subscription;
|
383
|
-
}
|
384
|
-
|
370
|
+
}
|
371
|
+
remove(subscription) {
|
385
372
|
this.forget(subscription);
|
386
373
|
if (!this.findAll(subscription.identifier).length) {
|
387
374
|
this.sendCommand(subscription, "unsubscribe");
|
388
375
|
}
|
389
376
|
return subscription;
|
390
|
-
}
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
_this.notify(subscription, "rejected");
|
377
|
+
}
|
378
|
+
reject(identifier) {
|
379
|
+
return this.findAll(identifier).map((subscription => {
|
380
|
+
this.forget(subscription);
|
381
|
+
this.notify(subscription, "rejected");
|
396
382
|
return subscription;
|
397
|
-
});
|
398
|
-
}
|
399
|
-
|
400
|
-
this.
|
401
|
-
|
402
|
-
});
|
383
|
+
}));
|
384
|
+
}
|
385
|
+
forget(subscription) {
|
386
|
+
this.guarantor.forget(subscription);
|
387
|
+
this.subscriptions = this.subscriptions.filter((s => s !== subscription));
|
403
388
|
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;
|
389
|
+
}
|
390
|
+
findAll(identifier) {
|
391
|
+
return this.subscriptions.filter((s => s.identifier === identifier));
|
392
|
+
}
|
393
|
+
reload() {
|
394
|
+
return this.subscriptions.map((subscription => this.subscribe(subscription)));
|
395
|
+
}
|
396
|
+
notifyAll(callbackName, ...args) {
|
397
|
+
return this.subscriptions.map((subscription => this.notify(subscription, callbackName, ...args)));
|
398
|
+
}
|
399
|
+
notify(subscription, callbackName, ...args) {
|
400
|
+
let subscriptions;
|
430
401
|
if (typeof subscription === "string") {
|
431
402
|
subscriptions = this.findAll(subscription);
|
432
403
|
} else {
|
433
404
|
subscriptions = [ subscription ];
|
434
405
|
}
|
435
|
-
return subscriptions.map(function(
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
406
|
+
return subscriptions.map((subscription => typeof subscription[callbackName] === "function" ? subscription[callbackName](...args) : undefined));
|
407
|
+
}
|
408
|
+
subscribe(subscription) {
|
409
|
+
if (this.sendCommand(subscription, "subscribe")) {
|
410
|
+
this.guarantor.guarantee(subscription);
|
411
|
+
}
|
412
|
+
}
|
413
|
+
confirmSubscription(identifier) {
|
414
|
+
logger.log(`Subscription confirmed ${identifier}`);
|
415
|
+
this.findAll(identifier).map((subscription => this.guarantor.forget(subscription)));
|
416
|
+
}
|
417
|
+
sendCommand(subscription, command) {
|
418
|
+
const {identifier: identifier} = subscription;
|
441
419
|
return this.consumer.send({
|
442
420
|
command: command,
|
443
421
|
identifier: identifier
|
444
422
|
});
|
445
|
-
}
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
function Consumer(url) {
|
450
|
-
classCallCheck(this, Consumer);
|
423
|
+
}
|
424
|
+
}
|
425
|
+
class Consumer {
|
426
|
+
constructor(url) {
|
451
427
|
this._url = url;
|
452
428
|
this.subscriptions = new Subscriptions(this);
|
453
429
|
this.connection = new Connection(this);
|
454
430
|
}
|
455
|
-
|
431
|
+
get url() {
|
432
|
+
return createWebSocketURL(this._url);
|
433
|
+
}
|
434
|
+
send(data) {
|
456
435
|
return this.connection.send(data);
|
457
|
-
}
|
458
|
-
|
436
|
+
}
|
437
|
+
connect() {
|
459
438
|
return this.connection.open();
|
460
|
-
}
|
461
|
-
|
439
|
+
}
|
440
|
+
disconnect() {
|
462
441
|
return this.connection.close({
|
463
442
|
allowReconnect: false
|
464
443
|
});
|
465
|
-
}
|
466
|
-
|
444
|
+
}
|
445
|
+
ensureActiveConnection() {
|
467
446
|
if (!this.connection.isActive()) {
|
468
447
|
return this.connection.open();
|
469
448
|
}
|
470
|
-
}
|
471
|
-
|
472
|
-
key: "url",
|
473
|
-
get: function get$$1() {
|
474
|
-
return createWebSocketURL(this._url);
|
475
|
-
}
|
476
|
-
} ]);
|
477
|
-
return Consumer;
|
478
|
-
}();
|
449
|
+
}
|
450
|
+
}
|
479
451
|
function createWebSocketURL(url) {
|
480
452
|
if (typeof url === "function") {
|
481
453
|
url = url();
|
482
454
|
}
|
483
455
|
if (url && !/^wss?:/i.test(url)) {
|
484
|
-
|
456
|
+
const a = document.createElement("a");
|
485
457
|
a.href = url;
|
486
458
|
a.href = a.href;
|
487
459
|
a.protocol = a.protocol.replace("http", "ws");
|
@@ -490,28 +462,29 @@
|
|
490
462
|
return url;
|
491
463
|
}
|
492
464
|
}
|
493
|
-
function createConsumer() {
|
494
|
-
var url = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getConfig("url") || INTERNAL.default_mount_path;
|
465
|
+
function createConsumer(url = getConfig("url") || INTERNAL.default_mount_path) {
|
495
466
|
return new Consumer(url);
|
496
467
|
}
|
497
468
|
function getConfig(name) {
|
498
|
-
|
469
|
+
const element = document.head.querySelector(`meta[name='action-cable-${name}']`);
|
499
470
|
if (element) {
|
500
471
|
return element.getAttribute("content");
|
501
472
|
}
|
502
473
|
}
|
474
|
+
console.log("DEPRECATION: action_cable.js has been renamed to actioncable.js – please update your reference before Rails 8");
|
503
475
|
exports.Connection = Connection;
|
504
476
|
exports.ConnectionMonitor = ConnectionMonitor;
|
505
477
|
exports.Consumer = Consumer;
|
506
478
|
exports.INTERNAL = INTERNAL;
|
507
479
|
exports.Subscription = Subscription;
|
480
|
+
exports.SubscriptionGuarantor = SubscriptionGuarantor;
|
508
481
|
exports.Subscriptions = Subscriptions;
|
509
482
|
exports.adapters = adapters;
|
510
|
-
exports.createWebSocketURL = createWebSocketURL;
|
511
|
-
exports.logger = logger;
|
512
483
|
exports.createConsumer = createConsumer;
|
484
|
+
exports.createWebSocketURL = createWebSocketURL;
|
513
485
|
exports.getConfig = getConfig;
|
486
|
+
exports.logger = logger;
|
514
487
|
Object.defineProperty(exports, "__esModule", {
|
515
488
|
value: true
|
516
489
|
});
|
517
|
-
});
|
490
|
+
}));
|