insite-ws 1.0.353 → 1.0.355
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.js +2 -0
- package/dist/client.js.map +7 -0
- package/dist/server.js +2 -0
- package/dist/server.js.map +7 -0
- package/package.json +6 -4
- package/lib/client/WebSocket.js +0 -223
- package/lib/client/index.js +0 -1
- package/lib/common.js +0 -2
- package/lib/extendEventEmitter.js +0 -46
- package/lib/server/WebSocketServer.js +0 -121
- package/lib/server/WebSocketServerClient.js +0 -29
- package/lib/server/index.js +0 -1
- package/lib/server/symbols.js +0 -3
package/dist/client.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var W=Object.defineProperty;var H=(e,s,t)=>s in e?W(e,s,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[s]=t;var u=(e,s,t)=>(H(e,typeof s!="symbol"?s+"":s,t),t),g=(e,s,t)=>{if(!s.has(e))throw TypeError("Cannot "+t)};var i=(e,s,t)=>(g(e,s,"read from private field"),t?t.call(e):s.get(e)),o=(e,s,t)=>{if(s.has(e))throw TypeError("Cannot add the same private member more than once");s instanceof WeakSet?s.add(e):s.set(e,t)},h=(e,s,t,n)=>(g(e,s,"write to private field"),n?n.call(e,t):s.set(e,t),t);import{debounce as D,noop as E}from"@nesvet/n";import G from"eventemitter3";function L(...e){for(let s of this.listenerHandlers)if(s.call(this,!0,...e)!==void 0)return;this.directOn(...e)}function _(...e){for(let s of this.listenerHandlers)if(s.call(this,!0,...e)!==void 0)return;this.directOnce(...e)}function T(...e){for(let s of this.listenerHandlers)if(s.call(this,!1,...e)!==void 0)return;this.directOff(...e)}function N(e){e.directOn=e.on,e.directOnce=e.once,e.directOff=e.off,e.listenerHandlers=new Set,e.on=L,e.once=_,e.off=T}var I=2e3,P=0,a,l,r,p,k,b,f,w,d,m,C=class extends G{constructor(t,n={}){super();u(this,"webSocket",null);o(this,a,D(function(){this.isOpen&&this.webSocket.close()},65e3));o(this,l,void 0);o(this,r,void 0);u(this,"isChanged",!1);o(this,p,()=>{i(this,l).call(this),h(this,l,void 0),h(this,r,void 0),this.emit("open"),i(this,a).call(this)});o(this,k,({data:t})=>{if(i(this,a).call(this),t)try{let[n,...c]=JSON.parse(t);this.emit("message",n,...c),this.emit(`message:${n}`,...c)}catch(n){i(this,b).call(this,n)}else this.webSocket.send("")});o(this,b,t=>{t instanceof Event&&(t=void 0),i(this,r)&&(i(this,r).call(this,t),h(this,l,void 0),h(this,r,void 0)),this.emit("error",t)});o(this,f,void 0);o(this,w,t=>{i(this,a).clear(),this.emit("close",t),this.autoReconnect&&![1002,3500,4e3].includes(t.code)&&h(this,f,setTimeout(()=>this.open().catch(E),I))});u(this,"connect",this.open);u(this,"disconnect",this.close);o(this,d,[]);o(this,m,()=>{for(let t of i(this,d))this.webSocket.send(t);i(this,d).length=0});N(this),this.url=t;let{name:c=P++,protocols:v,immediately:x=!0,autoReconnect:y=!0,on:S}=n;if(this.name=c,this.protocols=v,this.autoReconnect=y,S)for(let O in S)S[O]&&this.on(O,S[O]);this.url&&x&&this.open().catch(E)}get isConnecting(){return this.webSocket?this.webSocket.readyState===this.webSocket.CONNECTING:null}get isOpen(){return this.webSocket?this.webSocket.readyState===this.webSocket.OPEN:null}get isClosing(){return this.webSocket?this.webSocket.readyState===this.webSocket.CLOSING:null}get isClosed(){return this.webSocket?this.webSocket.readyState===this.webSocket.CLOSED:null}open(t={}){return clearTimeout(i(this,f)),this.close(4e3,"reopen").then(()=>(t.url&&(this.url=t.url),t.protocols&&(this.protocols=t.protocols),new Promise((n,c)=>{h(this,l,n),h(this,r,c),this.webSocket&&(this.isChanged=this.webSocket._url!==this.url,this.isChanged&&this.emit("server-change")),this.webSocket=new WebSocket(this.url,this.protocols),this.webSocket._url=this.url,this.emit("connecting"),this.send=this.webSocket.send.bind(this.webSocket),this.webSocket.addEventListener("open",i(this,p)),this.webSocket.addEventListener("message",i(this,k)),this.webSocket.addEventListener("error",i(this,b)),this.webSocket.addEventListener("close",i(this,w))})))}close(t=3500,n="manual"){return clearTimeout(i(this,f)),new Promise(c=>{this.isConnecting||this.isOpen?(this.webSocket.addEventListener("close",c),this.webSocket.close(t,n)):c()})}sendMessage(...t){let n=JSON.stringify(t);this.isOpen?this.webSocket.send(n):(i(this,d).length||this.once("open",i(this,m)),i(this,d).push(n))}};a=new WeakMap,l=new WeakMap,r=new WeakMap,p=new WeakMap,k=new WeakMap,b=new WeakMap,f=new WeakMap,w=new WeakMap,d=new WeakMap,m=new WeakMap;export{C as WebSocket};
|
|
2
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/client/WebSocket.js", "../src/extendEventEmitter.js"],
|
|
4
|
+
"sourcesContent": ["import { debounce, noop } from \"@nesvet/n\";\nimport EventEmitter from \"eventemitter3\";\nimport { heartbeatGap, heartbeatInterval } from \"../common\";\nimport { extendEventEmitter } from \"../extendEventEmitter\";\n\n\nconst reconnectTimeout = 2000;\n\nlet i = 0;\n\n\nclass InSiteWebSocket extends EventEmitter {\n\tconstructor(url, options = {}) {\n\t\tsuper();\n\t\t\n\t\textendEventEmitter(this);\n\t\t\n\t\tthis.url = url;\n\t\t\n\t\tconst {\n\t\t\tname = i++,\n\t\t\tprotocols,\n\t\t\timmediately = true,\n\t\t\tautoReconnect = true,\n\t\t\ton\n\t\t} = options;\n\t\t\n\t\tthis.name = name;\n\t\t\n\t\tthis.protocols = protocols;\n\t\t\n\t\tthis.autoReconnect = autoReconnect;\n\t\t\n\t\tif (on)\n\t\t\tfor (const eventName in on)\n\t\t\t\tif (on[eventName])\n\t\t\t\t\tthis.on(eventName, on[eventName]);\n\t\t\n\t\tif (this.url && immediately)\n\t\t\tthis.open().catch(noop);\n\t\t\n\t}\n\t\n\twebSocket = null;\n\t\n\t#defib = debounce(function () {\n\t\t\n\t\tif (this.isOpen) {\n\t\t\tif (process.env.NODE_ENV === \"development\")\n\t\t\t\tconsole.info(`WebSocket ${this.name} has no heartbeat - going offline`);\n\t\t\t\n\t\t\tthis.webSocket.close();\n\t\t}\n\t\t\n\t}, heartbeatInterval + heartbeatGap);\n\t\n\t#openResolve;\n\t#openReject;\n\t\n\tget isConnecting() {\n\t\treturn this.webSocket ? this.webSocket.readyState === this.webSocket.CONNECTING : null;\n\t}\n\t\n\tget isOpen() {\n\t\treturn this.webSocket ? this.webSocket.readyState === this.webSocket.OPEN : null;\n\t}\n\t\n\tget isClosing() {\n\t\treturn this.webSocket ? this.webSocket.readyState === this.webSocket.CLOSING : null;\n\t}\n\t\n\tget isClosed() {\n\t\treturn this.webSocket ? this.webSocket.readyState === this.webSocket.CLOSED : null;\n\t}\n\t\n\tisChanged = false;\n\t\n\t#handleWebSocketOpen = () => {\n\t\t\n\t\tthis.#openResolve();\n\t\tthis.#openResolve = undefined;\n\t\tthis.#openReject = undefined;\n\t\t\n\t\tthis.emit(\"open\");\n\t\t\n\t\tthis.#defib();\n\t\t\n\t};\n\t\n\t#handleWebSocketMessage = ({ data: message }) => {\n\t\t\n\t\tthis.#defib();\n\t\t\n\t\tif (message)\n\t\t\ttry {\n\t\t\t\tconst [ kind, ...rest ] = JSON.parse(message);\n\t\t\t\t\n\t\t\t\tthis.emit(\"message\", kind, ...rest);\n\t\t\t\tthis.emit(`message:${kind}`, ...rest);\n\t\t\t} catch (error) {\n\t\t\t\tthis.#handleWebSocketError(error);\n\t\t\t}\n\t\t else\n\t\t\tthis.webSocket.send(\"\");\n\t\t\n\t};\n\t\n\t#handleWebSocketError = error => {\n\t\tif (error instanceof Event)\n\t\t\terror = undefined;\n\t\t\n\t\tif (this.#openReject) {\n\t\t\tthis.#openReject(error);\n\t\t\tthis.#openResolve = undefined;\n\t\t\tthis.#openReject = undefined;\n\t\t}\n\t\t\n\t\tthis.emit(\"error\", error);\n\t\t\n\t};\n\t\n\t#reconnectTimeout;\n\t\n\t#handleWebSocketClose = event => {\n\t\t\n\t\tif (process.env.NODE_ENV === \"development\")\n\t\t\tconsole.info(`WebSocket ${this.name} is closed with code ${event.code} and reason \"${event.reason}\"`);\n\t\t\n\t\tthis.#defib.clear();\n\t\t\n\t\tthis.emit(\"close\", event);\n\t\t\n\t\tif (this.autoReconnect && ![ 1002, 3500, 4000 ].includes(event.code)) {\n\t\t\tif (process.env.NODE_ENV === \"development\")\n\t\t\t\tconsole.info(`WebSocket ${this.name} will try to reconnect in 2 sec\u2026`);\n\t\t\t\n\t\t\tthis.#reconnectTimeout = setTimeout(() => this.open().catch(noop), reconnectTimeout);\n\t\t}\n\t\t\n\t};\n\t\n\topen(options = {}) {\n\t\t\n\t\tclearTimeout(this.#reconnectTimeout);\n\t\t\n\t\treturn this.close(4000, \"reopen\").then(() => {\n\t\t\t\n\t\t\tif (options.url)\n\t\t\t\tthis.url = options.url;\n\t\t\t\n\t\t\tif (options.protocols)\n\t\t\t\tthis.protocols = options.protocols;\n\t\t\t\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tthis.#openResolve = resolve;\n\t\t\t\tthis.#openReject = reject;\n\t\t\t\t\n\t\t\t\tif (this.webSocket) {\n\t\t\t\t\tthis.isChanged = this.webSocket._url !== this.url;\n\t\t\t\t\tif (this.isChanged)\n\t\t\t\t\t\tthis.emit(\"server-change\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.webSocket = new WebSocket(this.url, this.protocols);\n\t\t\t\tthis.webSocket._url = this.url;\n\t\t\t\t\n\t\t\t\tthis.emit(\"connecting\");\n\t\t\t\t\n\t\t\t\tthis.send = this.webSocket.send.bind(this.webSocket);\n\t\t\t\t\n\t\t\t\tthis.webSocket.addEventListener(\"open\", this.#handleWebSocketOpen);\n\t\t\t\tthis.webSocket.addEventListener(\"message\", this.#handleWebSocketMessage);\n\t\t\t\tthis.webSocket.addEventListener(\"error\", this.#handleWebSocketError);\n\t\t\t\tthis.webSocket.addEventListener(\"close\", this.#handleWebSocketClose);\n\t\t\t\t\n\t\t\t});\n\t\t});\n\t}\n\t\n\tconnect = this.open;\n\t\n\tclose(code = 3500, reason = \"manual\") {\n\t\t\n\t\tclearTimeout(this.#reconnectTimeout);\n\t\t\n\t\treturn new Promise(resolve => {\n\t\t\tif (this.isConnecting || this.isOpen) {\n\t\t\t\tthis.webSocket.addEventListener(\"close\", resolve);\n\t\t\t\tthis.webSocket.close(code, reason);\n\t\t\t} else\n\t\t\t\tresolve();\n\t\t\t\n\t\t});\n\t}\n\t\n\tdisconnect = this.close;\n\t\n\t#queue = [];\n\t\n\t#releaseQueue = () => {\n\t\t\n\t\tfor (const message of this.#queue)\n\t\t\tthis.webSocket.send(message);\n\t\t\n\t\tthis.#queue.length = 0;\n\t\t\n\t};\n\t\n\tsendMessage(...args) {\n\t\tconst message = JSON.stringify(args);\n\t\t\n\t\tif (this.isOpen)\n\t\t\tthis.webSocket.send(message);\n\t\telse {\n\t\t\tif (!this.#queue.length)\n\t\t\t\tthis.once(\"open\", this.#releaseQueue);\n\t\t\t\n\t\t\tthis.#queue.push(message);\n\t\t}\n\t\t\n\t}\n\t\n}\n\nexport { InSiteWebSocket as WebSocket };\n", "/** @this EventEmitter */\nfunction extendedOn(...args) {\n\t\n\tfor (const listenerHandler of this.listenerHandlers)\n\t\tif (listenerHandler.call(this, true, ...args) !== undefined)\n\t\t\treturn;\n\t\n\tthis.directOn(...args);\n\t\n}\n\n/** @this EventEmitter */\nfunction extendedOnce(...args) {\n\t\n\tfor (const listenerHandler of this.listenerHandlers)\n\t\tif (listenerHandler.call(this, true, ...args) !== undefined)\n\t\t\treturn;\n\t\n\tthis.directOnce(...args);\n\t\n}\n\n/** @this EventEmitter */\nfunction extendedOff(...args) {\n\t\n\tfor (const listenerHandler of this.listenerHandlers)\n\t\tif (listenerHandler.call(this, false, ...args) !== undefined)\n\t\t\treturn;\n\t\n\tthis.directOff(...args);\n\t\n}\n\nexport function extendEventEmitter(eventEmitter) {\n\t\n\teventEmitter.directOn = eventEmitter.on;\n\teventEmitter.directOnce = eventEmitter.once;\n\teventEmitter.directOff = eventEmitter.off;\n\t\n\teventEmitter.listenerHandlers = new Set();\n\t\n\teventEmitter.on = extendedOn;\n\teventEmitter.once = extendedOnce;\n\teventEmitter.off = extendedOff;\n\t\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["debounce", "noop", "EventEmitter", "extendedOn", "args", "listenerHandler", "extendedOnce", "extendedOff", "extendEventEmitter", "eventEmitter", "reconnectTimeout", "i", "_defib", "_openResolve", "_openReject", "_handleWebSocketOpen", "_handleWebSocketMessage", "_handleWebSocketError", "_reconnectTimeout", "_handleWebSocketClose", "_queue", "_releaseQueue", "InSiteWebSocket", "EventEmitter", "url", "options", "__publicField", "__privateAdd", "debounce", "__privateGet", "__privateSet", "message", "kind", "rest", "error", "event", "noop", "extendEventEmitter", "name", "protocols", "immediately", "autoReconnect", "on", "eventName", "resolve", "reject", "code", "reason", "args"]
|
|
7
|
+
}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import y from"node:http";import x from"node:https";import{debounce as v}from"@nesvet/n";import{WebSocketServer as N}from"ws";function b(...t){for(let e of this.listenerHandlers)if(e.call(this,!0,...t)!==void 0)return;this.directOn(...t)}function u(...t){for(let e of this.listenerHandlers)if(e.call(this,!0,...t)!==void 0)return;this.directOnce(...t)}function g(...t){for(let e of this.listenerHandlers)if(e.call(this,!1,...t)!==void 0)return;this.directOff(...t)}function h(t){t.directOn=t.on,t.directOnce=t.once,t.directOff=t.off,t.listenerHandlers=new Set,t.on=b,t.once=u,t.off=g}var l=Symbol("heartbeatInterval"),i=Symbol("defib"),o=Symbol("pingTs");import C from"ws";var a=class extends C{isWebSocketServerClient=!0;get isConnecting(){return this.readyState===this.CONNECTING}get isOpen(){return this.readyState===this.OPEN}get isClosing(){return this.readyState===this.CLOSING}get isClosed(){return this.readyState===this.CLOSED}sendMessage(...e){this.send(JSON.stringify(e))}};var m=class t extends N{constructor(e={},r,n){let{upgrade:s,ssl:c,port:S,server:d=c?x.createServer({...c}):y.createServer(),...p}=e;if(super({...p,WebSocket:a,server:d}),h(this),"upgrade"in this)throw new Error('WebSocketServer now contains an "upgrade" property');r&&(typeof r=="function"?(n=r,r=void 0):Object.assign(this,r)),this.upgrade=s,this.on("connection",this.#e),d.listen(S,n)}isWebSocketServer=!0;#e(e,r){e.wss=this,e.userAgent=r.headers["user-agent"],e.remoteAddress=r.headers["x-real-ip"]??r.headers["x-forwarded-for"]??"127.0.0.1",e.on("message",t.handleClientMessage),e.on("error",t.handleClientError),e.on("close",t.handleClientClose),e[i]=v(()=>e.terminate(),65e3),e[i](),e.latency=0,e[l]=setInterval(()=>{e[o]=Date.now(),e.send("")},5e3),this.emit("client-connect",e,r)}static handleClientMessage(e){let r=e.toString();if(this[i](),r)try{let[n,...s]=JSON.parse(r);this.emit(`message:${n}`,...s),this.wss.emit("client-message",this,n,...s),this.wss.emit(`client-message:${n}`,this,...s)}catch(n){t.handleClientError.call(this,n)}else this[o]&&(this.latency=Date.now()-this[o],delete this[o])}static handleClientError(e){e instanceof Event&&(e=void 0),this.wss.emit("client-error",this,e)}static handleClientClose(...e){this[i].clear(),clearInterval(this[l]),this.wss.emit("client-close",this),this.wss.emit("client-closed",this)}};export{m as WebSocketServer};
|
|
2
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/server/WebSocketServer.js", "../src/extendEventEmitter.js", "../src/server/symbols.js", "../src/server/WebSocketServerClient.js"],
|
|
4
|
+
"sourcesContent": ["import http from \"node:http\";\nimport https from \"node:https\";\nimport { debounce } from \"@nesvet/n\";\nimport { WebSocketServer } from \"ws\";\nimport { heartbeatGap, heartbeatInterval } from \"../common\";\nimport { extendEventEmitter } from \"../extendEventEmitter\";\nimport { defibSymbol, heartbeatIntervalSymbol, pingTsSymbol } from \"./symbols\";\nimport { WebSocketServerClient } from \"./WebSocketServerClient\";\n\n\nclass InSiteWebSocketServer extends WebSocketServer {\n\tconstructor(options = {}, props, handleListen) {\n\t\tconst {\n\t\t\tupgrade,\n\t\t\tssl,\n\t\t\tport,\n\t\t\tserver = ssl ? https.createServer({ ...ssl }) : http.createServer(),\n\t\t\t...wssOptions\n\t\t} = options;\n\t\t\n\t\tsuper({\n\t\t\t...wssOptions,\n\t\t\tWebSocket: WebSocketServerClient,\n\t\t\tserver\n\t\t});\n\t\t\n\t\textendEventEmitter(this);\n\t\t\n\t\tif (\"upgrade\" in this)\n\t\t\tthrow new Error(\"WebSocketServer now contains an \\\"upgrade\\\" property\");\n\t\t\n\t\tif (props)\n\t\t\tif (typeof props == \"function\") {\n\t\t\t\thandleListen = props;\n\t\t\t\tprops = undefined;\n\t\t\t} else\n\t\t\t\tObject.assign(this, props);\n\t\t\n\t\tthis.upgrade = upgrade;\n\t\t\n\t\tthis.on(\"connection\", this.#handleConnection);\n\t\t\n\t\tserver.listen(port, handleListen);\n\t\t\n\t}\n\t\n\tisWebSocketServer = true;\n\t\n\t#handleConnection(ws, request) {\n\t\tws.wss = this;\n\t\t\n\t\tws.userAgent = request.headers[\"user-agent\"];\n\t\tws.remoteAddress = request.headers[\"x-real-ip\"] ?? request.headers[\"x-forwarded-for\"] ?? \"127.0.0.1\";\n\t\t\n\t\tws.on(\"message\", InSiteWebSocketServer.handleClientMessage);\n\t\tws.on(\"error\", InSiteWebSocketServer.handleClientError);\n\t\tws.on(\"close\", InSiteWebSocketServer.handleClientClose);\n\t\t\n\t\tws[defibSymbol] = debounce(() => ws.terminate(), heartbeatInterval + heartbeatGap);\n\t\tws[defibSymbol]();\n\t\t\n\t\tws.latency = 0;\n\t\t\n\t\tws[heartbeatIntervalSymbol] = setInterval(() => {\n\t\t\t\n\t\t\tws[pingTsSymbol] = Date.now();\n\t\t\tws.send(\"\");\n\t\t\t\n\t\t}, heartbeatInterval);\n\t\t\n\t\tthis.emit(\"client-connect\", ws, request);\n\t\t\n\t}\n\t\n\tstatic handleClientMessage(data) {\n\t\tconst message = data.toString();\n\t\t\n\t\tthis[defibSymbol]();\n\t\t\n\t\tif (message)\n\t\t\ttry {\n\t\t\t\tconst [ kind, ...rest ] = JSON.parse(message);\n\t\t\t\t\n\t\t\t\tthis.emit(`message:${kind}`, ...rest);\n\t\t\t\tthis.wss.emit(\"client-message\", this, kind, ...rest);\n\t\t\t\tthis.wss.emit(`client-message:${kind}`, this, ...rest);\n\t\t\t} catch (error) {\n\t\t\t\tInSiteWebSocketServer.handleClientError.call(this, error);\n\t\t\t}\n\t\t else if (this[pingTsSymbol]) {\n\t\t\tthis.latency = Date.now() - this[pingTsSymbol];\n\t\t\tdelete this[pingTsSymbol];\n\t\t}\n\t\t\n\t}\n\t\n\tstatic handleClientError(error) {\n\t\tif (error instanceof Event)\n\t\t\terror = undefined;\n\t\t\n\t\tif (process.env.NODE_ENV === \"development\")\n\t\t\tconsole.error(\"WebSocketServer Client error\", error);\n\t\t\n\t\tthis.wss.emit(\"client-error\", this, error);\n\t\t\n\t}\n\t\n\tstatic handleClientClose(...args) {\n\t\t\n\t\tif (process.env.NODE_ENV === \"development\")\n\t\t\tconsole.info(\"WebSocketServer Client closed\", ...args);\n\t\t\n\t\tthis[defibSymbol].clear();\n\t\tclearInterval(this[heartbeatIntervalSymbol]);\n\t\t\n\t\tthis.wss.emit(\"client-close\", this);\n\t\tthis.wss.emit(\"client-closed\", this);\n\t\t\n\t}\n\t\n}\n\nexport { InSiteWebSocketServer as WebSocketServer };\n", "/** @this EventEmitter */\nfunction extendedOn(...args) {\n\t\n\tfor (const listenerHandler of this.listenerHandlers)\n\t\tif (listenerHandler.call(this, true, ...args) !== undefined)\n\t\t\treturn;\n\t\n\tthis.directOn(...args);\n\t\n}\n\n/** @this EventEmitter */\nfunction extendedOnce(...args) {\n\t\n\tfor (const listenerHandler of this.listenerHandlers)\n\t\tif (listenerHandler.call(this, true, ...args) !== undefined)\n\t\t\treturn;\n\t\n\tthis.directOnce(...args);\n\t\n}\n\n/** @this EventEmitter */\nfunction extendedOff(...args) {\n\t\n\tfor (const listenerHandler of this.listenerHandlers)\n\t\tif (listenerHandler.call(this, false, ...args) !== undefined)\n\t\t\treturn;\n\t\n\tthis.directOff(...args);\n\t\n}\n\nexport function extendEventEmitter(eventEmitter) {\n\t\n\teventEmitter.directOn = eventEmitter.on;\n\teventEmitter.directOnce = eventEmitter.once;\n\teventEmitter.directOff = eventEmitter.off;\n\t\n\teventEmitter.listenerHandlers = new Set();\n\t\n\teventEmitter.on = extendedOn;\n\teventEmitter.once = extendedOnce;\n\teventEmitter.off = extendedOff;\n\t\n}\n", "export const heartbeatIntervalSymbol = Symbol(\"heartbeatInterval\");\nexport const defibSymbol = Symbol(\"defib\");\nexport const pingTsSymbol = Symbol(\"pingTs\");\n", "import WebSocket from \"ws\";\n\n\nclass InSiteWebSocketServerClient extends WebSocket {\n\t\n\tisWebSocketServerClient = true;\n\t\n\tget isConnecting() {\n\t\treturn this.readyState === this.CONNECTING;\n\t}\n\t\n\tget isOpen() {\n\t\treturn this.readyState === this.OPEN;\n\t}\n\t\n\tget isClosing() {\n\t\treturn this.readyState === this.CLOSING;\n\t}\n\t\n\tget isClosed() {\n\t\treturn this.readyState === this.CLOSED;\n\t}\n\t\n\tsendMessage(...args) {\n\t\tthis.send(JSON.stringify(args));\n\t\t\n\t}\n\t\n}\n\nexport { InSiteWebSocketServerClient as WebSocketServerClient };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["http", "https", "debounce", "WebSocketServer", "extendedOn", "args", "listenerHandler", "extendedOnce", "extendedOff", "extendEventEmitter", "eventEmitter", "heartbeatIntervalSymbol", "defibSymbol", "pingTsSymbol", "WebSocket", "InSiteWebSocketServerClient", "args", "InSiteWebSocketServer", "_InSiteWebSocketServer", "WebSocketServer", "options", "props", "handleListen", "upgrade", "ssl", "port", "server", "https", "http", "wssOptions", "InSiteWebSocketServerClient", "extendEventEmitter", "#handleConnection", "ws", "request", "defibSymbol", "debounce", "heartbeatIntervalSymbol", "pingTsSymbol", "data", "message", "kind", "rest", "error", "args"]
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "insite-ws",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.355",
|
|
4
4
|
"description": "inSite WebSockets",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
|
-
"./server": "./
|
|
8
|
-
"./client": "./
|
|
7
|
+
"./server": "./dist/server.js",
|
|
8
|
+
"./client": "./dist/client.js"
|
|
9
9
|
},
|
|
10
10
|
"packageManager": "yarn@1.22.22",
|
|
11
11
|
"scripts": {
|
|
12
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
13
|
+
"build": "node .conveyer"
|
|
13
14
|
},
|
|
14
15
|
"repository": {
|
|
15
16
|
"type": "git",
|
|
@@ -28,6 +29,7 @@
|
|
|
28
29
|
"ws": "^8"
|
|
29
30
|
},
|
|
30
31
|
"devDependencies": {
|
|
32
|
+
"@nesvet/conveyer": "^1",
|
|
31
33
|
"@nesvet/eslint-config": "^1"
|
|
32
34
|
}
|
|
33
35
|
}
|
package/lib/client/WebSocket.js
DELETED
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import { debounce, noop } from "@nesvet/n";
|
|
2
|
-
import EventEmitter from "eventemitter3";
|
|
3
|
-
import { heartbeatGap, heartbeatInterval } from "../common";
|
|
4
|
-
import { extendEventEmitter } from "../extendEventEmitter";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const reconnectTimeout = 2000;
|
|
8
|
-
|
|
9
|
-
let i = 0;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export class InSiteWebSocket extends EventEmitter {
|
|
13
|
-
constructor(url, options = {}) {
|
|
14
|
-
super();
|
|
15
|
-
|
|
16
|
-
extendEventEmitter(this);
|
|
17
|
-
|
|
18
|
-
this.url = url;
|
|
19
|
-
|
|
20
|
-
const {
|
|
21
|
-
name = i++,
|
|
22
|
-
protocols,
|
|
23
|
-
immediately = true,
|
|
24
|
-
autoReconnect = true,
|
|
25
|
-
on
|
|
26
|
-
} = options;
|
|
27
|
-
|
|
28
|
-
this.name = name;
|
|
29
|
-
|
|
30
|
-
this.protocols = protocols;
|
|
31
|
-
|
|
32
|
-
this.autoReconnect = autoReconnect;
|
|
33
|
-
|
|
34
|
-
if (on)
|
|
35
|
-
for (const eventName in on)
|
|
36
|
-
if (on[eventName])
|
|
37
|
-
this.on(eventName, on[eventName]);
|
|
38
|
-
|
|
39
|
-
if (this.url && immediately)
|
|
40
|
-
this.open().catch(noop);
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
webSocket = null;
|
|
45
|
-
|
|
46
|
-
#defib = debounce(function () {
|
|
47
|
-
|
|
48
|
-
if (this.isOpen) {
|
|
49
|
-
if (process.env.NODE_ENV === "development")
|
|
50
|
-
console.info(`WebSocket ${this.name} has no heartbeat - going offline`);
|
|
51
|
-
|
|
52
|
-
this.webSocket.close();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
}, heartbeatInterval + heartbeatGap);
|
|
56
|
-
|
|
57
|
-
#openResolve;
|
|
58
|
-
#openReject;
|
|
59
|
-
|
|
60
|
-
get isConnecting() {
|
|
61
|
-
return this.webSocket ? this.webSocket.readyState === this.webSocket.CONNECTING : null;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
get isOpen() {
|
|
65
|
-
return this.webSocket ? this.webSocket.readyState === this.webSocket.OPEN : null;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
get isClosing() {
|
|
69
|
-
return this.webSocket ? this.webSocket.readyState === this.webSocket.CLOSING : null;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
get isClosed() {
|
|
73
|
-
return this.webSocket ? this.webSocket.readyState === this.webSocket.CLOSED : null;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
isChanged = false;
|
|
77
|
-
|
|
78
|
-
#handleWebSocketOpen = () => {
|
|
79
|
-
|
|
80
|
-
this.#openResolve();
|
|
81
|
-
this.#openResolve = undefined;
|
|
82
|
-
this.#openReject = undefined;
|
|
83
|
-
|
|
84
|
-
this.emit("open");
|
|
85
|
-
|
|
86
|
-
this.#defib();
|
|
87
|
-
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
#handleWebSocketMessage = ({ data: message }) => {
|
|
91
|
-
|
|
92
|
-
this.#defib();
|
|
93
|
-
|
|
94
|
-
if (message)
|
|
95
|
-
try {
|
|
96
|
-
const [ kind, ...rest ] = JSON.parse(message);
|
|
97
|
-
|
|
98
|
-
this.emit("message", kind, ...rest);
|
|
99
|
-
this.emit(`message:${kind}`, ...rest);
|
|
100
|
-
} catch (error) {
|
|
101
|
-
this.#handleWebSocketError(error);
|
|
102
|
-
}
|
|
103
|
-
else
|
|
104
|
-
this.webSocket.send("");
|
|
105
|
-
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
#handleWebSocketError = error => {
|
|
109
|
-
if (error instanceof Event)
|
|
110
|
-
error = undefined;
|
|
111
|
-
|
|
112
|
-
if (this.#openReject) {
|
|
113
|
-
this.#openReject(error);
|
|
114
|
-
this.#openResolve = undefined;
|
|
115
|
-
this.#openReject = undefined;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
this.emit("error", error);
|
|
119
|
-
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
#reconnectTimeout;
|
|
123
|
-
|
|
124
|
-
#handleWebSocketClose = event => {
|
|
125
|
-
|
|
126
|
-
if (process.env.NODE_ENV === "development")
|
|
127
|
-
console.info(`WebSocket ${this.name} is closed with code ${event.code} and reason "${event.reason}"`);
|
|
128
|
-
|
|
129
|
-
this.#defib.clear();
|
|
130
|
-
|
|
131
|
-
this.emit("close", event);
|
|
132
|
-
|
|
133
|
-
if (this.autoReconnect && ![ 1002, 3500, 4000 ].includes(event.code)) {
|
|
134
|
-
if (process.env.NODE_ENV === "development")
|
|
135
|
-
console.info(`WebSocket ${this.name} will try to reconnect in 2 sec…`);
|
|
136
|
-
|
|
137
|
-
this.#reconnectTimeout = setTimeout(() => this.open().catch(noop), reconnectTimeout);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
open(options = {}) {
|
|
143
|
-
|
|
144
|
-
clearTimeout(this.#reconnectTimeout);
|
|
145
|
-
|
|
146
|
-
return this.close(4000, "reopen").then(() => {
|
|
147
|
-
|
|
148
|
-
if (options.url)
|
|
149
|
-
this.url = options.url;
|
|
150
|
-
|
|
151
|
-
if (options.protocols)
|
|
152
|
-
this.protocols = options.protocols;
|
|
153
|
-
|
|
154
|
-
return new Promise((resolve, reject) => {
|
|
155
|
-
this.#openResolve = resolve;
|
|
156
|
-
this.#openReject = reject;
|
|
157
|
-
|
|
158
|
-
if (this.webSocket) {
|
|
159
|
-
this.isChanged = this.webSocket._url !== this.url;
|
|
160
|
-
if (this.isChanged)
|
|
161
|
-
this.emit("server-change");
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
this.webSocket = new WebSocket(this.url, this.protocols);
|
|
165
|
-
this.webSocket._url = this.url;
|
|
166
|
-
|
|
167
|
-
this.emit("connecting");
|
|
168
|
-
|
|
169
|
-
this.send = this.webSocket.send.bind(this.webSocket);
|
|
170
|
-
|
|
171
|
-
this.webSocket.addEventListener("open", this.#handleWebSocketOpen);
|
|
172
|
-
this.webSocket.addEventListener("message", this.#handleWebSocketMessage);
|
|
173
|
-
this.webSocket.addEventListener("error", this.#handleWebSocketError);
|
|
174
|
-
this.webSocket.addEventListener("close", this.#handleWebSocketClose);
|
|
175
|
-
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
connect = this.open;
|
|
181
|
-
|
|
182
|
-
close(code = 3500, reason = "manual") {
|
|
183
|
-
|
|
184
|
-
clearTimeout(this.#reconnectTimeout);
|
|
185
|
-
|
|
186
|
-
return new Promise(resolve => {
|
|
187
|
-
if (this.isConnecting || this.isOpen) {
|
|
188
|
-
this.webSocket.addEventListener("close", resolve);
|
|
189
|
-
this.webSocket.close(code, reason);
|
|
190
|
-
} else
|
|
191
|
-
resolve();
|
|
192
|
-
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
disconnect = this.close;
|
|
197
|
-
|
|
198
|
-
#queue = [];
|
|
199
|
-
|
|
200
|
-
#releaseQueue = () => {
|
|
201
|
-
|
|
202
|
-
for (const message of this.#queue)
|
|
203
|
-
this.webSocket.send(message);
|
|
204
|
-
|
|
205
|
-
this.#queue.length = 0;
|
|
206
|
-
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
sendMessage(...args) {
|
|
210
|
-
const message = JSON.stringify(args);
|
|
211
|
-
|
|
212
|
-
if (this.isOpen)
|
|
213
|
-
this.webSocket.send(message);
|
|
214
|
-
else {
|
|
215
|
-
if (!this.#queue.length)
|
|
216
|
-
this.once("open", this.#releaseQueue);
|
|
217
|
-
|
|
218
|
-
this.#queue.push(message);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
}
|
package/lib/client/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./WebSocket";
|
package/lib/common.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/** @this EventEmitter */
|
|
2
|
-
function extendedOn(...args) {
|
|
3
|
-
|
|
4
|
-
for (const listenerHandler of this.listenerHandlers)
|
|
5
|
-
if (listenerHandler.call(this, true, ...args) !== undefined)
|
|
6
|
-
return;
|
|
7
|
-
|
|
8
|
-
this.directOn(...args);
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/** @this EventEmitter */
|
|
13
|
-
function extendedOnce(...args) {
|
|
14
|
-
|
|
15
|
-
for (const listenerHandler of this.listenerHandlers)
|
|
16
|
-
if (listenerHandler.call(this, true, ...args) !== undefined)
|
|
17
|
-
return;
|
|
18
|
-
|
|
19
|
-
this.directOnce(...args);
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/** @this EventEmitter */
|
|
24
|
-
function extendedOff(...args) {
|
|
25
|
-
|
|
26
|
-
for (const listenerHandler of this.listenerHandlers)
|
|
27
|
-
if (listenerHandler.call(this, false, ...args) !== undefined)
|
|
28
|
-
return;
|
|
29
|
-
|
|
30
|
-
this.directOff(...args);
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function extendEventEmitter(eventEmitter) {
|
|
35
|
-
|
|
36
|
-
eventEmitter.directOn = eventEmitter.on;
|
|
37
|
-
eventEmitter.directOnce = eventEmitter.once;
|
|
38
|
-
eventEmitter.directOff = eventEmitter.off;
|
|
39
|
-
|
|
40
|
-
eventEmitter.listenerHandlers = new Set();
|
|
41
|
-
|
|
42
|
-
eventEmitter.on = extendedOn;
|
|
43
|
-
eventEmitter.once = extendedOnce;
|
|
44
|
-
eventEmitter.off = extendedOff;
|
|
45
|
-
|
|
46
|
-
}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import http from "node:http";
|
|
2
|
-
import https from "node:https";
|
|
3
|
-
import { debounce } from "@nesvet/n";
|
|
4
|
-
import { WebSocketServer } from "ws";
|
|
5
|
-
import { heartbeatGap, heartbeatInterval } from "../common";
|
|
6
|
-
import { extendEventEmitter } from "../extendEventEmitter";
|
|
7
|
-
import { defibSymbol, heartbeatIntervalSymbol, pingTsSymbol } from "./symbols";
|
|
8
|
-
import { InSiteWebSocketServerClient } from "./WebSocketServerClient";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
export class InSiteWebSocketServer extends WebSocketServer {
|
|
12
|
-
constructor(options = {}, props, handleListen) {
|
|
13
|
-
const {
|
|
14
|
-
upgrade,
|
|
15
|
-
ssl,
|
|
16
|
-
port,
|
|
17
|
-
server = ssl ? https.createServer({ ...ssl }) : http.createServer(),
|
|
18
|
-
...wssOptions
|
|
19
|
-
} = options;
|
|
20
|
-
|
|
21
|
-
super({
|
|
22
|
-
...wssOptions,
|
|
23
|
-
WebSocket: InSiteWebSocketServerClient,
|
|
24
|
-
server
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
extendEventEmitter(this);
|
|
28
|
-
|
|
29
|
-
if ("upgrade" in this)
|
|
30
|
-
throw new Error("WebSocketServer now contains an \"upgrade\" property");
|
|
31
|
-
|
|
32
|
-
if (props)
|
|
33
|
-
if (typeof props == "function") {
|
|
34
|
-
handleListen = props;
|
|
35
|
-
props = undefined;
|
|
36
|
-
} else
|
|
37
|
-
Object.assign(this, props);
|
|
38
|
-
|
|
39
|
-
this.upgrade = upgrade;
|
|
40
|
-
|
|
41
|
-
this.on("connection", this.#handleConnection);
|
|
42
|
-
|
|
43
|
-
server.listen(port, handleListen);
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
isWebSocketServer = true;
|
|
48
|
-
|
|
49
|
-
#handleConnection(ws, request) {
|
|
50
|
-
ws.wss = this;
|
|
51
|
-
|
|
52
|
-
ws.userAgent = request.headers["user-agent"];
|
|
53
|
-
ws.remoteAddress = request.headers["x-real-ip"] ?? request.headers["x-forwarded-for"] ?? "127.0.0.1";
|
|
54
|
-
|
|
55
|
-
ws.on("message", InSiteWebSocketServer.handleClientMessage);
|
|
56
|
-
ws.on("error", InSiteWebSocketServer.handleClientError);
|
|
57
|
-
ws.on("close", InSiteWebSocketServer.handleClientClose);
|
|
58
|
-
|
|
59
|
-
ws[defibSymbol] = debounce(() => ws.terminate(), heartbeatInterval + heartbeatGap);
|
|
60
|
-
ws[defibSymbol]();
|
|
61
|
-
|
|
62
|
-
ws.latency = 0;
|
|
63
|
-
|
|
64
|
-
ws[heartbeatIntervalSymbol] = setInterval(() => {
|
|
65
|
-
|
|
66
|
-
ws[pingTsSymbol] = Date.now();
|
|
67
|
-
ws.send("");
|
|
68
|
-
|
|
69
|
-
}, heartbeatInterval);
|
|
70
|
-
|
|
71
|
-
this.emit("client-connect", ws, request);
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
static handleClientMessage(data) {
|
|
76
|
-
const message = data.toString();
|
|
77
|
-
|
|
78
|
-
this[defibSymbol]();
|
|
79
|
-
|
|
80
|
-
if (message)
|
|
81
|
-
try {
|
|
82
|
-
const [ kind, ...rest ] = JSON.parse(message);
|
|
83
|
-
|
|
84
|
-
this.emit(`message:${kind}`, ...rest);
|
|
85
|
-
this.wss.emit("client-message", this, kind, ...rest);
|
|
86
|
-
this.wss.emit(`client-message:${kind}`, this, ...rest);
|
|
87
|
-
} catch (error) {
|
|
88
|
-
InSiteWebSocketServer.handleClientError.call(this, error);
|
|
89
|
-
}
|
|
90
|
-
else if (this[pingTsSymbol]) {
|
|
91
|
-
this.latency = Date.now() - this[pingTsSymbol];
|
|
92
|
-
delete this[pingTsSymbol];
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
static handleClientError(error) {
|
|
98
|
-
if (error instanceof Event)
|
|
99
|
-
error = undefined;
|
|
100
|
-
|
|
101
|
-
if (process.env.NODE_ENV === "development")
|
|
102
|
-
console.error("WebSocketServer Client error", error);
|
|
103
|
-
|
|
104
|
-
this.wss.emit("client-error", this, error);
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
static handleClientClose(...args) {
|
|
109
|
-
|
|
110
|
-
if (process.env.NODE_ENV === "development")
|
|
111
|
-
console.info("WebSocketServer Client closed", ...args);
|
|
112
|
-
|
|
113
|
-
this[defibSymbol].clear();
|
|
114
|
-
clearInterval(this[heartbeatIntervalSymbol]);
|
|
115
|
-
|
|
116
|
-
this.wss.emit("client-close", this);
|
|
117
|
-
this.wss.emit("client-closed", this);
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import WebSocket from "ws";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export class InSiteWebSocketServerClient extends WebSocket {
|
|
5
|
-
|
|
6
|
-
isWebSocketServerClient = true;
|
|
7
|
-
|
|
8
|
-
get isConnecting() {
|
|
9
|
-
return this.readyState === this.CONNECTING;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
get isOpen() {
|
|
13
|
-
return this.readyState === this.OPEN;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
get isClosing() {
|
|
17
|
-
return this.readyState === this.CLOSING;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
get isClosed() {
|
|
21
|
-
return this.readyState === this.CLOSED;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
sendMessage(...args) {
|
|
25
|
-
this.send(JSON.stringify(args));
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
}
|
package/lib/server/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./WebSocketServer";
|
package/lib/server/symbols.js
DELETED