UNPKG

@leonardssh/use-lanyard

Version:

🚀 Lanyard with Composition API for Vue

234 lines (221 loc) • 7.97 kB
var LeonardsshUseLanyard = (function (exports, vueDemi) { 'use strict'; const API_URL = 'https://api.lanyard.rest/v1'; const WEBSOCKET_URL = 'wss://api.lanyard.rest/socket'; const isClient = typeof window !== 'undefined'; /** * Call onUnmounted() if it's inside a component lifecycle, if not, do nothing * * @param fn */ function tryOnUnmounted(fn) { if (vueDemi.getCurrentInstance()) vueDemi.onUnmounted(fn); } /** * Wrapper for `setInterval` with controls * * @param cb * @param interval * @param options */ function useIntervalFn(cb, interval = 1000, options = {}) { const { immediate = true, immediateCallback = false, } = options; let timer = null; const isActive = vueDemi.ref(false); function clean() { if (timer) { clearInterval(timer); timer = null; } } function pause() { isActive.value = false; clean(); } function resume() { if (interval <= 0) return; isActive.value = true; if (immediateCallback) cb(); clean(); timer = setInterval(cb, interval); } if (immediate && isClient) resume(); tryOnUnmounted(pause); return { isActive, pause, resume, }; } isClient ? window : undefined; isClient ? window.document : undefined; isClient ? window.navigator : undefined; var SwipeDirection; (function (SwipeDirection) { SwipeDirection["UP"] = "UP"; SwipeDirection["RIGHT"] = "RIGHT"; SwipeDirection["DOWN"] = "DOWN"; SwipeDirection["LEFT"] = "LEFT"; SwipeDirection["NONE"] = "NONE"; })(SwipeDirection || (SwipeDirection = {})); function resolveNestedOptions(options) { if (options === true) return {}; return options; } /** * Reactive WebSocket client. * * @see https://vueuse.org/useWebSocket * @param url */ function useWebSocket(url, options = {}) { const { onConnected, onDisconnected, onError, onMessage, immediate = true, } = options; const data = vueDemi.ref(null); const status = vueDemi.ref('CONNECTING'); const wsRef = vueDemi.ref(); let heartbeatPause; let heartbeatResume; let explicitlyClosed = false; let retried = 0; let bufferedData = []; const close = (code, reason) => { if (!wsRef.value) return; explicitlyClosed = true; heartbeatPause === null || heartbeatPause === void 0 ? void 0 : heartbeatPause(); wsRef.value.close(code, reason); }; const _sendBuffer = () => { if (bufferedData.length && wsRef.value && status.value === 'OPEN') { for (const buffer of bufferedData) wsRef.value.send(buffer); bufferedData = []; } }; const send = (data, useBuffer = true) => { if (!wsRef.value || status.value !== 'OPEN') { if (useBuffer) bufferedData.push(data); return false; } _sendBuffer(); wsRef.value.send(data); return true; }; const _init = () => { const ws = new WebSocket(url); wsRef.value = ws; status.value = 'CONNECTING'; explicitlyClosed = false; ws.onopen = () => { status.value = 'OPEN'; onConnected === null || onConnected === void 0 ? void 0 : onConnected(ws); heartbeatResume === null || heartbeatResume === void 0 ? void 0 : heartbeatResume(); _sendBuffer(); }; ws.onclose = (ev) => { status.value = 'CLOSED'; wsRef.value = undefined; onDisconnected === null || onDisconnected === void 0 ? void 0 : onDisconnected(ws, ev); if (!explicitlyClosed && options.autoReconnect) { const { retries = -1, delay = 1000, onFailed, } = resolveNestedOptions(options.autoReconnect); retried += 1; if (retries < 0 || retried < retries) setTimeout(_init, delay); else onFailed === null || onFailed === void 0 ? void 0 : onFailed(); } }; ws.onerror = (e) => { onError === null || onError === void 0 ? void 0 : onError(ws, e); }; ws.onmessage = (e) => { data.value = e.data; onMessage === null || onMessage === void 0 ? void 0 : onMessage(ws, e); }; }; if (options.heartbeat) { const { message = 'ping', interval = 1000, } = resolveNestedOptions(options.heartbeat); const { pause, resume } = useIntervalFn(() => send(message, false), interval, { immediate: false }); heartbeatPause = pause; heartbeatResume = resume; } if (immediate) _init(); const open = () => { close(); retried = 0; _init(); }; tryOnUnmounted(close); return { data, status, close, send, open, ws: wsRef, }; } async function useLanyard(options) { if (Reflect.has(options, 'socket')) { const { socket, onPresenceUpdate } = options; const supportsWebSockets = 'WebSocket' in window || 'MozWebSocket' in window; if (socket && !supportsWebSockets) { throw new Error("Browser doesn't support WebSocket connections."); } const subscription = typeof options.userId === 'object' ? 'subscribe_to_ids' : 'subscribe_to_id'; useWebSocket(WEBSOCKET_URL, { heartbeat: { interval: 30 * 1000, message: JSON.stringify({ op: 3 }) }, onMessage(_, e) { const { t, d } = JSON.parse(e.data); if (t === 'INIT_STATE' || t === 'PRESENCE_UPDATE') { onPresenceUpdate?.(d || {}); } }, onConnected(ws) { ws.send(JSON.stringify({ op: 2, d: { [subscription]: options.userId } })); } }); return; } if (typeof options.userId === 'string') { const req = await fetch(`${API_URL}/users/${options.userId}`); const body = (await req.json()); if (body.error) { throw new Error(body.error.message); } return body; } const responseArray = []; for (const id of options.userId) { const req = await fetch(`${API_URL}/users/${id}`); const body = (await req.json()); if (body.error) { throw new Error(body.error.message); } responseArray.push(body); } return responseArray; } exports.API_URL = API_URL; exports.WEBSOCKET_URL = WEBSOCKET_URL; exports.useLanyard = useLanyard; Object.defineProperty(exports, '__esModule', { value: true }); return exports; }({}, VueDemi));