diff --git a/dist/src/api/v1/calls/index.js b/dist/src/api/v1/calls/index.js index 807208c..17ae5e3 100644 --- a/dist/src/api/v1/calls/index.js +++ b/dist/src/api/v1/calls/index.js @@ -8,10 +8,12 @@ exports.default = ({ realm, messageHandler }) => { const app = express_1.default.Router(); const handle = (req, res, next) => { const { id } = req.params; - if (!id) { + if (!id) return next(); - } const client = realm.getClientById(id); + if (!client) { + throw new Error(`client not found:${id}`); + } const { type, dst, payload } = req.body; const message = { type, diff --git a/dist/src/index.js b/dist/src/index.js index 292c507..7137006 100644 --- a/dist/src/index.js +++ b/dist/src/index.js @@ -95,12 +95,7 @@ function PeerServer(options = {}, callback) { } const peerjs = ExpressPeerServer(server, newOptions); app.use(peerjs); - if (callback) { - server.listen(port, () => callback(server)); - } - else { - server.listen(port); - } + server.listen(port, () => { var _a; return (_a = callback) === null || _a === void 0 ? void 0 : _a(server); }); return peerjs; } exports.PeerServer = PeerServer; diff --git a/dist/src/messageHandler/handlers/heartbeat/index.js b/dist/src/messageHandler/handlers/heartbeat/index.js index 22269ab..d292fec 100644 --- a/dist/src/messageHandler/handlers/heartbeat/index.js +++ b/dist/src/messageHandler/handlers/heartbeat/index.js @@ -1,7 +1,9 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HeartbeatHandler = (client) => { - const nowTime = new Date().getTime(); - client.setLastPing(nowTime); + if (client) { + const nowTime = new Date().getTime(); + client.setLastPing(nowTime); + } return true; }; diff --git a/dist/src/messageHandler/handlers/transmission/index.js b/dist/src/messageHandler/handlers/transmission/index.js index 1a6d0d3..390eb6e 100644 --- a/dist/src/messageHandler/handlers/transmission/index.js +++ b/dist/src/messageHandler/handlers/transmission/index.js @@ -9,10 +9,11 @@ exports.TransmissionHandler = ({ realm }) => { const destinationClient = realm.getClientById(dstId); // User is connected! if (destinationClient) { + const socket = destinationClient.getSocket(); try { - if (destinationClient.getSocket()) { + if (socket) { const data = JSON.stringify(message); - destinationClient.getSocket().send(data); + socket.send(data); } else { // Neither socket no res available. Peer dead? @@ -23,8 +24,8 @@ exports.TransmissionHandler = ({ realm }) => { // This happens when a peer disconnects without closing connections and // the associated WebSocket has not closed. // Tell other side to stop trying. - if (destinationClient.getSocket()) { - destinationClient.getSocket().close(); + if (socket) { + socket.close(); } else { realm.removeClientById(destinationClient.getId()); diff --git a/dist/src/messageHandler/messageHandlers.js b/dist/src/messageHandler/messageHandlers.js index 167f3d6..01b1e06 100644 --- a/dist/src/messageHandler/messageHandlers.js +++ b/dist/src/messageHandler/messageHandlers.js @@ -5,17 +5,15 @@ class MessageHandlers { this.handlers = new Map(); } registerHandler(messageType, handler) { - if (this.handlers.has(messageType)) { + if (this.handlers.has(messageType)) return; - } this.handlers.set(messageType, handler); } handle(client, message) { const { type } = message; const handler = this.handlers.get(type); - if (!handler) { + if (!handler) return false; - } return handler(client, message); } } diff --git a/dist/src/models/client.js b/dist/src/models/client.js index 084d0b6..79473e4 100644 --- a/dist/src/models/client.js +++ b/dist/src/models/client.js @@ -26,7 +26,8 @@ class Client { this.lastPing = lastPing; } send(data) { - this.socket.send(JSON.stringify(data)); + var _a; + (_a = this.socket) === null || _a === void 0 ? void 0 : _a.send(JSON.stringify(data)); } } exports.Client = Client; diff --git a/dist/src/models/realm.js b/dist/src/models/realm.js index 63f09e1..53fc672 100644 --- a/dist/src/models/realm.js +++ b/dist/src/models/realm.js @@ -24,9 +24,8 @@ class Realm { } removeClientById(id) { const client = this.getClientById(id); - if (!client) { + if (!client) return false; - } this.clients.delete(id); return true; } diff --git a/dist/src/services/checkBrokenConnections/index.js b/dist/src/services/checkBrokenConnections/index.js index 60a96da..f0e7115 100644 --- a/dist/src/services/checkBrokenConnections/index.js +++ b/dist/src/services/checkBrokenConnections/index.js @@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); const DEFAULT_CHECK_INTERVAL = 300; class CheckBrokenConnections { constructor({ realm, config, checkInterval = DEFAULT_CHECK_INTERVAL, onClose }) { + this.timeoutId = null; this.realm = realm; this.config = config; this.onClose = onClose; @@ -25,30 +26,23 @@ class CheckBrokenConnections { } } checkConnections() { + var _a, _b, _c; const clientsIds = this.realm.getClientsIds(); const now = new Date().getTime(); const { alive_timeout: aliveTimeout } = this.config; for (const clientId of clientsIds) { const client = this.realm.getClientById(clientId); const timeSinceLastPing = now - client.getLastPing(); - if (timeSinceLastPing < aliveTimeout) { + if (timeSinceLastPing < aliveTimeout) continue; - } try { - if (client.getSocket()) { - client.getSocket().close(); - } - } - catch (e) { - // @ts-nocheck + (_a = client.getSocket()) === null || _a === void 0 ? void 0 : _a.close(); } finally { this.realm.clearMessageQueue(clientId); this.realm.removeClientById(clientId); client.setSocket(null); - if (this.onClose) { - this.onClose(client); - } + (_c = (_b = this).onClose) === null || _c === void 0 ? void 0 : _c.call(_b, client); } } } diff --git a/dist/src/services/messagesExpire/index.js b/dist/src/services/messagesExpire/index.js index 7e63c3b..9e9d6f2 100644 --- a/dist/src/services/messagesExpire/index.js +++ b/dist/src/services/messagesExpire/index.js @@ -33,13 +33,12 @@ class MessagesExpire { for (const destinationClientId of destinationClientsIds) { const messageQueue = this.realm.getMessageQueueById(destinationClientId); const lastReadDiff = now - messageQueue.getLastReadAt(); - if (lastReadDiff < maxDiff) { + if (lastReadDiff < maxDiff) continue; - } const messages = messageQueue.getMessages(); for (const message of messages) { if (!seen[message.src]) { - this.messageHandler.handle(null, { + this.messageHandler.handle(undefined, { type: enums_1.MessageType.EXPIRE, src: message.dst, dst: message.src diff --git a/src/api/v1/calls/index.ts b/src/api/v1/calls/index.ts index f96aae6..ea42f8c 100644 --- a/src/api/v1/calls/index.ts +++ b/src/api/v1/calls/index.ts @@ -3,16 +3,20 @@ import { IMessageHandler } from "../../../messageHandler"; import { IMessage } from "../../../models/message"; import { IRealm } from "../../../models/realm"; -export default ({ realm, messageHandler }: { realm: IRealm, messageHandler: IMessageHandler }): express.Router => { +export default ({ realm, messageHandler }: { realm: IRealm, messageHandler: IMessageHandler; }): express.Router => { const app = express.Router(); const handle = (req: express.Request, res: express.Response, next: express.NextFunction): any => { const { id } = req.params; - if (!id) { return next(); } + if (!id) return next(); const client = realm.getClientById(id); + if (!client) { + throw new Error(`client not found:${id}`); + } + const { type, dst, payload } = req.body; const message: IMessage = { diff --git a/src/index.ts b/src/index.ts index 849e33f..7e4b7e9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -18,7 +18,7 @@ import { IWebSocketServer, WebSocketServer } from "./services/webSocketServer"; const init = ({ app, server, options }: { app: express.Express, server: Server, - options: IConfig + options: IConfig; }) => { const config = options; const realm: IRealm = new Realm(); @@ -125,7 +125,7 @@ function PeerServer(options: Optional = {}, callback?: (server: Server) let server: Server; if (newOptions.ssl && newOptions.ssl.key && newOptions.ssl.cert) { - server = https.createServer(options.ssl, app); + server = https.createServer(options.ssl!, app); // @ts-ignore delete newOptions.ssl; } else { @@ -135,11 +135,7 @@ function PeerServer(options: Optional = {}, callback?: (server: Server) const peerjs = ExpressPeerServer(server, newOptions); app.use(peerjs); - if (callback) { - server.listen(port, () => callback(server)); - } else { - server.listen(port); - } + server.listen(port, () => callback?.(server)); return peerjs; } diff --git a/src/messageHandler/handler.ts b/src/messageHandler/handler.ts index b265878..4c81fde 100644 --- a/src/messageHandler/handler.ts +++ b/src/messageHandler/handler.ts @@ -1,4 +1,4 @@ import { IClient } from "../models/client"; import { IMessage } from "../models/message"; -export type Handler = (client: IClient, message: IMessage) => boolean; +export type Handler = (client: IClient | undefined, message: IMessage) => boolean; diff --git a/src/messageHandler/handlers/heartbeat/index.ts b/src/messageHandler/handlers/heartbeat/index.ts index 6d8fcdf..43bf35e 100644 --- a/src/messageHandler/handlers/heartbeat/index.ts +++ b/src/messageHandler/handlers/heartbeat/index.ts @@ -1,7 +1,10 @@ import { IClient } from "../../../models/client"; -export const HeartbeatHandler = (client: IClient): boolean => { - const nowTime = new Date().getTime(); - client.setLastPing(nowTime); +export const HeartbeatHandler = (client: IClient | undefined): boolean => { + if (client) { + const nowTime = new Date().getTime(); + client.setLastPing(nowTime); + } + return true; }; diff --git a/src/messageHandler/handlers/transmission/index.ts b/src/messageHandler/handlers/transmission/index.ts index 7be3cb6..defa00f 100644 --- a/src/messageHandler/handlers/transmission/index.ts +++ b/src/messageHandler/handlers/transmission/index.ts @@ -3,8 +3,8 @@ import { IClient } from "../../../models/client"; import { IMessage } from "../../../models/message"; import { IRealm } from "../../../models/realm"; -export const TransmissionHandler = ({ realm }: { realm: IRealm }): (client: IClient, message: IMessage) => boolean => { - const handle = (client: IClient, message: IMessage) => { +export const TransmissionHandler = ({ realm }: { realm: IRealm; }): (client: IClient | undefined, message: IMessage) => boolean => { + const handle = (client: IClient | undefined, message: IMessage) => { const type = message.type; const srcId = message.src; const dstId = message.dst; @@ -13,11 +13,12 @@ export const TransmissionHandler = ({ realm }: { realm: IRealm }): (client: ICli // User is connected! if (destinationClient) { + const socket = destinationClient.getSocket(); try { - if (destinationClient.getSocket()) { + if (socket) { const data = JSON.stringify(message); - destinationClient.getSocket().send(data); + socket.send(data); } else { // Neither socket no res available. Peer dead? throw new Error("Peer dead"); @@ -26,8 +27,8 @@ export const TransmissionHandler = ({ realm }: { realm: IRealm }): (client: ICli // This happens when a peer disconnects without closing connections and // the associated WebSocket has not closed. // Tell other side to stop trying. - if (destinationClient.getSocket()) { - destinationClient.getSocket().close(); + if (socket) { + socket.close(); } else { realm.removeClientById(destinationClient.getId()); } diff --git a/src/messageHandler/index.ts b/src/messageHandler/index.ts index cb75920..de03c45 100644 --- a/src/messageHandler/index.ts +++ b/src/messageHandler/index.ts @@ -7,7 +7,7 @@ import { HeartbeatHandler, TransmissionHandler } from "./handlers"; import { IMessageHandlers, MessageHandlers } from "./messageHandlers"; export interface IMessageHandler { - handle(client: IClient, message: IMessage): boolean; + handle(client: IClient | undefined, message: IMessage): boolean; } export class MessageHandler implements IMessageHandler { @@ -17,7 +17,7 @@ export class MessageHandler implements IMessageHandler { const transmissionHandler: Handler = TransmissionHandler({ realm }); const heartbeatHandler: Handler = HeartbeatHandler; - const handleTransmission: Handler = (client: IClient, message: IMessage): boolean => { + const handleTransmission: Handler = (client: IClient | undefined, message: IMessage): boolean => { return transmissionHandler(client, { type: message.type, src: message.src, @@ -26,7 +26,7 @@ export class MessageHandler implements IMessageHandler { }); }; - const handleHeartbeat = (client: IClient, message: IMessage) => heartbeatHandler(client, message); + const handleHeartbeat = (client: IClient | undefined, message: IMessage) => heartbeatHandler(client, message); this.messageHandlers.registerHandler(MessageType.HEARTBEAT, handleHeartbeat); this.messageHandlers.registerHandler(MessageType.OFFER, handleTransmission); @@ -36,7 +36,7 @@ export class MessageHandler implements IMessageHandler { this.messageHandlers.registerHandler(MessageType.EXPIRE, handleTransmission); } - public handle(client: IClient, message: IMessage): boolean { + public handle(client: IClient | undefined, message: IMessage): boolean { return this.messageHandlers.handle(client, message); } } diff --git a/src/messageHandler/messageHandlers.ts b/src/messageHandler/messageHandlers.ts index 2a48cb4..4aa82d9 100644 --- a/src/messageHandler/messageHandlers.ts +++ b/src/messageHandler/messageHandlers.ts @@ -5,24 +5,24 @@ import { Handler } from "./handler"; export interface IMessageHandlers { registerHandler(messageType: MessageType, handler: Handler): void; - handle(client: IClient, message: IMessage): boolean; + handle(client: IClient | undefined, message: IMessage): boolean; } export class MessageHandlers implements IMessageHandlers { private readonly handlers: Map = new Map(); public registerHandler(messageType: MessageType, handler: Handler): void { - if (this.handlers.has(messageType)) { return; } + if (this.handlers.has(messageType)) return; this.handlers.set(messageType, handler); } - public handle(client: IClient, message: IMessage): boolean { + public handle(client: IClient | undefined, message: IMessage): boolean { const { type } = message; const handler = this.handlers.get(type); - if (!handler) { return false; } + if (!handler) return false; return handler(client, message); } diff --git a/src/models/client.ts b/src/models/client.ts index cd991a9..4dee3ca 100644 --- a/src/models/client.ts +++ b/src/models/client.ts @@ -7,7 +7,7 @@ export interface IClient { getSocket(): MyWebSocket | null; - setSocket(socket: MyWebSocket): void; + setSocket(socket: MyWebSocket | null): void; getLastPing(): number; @@ -19,10 +19,10 @@ export interface IClient { export class Client implements IClient { private readonly id: string; private readonly token: string; - private socket: MyWebSocket = null; + private socket: MyWebSocket | null = null; private lastPing: number = new Date().getTime(); - constructor({ id, token }: { id: string, token: string }) { + constructor({ id, token }: { id: string, token: string; }) { this.id = id; this.token = token; } @@ -39,7 +39,7 @@ export class Client implements IClient { return this.socket; } - public setSocket(socket: MyWebSocket): void { + public setSocket(socket: MyWebSocket | null): void { this.socket = socket; } @@ -52,6 +52,6 @@ export class Client implements IClient { } public send(data: any): void { - this.socket.send(JSON.stringify(data)); + this.socket?.send(JSON.stringify(data)); } } diff --git a/src/models/messageQueue.ts b/src/models/messageQueue.ts index 4c0e2ce..1b5a94c 100644 --- a/src/models/messageQueue.ts +++ b/src/models/messageQueue.ts @@ -25,7 +25,7 @@ export class MessageQueue implements IMessageQueue { public readMessage(): IMessage | null { if (this.messages.length > 0) { this.lastReadAt = new Date().getTime(); - return this.messages.shift(); + return this.messages.shift()!; } return null; diff --git a/src/models/realm.ts b/src/models/realm.ts index 7b3ce19..cd4d0c9 100644 --- a/src/models/realm.ts +++ b/src/models/realm.ts @@ -46,7 +46,7 @@ export class Realm implements IRealm { public removeClientById(id: string): boolean { const client = this.getClientById(id); - if (!client) { return false; } + if (!client) return false; this.clients.delete(id); @@ -62,7 +62,7 @@ export class Realm implements IRealm { this.messageQueues.set(id, new MessageQueue()); } - this.getMessageQueueById(id).addMessage(message); + this.getMessageQueueById(id)!.addMessage(message); } public clearMessageQueue(id: string): void { diff --git a/src/services/checkBrokenConnections/index.ts b/src/services/checkBrokenConnections/index.ts index 06f600b..9ef3c4e 100644 --- a/src/services/checkBrokenConnections/index.ts +++ b/src/services/checkBrokenConnections/index.ts @@ -9,7 +9,7 @@ type CustomConfig = Pick; export class CheckBrokenConnections { public readonly checkInterval: number; - private timeoutId: NodeJS.Timeout; + private timeoutId: NodeJS.Timeout | null = null; private readonly realm: IRealm; private readonly config: CustomConfig; private readonly onClose?: (client: IClient) => void; @@ -18,7 +18,7 @@ export class CheckBrokenConnections { realm: IRealm, config: CustomConfig, checkInterval?: number, - onClose?: (client: IClient) => void + onClose?: (client: IClient) => void; }) { this.realm = realm; this.config = config; @@ -54,23 +54,20 @@ export class CheckBrokenConnections { const { alive_timeout: aliveTimeout } = this.config; for (const clientId of clientsIds) { - const client = this.realm.getClientById(clientId); + const client = this.realm.getClientById(clientId)!; const timeSinceLastPing = now - client.getLastPing(); - if (timeSinceLastPing < aliveTimeout) { continue; } + if (timeSinceLastPing < aliveTimeout) continue; try { - if (client.getSocket()) { - client.getSocket().close(); - } - } catch (e) { - // @ts-nocheck + client.getSocket()?.close(); } finally { this.realm.clearMessageQueue(clientId); this.realm.removeClientById(clientId); + client.setSocket(null); - if (this.onClose) { this.onClose(client); } + this.onClose?.(client); } } } diff --git a/src/services/messagesExpire/index.ts b/src/services/messagesExpire/index.ts index 4d8ebe7..9c3722b 100644 --- a/src/services/messagesExpire/index.ts +++ b/src/services/messagesExpire/index.ts @@ -13,7 +13,7 @@ export class MessagesExpire implements IMessagesExpire { private readonly config: IConfig; private readonly messageHandler: IMessageHandler; - private timeoutId: NodeJS.Timeout = null; + private timeoutId: NodeJS.Timeout | null = null; constructor({ realm, config, messageHandler }: { realm: IRealm; @@ -53,19 +53,19 @@ export class MessagesExpire implements IMessagesExpire { const now = new Date().getTime(); const maxDiff = this.config.expire_timeout; - const seen: { [id: string]: boolean } = {}; + const seen: Record = {}; for (const destinationClientId of destinationClientsIds) { - const messageQueue = this.realm.getMessageQueueById(destinationClientId); + const messageQueue = this.realm.getMessageQueueById(destinationClientId)!; const lastReadDiff = now - messageQueue.getLastReadAt(); - if (lastReadDiff < maxDiff) { continue; } + if (lastReadDiff < maxDiff) continue; const messages = messageQueue.getMessages(); for (const message of messages) { if (!seen[message.src]) { - this.messageHandler.handle(null, { + this.messageHandler.handle(undefined, { type: MessageType.EXPIRE, src: message.dst, dst: message.src diff --git a/src/services/webSocketServer/index.ts b/src/services/webSocketServer/index.ts index ae0ddf2..d345a31 100644 --- a/src/services/webSocketServer/index.ts +++ b/src/services/webSocketServer/index.ts @@ -25,7 +25,7 @@ export class WebSocketServer extends EventEmitter implements IWebSocketServer { private readonly config: IConfig; private readonly webSocketServer: WebSocketLib.Server; - constructor({ server, realm, config }: { server: any, realm: IRealm, config: IConfig }) { + constructor({ server, realm, config }: { server: any, realm: IRealm, config: IConfig; }) { super(); this.setMaxListeners(0); this.realm = realm; @@ -41,7 +41,7 @@ export class WebSocketServer extends EventEmitter implements IWebSocketServer { } private _onSocketConnection(socket: MyWebSocket, req: IncomingMessage): void { - const { query = {} } = url.parse(req.url, true); + const { query = {} } = url.parse(req.url!, true); const { id, token, key }: IAuthParams = query; diff --git a/tsconfig.json b/tsconfig.json index 65ed033..3c7af7a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,6 +5,7 @@ ], "target": "es2016", "module": "commonjs", + "strict": true, "esModuleInterop": true, "downlevelIteration": true, "moduleResolution": "node", @@ -16,6 +17,9 @@ "sourceMap": false, "outDir": "dist" }, + "include": [ + "./src/**/*", + ], "exclude": [ "test", "bin",