From 9ef76a7c26bb6e36a4069a08bbe24b3eaeb1225a Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Tue, 15 Jul 2025 11:52:44 +0200 Subject: [PATCH] add socketio to app --- src/serverCom.ts | 4 +- src/socketManager.ts | 81 ++++++++++++++++++++++++++++++++++++++ src/stores/notification.ts | 2 +- 3 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 src/socketManager.ts diff --git a/src/serverCom.ts b/src/serverCom.ts index ad4d39f..5b10d28 100644 --- a/src/serverCom.ts +++ b/src/serverCom.ts @@ -78,7 +78,7 @@ http.interceptors.response.use( } ); -export async function refreshToken(): Promise { +async function refreshToken(): Promise { return new Promise(async (resolve, reject) => { await http .post(`/auth/refresh`, { @@ -135,4 +135,4 @@ async function* streamingFetch(path: string, abort?: AbortController) { } } -export { http, newEventSource, streamingFetch, host, url }; +export { http, newEventSource, streamingFetch, host, url, refreshToken }; diff --git a/src/socketManager.ts b/src/socketManager.ts new file mode 100644 index 0000000..85c0c44 --- /dev/null +++ b/src/socketManager.ts @@ -0,0 +1,81 @@ +import { Manager, Socket } from "socket.io-client"; +import { refreshToken, url } from "./serverCom"; +import { useNotificationStore } from "./stores/notification"; + +export enum SocketConnectionTypes { + scanner = "/scanner", + pscanner = "/public_scanner", +} + +export abstract class SocketManager { + private readonly manager = new Manager(url, { + reconnection: true, + reconnectionDelayMax: 10000, + }); + private readonly connections = new Map(); + + public establishConnection(connection: SocketConnectionTypes) { + if (this.connections.has(connection)) return this.connections.get(connection); + const notificationStore = useNotificationStore(); + let socket = this.manager.socket(connection, { + auth: (cb) => { + cb({ token: localStorage.getItem("accessToken") }); + }, + }); + socket.on("connect", () => { + notificationStore.push("Socket-Erfolg", `Verbindung aufgebaut`, "success"); + }); + socket.on("connect_error", (err) => { + this.socketHandleError(connection, err, true); + }); + socket.on("disconnect", () => { + this.establishConnection(connection); + }); + socket.on("warning", (msg: string) => { + notificationStore.push("Socket-Warnung", msg, "warning"); + }); + socket.on("error", (msg: string) => { + this.socketHandleError(connection, { + name: "Error", + message: msg, + }); + }); + + this.connections.set(connection, socket); + return socket; + } + + public getConnection(connection: SocketConnectionTypes) { + return this.connections.get(connection); + } + + public closeConnection(connection: SocketConnectionTypes) { + let socket = this.connections.get(connection); + if (socket) { + socket.disconnect(); + this.connections.delete(connection); + } + } + + private socketHandleError(connection: SocketConnectionTypes, err: Error, onConnect = false) { + const notificationStore = useNotificationStore(); + + if (err.message == "xhr poll error") { + notificationStore.push("Socket-Netzwerk-Fehler", "Reconnect Versuch in 10s", "error"); + } else if (err.message == "Token expired") { + notificationStore.push("Session", "Session wird verlängert", "info"); + refreshToken() + .then(() => { + notificationStore.push("Session", "Session erfolgreich verlängert", "success"); + this.closeConnection(connection); + }) + .catch(() => { + notificationStore.push("Session-Fehler", "Anmeldung wurde nicht verlängert", "error"); + }); + } else if (onConnect) { + notificationStore.push("Socket-Fehler", `Verbindung fehlgeschlagen`, "error"); + } else { + notificationStore.push("Socket-Fehler", err.message, "error"); + } + } +} diff --git a/src/stores/notification.ts b/src/stores/notification.ts index 872b108..0ec8fc0 100644 --- a/src/stores/notification.ts +++ b/src/stores/notification.ts @@ -8,7 +8,7 @@ export interface Notification { indicator: boolean; } -export type NotificationType = "info" | "warning" | "error"; +export type NotificationType = "info" | "warning" | "error" | "success"; export const useNotificationStore = defineStore("notification", { state: () => {