PageSourceSearch

https://hunter.io/assets/useActionCable-BWRJhDYY.js

js hunter.io collected 2026-10-01 08:21:41 UTC 17,189 bytes, 497 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.