insite-ws 2.0.3 → 2.0.5

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/.conveyer.ts ADDED
@@ -0,0 +1,36 @@
1
+ import path from "node:path";
2
+ import { Conveyer, ESBuild } from "@nesvet/conveyer";
3
+
4
+
5
+ const distDir = "dist";
6
+
7
+ const common = {
8
+ external: true,
9
+ format: "esm",
10
+ sourcemap: true
11
+ };
12
+
13
+
14
+ new Conveyer([
15
+
16
+ new ESBuild({
17
+ title: "Server",
18
+ entryPoints: [ "src/server/index.ts" ],
19
+ outfile: path.resolve(distDir, "server/index.js"),
20
+ platform: "node",
21
+ target: "node20",
22
+ ...common
23
+ }),
24
+
25
+ new ESBuild({
26
+ title: "Client",
27
+ entryPoints: [ "src/client/index.ts" ],
28
+ outfile: path.resolve(distDir, "client/index.js"),
29
+ platform: "neutral",
30
+ target: "es2020",
31
+ ...common
32
+ })
33
+
34
+ ], {
35
+ initialCleanup: distDir
36
+ });
package/bun.lockb CHANGED
Binary file
@@ -1,4 +1,5 @@
1
1
  import EventEmitter from "eventemitter3";
2
+ import { type RequestListener } from "../common";
2
3
  import { Options } from "./types";
