import * as io from "socket.io"; import { Server } from "http"; import { DatabaseManager } from "./database/database"; import Logging from "@hibas123/logging"; import Query from "./database/query"; import Session from "./database/session"; import shortid = require("shortid"); type QueryTypes = "get" | "set" | "push" | "subscribe" | "unsubscribe"; export class ConnectionManager { static server: io.Server; static bind(server: Server) { this.server = io(server); this.server.on("connection", this.onConnection.bind(this)); } private static onConnection(socket: io.Socket) { Logging.debug("New Connection:", socket.id); const reqMap = new Map(); const stored = new Map(); const session = new Session(); const answer = (id: string, data: any, err: boolean = false) => { let time = process.hrtime(reqMap.get(id)); reqMap.delete(id); // Logging.debug(`Sending answer for ${id} with data`, data, err ? "as error" : "", "Took", time[1] / 1000, "us"); socket.emit("message", id, err, data); } socket.on("login", (id: string) => { //TODO: implement }) socket.on("query", async (id: string, type: QueryTypes, database: string, path: string[], data: any) => { Logging.debug(`Request with id '${id}' from type '${type}' for database '${database}' and path '${path}' with data`, data) reqMap.set(id, process.hrtime()); try { const db = DatabaseManager.getDatabase(database); const perms = db.rules.hasPermission(path, session); const noperm = new Error("No permisison!"); if (!db) answer(id, "Database not found!", true); else { const query = stored.get(id) || db.getQuery(path); switch (type) { case "get": if (!perms.read) throw noperm; answer(id, await query.get()); return; case "set": if (!perms.write) throw noperm; answer(id, await query.set(data)); return; case "push": if (!perms.write) throw noperm; answer(id, await query.push(data)); return; case "subscribe": if (!perms.read) throw noperm; let subscriptionID = shortid.generate(); query.subscribe(data, (data) => { socket.emit("event", subscriptionID, data); }); stored.set(id, query); answer(id, subscriptionID); return; case "unsubscribe": query.unsubscribe(); stored.delete(id); answer(id, true); return; } answer(id, "Invalid request!", true); } } catch (err) { Logging.error(err); answer(id, err.message, true); } }) socket.on("disconnect", () => { reqMap.clear(); stored.clear(); socket.removeAllListeners(); }) } }