import { reactive, toRefs } from 'vue';
import { useEcho } from './useEcho.js';
import { safeStringify } from '../utils/safeStringify.js';
const state = reactive({
initialized: false,
connected: false,
connecting: false,
failed: false,
unavailable: false,
info: null,
status: 'uninitialized',
});
const log = [];
const debug = (...args) => log.push(args.join(' '));
window.debugSocket = () => {
return { state, log };
};
/**
* Exposes the state of the current websocket connection
* that is a requirement for collaborative features.
* @return {{connected: boolean, reason: null, unavailable: boolean, failed: boolean,
* connecting: boolean}}
*/
export const useWebSocketConnection = () => {
const { connected, connecting, unavailable, failed, status, initialized } =
toRefs(state);
const initWebSocket = () => {
debug('initWebSocket');
if (initialized.value) {
debug('websocket already initialized');
return;
}
debug('get echo');
const { init, options } = useEcho();
debug('echo options are', safeStringify(options()));
const echo = init();
debug(`echo state: ${echo.connector.pusher.connection.state}`);
debug('add connecting listener');
echo.connector.pusher.connection.bind('connecting', (payload) => {
/**
* All dependencies have been loaded and Channels is trying to connect.
* The connection will also enter this state when it is trying to reconnect after a connection failure.
*/
state.connecting = true;
state.status = 'Connecting';
debug('Echo connecting...', safeStringify(payload));
});
debug('add connected listener');
echo.connector.pusher.connection.bind('connected', (payload) => {
/**
* The connection to Channels is open and authenticated with your app.
*/
state.connected = true;
state.connecting = false;
state.status = 'Connected';
debug('Echo connected!', safeStringify(payload));
});
debug('add unavailable listener');
echo.connector.pusher.connection.bind('unavailable', (payload) => {
/**
* The connection is temporarily unavailable. In most cases this means that there is no internet connection.
* It could also mean that Channels is down, or some intermediary is blocking the connection. In this state,
* pusher-js will automatically retry the connection every 15 seconds.
*/
state.unavailable = true;
state.connecting = false;
state.status = 'Unavailable or unreachable';
debug('Echo unavailable or unreachable.', JSON.stringify(payload));
});
debug('add failed listener');
echo.connector.pusher.connection.bind('failed', (payload) => {
/**
* Channels is not supported by the browser.
* This implies that WebSockets are not natively available and an HTTP-based transport could not be found.
*/
state.failed = true;
state.connecting = false;
state.status = `Failed: ${payload}`;
debug('Echo failed →', safeStringify(payload));
});
debug('add disconnected listener');
echo.connector.pusher.connection.bind('disconnected', (payload) => {
/**
* The Channels connection was previously connected and has now intentionally been closed
*/
state.connected = false;
state.status = 'disconnected';
state.info = payload;
debug('Echo disconnected...', safeStringify(payload));
});
debug('add error listener');
echo.connector.pusher.connection.bind('error', (payload) => {
/**
* The Channels connection was previously connected and has now intentionally been closed
*/
state.connected = false;
state.status = 'error';
state.info = payload;
debug('Echo disconnected...', safeStringify(payload));
});
debug('complete init');
state.initialized = true;
};
return {
connected,
connecting,
unavailable,
failed,
status,
initWebSocket,
initialized,
};
};