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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +140 -31
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +1 -1
  5. data/app/assets/javascripts/action_cable.js +230 -257
  6. data/app/assets/javascripts/actioncable.esm.js +491 -0
  7. data/app/assets/javascripts/actioncable.js +489 -0
  8. data/lib/action_cable/channel/base.rb +1 -1
  9. data/lib/action_cable/channel/broadcasting.rb +1 -1
  10. data/lib/action_cable/channel/naming.rb +1 -1
  11. data/lib/action_cable/channel/streams.rb +5 -7
  12. data/lib/action_cable/channel/test_case.rb +16 -1
  13. data/lib/action_cable/connection/base.rb +5 -5
  14. data/lib/action_cable/connection/identification.rb +1 -1
  15. data/lib/action_cable/connection/subscriptions.rb +1 -1
  16. data/lib/action_cable/connection/tagged_logger_proxy.rb +3 -3
  17. data/lib/action_cable/connection/test_case.rb +1 -1
  18. data/lib/action_cable/engine.rb +10 -1
  19. data/lib/action_cable/gem_version.rb +5 -5
  20. data/lib/action_cable/helpers/action_cable_helper.rb +3 -2
  21. data/lib/action_cable/remote_connections.rb +1 -1
  22. data/lib/action_cable/server/broadcasting.rb +1 -1
  23. data/lib/action_cable/server/configuration.rb +1 -0
  24. data/lib/action_cable/server/worker/active_record_connection_management.rb +2 -2
  25. data/lib/action_cable/server/worker.rb +3 -4
  26. data/lib/action_cable/subscription_adapter/postgresql.rb +2 -2
  27. data/lib/action_cable/subscription_adapter/redis.rb +98 -22
  28. data/lib/action_cable/subscription_adapter/test.rb +1 -1
  29. data/lib/action_cable/test_helper.rb +2 -2
  30. data/lib/action_cable/version.rb +1 -1
  31. data/lib/action_cable.rb +1 -1
  32. data/lib/rails/generators/channel/USAGE +1 -1
  33. data/lib/rails/generators/channel/channel_generator.rb +79 -20
  34. data/lib/rails/generators/channel/templates/javascript/index.js.tt +1 -5
  35. metadata +16 -13
  36. /data/lib/rails/generators/channel/templates/application_cable/{channel.rb.tt → channel.rb} +0 -0
  37. /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) : factory(global.ActionCable = {});
