import { BASE_API_URL } from '$lib/constants'; import { EventEmitter } from '$lib/event'; import { derived, get } from 'svelte/store'; import { token as tokenStore } from './user'; import type { Channel, Message } from '$lib/types'; import { messagesCache, channelsCache } from './cache'; export type WebSocketMessageType = | 'createMessage' | 'updateChannel' | 'createChannel' | 'deleteChannel' | 'connect' | 'disconnect' | 'any'; export type WebSocketMessageData = | Message | Channel | { id: number } | null | { type: WebSocketMessageType; }; export type WebsoketMessage = { type: WebSocketMessageType; data: WebSocketMessageData; }; export const appWebsocket = new EventEmitter(); appWebsocket.on('any', (data) => { console.log(`[WS] Recieved message: `, data); }); function updateCache(type: WebSocketMessageType, data: WebSocketMessageData) { switch (type) { case 'createMessage': messagesCache.set((data as Message).id, data as Message); break; case 'updateChannel': channelsCache.set((data as Channel).id, data as Channel); break; case 'createChannel': channelsCache.set((data as Channel).id, data as Channel); break; case 'deleteChannel': channelsCache.remove((data as { id: number }).id); break; default: break; } } const connect = (token: string) => { const websocket = new WebSocket(`ws://${BASE_API_URL}/ws/${token}`); websocket.onopen = () => { appWebsocket.emit('connect', null); appWebsocket.emit('any', { type: 'connect' }); }; websocket.onmessage = (event) => { const message: WebsoketMessage = JSON.parse(event.data); updateCache(message.type, message.data); appWebsocket.emit(message.type, message.data as WebSocketMessageData); appWebsocket.emit('any', message); }; websocket.onclose = () => { appWebsocket.emit('disconnect', null); appWebsocket.emit('any', { type: 'disconnect' }); setTimeout(() => { const token = get(tokenStore); if (token) connect(token); }, 500); }; return websocket; }; const socket = derived( tokenStore, ($token, set) => { if ($token) { set(connect($token)); } else { set(null); } }, null ); socket.subscribe((socket) => { console.log(`[WS] Connected: `, socket); });