99 lines
2.6 KiB
TypeScript
99 lines
2.6 KiB
TypeScript
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<WebSocketMessageType, WebSocketMessageData>();
|
|
|
|
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<typeof tokenStore, WebSocket | null>(
|
|
tokenStore,
|
|
($token, set) => {
|
|
if ($token) {
|
|
set(connect($token));
|
|
} else {
|
|
set(null);
|
|
}
|
|
},
|
|
null
|
|
);
|
|
|
|
socket.subscribe((socket) => {
|
|
console.log(`[WS] Connected: `, socket);
|
|
});
|