{"version":3,"sources":["../../src/network/Connection.ts"],"sourcesContent":["import { io } from \"socket.io-client\";\nimport { Socket } from 'socket.io';\nimport log from '../utils/log.js';\nimport type Listener from './types/Listener.js';\n\nclass Connection {\n    /*\n     * this class is manager for the socket instance\n     * it takes either a socket or a host and port to create the socket\n     * if it takes the host and port it will consider that connection is a server\n     * if it takes a socket it will consider that connection is a client\n     *\n     * it manages conenction, the listeners and the available emitters */\n    private socket: Socket | any;\n    private request_id: number = 0;\n    // this node information\n    public name?: string;\n    public id?: string;\n    public listeners: Listener[] = [];\n    public type: 'client' | 'server';\n    public host?: string;\n    public port?: number;\n    // is connected or not\n    public isConnected: boolean;\n    // ot target of the socket\n    public socketId: string;\n    public targetType: 'client' | 'server';\n    public targetName?: string;\n    public targetId?: string;\n    public targetListeners: Listener[] = [];\n    public targetHost?: string;\n    public targetPort?: number;\n    // callbacks\n    private onConnectCallback: Function;\n    public onDisconnectCallback: Function;\n    public onSetListenersCallback: Function;\n\n    /*\n     * @param Node: Node\n     * @param socket: Socket\n     * @param host: string\n     * @param port: number\n     * @param id: string\n     * @param name: string\n     * */\n\n    constructor({ socket, host, port, id, name, listeners, timeout,\n                onConnect, onDisconnect, onSetListeners } : {\n        id?: string, socket?: Socket, host?: string,\n        port?: number, name?: string, listeners?: Listener[],\n        timeout?: number, onConnect?: Function, onDisconnect?: Function,\n        onSetListeners?: Function\n    }) {\n        // callbacks\n        this.onConnectCallback = onConnect || (() => {});\n        this.onDisconnectCallback = onDisconnect || (() => {});\n        this.onSetListenersCallback = onSetListeners || (() => {});\n        // set listeners\n        if(listeners) this.listeners = listeners;\n        // if get a socket to connect to the server\n        if (socket && name) {\n            this.type = 'server';\n            this.name = name;\n            this.targetType = 'client';\n            // the socket\n            this.socket = socket;\n            // get the id of client\n            this.targetId = socket.handshake.auth.id;\n            //log('[Connection][server] targetId: ', this.targetId)\n            // since we are already getting the socket\n            this.isConnected = true;\n            // if get a host and port to connect to the server\n        } else if (host && port && id) {\n            this.type = 'client';\n            this.targetType = 'server';\n            // use the id\n            this.id = id;\n            this.socket = io(`ws://${host}:${port}`, {\n                auth: { id },\n                timeout: timeout || 1000 * 60 // 1 minute\n            });\n            // since we are not connected yet\n            this.isConnected = false;\n        } else\n            throw new Error('Connection must have either a socket and a name or a host and port');\n        // set the socket id\n        this.socketId = this.socket.id;\n        // initialize the listeners\n        this.initilaizeListeners()\n    }\n\n    private initilaizeListeners(): void {\n        /* this function inizializes the default listeners for the socket */\n        // set the object listeners \n        this.listeners.forEach( l => {\n            this.socket.removeAllListeners(l.event);\n            this.socket.on(l.event, this.respond(l.event, async (parameters:any) => {\n                //log(`[${this.id}] [Connection][initilaizeListeners] got event: ${l.event} from ${this.targetName}: `, parameters)\n                return await l.callback(parameters);\n            }));\n        });\n        // if target is asking for connections\n        this.socket.on(\"_listeners\", this.respond(\"_listeners\", () => this.getListeners()));\n        // if the target is sending a their listeners\n        this.socket.on(\"_set_listeners\", this.respond(\"_set_listeners\", (listeners: string[]) => {\n            //log(`[${this.id}] [Connection][Node] got liteners from ${this.targetName}: `, listeners)\n            this.targetListeners =\n                listeners.map(event => ({ event, callback: () => {} }));\n            this.onSetListenersCallback(this.targetListeners);\n            return 'ok';\n        }));\n        // if target is asking for name\n        this.socket.on(\"_name\", this.respond(\"_name\", () => this.name));\n        // if target is asking for id\n        this.socket.on(\"_id\", () => this.id);\n        // on connected\n        this.socket.on(\"connect\", async () => {\n            //log(`[connection][${this.socket.id}] is connected, querying target name and listeners:`)\n            // ask for listeners\n            this.targetName = await this.queryTargetName();\n            this.targetListeners = await this.queryTargetListeners();\n            //log(`[connection][${this.socket.id}] target name: ${this.targetName}, target listeners: ${this.targetListeners}`)\n            this.isConnected = true;\n            this.onConnectCallback(this);\n        });\n        // if it disconnects\n        this.socket.on(\"reconnect\", async (attempt: number) => {\n            //log(`[connection][${this.socket.id}] is reconnected, attempt: ${attempt}`)\n            this.targetName = await this.queryTargetName();\n            this.targetListeners = await this.queryTargetListeners();\n            this.isConnected = true;\n            this.onConnectCallback(this);\n        });\n        // if it disconnects\n        this.socket.on(\"diconnect\", () => {\n            //log(`[connection][${this.socket.id}] is disconnected`)\n            this.isConnected = false;\n            this.onDisconnectCallback(this);\n        });\n    }\n\n    public async connected(): Promise<boolean> {\n        return new Promise((resolve, reject) => {\n            let interval: NodeJS.Timeout;\n            let timeout: NodeJS.Timeout\n            // set interval to check for connection\n            interval = setInterval(() => {\n                if(this.isConnected) {\n                    clearInterval(interval);\n                    clearTimeout(timeout);\n                    resolve(true);\n                }\n            }, 100); // 100 ms\n            // set timeout to reject if no connection\n            timeout = setTimeout(() => {\n                clearInterval(interval);\n                reject(false);\n            }, 1000 * 60 ); // 1 minute\n        })\n    }\n\n\n    public getType(){\n        return this.type;\n    }\n\n    public on(event: string, callback: Function): void {\n        this.socket.on(event, callback);\n    }\n\n    public emit(event: string, data: any): void {\n        this.socket.emit(event, data);\n    }\n\n    public getName(): string | undefined {\n        return this.name;\n    }\n\n    // this is the id of the conenction?\n    public getId(): string | undefined {\n        return this.id;\n    }\n\n    public getTargetName(): string | undefined {\n        return this.targetName;\n    }\n\n    // this is the id of the target client\n    public getTargetId(): string | undefined {\n        return this.targetId;\n    }\n\n    public async setListeners(listeners: Listener[]): Promise<void> {\n        // set the listeners on the socket\n        listeners.forEach( l => {\n            this.listeners.push(l);\n            // remove the listener if it exists\n            this.socket.removeAllListeners(l.event);\n            // add new listener\n            this.socket.on(l.event, this.respond(l.event, async (parameters:any) => {\n                // run the callback defined in the listner\n                return await l.callback(parameters);\n            }));    \n        });\n        // update the listeners on the target\n        if(this.type === 'server'){\n            //let response = \n            await this.query('_set_listeners', listeners.map(listener => listener.event));\n            //if(response === 'ok') log('[Connection]<setListeners> listeners set successfully')\n        }\n    }\n\n    public addListeners(listeners: Listener[]): void {\n        // make sure we are not adding the same listener\n        const eventMap = new Map(this.listeners.map(l => [l.event, l]));\n        // add the listeners\n        listeners.forEach( l => eventMap.set(l.event, l) );\n        // set the listeners in the connection\n        this.listeners = Array.from(eventMap.values());\n        // set the listeners on the socket\n        this.setListeners(this.listeners);\n    }\n\n    public getTargetListeners(): Listener[] {\n        return this.targetListeners;\n    }\n\n    public onSetListeners(callback: Function): void {\n        this.onSetListenersCallback = callback;\n    }\n\n    public onConnect(callback: Function): void {\n        this.onConnectCallback = callback;\n    }\n\n    public onDisconnect(callback: Function): void {\n        this.onDisconnectCallback = callback;\n    }\n\n    private queryTargetListeners(): Promise<Listener[]> {\n        // query the target listeners\n        return this.query('_listeners');\n    }\n\n    private queryTargetName(): Promise<string> {\n        // query the target name\n        return this.query('_name');\n    }\n\n    // this function need to be awaited\n    public query(event: string, data?: any): Promise<any> {\n        /* this function makes the query to the socket and waits for the response */\n        return new Promise((resolve, reject) => {\n            // set a time out\n            let timeout = setTimeout( () => { reject('timeout') }, 1000 * 60); // 1 minute\n            // get request id\n            let request_id = ++this.request_id;\n            if (this.request_id >= Number.MAX_SAFE_INTEGER - 1) this.request_id = 0;\n            // send the query\n            this.socket.emit(event, {data, request_id: request_id});\n            this.socket.on(event + `_${request_id}_response`, (response: any) => {\n                //log('[Connection][Query] got response from ', this.targetType, 'event: ', event, 'response: ', response)\n                // clear the timeout\n                clearTimeout(timeout);\n                // clear the listener\n                this.socket.removeAllListeners(event + `_${request_id}_response`);\n                // resolve the response\n                resolve(response);\n            });\n        });\n    }\n\n    public send = this.query;\n\n    private respond(event: string, callback: Function) {\n        /* this is a wrapper function to respond to a query */\n        return async (parameters: any) => {\n            let data = parameters.data;\n            let request_id = parameters.request_id;\n            let response = await callback(data);\n            this.socket.emit(event + `_${request_id}_response`, response);\n        }\n    }\n\n    public getListeners(): any[] {\n        if(this.type === 'server')\n            return this.listeners;\n        else if(this.type === 'client')\n            return this.socket._callbacks;\n        else\n            throw new Error('Connection type not recognized');\n    }\n\n    public close(): void {\n        this.socket.disconnect();\n    }\n\n}\n\nexport default Connection;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAmB;AAKnB,MAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyCb,YAAY;AAAA,IAAE;AAAA,IAAQ;AAAA,IAAM;AAAA,IAAM;AAAA,IAAI;AAAA,IAAM;AAAA,IAAW;AAAA,IAC3C;AAAA,IAAW;AAAA,IAAc;AAAA,EAAe,GAKjD;AAvCH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAAQ;AACR,wBAAQ,cAAqB;AAE7B;AAAA,wBAAO;AACP,wBAAO;AACP,wBAAO,aAAwB,CAAC;AAChC,wBAAO;AACP,wBAAO;AACP,wBAAO;AAEP;AAAA,wBAAO;AAEP;AAAA,wBAAO;AACP,wBAAO;AACP,wBAAO;AACP,wBAAO;AACP,wBAAO,mBAA8B,CAAC;AACtC,wBAAO;AACP,wBAAO;AAEP;AAAA,wBAAQ;AACR,wBAAO;AACP,wBAAO;AA6OP,wBAAO,QAAO,KAAK;AA1Nf,SAAK,oBAAoB,cAAc,MAAM;AAAA,IAAC;AAC9C,SAAK,uBAAuB,iBAAiB,MAAM;AAAA,IAAC;AACpD,SAAK,yBAAyB,mBAAmB,MAAM;AAAA,IAAC;AAExD,QAAG,UAAW,MAAK,YAAY;AAE/B,QAAI,UAAU,MAAM;AAChB,WAAK,OAAO;AACZ,WAAK,OAAO;AACZ,WAAK,aAAa;AAElB,WAAK,SAAS;AAEd,WAAK,WAAW,OAAO,UAAU,KAAK;AAGtC,WAAK,cAAc;AAAA,IAEvB,WAAW,QAAQ,QAAQ,IAAI;AAC3B,WAAK,OAAO;AACZ,WAAK,aAAa;AAElB,WAAK,KAAK;AACV,WAAK,aAAS,kBAAG,QAAQ,IAAI,IAAI,IAAI,IAAI;AAAA,QACrC,MAAM,EAAE,GAAG;AAAA,QACX,SAAS,WAAW,MAAO;AAAA;AAAA,MAC/B,CAAC;AAED,WAAK,cAAc;AAAA,IACvB;AACI,YAAM,IAAI,MAAM,oEAAoE;AAExF,SAAK,WAAW,KAAK,OAAO;AAE5B,SAAK,oBAAoB;AAAA,EAC7B;AAAA,EAEQ,sBAA4B;AAGhC,SAAK,UAAU,QAAS,OAAK;AACzB,WAAK,OAAO,mBAAmB,EAAE,KAAK;AACtC,WAAK,OAAO,GAAG,EAAE,OAAO,KAAK,QAAQ,EAAE,OAAO,OAAO,eAAmB;AAEpE,eAAO,MAAM,EAAE,SAAS,UAAU;AAAA,MACtC,CAAC,CAAC;AAAA,IACN,CAAC;AAED,SAAK,OAAO,GAAG,cAAc,KAAK,QAAQ,cAAc,MAAM,KAAK,aAAa,CAAC,CAAC;AAElF,SAAK,OAAO,GAAG,kBAAkB,KAAK,QAAQ,kBAAkB,CAAC,cAAwB;AAErF,WAAK,kBACD,UAAU,IAAI,YAAU,EAAE,OAAO,UAAU,MAAM;AAAA,MAAC,EAAE,EAAE;AAC1D,WAAK,uBAAuB,KAAK,eAAe;AAChD,aAAO;AAAA,IACX,CAAC,CAAC;AAEF,SAAK,OAAO,GAAG,SAAS,KAAK,QAAQ,SAAS,MAAM,KAAK,IAAI,CAAC;AAE9D,SAAK,OAAO,GAAG,OAAO,MAAM,KAAK,EAAE;AAEnC,SAAK,OAAO,GAAG,WAAW,YAAY;AAGlC,WAAK,aAAa,MAAM,KAAK,gBAAgB;AAC7C,WAAK,kBAAkB,MAAM,KAAK,qBAAqB;AAEvD,WAAK,cAAc;AACnB,WAAK,kBAAkB,IAAI;AAAA,IAC/B,CAAC;AAED,SAAK,OAAO,GAAG,aAAa,OAAO,YAAoB;AAEnD,WAAK,aAAa,MAAM,KAAK,gBAAgB;AAC7C,WAAK,kBAAkB,MAAM,KAAK,qBAAqB;AACvD,WAAK,cAAc;AACnB,WAAK,kBAAkB,IAAI;AAAA,IAC/B,CAAC;AAED,SAAK,OAAO,GAAG,aAAa,MAAM;AAE9B,WAAK,cAAc;AACnB,WAAK,qBAAqB,IAAI;AAAA,IAClC,CAAC;AAAA,EACL;AAAA,EAEA,MAAa,YAA8B;AACvC,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACpC,UAAI;AACJ,UAAI;AAEJ,iBAAW,YAAY,MAAM;AACzB,YAAG,KAAK,aAAa;AACjB,wBAAc,QAAQ;AACtB,uBAAa,OAAO;AACpB,kBAAQ,IAAI;AAAA,QAChB;AAAA,MACJ,GAAG,GAAG;AAEN,gBAAU,WAAW,MAAM;AACvB,sBAAc,QAAQ;AACtB,eAAO,KAAK;AAAA,MAChB,GAAG,MAAO,EAAG;AAAA,IACjB,CAAC;AAAA,EACL;AAAA,EAGO,UAAS;AACZ,WAAO,KAAK;AAAA,EAChB;AAAA,EAEO,GAAG,OAAe,UAA0B;AAC/C,SAAK,OAAO,GAAG,OAAO,QAAQ;AAAA,EAClC;AAAA,EAEO,KAAK,OAAe,MAAiB;AACxC,SAAK,OAAO,KAAK,OAAO,IAAI;AAAA,EAChC;AAAA,EAEO,UAA8B;AACjC,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA,EAGO,QAA4B;AAC/B,WAAO,KAAK;AAAA,EAChB;AAAA,EAEO,gBAAoC;AACvC,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA,EAGO,cAAkC;AACrC,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,MAAa,aAAa,WAAsC;AAE5D,cAAU,QAAS,OAAK;AACpB,WAAK,UAAU,KAAK,CAAC;AAErB,WAAK,OAAO,mBAAmB,EAAE,KAAK;AAEtC,WAAK,OAAO,GAAG,EAAE,OAAO,KAAK,QAAQ,EAAE,OAAO,OAAO,eAAmB;AAEpE,eAAO,MAAM,EAAE,SAAS,UAAU;AAAA,MACtC,CAAC,CAAC;AAAA,IACN,CAAC;AAED,QAAG,KAAK,SAAS,UAAS;AAEtB,YAAM,KAAK,MAAM,kBAAkB,UAAU,IAAI,cAAY,SAAS,KAAK,CAAC;AAAA,IAEhF;AAAA,EACJ;AAAA,EAEO,aAAa,WAA6B;AAE7C,UAAM,WAAW,IAAI,IAAI,KAAK,UAAU,IAAI,OAAK,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAE9D,cAAU,QAAS,OAAK,SAAS,IAAI,EAAE,OAAO,CAAC,CAAE;AAEjD,SAAK,YAAY,MAAM,KAAK,SAAS,OAAO,CAAC;AAE7C,SAAK,aAAa,KAAK,SAAS;AAAA,EACpC;AAAA,EAEO,qBAAiC;AACpC,WAAO,KAAK;AAAA,EAChB;AAAA,EAEO,eAAe,UAA0B;AAC5C,SAAK,yBAAyB;AAAA,EAClC;AAAA,EAEO,UAAU,UAA0B;AACvC,SAAK,oBAAoB;AAAA,EAC7B;AAAA,EAEO,aAAa,UAA0B;AAC1C,SAAK,uBAAuB;AAAA,EAChC;AAAA,EAEQ,uBAA4C;AAEhD,WAAO,KAAK,MAAM,YAAY;AAAA,EAClC;AAAA,EAEQ,kBAAmC;AAEvC,WAAO,KAAK,MAAM,OAAO;AAAA,EAC7B;AAAA;AAAA,EAGO,MAAM,OAAe,MAA0B;AAElD,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AAEpC,UAAI,UAAU,WAAY,MAAM;AAAE,eAAO,SAAS;AAAA,MAAE,GAAG,MAAO,EAAE;AAEhE,UAAI,aAAa,EAAE,KAAK;AACxB,UAAI,KAAK,cAAc,OAAO,mBAAmB,EAAG,MAAK,aAAa;AAEtE,WAAK,OAAO,KAAK,OAAO,EAAC,MAAM,WAAsB,CAAC;AACtD,WAAK,OAAO,GAAG,QAAQ,IAAI,UAAU,aAAa,CAAC,aAAkB;AAGjE,qBAAa,OAAO;AAEpB,aAAK,OAAO,mBAAmB,QAAQ,IAAI,UAAU,WAAW;AAEhE,gBAAQ,QAAQ;AAAA,MACpB,CAAC;AAAA,IACL,CAAC;AAAA,EACL;AAAA,EAIQ,QAAQ,OAAe,UAAoB;AAE/C,WAAO,OAAO,eAAoB;AAC9B,UAAI,OAAO,WAAW;AACtB,UAAI,aAAa,WAAW;AAC5B,UAAI,WAAW,MAAM,SAAS,IAAI;AAClC,WAAK,OAAO,KAAK,QAAQ,IAAI,UAAU,aAAa,QAAQ;AAAA,IAChE;AAAA,EACJ;AAAA,EAEO,eAAsB;AACzB,QAAG,KAAK,SAAS;AACb,aAAO,KAAK;AAAA,aACR,KAAK,SAAS;AAClB,aAAO,KAAK,OAAO;AAAA;AAEnB,YAAM,IAAI,MAAM,gCAAgC;AAAA,EACxD;AAAA,EAEO,QAAc;AACjB,SAAK,OAAO,WAAW;AAAA,EAC3B;AAEJ;AAEA,IAAO,qBAAQ;","names":[]}