3
- })(this, function(exports) {
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: function 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
- (_adapters$logger = adapters.logger).log.apply(_adapters$logger, [ "[ActionCable]" ].concat(messages));
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
- var ConnectionMonitor = function() {
57
- function ConnectionMonitor(connection) {
58
- classCallCheck(this, ConnectionMonitor);
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
- ConnectionMonitor.prototype.start = function start() {
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("ConnectionMonitor started. pollInterval = " + this.getPollInterval() + " ms");
32
+ logger.log(`ConnectionMonitor started. stale threshold = ${this.constructor.staleThreshold} s`);
70
33
  }
71
- };
72
- ConnectionMonitor.prototype.stop = function stop() {
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
- ConnectionMonitor.prototype.isRunning = function isRunning() {
42
+ }
43
+ isRunning() {
81
44
  return this.startedAt && !this.stoppedAt;
82
- };
83
- ConnectionMonitor.prototype.recordPing = function recordPing() {
45
+ }
46
+ recordPing() {
84
47
  this.pingedAt = now();
85
- };
86
- ConnectionMonitor.prototype.recordConnect = function recordConnect() {
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
- ConnectionMonitor.prototype.recordDisconnect = function recordDisconnect() {
54
+ }
55
+ recordDisconnect() {
93
56
  this.disconnectedAt = now();
94
57
  logger.log("ConnectionMonitor recorded disconnect");
95
- };
96
- ConnectionMonitor.prototype.startPolling = function startPolling() {
58
+ }
59
+ startPolling() {
97
60
  this.stopPolling();
98
61
  this.poll();
99
- };
100
- ConnectionMonitor.prototype.stopPolling = function stopPolling() {
62
+ }
63
+ stopPolling() {
101
64
  clearTimeout(this.pollTimeout);
102
- };
103
- ConnectionMonitor.prototype.poll = function poll() {
104
- var _this = this;
105
- this.pollTimeout = setTimeout(function() {
106
- _this.reconnectIfStale();
107
- _this.poll();
108
- }, this.getPollInterval());
109
- };
110
- ConnectionMonitor.prototype.getPollInterval = function getPollInterval() {
111
- var _constructor$pollInte = this.constructor.pollInterval, min = _constructor$pollInte.min, max = _constructor$pollInte.max, multiplier = _constructor$pollInte.multiplier;
112
- var interval = multiplier * Math.log(this.reconnectAttempts + 1);
113
- return Math.round(clamp(interval, min, max) * 1e3);
114
- };
115
- ConnectionMonitor.prototype.reconnectIfStale = function reconnectIfStale() {
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("ConnectionMonitor detected stale connection. reconnectAttempts = " + this.reconnectAttempts + ", pollInterval = " + this.getPollInterval() + " ms, time disconnected = " + secondsSince(this.disconnectedAt) + " s, stale threshold = " + this.constructor.staleThreshold + " s");
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("ConnectionMonitor skipping reopening recent disconnect");
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
- ConnectionMonitor.prototype.connectionIsStale = function connectionIsStale() {
128
- return secondsSince(this.pingedAt ? this.pingedAt : this.startedAt) > this.constructor.staleThreshold;
129
- };
130
- ConnectionMonitor.prototype.disconnectedRecently = function disconnectedRecently() {
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
- ConnectionMonitor.prototype.visibilityDidChange = function visibilityDidChange() {
134
- var _this2 = this;
99
+ }
100
+ visibilityDidChange() {
135
101
  if (document.visibilityState === "visible") {
136
- setTimeout(function() {
137
- if (_this2.connectionIsStale() || !_this2.connection.isOpen()) {
138
- logger.log("ConnectionMonitor reopening stale connection on visibilitychange. visibilityState = " + document.visibilityState);
139
- _this2.connection.reopen();
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
- return ConnectionMonitor;
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
- var message_types = INTERNAL.message_types, protocols = INTERNAL.protocols;
169
- var supportedProtocols = protocols.slice(0, protocols.length - 1);
170
- var indexOf = [].indexOf;
171
- var Connection = function() {
172
- function Connection(consumer) {
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
- Connection.prototype.send = function send(data) {
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
- Connection.prototype.open = function open() {
147
+ }
148
+ open() {
189
149
  if (this.isActive()) {
190
- logger.log("Attempted to open WebSocket, but existing socket is " + this.getState());
150
+ logger.log(`Attempted to open WebSocket, but existing socket is ${this.getState()}`);
191
151
  return false;
192
152
  } else {
193
- logger.log("Opening WebSocket, current state is " + this.getState() + ", subprotocols: " + protocols);
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
- Connection.prototype.close = function close() {
204
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
205
- allowReconnect: true
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.isActive()) {
169
+ if (this.isOpen()) {
211
170
  return this.webSocket.close();
212
171
  }
213
- };
214
- Connection.prototype.reopen = function reopen() {
215
- logger.log("Reopening WebSocket, current state is " + this.getState());
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("Reopening WebSocket in " + this.constructor.reopenDelay + "ms");
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
- Connection.prototype.getProtocol = function getProtocol() {
187
+ }
188
+ getProtocol() {
230
189
  if (this.webSocket) {
231
190
  return this.webSocket.protocol;
232
191
  }
233
- };
234
- Connection.prototype.isOpen = function isOpen() {
192
+ }
193
+ isOpen() {
235
194
  return this.isState("open");
236
- };
237
- Connection.prototype.isActive = function isActive() {
195
+ }
196
+ isActive() {
238
197
  return this.isState("open", "connecting");
239
- };
240
- Connection.prototype.isProtocolSupported = function isProtocolSupported() {
198
+ }
199
+ isProtocolSupported() {
241
200
  return indexOf.call(supportedProtocols, this.getProtocol()) >= 0;
242
- };
243
- Connection.prototype.isState = function isState() {
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
- Connection.prototype.getState = function getState() {
204
+ }
205
+ getState() {
250
206
  if (this.webSocket) {
251
- for (var state in adapters.WebSocket) {
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
- Connection.prototype.installEventHandlers = function installEventHandlers() {
260
- for (var eventName in this.events) {
261
- var handler = this.events[eventName].bind(this);
262
- this.webSocket["on" + eventName] = handler;
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
- Connection.prototype.uninstallEventHandlers = function uninstallEventHandlers() {
266
- for (var eventName in this.events) {
267
- this.webSocket["on" + eventName] = function() {};
220
+ }
221
+ uninstallEventHandlers() {
222
+ for (let eventName in this.events) {
223
+ this.webSocket[`on${eventName}`] = function() {};
268
224
  }
269
- };
270
- return Connection;
271
- }();
225
+ }
226
+ }
272
227
  Connection.reopenDelay = 500;
273
228
  Connection.prototype.events = {
274
- message: function message(event) {
229
+ message(event) {
275
230
  if (!this.isProtocolSupported()) {
276
231
  return;
277
232
  }
278
- var _JSON$parse = JSON.parse(event.data), identifier = _JSON$parse.identifier, message = _JSON$parse.message, reason = _JSON$parse.reason, reconnect = _JSON$parse.reconnect, type = _JSON$parse.type;
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("Disconnecting. Reason: " + reason);
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: function open() {
304
- logger.log("WebSocket onopen event, using '" + this.getProtocol() + "' subprotocol");
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: function close(event) {
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: function error() {
280
+ error() {
325
281
  logger.log("WebSocket onerror event");
326
282
  }
327
283
  };
328
- var extend = function extend(object, properties) {
284
+ const extend = function(object, properties) {
329
285
  if (properties != null) {
330
- for (var key in properties) {
331
- var value = properties[key];
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
- var Subscription = function() {
338
- function Subscription(consumer) {
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
- Subscription.prototype.perform = function perform(action) {
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
- Subscription.prototype.send = function send(data) {
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
- Subscription.prototype.unsubscribe = function unsubscribe() {
309
+ }
310
+ unsubscribe() {
359
311
  return this.consumer.subscriptions.remove(this);
360
- };
361
- return Subscription;
362
- }();
363
- var Subscriptions = function() {
364
- function Subscriptions(consumer) {
365
- classCallCheck(this, Subscriptions);
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
- Subscriptions.prototype.create = function create(channelName, mixin) {
370
- var channel = channelName;
371
- var params = (typeof channel === "undefined" ? "undefined" : _typeof(channel)) === "object" ? channel : {
356
+ create(channelName, mixin) {
357
+ const channel = channelName;
358
+ const params = typeof channel === "object" ? channel : {
372
359
  channel: channel
373
360
  };
374
- var subscription = new Subscription(this.consumer, params, mixin);
361
+ const subscription = new Subscription(this.consumer, params, mixin);
375
362
  return this.add(subscription);
376
- };
377
- Subscriptions.prototype.add = function add(subscription) {
363
+ }
364
+ add(subscription) {
378
365
  this.subscriptions.push(subscription);
379
366
  this.consumer.ensureActiveConnection();
380
367
  this.notify(subscription, "initialized");
381
- this.sendCommand(subscription, "subscribe");
368
+ this.subscribe(subscription);
382
369
  return subscription;
383
- };
384
- Subscriptions.prototype.remove = function remove(subscription) {
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
- Subscriptions.prototype.reject = function reject(identifier) {
392
- var _this = this;
393
- return this.findAll(identifier).map(function(subscription) {
394
- _this.forget(subscription);
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
- Subscriptions.prototype.forget = function forget(subscription) {
400
- this.subscriptions = this.subscriptions.filter(function(s) {
401
- return s !== subscription;
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
- Subscriptions.prototype.findAll = function findAll(identifier) {
406
- return this.subscriptions.filter(function(s) {
407
- return s.identifier === identifier;
408
- });
409
- };
410
- Subscriptions.prototype.reload = function reload() {
411
- var _this2 = this;
412
- return this.subscriptions.map(function(subscription) {
413
- return _this2.sendCommand(subscription, "subscribe");
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(subscription) {
436
- return typeof subscription[callbackName] === "function" ? subscription[callbackName].apply(subscription, args) : undefined;
437
- });
438
- };
439
- Subscriptions.prototype.sendCommand = function sendCommand(subscription, command) {
440
- var identifier = subscription.identifier;
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
- return Subscriptions;
447
- }();
448
- var Consumer = function() {
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
- Consumer.prototype.send = function send(data) {
431
+ get url() {
432
+ return createWebSocketURL(this._url);
433
+ }
434
+ send(data) {
456
435
  return this.connection.send(data);
457
- };
458
- Consumer.prototype.connect = function connect() {
436
+ }
437
+ connect() {
459
438
  return this.connection.open();
460
- };
461
- Consumer.prototype.disconnect = function disconnect() {
439
+ }
440
+ disconnect() {
462
441
  return this.connection.close({
463
442
  allowReconnect: false
464
443
  });
465
- };
466
- Consumer.prototype.ensureActiveConnection = function ensureActiveConnection() {
444
+ }
445
+ ensureActiveConnection() {
467
446
  if (!this.connection.isActive()) {
468
447
  return this.connection.open();
469
448
  }
470
- };
471
- createClass(Consumer, [ {
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
- var a = document.createElement("a");
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
- var element = document.head.querySelector("meta[name='action-cable-" + name + "']");
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
+ }));