3
4
  export declare class InSiteWebSocket extends EventEmitter {
4
5
  #private;
@@ -21,6 +22,11 @@ export declare class InSiteWebSocket extends EventEmitter {
21
22
  close(code?: number, reason?: string): Promise<unknown>;
22
23
  disconnect: (code?: number, reason?: string) => Promise<unknown>;
23
24
  sendMessage(...args: unknown[]): void;
25
+ sendRequest(...args: unknown[]): Promise<unknown> | this;
26
+ addRequestListener(kind: string, listener: RequestListener): this;
27
+ onRequest: (kind: string, listener: RequestListener) => this;
28
+ removeRequestListener(kind: string): this;
29
+ offRequest: (kind: string) => this;
24
30
  static defib(this: InSiteWebSocket): void;
25
31
  }
26
32
  //# sourceMappingURL=WebSocket.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"WebSocket.d.ts","sourceRoot":"","sources":["../../src/client/WebSocket.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAC;AAGzC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAUlC,qBAAa,eAAgB,SAAQ,YAAY;;gBACpC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,OAAY;IA6B9C,QAAQ,CAAC,WAAW,QAAQ;IAC5B,QAAQ,CAAC,iBAAiB,SAAS;IACnC,QAAQ,CAAC,uBAAuB,SAAS;IAEzC,GAAG,EAAE,MAAM,CAAC;IAEZ,IAAI,EAAE,MAAM,CAAC;IAEb,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB,aAAa,EAAE,OAAO,CAAC;IAEvB,IAAI,CAAC,CAAC,IAAI,EAAE,eAAe,GAAG,eAAe,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI;IAEpE,SAAS,EAAE,IAAI,GAAG,SAAS,CAAQ;IAInC,IAAI,YAAY,mBAEf;IAED,IAAI,MAAM,mBAET;IAED,IAAI,SAAS,mBAEZ;IAED,IAAI,QAAQ,mBAEX;IAqEK,IAAI,CAAC,OAAO,GAAE,OAAY;IAmChC,OAAO,aAnCa,OAAO,sBAmCP;IAEpB,KAAK,CAAC,IAAI,SAAO,EAAE,MAAM,SAAW;IAcpC,UAAU,uDAAc;IAaxB,WAAW,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE;IAe9B,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,eAAe;CAWlC"}
1
+ {"version":3,"file":"WebSocket.d.ts","sourceRoot":"","sources":["../../src/client/WebSocket.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAC;AAEzC,OAAO,EAIN,KAAK,eAAe,EACpB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAUlC,qBAAa,eAAgB,SAAQ,YAAY;;gBACpC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,OAAY;IA+B9C,QAAQ,CAAC,WAAW,QAAQ;IAC5B,QAAQ,CAAC,iBAAiB,SAAS;IACnC,QAAQ,CAAC,uBAAuB,SAAS;IAEzC,GAAG,EAAE,MAAM,CAAC;IAEZ,IAAI,EAAE,MAAM,CAAC;IAEb,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB,aAAa,EAAE,OAAO,CAAC;IAEvB,IAAI,CAAC,CAAC,IAAI,EAAE,eAAe,GAAG,eAAe,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI;IAEpE,SAAS,EAAE,IAAI,GAAG,SAAS,CAAQ;IAInC,IAAI,YAAY,mBAEf;IAED,IAAI,MAAM,mBAET;IAED,IAAI,SAAS,mBAEZ;IAED,IAAI,QAAQ,mBAEX;IAqEK,IAAI,CAAC,OAAO,GAAE,OAAY;IAmChC,OAAO,aAnCa,OAAO,sBAmCP;IAEpB,KAAK,CAAC,IAAI,SAAO,EAAE,MAAM,SAAW;IAcpC,UAAU,uDAAc;IAaxB,WAAW,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE;IAc9B,WAAW,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE;IA6B9B,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe;IAM1D,SAAS,SANgB,MAAM,YAAY,eAAe,UAMtB;IAEpC,qBAAqB,CAAC,IAAI,EAAE,MAAM;IAMlC,UAAU,SANkB,MAAM,UAMM;IAyBxC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,eAAe;CAWlC"}
@@ -1,2 +1,2 @@
1
- var T=Object.defineProperty;var E=t=>{throw TypeError(t)};var $=(t,s,e)=>s in t?T(t,s,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[s]=e;var n=(t,s,e)=>$(t,typeof s!="symbol"?s+"":s,e),O=(t,s,e)=>s.has(t)||E("Cannot "+e);var i=(t,s,e)=>(O(t,s,"read from private field"),e?e.call(t):s.get(t)),r=(t,s,e)=>s.has(t)?E("Cannot add the same private member more than once"):s instanceof WeakSet?s.add(t):s.set(t,e),h=(t,s,e,o)=>(O(t,s,"write to private field"),o?o.call(t,e):s.set(t,e),e);import D from"eventemitter3";import{debounce as G,noop as W}from"@nesvet/n";var I=2e3,V=0,y=new WeakMap,u,l,a,f,p,S,b,m,d,w,v=class v extends D{constructor(e,o={}){super();n(this,"isWebSocket",!0);n(this,"isWebSocketServer",!1);n(this,"isWebSocketServerClient",!1);n(this,"url");n(this,"name");n(this,"protocols");n(this,"autoReconnect");n(this,"webSocket",null);r(this,u,G(v.defib,65e3));r(this,l);r(this,a);r(this,f,()=>{i(this,l).call(this),h(this,l,void 0),h(this,a,void 0),this.emit("open"),i(this,u).call(this)});r(this,p,({data:e})=>{if(i(this,u).call(this),e)try{let[o,...c]=JSON.parse(e);this.emit("message",o,...c),this.emit(`message:${o}`,...c)}catch(o){i(this,S).call(this,o)}else this.webSocket.send("")});r(this,S,e=>{e instanceof Event&&(e=void 0),i(this,a)&&(i(this,a).call(this,e),h(this,l,void 0),h(this,a,void 0)),this.emit("error",e)});r(this,b);r(this,m,e=>{process.env.NODE_ENV==="development"&&console.info(`WebSocket ${this.name} is closed with code ${e.code} and reason "${e.reason}"`),i(this,u).clear(),this.emit("close",e),this.autoReconnect&&![1002,3500,4e3].includes(e.code)&&(process.env.NODE_ENV==="development"&&console.info(`WebSocket ${this.name} will try to reconnect in 2 sec\u2026`),h(this,b,setTimeout(()=>this.open().catch(W),I)))});n(this,"connect",this.open);n(this,"disconnect",this.close);r(this,d,[]);r(this,w,()=>{for(let e of i(this,d))this.webSocket.send(e);i(this,d).length=0});this.url=e;let{name:c=(V++).toString(),protocols:C,immediately:L=!0,autoReconnect:R=!0,on:k}=o;if(this.name=c,this.protocols=C,this.autoReconnect=!!R,k)for(let g in k)k[g]&&this.on(g,k[g]);this.url&&L&&this.open().catch(W)}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}async open(e={}){return clearTimeout(i(this,b)),await this.close(4e3,"reopen"),e.url&&(this.url=e.url),e.protocols&&(this.protocols=e.protocols),this.webSocket&&y.get(this.webSocket)!==this.url&&this.emit("server-change"),new Promise((o,c)=>{h(this,l,o),h(this,a,c),this.webSocket=new WebSocket(this.url,this.protocols),this.webSocket.addEventListener("open",i(this,f)),this.webSocket.addEventListener("message",i(this,p)),this.webSocket.addEventListener("error",i(this,S)),this.webSocket.addEventListener("close",i(this,m)),this.send=this.webSocket.send.bind(this.webSocket),y.set(this.webSocket,this.url),this.emit("connecting")})}close(e=3500,o="manual"){return clearTimeout(i(this,b)),new Promise(c=>{this.isConnecting||this.isOpen?(this.webSocket.addEventListener("close",c),this.webSocket.close(e,o)):c(null)})}sendMessage(...e){let o=JSON.stringify(e);this.isOpen?this.webSocket.send(o):(i(this,d).length||this.once("open",i(this,w)),i(this,d).push(o))}static defib(){this.isOpen&&(process.env.NODE_ENV==="development"&&console.info(`WebSocket ${this.name} has no heartbeat - going offline`),this.webSocket.close())}};u=new WeakMap,l=new WeakMap,a=new WeakMap,f=new WeakMap,p=new WeakMap,S=new WeakMap,b=new WeakMap,m=new WeakMap,d=new WeakMap,w=new WeakMap;var N=v;export{N as InSiteWebSocket};
1
+ var P=Object.defineProperty;var W=n=>{throw TypeError(n)};var T=(n,i,e)=>i in n?P(n,i,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[i]=e;var r=(n,i,e)=>T(n,typeof i!="symbol"?i+"":i,e),$=(n,i,e)=>i.has(n)||W("Cannot "+e);var s=(n,i,e)=>($(n,i,"read from private field"),e?e.call(n):i.get(n)),c=(n,i,e)=>i.has(n)?W("Cannot add the same private member more than once"):i instanceof WeakSet?i.add(n):i.set(n,e),l=(n,i,e,t)=>($(n,i,"write to private field"),t?t.call(n,e):i.set(n,e),e);import I from"eventemitter3";import{debounce as V,noop as C,uid as _}from"@nesvet/n";var S={request:"~r-q",response:"~r-s"};var B=2e3,j=0,M=new WeakMap,m,b,u,E,q,v,w,y,p,O,g,R,N=class N extends I{constructor(e,t={}){super();r(this,"isWebSocket",!0);r(this,"isWebSocketServer",!1);r(this,"isWebSocketServerClient",!1);r(this,"url");r(this,"name");r(this,"protocols");r(this,"autoReconnect");r(this,"webSocket",null);c(this,m,V(N.defib,65e3));c(this,b);c(this,u);c(this,E,()=>{s(this,b).call(this),l(this,b,void 0),l(this,u,void 0),this.emit("open"),s(this,m).call(this)});c(this,q,({data:e})=>{if(s(this,m).call(this),e)try{let[t,...o]=JSON.parse(e);this.emit("message",t,...o),this.emit(`message:${t}`,...o)}catch(t){s(this,v).call(this,t)}else this.webSocket.send("")});c(this,v,e=>{e instanceof Event&&(e=void 0),s(this,u)&&(s(this,u).call(this,e),l(this,b,void 0),l(this,u,void 0)),this.emit("error",e)});c(this,w);c(this,y,e=>{process.env.NODE_ENV==="development"&&console.info(`WebSocket ${this.name} is closed with code ${e.code} and reason "${e.reason}"`),s(this,m).clear(),this.emit("close",e),this.autoReconnect&&![1002,3500,4e3].includes(e.code)&&(process.env.NODE_ENV==="development"&&console.info(`WebSocket ${this.name} will try to reconnect in 2 sec\u2026`),l(this,w,setTimeout(()=>this.open().catch(C),B)))});r(this,"connect",this.open);r(this,"disconnect",this.close);c(this,p,[]);c(this,O,()=>{for(let e of s(this,p))this.webSocket.send(e);s(this,p).length=0});c(this,g,new Map);r(this,"onRequest",this.addRequestListener);r(this,"offRequest",this.removeRequestListener);c(this,R,async(e,t,...o)=>{let k=s(this,g).get(t),f,a=null;if(k)try{f=await k.apply(this,o)}catch(h){if(h instanceof Error){let{message:d,...L}=h;a={message:d,...L}}}else a={message:`Unknown request kind "${t}"`};this.sendMessage(`${S.response}-${e}`,a,f)});this.url=e;let{name:o=(j++).toString(),protocols:k,immediately:f=!0,autoReconnect:a=!0,on:h}=t;if(this.name=o,this.protocols=k,this.autoReconnect=!!a,this.on(`message:${S.request}`,s(this,R)),h)for(let d in h)h[d]&&this.on(d,h[d]);this.url&&f&&this.open().catch(C)}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}async open(e={}){return clearTimeout(s(this,w)),await this.close(4e3,"reopen"),e.url&&(this.url=e.url),e.protocols&&(this.protocols=e.protocols),this.webSocket&&M.get(this.webSocket)!==this.url&&this.emit("server-change"),new Promise((t,o)=>{l(this,b,t),l(this,u,o),this.webSocket=new WebSocket(this.url,this.protocols),this.webSocket.addEventListener("open",s(this,E)),this.webSocket.addEventListener("message",s(this,q)),this.webSocket.addEventListener("error",s(this,v)),this.webSocket.addEventListener("close",s(this,y)),this.send=this.webSocket.send.bind(this.webSocket),M.set(this.webSocket,this.url),this.emit("connecting")})}close(e=3500,t="manual"){return clearTimeout(s(this,w)),new Promise(o=>{this.isConnecting||this.isOpen?(this.webSocket.addEventListener("close",o),this.webSocket.close(e,t)):o(null)})}sendMessage(...e){let t=JSON.stringify(e);this.isOpen?this.webSocket.send(t):(s(this,p).length||this.once("open",s(this,O)),s(this,p).push(t))}sendRequest(...e){let t=_(),o=`message:${S.response}-${t}`;return typeof e.at(-1)=="function"?(this.once(o,e.splice(-1,1)[0]),this.sendMessage(S.request,t,...e),this):new Promise((k,f)=>{this.once(o,(a,h)=>{if(a){let{message:d,...L}=a;f(Object.assign(new Error(d),L))}else k(h)}),this.sendMessage(S.request,t,...e)})}addRequestListener(e,t){return s(this,g).set(e,t),this}removeRequestListener(e){return s(this,g).delete(e),this}static defib(){this.isOpen&&(process.env.NODE_ENV==="development"&&console.info(`WebSocket ${this.name} has no heartbeat - going offline`),this.webSocket.close())}};m=new WeakMap,b=new WeakMap,u=new WeakMap,E=new WeakMap,q=new WeakMap,v=new WeakMap,w=new WeakMap,y=new WeakMap,p=new WeakMap,O=new WeakMap,g=new WeakMap,R=new WeakMap;var x=N;export{x as InSiteWebSocket};
2
2
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/client/WebSocket.ts"],
4
- "sourcesContent": ["import EventEmitter from \"eventemitter3\";\nimport { debounce, noop } from \"@nesvet/n\";\nimport { heartbeatGap, heartbeatInterval } from \"../common\";\nimport { Options } from \"./types\";\n\n\nconst reconnectTimeout = 2000;\n\nlet i = 0;\n\nconst webSocketUrlWeakMap = new WeakMap<WebSocket, string>();\n\n\nexport class InSiteWebSocket extends EventEmitter {\n\tconstructor(url: string, options: Options = {}) {\n\t\tsuper();\n\t\t\n\t\tthis.url = url;\n\t\t\n\t\tconst {\n\t\t\tname = (i++).toString(),\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\treadonly isWebSocket = true;\n\treadonly isWebSocketServer = false;\n\treadonly isWebSocketServerClient = false;\n\t\n\turl: string;\n\t\n\tname: string;\n\t\n\tprotocols?: string[];\n\t\n\tautoReconnect: boolean;\n\t\n\tsend?(data: ArrayBufferLike | ArrayBufferView | Blob | string): void;\n\t\n\twebSocket: null | WebSocket = null;\n\t\n\t#defib = debounce(InSiteWebSocket.defib, heartbeatInterval + heartbeatGap);\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\t#openResolve?: (value?: unknown) => void;\n\t#openReject?: (reason?: unknown) => void;\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 }: MessageEvent) => {\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 as Error);\n\t\t\t}\n\t\telse\n\t\t\tthis.webSocket!.send(\"\");\n\t\t\n\t};\n\t\n\t#handleWebSocketError = (error: Error | Event | undefined) => {\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?: number;\n\t\n\t#handleWebSocketClose = (event: CloseEvent) => {\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) as unknown as number;\n\t\t}\n\t\t\n\t};\n\t\n\tasync open(options: Options = {}) {\n\t\t\n\t\tclearTimeout(this.#reconnectTimeout);\n\t\t\n\t\tawait this.close(4000, \"reopen\");\n\t\t\n\t\tif (options.url)\n\t\t\tthis.url = options.url;\n\t\t\n\t\tif (options.protocols)\n\t\t\tthis.protocols = options.protocols;\n\t\t\n\t\tif (this.webSocket && webSocketUrlWeakMap.get(this.webSocket) !== this.url)\n\t\t\tthis.emit(\"server-change\");\n\t\t\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.#openResolve = resolve;\n\t\t\tthis.#openReject = reject;\n\t\t\t\n\t\t\tthis.webSocket = new WebSocket(this.url, this.protocols);\n\t\t\t\n\t\t\tthis.webSocket.addEventListener(\"open\", this.#handleWebSocketOpen);\n\t\t\tthis.webSocket.addEventListener(\"message\", this.#handleWebSocketMessage);\n\t\t\tthis.webSocket.addEventListener(\"error\", this.#handleWebSocketError);\n\t\t\tthis.webSocket.addEventListener(\"close\", this.#handleWebSocketClose);\n\t\t\t\n\t\t\tthis.send = this.webSocket.send.bind(this.webSocket);\n\t\t\t\n\t\t\twebSocketUrlWeakMap.set(this.webSocket, this.url);\n\t\t\t\n\t\t\tthis.emit(\"connecting\");\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(null);\n\t\t\t\n\t\t});\n\t}\n\t\n\tdisconnect = this.close;\n\t\n\t#queue: string[] = [];\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: unknown[]) {\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\t\n\tstatic defib(this: InSiteWebSocket) {\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}\n\t\n}\n"],
5
- "mappings": "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",
6
- "names": ["EventEmitter", "debounce", "noop", "reconnectTimeout", "i", "webSocketUrlWeakMap", "_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", "name", "protocols", "immediately", "autoReconnect", "on", "eventName", "resolve", "reject", "code", "reason", "args", "InSiteWebSocket"]
3
+ "sources": ["../../src/client/WebSocket.ts", "../../src/common.ts"],
4
+ "sourcesContent": ["import EventEmitter from \"eventemitter3\";\nimport { debounce, noop, uid } from \"@nesvet/n\";\nimport {\n\theartbeatGap,\n\theartbeatInterval,\n\trequestHeaders,\n\ttype RequestListener\n} from \"../common\";\nimport { Options } from \"./types\";\n\n\nconst reconnectTimeout = 2000;\n\nlet i = 0;\n\nconst webSocketUrlWeakMap = new WeakMap<WebSocket, string>();\n\n\nexport class InSiteWebSocket extends EventEmitter {\n\tconstructor(url: string, options: Options = {}) {\n\t\tsuper();\n\t\t\n\t\tthis.url = url;\n\t\t\n\t\tconst {\n\t\t\tname = (i++).toString(),\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\tthis.on(`message:${requestHeaders.request}`, this.#handleRequest);\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\treadonly isWebSocket = true;\n\treadonly isWebSocketServer = false;\n\treadonly isWebSocketServerClient = false;\n\t\n\turl: string;\n\t\n\tname: string;\n\t\n\tprotocols?: string[];\n\t\n\tautoReconnect: boolean;\n\t\n\tsend?(data: ArrayBufferLike | ArrayBufferView | Blob | string): void;\n\t\n\twebSocket: null | WebSocket = null;\n\t\n\t#defib = debounce(InSiteWebSocket.defib, heartbeatInterval + heartbeatGap);\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\t#openResolve?: (value?: unknown) => void;\n\t#openReject?: (reason?: unknown) => void;\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 }: MessageEvent) => {\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 as Error);\n\t\t\t}\n\t\telse\n\t\t\tthis.webSocket!.send(\"\");\n\t\t\n\t};\n\t\n\t#handleWebSocketError = (error: Error | Event | undefined) => {\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?: number;\n\t\n\t#handleWebSocketClose = (event: CloseEvent) => {\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) as unknown as number;\n\t\t}\n\t\t\n\t};\n\t\n\tasync open(options: Options = {}) {\n\t\t\n\t\tclearTimeout(this.#reconnectTimeout);\n\t\t\n\t\tawait this.close(4000, \"reopen\");\n\t\t\n\t\tif (options.url)\n\t\t\tthis.url = options.url;\n\t\t\n\t\tif (options.protocols)\n\t\t\tthis.protocols = options.protocols;\n\t\t\n\t\tif (this.webSocket && webSocketUrlWeakMap.get(this.webSocket) !== this.url)\n\t\t\tthis.emit(\"server-change\");\n\t\t\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.#openResolve = resolve;\n\t\t\tthis.#openReject = reject;\n\t\t\t\n\t\t\tthis.webSocket = new WebSocket(this.url, this.protocols);\n\t\t\t\n\t\t\tthis.webSocket.addEventListener(\"open\", this.#handleWebSocketOpen);\n\t\t\tthis.webSocket.addEventListener(\"message\", this.#handleWebSocketMessage);\n\t\t\tthis.webSocket.addEventListener(\"error\", this.#handleWebSocketError);\n\t\t\tthis.webSocket.addEventListener(\"close\", this.#handleWebSocketClose);\n\t\t\t\n\t\t\tthis.send = this.webSocket.send.bind(this.webSocket);\n\t\t\t\n\t\t\twebSocketUrlWeakMap.set(this.webSocket, this.url);\n\t\t\t\n\t\t\tthis.emit(\"connecting\");\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(null);\n\t\t\t\n\t\t});\n\t}\n\t\n\tdisconnect = this.close;\n\t\n\t#queue: string[] = [];\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: unknown[]) {\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\tsendRequest(...args: unknown[]) {\n\t\t\n\t\tconst id = uid();\n\t\tconst eventName = `message:${requestHeaders.response}-${id}`;\n\t\t\n\t\tif (typeof args.at(-1) == \"function\") {\n\t\t\tthis.once(eventName, args.splice(-1, 1)[0] as () => void);\n\t\t\tthis.sendMessage(requestHeaders.request, id, ...args);\n\t\t\t\n\t\t\treturn this;\n\t\t}\n\t\t\n\t\treturn new Promise((resolve, reject) => {\n\t\t\t\n\t\t\tthis.once(eventName, (error, result) => {\n\t\t\t\tif (error) {\n\t\t\t\t\tconst { message, ...restProps } = error;\n\t\t\t\t\treject(Object.assign(new Error(message), restProps));\n\t\t\t\t} else\n\t\t\t\t\tresolve(result);\n\t\t\t\t\n\t\t\t});\n\t\t\tthis.sendMessage(requestHeaders.request, id, ...args);\n\t\t\t\n\t\t});\n\t}\n\t\n\t#requestListeners = new Map<string, RequestListener>();\n\t\n\taddRequestListener(kind: string, listener: RequestListener) {\n\t\tthis.#requestListeners.set(kind, listener);\n\t\t\n\t\treturn this;\n\t}\n\t\n\tonRequest = this.addRequestListener;\n\t\n\tremoveRequestListener(kind: string) {\n\t\tthis.#requestListeners.delete(kind);\n\t\t\n\t\treturn this;\n\t}\n\t\n\toffRequest = this.removeRequestListener;\n\t\n\t#handleRequest = async (id: string, kind: string, ...rest: unknown[]) => {\n\t\tconst listener = this.#requestListeners.get(kind);\n\t\t\n\t\tlet result;\n\t\tlet requestError = null;\n\t\t\n\t\tif (listener)\n\t\t\ttry {\n\t\t\t\tresult = await listener.apply(this, rest);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof Error) {\n\t\t\t\t\tconst { message, ...restProps } = error;\n\t\t\t\t\trequestError = { message, ...restProps };\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\trequestError = { message: `Unknown request kind \"${kind}\"` };\n\t\t\n\t\tthis.sendMessage(`${requestHeaders.response}-${id}`, requestError, result);\n\t\t\n\t};\n\t\n\t\n\tstatic defib(this: InSiteWebSocket) {\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}\n\t\n}\n", "export const heartbeatInterval = 5_000;\nexport const heartbeatGap = 60_000;\n\nexport const requestHeaders = {\n\trequest: \"~r-q\",\n\tresponse: \"~r-s\"\n};\n\nexport type RequestListener = (...args: unknown[]) => Promise<unknown> | unknown;\n"],
5
+ "mappings": "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",
6
+ "names": ["EventEmitter", "debounce", "noop", "uid", "requestHeaders", "reconnectTimeout", "i", "webSocketUrlWeakMap", "_defib", "_openResolve", "_openReject", "_handleWebSocketOpen", "_handleWebSocketMessage", "_handleWebSocketError", "_reconnectTimeout", "_handleWebSocketClose", "_queue", "_releaseQueue", "_requestListeners", "_handleRequest", "_InSiteWebSocket", "EventEmitter", "url", "options", "__publicField", "__privateAdd", "debounce", "__privateGet", "__privateSet", "message", "kind", "rest", "error", "event", "noop", "id", "listener", "result", "requestError", "restProps", "requestHeaders", "name", "protocols", "immediately", "autoReconnect", "on", "eventName", "resolve", "reject", "code", "reason", "args", "uid", "InSiteWebSocket"]
7
7
  }
package/dist/common.d.ts CHANGED
@@ -1,3 +1,8 @@
1
1
  export declare const heartbeatInterval = 5000;
2
2
  export declare const heartbeatGap = 60000;
3
+ export declare const requestHeaders: {
4
+ request: string;
5
+ response: string;
6
+ };
7
+ export type RequestListener = (...args: unknown[]) => Promise<unknown> | unknown;
3
8
  //# sourceMappingURL=common.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,OAAQ,CAAC;AACvC,eAAO,MAAM,YAAY,QAAS,CAAC"}
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,OAAQ,CAAC;AACvC,eAAO,MAAM,YAAY,QAAS,CAAC;AAEnC,eAAO,MAAM,cAAc;;;CAG1B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC"}
@@ -1,14 +1,20 @@
1
1
  /// <reference types="node" />
2
2
  import http from "node:http";
3
3
  import WebSocket, { WebSocketServer } from "ws";
4
+ import { type RequestListener } from "../common";
4
5
  import { Options } from "./types";
5
6
  import { InSiteWebSocketServerClient } from "./WebSocketServerClient";
6
7
  export declare class InSiteWebSocketServer extends WebSocketServer<typeof InSiteWebSocketServerClient> {
8
+ #private;
7
9
  constructor(options: Options, props?: Record<string, unknown>, handleListen?: (() => void));
8
10
  readonly isWebSocketServer = true;
9
11
  readonly isWebSocketServerClient = false;
10
12
  readonly isWebSocket = false;
11
- static handleConnection(this: InSiteWebSocketServer, ws: InSiteWebSocketServerClient | WebSocket, request: http.IncomingMessage): void;
13
+ addRequestListener(kind: string, listener: RequestListener): this;
14
+ onRequest: (kind: string, listener: RequestListener) => this;
15
+ removeRequestListener(kind: string): this;
16
+ offRequest: (kind: string) => this;
17
+ static handleConnection(this: InSiteWebSocketServer, wssc: InSiteWebSocketServerClient | WebSocket, request: http.IncomingMessage): void;
12
18
  static handleClientMessage(this: InSiteWebSocketServerClient, data: WebSocket.RawData): void;
13
19
  static handleClientError(this: InSiteWebSocketServerClient, error: Error | Event | undefined): void;
14
20
  static handleClientClose(this: InSiteWebSocketServerClient, ...args: unknown[]): void;
@@ -1 +1 @@
1
- {"version":3,"file":"WebSocketServer.d.ts","sourceRoot":"","sources":["../../src/server/WebSocketServer.ts"],"names":[],"mappings":";AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,SAAS,EAAE,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC;AAEhD,OAAO,EAAsB,OAAO,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAGtE,qBAAa,qBAAsB,SAAQ,eAAe,CAAC,OAAO,2BAA2B,CAAC;gBACjF,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC;IA0B1F,QAAQ,CAAC,iBAAiB,QAAQ;IAClC,QAAQ,CAAC,uBAAuB,SAAS;IACzC,QAAQ,CAAC,WAAW,SAAS;IAG7B,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,qBAAqB,EAAE,EAAE,EAAE,2BAA2B,GAAG,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,eAAe;IAwD/H,MAAM,CAAC,mBAAmB,CAAC,IAAI,EAAE,2BAA2B,EAAE,IAAI,EAAE,SAAS,CAAC,OAAO;IAsBrF,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,2BAA2B,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS;IAW5F,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,2BAA2B,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE;CAa9E"}
1
+ {"version":3,"file":"WebSocketServer.d.ts","sourceRoot":"","sources":["../../src/server/WebSocketServer.ts"],"names":[],"mappings":";AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,SAAS,EAAE,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC;AAChD,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjE,OAAO,EAAsB,OAAO,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAGtE,qBAAa,qBAAsB,SAAQ,eAAe,CAAC,OAAO,2BAA2B,CAAC;;gBACjF,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC;IA4B1F,QAAQ,CAAC,iBAAiB,QAAQ;IAClC,QAAQ,CAAC,uBAAuB,SAAS;IACzC,QAAQ,CAAC,WAAW,SAAS;IAI7B,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe;IAM1D,SAAS,SANgB,MAAM,YAAY,eAAe,UAMtB;IAEpC,qBAAqB,CAAC,IAAI,EAAE,MAAM;IAMlC,UAAU,SANkB,MAAM,UAMM;IAyBxC,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,qBAAqB,EAAE,IAAI,EAAE,2BAA2B,GAAG,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,eAAe;IAyDjI,MAAM,CAAC,mBAAmB,CAAC,IAAI,EAAE,2BAA2B,EAAE,IAAI,EAAE,SAAS,CAAC,OAAO;IAsBrF,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,2BAA2B,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS;IAW5F,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,2BAA2B,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE;CAa9E"}
@@ -18,6 +18,7 @@ export declare class InSiteWebSocketServerClient extends WebSocket {
18
18
  [pingTsSymbol]?: number;
19
19
  [heartbeatIntervalSymbol]: NodeJS.Timeout;
20
20
  sendMessage(...args: unknown[]): void;
21
+ sendRequest(...args: unknown[]): Promise<unknown> | this;
21
22
  static makeDefib(this: InSiteWebSocketServerClient): import("@nesvet/n").Debounced<void>;
22
23
  static makeHeartbeatInterval(this: InSiteWebSocketServerClient): NodeJS.Timeout;
23
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"WebSocketServerClient.d.ts","sourceRoot":"","sources":["../../src/server/WebSocketServerClient.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAG/B,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,qBAAa,2BAA4B,SAAQ,SAAS;IAEzD,IAAI,YAAY,YAEf;IAED,IAAI,MAAM,YAET;IAED,IAAI,SAAS,YAEZ;IAED,IAAI,QAAQ,YAEX;IAED,QAAQ,CAAC,uBAAuB,QAAQ;IACxC,QAAQ,CAAC,iBAAiB,SAAS;IACnC,QAAQ,CAAC,WAAW,SAAS;IAE7B,GAAG,CAAC,EAAE,qBAAqB,CAAC;IAE5B,SAAS,SAAM;IAEf,aAAa,SAAM;IAEnB,CAAC,WAAW,CAAC,sCAAoD;IAEjE,OAAO,SAAK;IAEZ,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC;IAExB,CAAC,uBAAuB,CAAC,iBAAgE;IAEzF,WAAW,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE;IAK9B,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,2BAA2B;IAIlD,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,2BAA2B;CAS9D"}
1
+ {"version":3,"file":"WebSocketServerClient.d.ts","sourceRoot":"","sources":["../../src/server/WebSocketServerClient.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAG/B,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,qBAAa,2BAA4B,SAAQ,SAAS;IAEzD,IAAI,YAAY,YAEf;IAED,IAAI,MAAM,YAET;IAED,IAAI,SAAS,YAEZ;IAED,IAAI,QAAQ,YAEX;IAED,QAAQ,CAAC,uBAAuB,QAAQ;IACxC,QAAQ,CAAC,iBAAiB,SAAS;IACnC,QAAQ,CAAC,WAAW,SAAS;IAE7B,GAAG,CAAC,EAAE,qBAAqB,CAAC;IAE5B,SAAS,SAAM;IAEf,aAAa,SAAM;IAEnB,CAAC,WAAW,CAAC,sCAAoD;IAEjE,OAAO,SAAK;IAEZ,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC;IAExB,CAAC,uBAAuB,CAAC,iBAAgE;IAEzF,WAAW,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE;IAI9B,WAAW,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE;IA4B9B,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,2BAA2B;IAIlD,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,2BAA2B;CAS9D"}
@@ -1,2 +1,2 @@
1
- import f from"node:http";import C from"node:https";import{WebSocketServer as v}from"ws";var l=Symbol("heartbeatInterval"),o=Symbol("defib"),a=Symbol("pingTs");import{WebSocket as d}from"ws";import{debounce as g}from"@nesvet/n";var r=class s extends d{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}isWebSocketServerClient=!0;isWebSocketServer=!1;isWebSocket=!1;wss;userAgent="";remoteAddress="";[o]=s.makeDefib.call(this);latency=0;[a];[l]=s.makeHeartbeatInterval.call(this);sendMessage(...e){return this.send(JSON.stringify(e))}static makeDefib(){return g(()=>this.terminate(),65e3)}static makeHeartbeatInterval(){return setInterval(()=>{this[a]=Date.now(),this.send("")},5e3)}};var b=class s extends v{constructor(e,t,i){let{ssl:n,port:m,server:c=n?C.createServer({...n}):f.createServer(),...h}=e;super({...h,WebSocket:r,server:c}),t&&(typeof t=="function"?i=t:Object.assign(this,t)),this.on("connection",s.handleConnection),c.listen(m,i)}isWebSocketServer=!0;isWebSocketServerClient=!1;isWebSocket=!1;static handleConnection(e,t){if(!(e instanceof r)){Object.defineProperties(e,{isConnecting:{get:Object.getOwnPropertyDescriptor(r.prototype,"isConnecting").get},isOpen:{get:Object.getOwnPropertyDescriptor(r.prototype,"isOpen").get},isClosing:{get:Object.getOwnPropertyDescriptor(r.prototype,"isClosing").get},isClosed:{get:Object.getOwnPropertyDescriptor(r.prototype,"isClosed").get}});let{terminate:i}=e;Object.assign(e,{isWebSocketServerClient:!0,isWebSocketServer:!1,isWebSocket:!1,[o]:r.makeDefib.call(e),latency:0,[l]:r.makeHeartbeatInterval.call(e),sendMessage:r.prototype.sendMessage,terminate(){try{i.call(e)}catch(n){console.error(n)}}})}Object.assign(e,{wss:this,userAgent:t.headers["user-agent"],remoteAddress:t.headers["x-real-ip"]??t.headers["x-forwarded-for"]??"127.0.0.1"}),e[o](),e.on("message",s.handleClientMessage),e.on("error",s.handleClientError),e.on("close",s.handleClientClose),this.emit("client-connect",e,t)}static handleClientMessage(e){let t=e.toString();if(this[o](),t)try{let[i,...n]=JSON.parse(t);this.emit(`message:${i}`,...n),this.wss.emit("client-message",this,i,...n),this.wss.emit(`client-message:${i}`,this,...n)}catch(i){s.handleClientError.call(this,i)}else this[a]&&(this.latency=Date.now()-this[a],delete this[a])}static handleClientError(e){e instanceof Event&&(e=void 0),process.env.NODE_ENV==="development"&&console.error("WebSocketServer Client error",e),this.wss.emit("client-error",this,e)}static handleClientClose(...e){process.env.NODE_ENV==="development"&&console.info("WebSocketServer Client closed",...e),this[o].clear(),clearInterval(this[l]),this.wss.emit("client-close",this),this.wss.emit("client-closed",this)}};export{b as InSiteWebSocketServer,r as InSiteWebSocketServerClient};
1
+ import C from"node:http";import W from"node:https";import{WebSocketServer as I}from"ws";var l={request:"~r-q",response:"~r-s"};var m=Symbol("heartbeatInterval"),c=Symbol("defib"),S=Symbol("pingTs");import{WebSocket as v}from"ws";import{debounce as k,uid as y}from"@nesvet/n";var r=class i extends v{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}isWebSocketServerClient=!0;isWebSocketServer=!1;isWebSocket=!1;wss;userAgent="";remoteAddress="";[c]=i.makeDefib.call(this);latency=0;[S];[m]=i.makeHeartbeatInterval.call(this);sendMessage(...e){return this.send(JSON.stringify(e))}sendRequest(...e){let t=y(),s=`message:${l.response}-${t}`;return typeof e.at(-1)=="function"?(this.once(s,e.splice(-1,1)[0]),this.sendMessage(l.request,t,...e),this):new Promise((n,h)=>{this.once(s,(o,a)=>{if(o){let{message:p,...b}=o;h(Object.assign(new Error(p),b))}else n(a)}),this.sendMessage(l.request,t,...e)})}static makeDefib(){return k(()=>this.terminate(),65e3)}static makeHeartbeatInterval(){return setInterval(()=>{this[S]=Date.now(),this.send("")},5e3)}};var g=class i extends I{constructor(e,t,s){let{ssl:n,port:h,server:o=n?W.createServer({...n}):C.createServer(),...a}=e;super({...a,WebSocket:r,server:o}),t&&(typeof t=="function"?s=t:Object.assign(this,t)),this.on("connection",i.handleConnection),this.on(`client-message:${l.request}`,this.#t),o.listen(h,s)}isWebSocketServer=!0;isWebSocketServerClient=!1;isWebSocket=!1;#e=new Map;addRequestListener(e,t){return this.#e.set(e,t),this}onRequest=this.addRequestListener;removeRequestListener(e){return this.#e.delete(e),this}offRequest=this.removeRequestListener;#t=async(e,t,s,...n)=>{let h=this.#e.get(s),o,a=null;if(h)try{o=await h.call(this,e,...n)}catch(p){if(p instanceof Error){let{message:b,...u}=p;a={message:b,...u}}}else a={message:`Unknown request kind "${s}"`};e.sendMessage(`${l.response}-${t}`,a,o)};static handleConnection(e,t){if(!(e instanceof r)){Object.defineProperties(e,{isConnecting:{get:Object.getOwnPropertyDescriptor(r.prototype,"isConnecting").get},isOpen:{get:Object.getOwnPropertyDescriptor(r.prototype,"isOpen").get},isClosing:{get:Object.getOwnPropertyDescriptor(r.prototype,"isClosing").get},isClosed:{get:Object.getOwnPropertyDescriptor(r.prototype,"isClosed").get}});let{terminate:s}=e;Object.assign(e,{isWebSocketServerClient:!0,isWebSocketServer:!1,isWebSocket:!1,[c]:r.makeDefib.call(e),latency:0,[m]:r.makeHeartbeatInterval.call(e),sendMessage:r.prototype.sendMessage,sendRequest:r.prototype.sendRequest,terminate(){try{s.call(e)}catch(n){console.error(n)}}})}Object.assign(e,{wss:this,userAgent:t.headers["user-agent"],remoteAddress:t.headers["x-real-ip"]??t.headers["x-forwarded-for"]??"127.0.0.1"}),e[c](),e.on("message",i.handleClientMessage),e.on("error",i.handleClientError),e.on("close",i.handleClientClose),this.emit("client-connect",e,t)}static handleClientMessage(e){let t=e.toString();if(this[c](),t)try{let[s,...n]=JSON.parse(t);this.emit(`message:${s}`,...n),this.wss.emit("client-message",this,s,...n),this.wss.emit(`client-message:${s}`,this,...n)}catch(s){i.handleClientError.call(this,s)}else this[S]&&(this.latency=Date.now()-this[S],delete this[S])}static handleClientError(e){e instanceof Event&&(e=void 0),process.env.NODE_ENV==="development"&&console.error("WebSocketServer Client error",e),this.wss.emit("client-error",this,e)}static handleClientClose(...e){process.env.NODE_ENV==="development"&&console.info("WebSocketServer Client closed",...e),this[c].clear(),clearInterval(this[m]),this.wss.emit("client-close",this),this.wss.emit("client-closed",this)}};export{g as InSiteWebSocketServer,r as InSiteWebSocketServerClient};
2
2
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/server/WebSocketServer.ts", "../../src/server/symbols.ts", "../../src/server/WebSocketServerClient.ts"],
4
- "sourcesContent": ["import http from \"node:http\";\nimport https from \"node:https\";\nimport WebSocket, { WebSocketServer } from \"ws\";\nimport { defibSymbol, heartbeatIntervalSymbol, pingTsSymbol } from \"./symbols\";\nimport { CompatibleListener, Options } from \"./types\";\nimport { InSiteWebSocketServerClient } from \"./WebSocketServerClient\";\n\n\nexport class InSiteWebSocketServer extends WebSocketServer<typeof InSiteWebSocketServerClient> {\n\tconstructor(options: Options, props?: Record<string, unknown>, handleListen?: (() => void)) {\n\t\tconst {\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: InSiteWebSocketServerClient,\n\t\t\tserver\n\t\t});\n\t\t\n\t\tif (props)\n\t\t\tif (typeof props == \"function\")\n\t\t\t\thandleListen = props;\n\t\t\telse\n\t\t\t\tObject.assign(this, props);\n\t\t\n\t\tthis.on(\"connection\", InSiteWebSocketServer.handleConnection as CompatibleListener);\n\t\t\n\t\tserver.listen(port, handleListen);\n\t\t\n\t}\n\t\n\treadonly isWebSocketServer = true;\n\treadonly isWebSocketServerClient = false;\n\treadonly isWebSocket = false;\n\t\n\t\n\tstatic handleConnection(this: InSiteWebSocketServer, ws: InSiteWebSocketServerClient | WebSocket, request: http.IncomingMessage) {\n\t\tif (!(ws instanceof InSiteWebSocketServerClient)) { /* Compatibility with Bun */\n\t\t\tObject.defineProperties(ws, {\n\t\t\t\tisConnecting: {\n\t\t\t\t\tget: Object.getOwnPropertyDescriptor(InSiteWebSocketServerClient.prototype, \"isConnecting\")!.get\n\t\t\t\t},\n\t\t\t\tisOpen: {\n\t\t\t\t\tget: Object.getOwnPropertyDescriptor(InSiteWebSocketServerClient.prototype, \"isOpen\")!.get\n\t\t\t\t},\n\t\t\t\tisClosing: {\n\t\t\t\t\tget: Object.getOwnPropertyDescriptor(InSiteWebSocketServerClient.prototype, \"isClosing\")!.get\n\t\t\t\t},\n\t\t\t\tisClosed: {\n\t\t\t\t\tget: Object.getOwnPropertyDescriptor(InSiteWebSocketServerClient.prototype, \"isClosed\")!.get\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\tconst { terminate } = ws;\n\t\t\t\n\t\t\tObject.assign(ws, {\n\t\t\t\tisWebSocketServerClient: true,\n\t\t\t\tisWebSocketServer: false,\n\t\t\t\tisWebSocket: false,\n\t\t\t\t[defibSymbol]: InSiteWebSocketServerClient.makeDefib.call(ws as InSiteWebSocketServerClient),\n\t\t\t\tlatency: 0,\n\t\t\t\t[heartbeatIntervalSymbol]: InSiteWebSocketServerClient.makeHeartbeatInterval.call(ws as InSiteWebSocketServerClient),\n\t\t\t\tsendMessage: InSiteWebSocketServerClient.prototype.sendMessage,\n\t\t\t\tterminate() { /* Workaround Bun's WebSocket#terminate bug */\n\t\t\t\t\t\n\t\t\t\t\ttry {\n\t\t\t\t\t\tterminate.call(ws);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconsole.error(error);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t\tObject.assign(ws, {\n\t\t\twss: this,\n\t\t\tuserAgent: request.headers[\"user-agent\"],\n\t\t\tremoteAddress: request.headers[\"x-real-ip\"] ?? request.headers[\"x-forwarded-for\"] ?? \"127.0.0.1\"\n\t\t});\n\t\t\n\t\t(ws as InSiteWebSocketServerClient)[defibSymbol]();\n\t\t\n\t\tws.on(\"message\", InSiteWebSocketServer.handleClientMessage as CompatibleListener);\n\t\tws.on(\"error\", InSiteWebSocketServer.handleClientError as CompatibleListener);\n\t\tws.on(\"close\", InSiteWebSocketServer.handleClientClose as CompatibleListener);\n\t\t\n\t\tthis.emit(\"client-connect\", ws, request);\n\t\t\n\t}\n\t\n\t\n\tstatic handleClientMessage(this: InSiteWebSocketServerClient, data: WebSocket.RawData) {\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 as Error);\n\t\t\t}\n\t\telse 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(this: InSiteWebSocketServerClient, error: Error | Event | undefined) {\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(this: InSiteWebSocketServerClient, ...args: unknown[]) {\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", "export const heartbeatIntervalSymbol = Symbol(\"heartbeatInterval\");\nexport const defibSymbol = Symbol(\"defib\");\nexport const pingTsSymbol = Symbol(\"pingTs\");\n", "import { WebSocket } from \"ws\";\nimport { debounce } from \"@nesvet/n\";\nimport { heartbeatGap, heartbeatInterval } from \"../common\";\nimport { defibSymbol, heartbeatIntervalSymbol, pingTsSymbol } from \"./symbols\";\nimport { InSiteWebSocketServer } from \"./WebSocketServer\";\n\n\nexport class InSiteWebSocketServerClient extends WebSocket {\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\treadonly isWebSocketServerClient = true;\n\treadonly isWebSocketServer = false;\n\treadonly isWebSocket = false;\n\t\n\twss?: InSiteWebSocketServer;\n\t\n\tuserAgent = \"\";\n\t\n\tremoteAddress = \"\";\n\t\n\t[defibSymbol] = InSiteWebSocketServerClient.makeDefib.call(this);\n\t\n\tlatency = 0;\n\t\n\t[pingTsSymbol]?: number;\n\t\n\t[heartbeatIntervalSymbol] = InSiteWebSocketServerClient.makeHeartbeatInterval.call(this);\n\t\n\tsendMessage(...args: unknown[]) {\n\t\treturn this.send(JSON.stringify(args));\n\t}\n\t\n\t\n\tstatic makeDefib(this: InSiteWebSocketServerClient) {\n\t\treturn debounce(() => this.terminate(), heartbeatInterval + heartbeatGap);\n\t}\n\t\n\tstatic makeHeartbeatInterval(this: InSiteWebSocketServerClient) {\n\t\treturn setInterval(() => {\n\t\t\t\n\t\t\tthis[pingTsSymbol] = Date.now();\n\t\t\tthis.send(\"\");\n\t\t\t\n\t\t}, heartbeatInterval);\n\t}\n\t\n}\n"],
5
- "mappings": "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",
6
- "names": ["http", "https", "WebSocketServer", "heartbeatIntervalSymbol", "defibSymbol", "pingTsSymbol", "WebSocket", "debounce", "InSiteWebSocketServerClient", "_InSiteWebSocketServerClient", "WebSocket", "defibSymbol", "pingTsSymbol", "heartbeatIntervalSymbol", "args", "debounce", "InSiteWebSocketServer", "_InSiteWebSocketServer", "WebSocketServer", "options", "props", "handleListen", "ssl", "port", "server", "https", "http", "wssOptions", "InSiteWebSocketServerClient", "ws", "request", "terminate", "defibSymbol", "heartbeatIntervalSymbol", "error", "data", "message", "kind", "rest", "pingTsSymbol", "args"]
3
+ "sources": ["../../src/server/WebSocketServer.ts", "../../src/common.ts", "../../src/server/symbols.ts", "../../src/server/WebSocketServerClient.ts"],
4
+ "sourcesContent": ["import http from \"node:http\";\nimport https from \"node:https\";\nimport WebSocket, { WebSocketServer } from \"ws\";\nimport { requestHeaders, type RequestListener } from \"../common\";\nimport { defibSymbol, heartbeatIntervalSymbol, pingTsSymbol } from \"./symbols\";\nimport { CompatibleListener, Options } from \"./types\";\nimport { InSiteWebSocketServerClient } from \"./WebSocketServerClient\";\n\n\nexport class InSiteWebSocketServer extends WebSocketServer<typeof InSiteWebSocketServerClient> {\n\tconstructor(options: Options, props?: Record<string, unknown>, handleListen?: (() => void)) {\n\t\tconst {\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: InSiteWebSocketServerClient,\n\t\t\tserver\n\t\t});\n\t\t\n\t\tif (props)\n\t\t\tif (typeof props == \"function\")\n\t\t\t\thandleListen = props;\n\t\t\telse\n\t\t\t\tObject.assign(this, props);\n\t\t\n\t\tthis.on(\"connection\", InSiteWebSocketServer.handleConnection as CompatibleListener);\n\t\t\n\t\tthis.on(`client-message:${requestHeaders.request}`, this.#handleRequest);\n\t\t\n\t\tserver.listen(port, handleListen);\n\t\t\n\t}\n\t\n\treadonly isWebSocketServer = true;\n\treadonly isWebSocketServerClient = false;\n\treadonly isWebSocket = false;\n\t\n\t#requestListeners = new Map<string, RequestListener>();\n\t\n\taddRequestListener(kind: string, listener: RequestListener) {\n\t\tthis.#requestListeners.set(kind, listener);\n\t\t\n\t\treturn this;\n\t}\n\t\n\tonRequest = this.addRequestListener;\n\t\n\tremoveRequestListener(kind: string) {\n\t\tthis.#requestListeners.delete(kind);\n\t\t\n\t\treturn this;\n\t}\n\t\n\toffRequest = this.removeRequestListener;\n\t\n\t#handleRequest = async (wssc: InSiteWebSocketServerClient, id: string, kind: string, ...rest: unknown[]) => {\n\t\tconst listener = this.#requestListeners.get(kind);\n\t\t\n\t\tlet result;\n\t\tlet requestError = null;\n\t\t\n\t\tif (listener)\n\t\t\ttry {\n\t\t\t\tresult = await listener.call(this, wssc, ...rest);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof Error) {\n\t\t\t\t\tconst { message, ...restProps } = error;\n\t\t\t\t\trequestError = { message, ...restProps };\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\trequestError = { message: `Unknown request kind \"${kind}\"` };\n\t\t\n\t\twssc.sendMessage(`${requestHeaders.response}-${id}`, requestError, result);\n\t\t\n\t};\n\t\n\t\n\tstatic handleConnection(this: InSiteWebSocketServer, wssc: InSiteWebSocketServerClient | WebSocket, request: http.IncomingMessage) {\n\t\tif (!(wssc instanceof InSiteWebSocketServerClient)) { /* Compatibility with Bun */\n\t\t\tObject.defineProperties(wssc, {\n\t\t\t\tisConnecting: {\n\t\t\t\t\tget: Object.getOwnPropertyDescriptor(InSiteWebSocketServerClient.prototype, \"isConnecting\")!.get\n\t\t\t\t},\n\t\t\t\tisOpen: {\n\t\t\t\t\tget: Object.getOwnPropertyDescriptor(InSiteWebSocketServerClient.prototype, \"isOpen\")!.get\n\t\t\t\t},\n\t\t\t\tisClosing: {\n\t\t\t\t\tget: Object.getOwnPropertyDescriptor(InSiteWebSocketServerClient.prototype, \"isClosing\")!.get\n\t\t\t\t},\n\t\t\t\tisClosed: {\n\t\t\t\t\tget: Object.getOwnPropertyDescriptor(InSiteWebSocketServerClient.prototype, \"isClosed\")!.get\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\tconst { terminate } = wssc;\n\t\t\t\n\t\t\tObject.assign(wssc, {\n\t\t\t\tisWebSocketServerClient: true,\n\t\t\t\tisWebSocketServer: false,\n\t\t\t\tisWebSocket: false,\n\t\t\t\t[defibSymbol]: InSiteWebSocketServerClient.makeDefib.call(wssc as InSiteWebSocketServerClient),\n\t\t\t\tlatency: 0,\n\t\t\t\t[heartbeatIntervalSymbol]: InSiteWebSocketServerClient.makeHeartbeatInterval.call(wssc as InSiteWebSocketServerClient),\n\t\t\t\tsendMessage: InSiteWebSocketServerClient.prototype.sendMessage,\n\t\t\t\tsendRequest: InSiteWebSocketServerClient.prototype.sendRequest,\n\t\t\t\tterminate() { /* Workaround Bun's WebSocket#terminate bug */\n\t\t\t\t\t\n\t\t\t\t\ttry {\n\t\t\t\t\t\tterminate.call(wssc);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconsole.error(error);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t\tObject.assign(wssc, {\n\t\t\twss: this,\n\t\t\tuserAgent: request.headers[\"user-agent\"],\n\t\t\tremoteAddress: request.headers[\"x-real-ip\"] ?? request.headers[\"x-forwarded-for\"] ?? \"127.0.0.1\"\n\t\t});\n\t\t\n\t\t(wssc as InSiteWebSocketServerClient)[defibSymbol]();\n\t\t\n\t\twssc.on(\"message\", InSiteWebSocketServer.handleClientMessage as CompatibleListener);\n\t\twssc.on(\"error\", InSiteWebSocketServer.handleClientError as CompatibleListener);\n\t\twssc.on(\"close\", InSiteWebSocketServer.handleClientClose as CompatibleListener);\n\t\t\n\t\tthis.emit(\"client-connect\", wssc, request);\n\t\t\n\t}\n\t\n\t\n\tstatic handleClientMessage(this: InSiteWebSocketServerClient, data: WebSocket.RawData) {\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 as Error);\n\t\t\t}\n\t\telse 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(this: InSiteWebSocketServerClient, error: Error | Event | undefined) {\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(this: InSiteWebSocketServerClient, ...args: unknown[]) {\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", "export const heartbeatInterval = 5_000;\nexport const heartbeatGap = 60_000;\n\nexport const requestHeaders = {\n\trequest: \"~r-q\",\n\tresponse: \"~r-s\"\n};\n\nexport type RequestListener = (...args: unknown[]) => Promise<unknown> | unknown;\n", "export const heartbeatIntervalSymbol = Symbol(\"heartbeatInterval\");\nexport const defibSymbol = Symbol(\"defib\");\nexport const pingTsSymbol = Symbol(\"pingTs\");\n", "import { WebSocket } from \"ws\";\nimport { debounce, uid } from \"@nesvet/n\";\nimport { heartbeatGap, heartbeatInterval, requestHeaders } from \"../common\";\nimport { defibSymbol, heartbeatIntervalSymbol, pingTsSymbol } from \"./symbols\";\nimport { InSiteWebSocketServer } from \"./WebSocketServer\";\n\n\nexport class InSiteWebSocketServerClient extends WebSocket {\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\treadonly isWebSocketServerClient = true;\n\treadonly isWebSocketServer = false;\n\treadonly isWebSocket = false;\n\t\n\twss?: InSiteWebSocketServer;\n\t\n\tuserAgent = \"\";\n\t\n\tremoteAddress = \"\";\n\t\n\t[defibSymbol] = InSiteWebSocketServerClient.makeDefib.call(this);\n\t\n\tlatency = 0;\n\t\n\t[pingTsSymbol]?: number;\n\t\n\t[heartbeatIntervalSymbol] = InSiteWebSocketServerClient.makeHeartbeatInterval.call(this);\n\t\n\tsendMessage(...args: unknown[]) {\n\t\treturn this.send(JSON.stringify(args));\n\t}\n\t\n\tsendRequest(...args: unknown[]) {\n\t\t\n\t\tconst id = uid();\n\t\tconst eventName = `message:${requestHeaders.response}-${id}`;\n\t\t\n\t\tif (typeof args.at(-1) == \"function\") {\n\t\t\tthis.once(eventName, args.splice(-1, 1)[0] as () => void);\n\t\t\tthis.sendMessage(requestHeaders.request, id, ...args);\n\t\t\t\n\t\t\treturn this;\n\t\t}\n\t\t\n\t\treturn new Promise((resolve, reject) => {\n\t\t\t\n\t\t\tthis.once(eventName, (error, result) => {\n\t\t\t\tif (error) {\n\t\t\t\t\tconst { message, ...restProps } = error;\n\t\t\t\t\treject(Object.assign(new Error(message), restProps));\n\t\t\t\t} else\n\t\t\t\t\tresolve(result);\n\t\t\t\t\n\t\t\t});\n\t\t\tthis.sendMessage(requestHeaders.request, id, ...args);\n\t\t\t\n\t\t});\n\t}\n\t\n\t\n\tstatic makeDefib(this: InSiteWebSocketServerClient) {\n\t\treturn debounce(() => this.terminate(), heartbeatInterval + heartbeatGap);\n\t}\n\t\n\tstatic makeHeartbeatInterval(this: InSiteWebSocketServerClient) {\n\t\treturn setInterval(() => {\n\t\t\t\n\t\t\tthis[pingTsSymbol] = Date.now();\n\t\t\tthis.send(\"\");\n\t\t\t\n\t\t}, heartbeatInterval);\n\t}\n\t\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["http", "https", "WebSocketServer", "requestHeaders", "heartbeatIntervalSymbol", "defibSymbol", "pingTsSymbol", "WebSocket", "debounce", "uid", "InSiteWebSocketServerClient", "_InSiteWebSocketServerClient", "WebSocket", "defibSymbol", "pingTsSymbol", "heartbeatIntervalSymbol", "args", "id", "uid", "eventName", "requestHeaders", "resolve", "reject", "error", "result", "message", "restProps", "debounce", "InSiteWebSocketServer", "_InSiteWebSocketServer", "WebSocketServer", "options", "props", "handleListen", "ssl", "port", "server", "https", "http", "wssOptions", "InSiteWebSocketServerClient", "requestHeaders", "#handleRequest", "#requestListeners", "kind", "listener", "wssc", "id", "rest", "result", "requestError", "error", "message", "restProps", "request", "terminate", "defibSymbol", "heartbeatIntervalSymbol", "data", "pingTsSymbol", "args"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "insite-ws",
3
- "version": "2.0.3",
3
+ "version": "2.0.5",
4
4
  "description": "inSite WebSockets",
5
5
  "type": "module",
6
6
  "exports": {
@@ -10,7 +10,7 @@
10
10
  "packageManager": "bun@1.1.18",
11
11
  "scripts": {
12
12
  "test": "echo \"Error: no test specified\" && exit 1",
13
- "build": "bun .conveyer.js",
13
+ "build": "bun .conveyer.ts",
14
14
  "postbuild": "tsc -p ."
15
15
  },
16
16
  "repository": {
@@ -25,13 +25,13 @@
25
25
  "author": "Eugene Nesvetaev <dev@nesvet.dev> (https://nesvet.dev/)",
26
26
  "license": "MIT",
27
27
  "dependencies": {
28
- "@nesvet/n": "^1.0.64",
28
+ "@nesvet/n": "^1.0.66",
29
29
  "eventemitter3": "^5.0.1",
30
30
  "ws": "^8.18.0"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@nesvet/conveyer": "^2.2.1",
34
- "@nesvet/eslint-config": "^2.0.22",
34
+ "@nesvet/eslint-config": "^2.0.23",
35
35
  "@types/node": "^20.14.10",
36
36
  "@types/ws": "^8.5.10"
37
37
  }